Index: llvm/trunk/lib/MC/CMakeLists.txt =================================================================== --- llvm/trunk/lib/MC/CMakeLists.txt +++ llvm/trunk/lib/MC/CMakeLists.txt @@ -45,13 +45,13 @@ MCWasmObjectTargetWriter.cpp MCWasmStreamer.cpp MCWin64EH.cpp + MCWinCOFFStreamer.cpp MCWinEH.cpp MachObjectWriter.cpp StringTableBuilder.cpp SubtargetFeature.cpp WasmObjectWriter.cpp WinCOFFObjectWriter.cpp - WinCOFFStreamer.cpp ADDITIONAL_HEADER_DIRS ${LLVM_MAIN_INCLUDE_DIR}/llvm/MC Index: llvm/trunk/lib/MC/MCWinCOFFStreamer.cpp =================================================================== --- llvm/trunk/lib/MC/MCWinCOFFStreamer.cpp +++ llvm/trunk/lib/MC/MCWinCOFFStreamer.cpp @@ -0,0 +1,296 @@ +//===- llvm/MC/MCWinCOFFStreamer.cpp --------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains an implementation of a Windows COFF object file streamer. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Triple.h" +#include "llvm/ADT/Twine.h" +#include "llvm/BinaryFormat/COFF.h" +#include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCFragment.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCObjectStreamer.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCSymbolCOFF.h" +#include "llvm/MC/MCWinCOFFStreamer.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/SMLoc.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include + +using namespace llvm; + +#define DEBUG_TYPE "WinCOFFStreamer" + +MCWinCOFFStreamer::MCWinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB, + MCCodeEmitter &CE, raw_pwrite_stream &OS) + : MCObjectStreamer(Context, MAB, OS, &CE), CurSymbol(nullptr) {} + +void MCWinCOFFStreamer::EmitInstToData(const MCInst &Inst, + const MCSubtargetInfo &STI) { + MCDataFragment *DF = getOrCreateDataFragment(); + + SmallVector Fixups; + SmallString<256> Code; + raw_svector_ostream VecOS(Code); + getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI); + + // Add the fixups and data. + for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { + Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); + DF->getFixups().push_back(Fixups[i]); + } + + DF->getContents().append(Code.begin(), Code.end()); +} + +void MCWinCOFFStreamer::InitSections(bool NoExecStack) { + // FIXME: this is identical to the ELF one. + // This emulates the same behavior of GNU as. This makes it easier + // to compare the output as the major sections are in the same order. + SwitchSection(getContext().getObjectFileInfo()->getTextSection()); + EmitCodeAlignment(4); + + SwitchSection(getContext().getObjectFileInfo()->getDataSection()); + EmitCodeAlignment(4); + + SwitchSection(getContext().getObjectFileInfo()->getBSSSection()); + EmitCodeAlignment(4); + + SwitchSection(getContext().getObjectFileInfo()->getTextSection()); +} + +void MCWinCOFFStreamer::EmitLabel(MCSymbol *S, SMLoc Loc) { + auto *Symbol = cast(S); + MCObjectStreamer::EmitLabel(Symbol, Loc); +} + +void MCWinCOFFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { + llvm_unreachable("not implemented"); +} + +void MCWinCOFFStreamer::EmitThumbFunc(MCSymbol *Func) { + llvm_unreachable("not implemented"); +} + +bool MCWinCOFFStreamer::EmitSymbolAttribute(MCSymbol *S, + MCSymbolAttr Attribute) { + auto *Symbol = cast(S); + getAssembler().registerSymbol(*Symbol); + + switch (Attribute) { + default: return false; + case MCSA_WeakReference: + case MCSA_Weak: + Symbol->setIsWeakExternal(); + Symbol->setExternal(true); + break; + case MCSA_Global: + Symbol->setExternal(true); + break; + case MCSA_AltEntry: + llvm_unreachable("COFF doesn't support the .alt_entry attribute"); + } + + return true; +} + +void MCWinCOFFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { + llvm_unreachable("not implemented"); +} + +void MCWinCOFFStreamer::BeginCOFFSymbolDef(MCSymbol const *S) { + auto *Symbol = cast(S); + if (CurSymbol) + Error("starting a new symbol definition without completing the " + "previous one"); + CurSymbol = Symbol; +} + +void MCWinCOFFStreamer::EmitCOFFSymbolStorageClass(int StorageClass) { + if (!CurSymbol) { + Error("storage class specified outside of symbol definition"); + return; + } + + if (StorageClass & ~COFF::SSC_Invalid) { + Error("storage class value '" + Twine(StorageClass) + + "' out of range"); + return; + } + + getAssembler().registerSymbol(*CurSymbol); + cast(CurSymbol)->setClass((uint16_t)StorageClass); +} + +void MCWinCOFFStreamer::EmitCOFFSymbolType(int Type) { + if (!CurSymbol) { + Error("symbol type specified outside of a symbol definition"); + return; + } + + if (Type & ~0xffff) { + Error("type value '" + Twine(Type) + "' out of range"); + return; + } + + getAssembler().registerSymbol(*CurSymbol); + cast(CurSymbol)->setType((uint16_t)Type); +} + +void MCWinCOFFStreamer::EndCOFFSymbolDef() { + if (!CurSymbol) + Error("ending symbol definition without starting one"); + CurSymbol = nullptr; +} + +void MCWinCOFFStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) { + // SafeSEH is a feature specific to 32-bit x86. It does not exist (and is + // unnecessary) on all platforms which use table-based exception dispatch. + if (getContext().getObjectFileInfo()->getTargetTriple().getArch() != + Triple::x86) + return; + + const MCSymbolCOFF *CSymbol = cast(Symbol); + if (CSymbol->isSafeSEH()) + return; + + MCSection *SXData = getContext().getObjectFileInfo()->getSXDataSection(); + getAssembler().registerSection(*SXData); + if (SXData->getAlignment() < 4) + SXData->setAlignment(4); + + new MCSafeSEHFragment(Symbol, SXData); + + getAssembler().registerSymbol(*Symbol); + CSymbol->setIsSafeSEH(); + + // The Microsoft linker requires that the symbol type of a handler be + // function. Go ahead and oblige it here. + CSymbol->setType(COFF::IMAGE_SYM_DTYPE_FUNCTION + << COFF::SCT_COMPLEX_TYPE_SHIFT); +} + +void MCWinCOFFStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) { + MCDataFragment *DF = getOrCreateDataFragment(); + const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext()); + MCFixup Fixup = MCFixup::create(DF->getContents().size(), SRE, FK_SecRel_2); + DF->getFixups().push_back(Fixup); + DF->getContents().resize(DF->getContents().size() + 2, 0); +} + +void MCWinCOFFStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, + uint64_t Offset) { + MCDataFragment *DF = getOrCreateDataFragment(); + // Create Symbol A for the relocation relative reference. + const MCExpr *MCE = MCSymbolRefExpr::create(Symbol, getContext()); + // Add the constant offset, if given. + if (Offset) + MCE = MCBinaryExpr::createAdd( + MCE, MCConstantExpr::create(Offset, getContext()), getContext()); + // Build the secrel32 relocation. + MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_SecRel_4); + // Record the relocation. + DF->getFixups().push_back(Fixup); + // Emit 4 bytes (zeros) to the object file. + DF->getContents().resize(DF->getContents().size() + 4, 0); +} + +void MCWinCOFFStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size, + unsigned ByteAlignment) { + auto *Symbol = cast(S); + + const Triple &T = getContext().getObjectFileInfo()->getTargetTriple(); + if (T.isKnownWindowsMSVCEnvironment()) { + if (ByteAlignment > 32) + report_fatal_error("alignment is limited to 32-bytes"); + + // Round size up to alignment so that we will honor the alignment request. + Size = std::max(Size, static_cast(ByteAlignment)); + } + + getAssembler().registerSymbol(*Symbol); + Symbol->setExternal(true); + Symbol->setCommon(Size, ByteAlignment); + + if (!T.isKnownWindowsMSVCEnvironment() && ByteAlignment > 1) { + SmallString<128> Directive; + raw_svector_ostream OS(Directive); + const MCObjectFileInfo *MFI = getContext().getObjectFileInfo(); + + OS << " -aligncomm:\"" << Symbol->getName() << "\"," + << Log2_32_Ceil(ByteAlignment); + + PushSection(); + SwitchSection(MFI->getDrectveSection()); + EmitBytes(Directive); + PopSection(); + } +} + +void MCWinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size, + unsigned ByteAlignment) { + auto *Symbol = cast(S); + + MCSection *Section = getContext().getObjectFileInfo()->getBSSSection(); + getAssembler().registerSection(*Section); + if (Section->getAlignment() < ByteAlignment) + Section->setAlignment(ByteAlignment); + + getAssembler().registerSymbol(*Symbol); + Symbol->setExternal(false); + + if (ByteAlignment != 1) + new MCAlignFragment(ByteAlignment, /*Value=*/0, /*ValueSize=*/0, + ByteAlignment, Section); + + MCFillFragment *Fragment = new MCFillFragment( + /*Value=*/0, Size, Section); + Symbol->setFragment(Fragment); +} + +void MCWinCOFFStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment) { + llvm_unreachable("not implemented"); +} + +void MCWinCOFFStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment) { + llvm_unreachable("not implemented"); +} + +// TODO: Implement this if you want to emit .comment section in COFF obj files. +void MCWinCOFFStreamer::EmitIdent(StringRef IdentString) { + llvm_unreachable("not implemented"); +} + +void MCWinCOFFStreamer::EmitWinEHHandlerData() { + llvm_unreachable("not implemented"); +} + +void MCWinCOFFStreamer::FinishImpl() { + MCObjectStreamer::FinishImpl(); +} + +void MCWinCOFFStreamer::Error(const Twine &Msg) const { + getContext().reportError(SMLoc(), Msg); +} Index: llvm/trunk/lib/MC/WinCOFFStreamer.cpp =================================================================== --- llvm/trunk/lib/MC/WinCOFFStreamer.cpp +++ llvm/trunk/lib/MC/WinCOFFStreamer.cpp @@ -1,296 +0,0 @@ -//===- llvm/MC/WinCOFFStreamer.cpp ----------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains an implementation of a Windows COFF object file streamer. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Triple.h" -#include "llvm/ADT/Twine.h" -#include "llvm/BinaryFormat/COFF.h" -#include "llvm/MC/MCAsmBackend.h" -#include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCCodeEmitter.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCFixup.h" -#include "llvm/MC/MCFragment.h" -#include "llvm/MC/MCObjectFileInfo.h" -#include "llvm/MC/MCObjectStreamer.h" -#include "llvm/MC/MCSection.h" -#include "llvm/MC/MCSymbolCOFF.h" -#include "llvm/MC/MCWinCOFFStreamer.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/SMLoc.h" -#include "llvm/Support/raw_ostream.h" -#include -#include -#include - -using namespace llvm; - -#define DEBUG_TYPE "WinCOFFStreamer" - -MCWinCOFFStreamer::MCWinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB, - MCCodeEmitter &CE, raw_pwrite_stream &OS) - : MCObjectStreamer(Context, MAB, OS, &CE), CurSymbol(nullptr) {} - -void MCWinCOFFStreamer::EmitInstToData(const MCInst &Inst, - const MCSubtargetInfo &STI) { - MCDataFragment *DF = getOrCreateDataFragment(); - - SmallVector Fixups; - SmallString<256> Code; - raw_svector_ostream VecOS(Code); - getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI); - - // Add the fixups and data. - for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { - Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size()); - DF->getFixups().push_back(Fixups[i]); - } - - DF->getContents().append(Code.begin(), Code.end()); -} - -void MCWinCOFFStreamer::InitSections(bool NoExecStack) { - // FIXME: this is identical to the ELF one. - // This emulates the same behavior of GNU as. This makes it easier - // to compare the output as the major sections are in the same order. - SwitchSection(getContext().getObjectFileInfo()->getTextSection()); - EmitCodeAlignment(4); - - SwitchSection(getContext().getObjectFileInfo()->getDataSection()); - EmitCodeAlignment(4); - - SwitchSection(getContext().getObjectFileInfo()->getBSSSection()); - EmitCodeAlignment(4); - - SwitchSection(getContext().getObjectFileInfo()->getTextSection()); -} - -void MCWinCOFFStreamer::EmitLabel(MCSymbol *S, SMLoc Loc) { - auto *Symbol = cast(S); - MCObjectStreamer::EmitLabel(Symbol, Loc); -} - -void MCWinCOFFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { - llvm_unreachable("not implemented"); -} - -void MCWinCOFFStreamer::EmitThumbFunc(MCSymbol *Func) { - llvm_unreachable("not implemented"); -} - -bool MCWinCOFFStreamer::EmitSymbolAttribute(MCSymbol *S, - MCSymbolAttr Attribute) { - auto *Symbol = cast(S); - getAssembler().registerSymbol(*Symbol); - - switch (Attribute) { - default: return false; - case MCSA_WeakReference: - case MCSA_Weak: - Symbol->setIsWeakExternal(); - Symbol->setExternal(true); - break; - case MCSA_Global: - Symbol->setExternal(true); - break; - case MCSA_AltEntry: - llvm_unreachable("COFF doesn't support the .alt_entry attribute"); - } - - return true; -} - -void MCWinCOFFStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) { - llvm_unreachable("not implemented"); -} - -void MCWinCOFFStreamer::BeginCOFFSymbolDef(MCSymbol const *S) { - auto *Symbol = cast(S); - if (CurSymbol) - Error("starting a new symbol definition without completing the " - "previous one"); - CurSymbol = Symbol; -} - -void MCWinCOFFStreamer::EmitCOFFSymbolStorageClass(int StorageClass) { - if (!CurSymbol) { - Error("storage class specified outside of symbol definition"); - return; - } - - if (StorageClass & ~COFF::SSC_Invalid) { - Error("storage class value '" + Twine(StorageClass) + - "' out of range"); - return; - } - - getAssembler().registerSymbol(*CurSymbol); - cast(CurSymbol)->setClass((uint16_t)StorageClass); -} - -void MCWinCOFFStreamer::EmitCOFFSymbolType(int Type) { - if (!CurSymbol) { - Error("symbol type specified outside of a symbol definition"); - return; - } - - if (Type & ~0xffff) { - Error("type value '" + Twine(Type) + "' out of range"); - return; - } - - getAssembler().registerSymbol(*CurSymbol); - cast(CurSymbol)->setType((uint16_t)Type); -} - -void MCWinCOFFStreamer::EndCOFFSymbolDef() { - if (!CurSymbol) - Error("ending symbol definition without starting one"); - CurSymbol = nullptr; -} - -void MCWinCOFFStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) { - // SafeSEH is a feature specific to 32-bit x86. It does not exist (and is - // unnecessary) on all platforms which use table-based exception dispatch. - if (getContext().getObjectFileInfo()->getTargetTriple().getArch() != - Triple::x86) - return; - - const MCSymbolCOFF *CSymbol = cast(Symbol); - if (CSymbol->isSafeSEH()) - return; - - MCSection *SXData = getContext().getObjectFileInfo()->getSXDataSection(); - getAssembler().registerSection(*SXData); - if (SXData->getAlignment() < 4) - SXData->setAlignment(4); - - new MCSafeSEHFragment(Symbol, SXData); - - getAssembler().registerSymbol(*Symbol); - CSymbol->setIsSafeSEH(); - - // The Microsoft linker requires that the symbol type of a handler be - // function. Go ahead and oblige it here. - CSymbol->setType(COFF::IMAGE_SYM_DTYPE_FUNCTION - << COFF::SCT_COMPLEX_TYPE_SHIFT); -} - -void MCWinCOFFStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) { - MCDataFragment *DF = getOrCreateDataFragment(); - const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext()); - MCFixup Fixup = MCFixup::create(DF->getContents().size(), SRE, FK_SecRel_2); - DF->getFixups().push_back(Fixup); - DF->getContents().resize(DF->getContents().size() + 2, 0); -} - -void MCWinCOFFStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, - uint64_t Offset) { - MCDataFragment *DF = getOrCreateDataFragment(); - // Create Symbol A for the relocation relative reference. - const MCExpr *MCE = MCSymbolRefExpr::create(Symbol, getContext()); - // Add the constant offset, if given. - if (Offset) - MCE = MCBinaryExpr::createAdd( - MCE, MCConstantExpr::create(Offset, getContext()), getContext()); - // Build the secrel32 relocation. - MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_SecRel_4); - // Record the relocation. - DF->getFixups().push_back(Fixup); - // Emit 4 bytes (zeros) to the object file. - DF->getContents().resize(DF->getContents().size() + 4, 0); -} - -void MCWinCOFFStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size, - unsigned ByteAlignment) { - auto *Symbol = cast(S); - - const Triple &T = getContext().getObjectFileInfo()->getTargetTriple(); - if (T.isKnownWindowsMSVCEnvironment()) { - if (ByteAlignment > 32) - report_fatal_error("alignment is limited to 32-bytes"); - - // Round size up to alignment so that we will honor the alignment request. - Size = std::max(Size, static_cast(ByteAlignment)); - } - - getAssembler().registerSymbol(*Symbol); - Symbol->setExternal(true); - Symbol->setCommon(Size, ByteAlignment); - - if (!T.isKnownWindowsMSVCEnvironment() && ByteAlignment > 1) { - SmallString<128> Directive; - raw_svector_ostream OS(Directive); - const MCObjectFileInfo *MFI = getContext().getObjectFileInfo(); - - OS << " -aligncomm:\"" << Symbol->getName() << "\"," - << Log2_32_Ceil(ByteAlignment); - - PushSection(); - SwitchSection(MFI->getDrectveSection()); - EmitBytes(Directive); - PopSection(); - } -} - -void MCWinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size, - unsigned ByteAlignment) { - auto *Symbol = cast(S); - - MCSection *Section = getContext().getObjectFileInfo()->getBSSSection(); - getAssembler().registerSection(*Section); - if (Section->getAlignment() < ByteAlignment) - Section->setAlignment(ByteAlignment); - - getAssembler().registerSymbol(*Symbol); - Symbol->setExternal(false); - - if (ByteAlignment != 1) - new MCAlignFragment(ByteAlignment, /*Value=*/0, /*ValueSize=*/0, - ByteAlignment, Section); - - MCFillFragment *Fragment = new MCFillFragment( - /*Value=*/0, Size, Section); - Symbol->setFragment(Fragment); -} - -void MCWinCOFFStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment) { - llvm_unreachable("not implemented"); -} - -void MCWinCOFFStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment) { - llvm_unreachable("not implemented"); -} - -// TODO: Implement this if you want to emit .comment section in COFF obj files. -void MCWinCOFFStreamer::EmitIdent(StringRef IdentString) { - llvm_unreachable("not implemented"); -} - -void MCWinCOFFStreamer::EmitWinEHHandlerData() { - llvm_unreachable("not implemented"); -} - -void MCWinCOFFStreamer::FinishImpl() { - MCObjectStreamer::FinishImpl(); -} - -void MCWinCOFFStreamer::Error(const Twine &Msg) const { - getContext().reportError(SMLoc(), Msg); -}