Index: llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -140,6 +140,8 @@ class TargetLoweringObjectFileCOFF : public TargetLoweringObjectFile { + mutable unsigned NextUniqueID = 0; + public: ~TargetLoweringObjectFileCOFF() override {} Index: llvm/trunk/include/llvm/MC/MCContext.h =================================================================== --- llvm/trunk/include/llvm/MC/MCContext.h +++ llvm/trunk/include/llvm/MC/MCContext.h @@ -200,16 +200,19 @@ std::string SectionName; StringRef GroupName; int SelectionKey; + unsigned UniqueID; COFFSectionKey(StringRef SectionName, StringRef GroupName, - int SelectionKey) + int SelectionKey, unsigned UniqueID) : SectionName(SectionName), GroupName(GroupName), - SelectionKey(SelectionKey) {} + SelectionKey(SelectionKey), UniqueID(UniqueID) {} bool operator<(const COFFSectionKey &Other) const { if (SectionName != Other.SectionName) return SectionName < Other.SectionName; if (GroupName != Other.GroupName) return GroupName < Other.GroupName; - return SelectionKey < Other.SelectionKey; + if (SelectionKey != Other.SelectionKey) + return SelectionKey < Other.SelectionKey; + return UniqueID < Other.UniqueID; } }; @@ -315,6 +318,13 @@ /// \name Section Management /// @{ + enum : unsigned { + /// Pass this value as the UniqueID during section creation to get the + /// generic section with the given name and characteristics. The usual + /// sections such as .text use this ID. + GenericSectionID = ~0U + }; + /// Return the MCSection for the specified mach-o section. This requires /// the operands to be valid. MCSectionMachO *getMachOSection(StringRef Segment, StringRef Section, @@ -382,6 +392,7 @@ MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics, SectionKind Kind, StringRef COMDATSymName, int Selection, + unsigned UniqueID = GenericSectionID, const char *BeginSymName = nullptr); MCSectionCOFF *getCOFFSection(StringRef Section, unsigned Characteristics, @@ -394,8 +405,9 @@ /// section containing KeySym. For example, to create a debug info section /// associated with an inline function, pass the normal debug info section /// as Sec and the function symbol as KeySym. - MCSectionCOFF *getAssociativeCOFFSection(MCSectionCOFF *Sec, - const MCSymbol *KeySym); + MCSectionCOFF * + getAssociativeCOFFSection(MCSectionCOFF *Sec, const MCSymbol *KeySym, + unsigned UniqueID = GenericSectionID); // Create and save a copy of STI and return a reference to the copy. MCSubtargetInfo &getSubtargetCopy(const MCSubtargetInfo &STI); Index: llvm/trunk/include/llvm/MC/MCSectionCOFF.h =================================================================== --- llvm/trunk/include/llvm/MC/MCSectionCOFF.h +++ llvm/trunk/include/llvm/MC/MCSectionCOFF.h @@ -32,6 +32,13 @@ /// below. mutable unsigned Characteristics; + /// The unique IDs used with the .pdata and .xdata sections created internally + /// by the assembler. This ID is used to ensure that for every .text section, + /// there is exactly one .pdata and one .xdata section, which is required by + /// the Microsoft incremental linker. This data is mutable because this ID is + /// not notionally part of the section. + mutable unsigned WinCFISectionID = ~0U; + /// The COMDAT symbol of this section. Only valid if this is a COMDAT section. /// Two COMDAT sections are merged if they have the same COMDAT symbol. MCSymbol *COMDATSymbol; @@ -71,6 +78,12 @@ bool UseCodeAlign() const override; bool isVirtualSection() const override; + unsigned getOrAssignWinCFISectionID(unsigned *NextID) const { + if (WinCFISectionID == ~0U) + WinCFISectionID = (*NextID)++; + return WinCFISectionID; + } + static bool classof(const MCSection *S) { return S->getVariant() == SV_COFF; } }; Index: llvm/trunk/include/llvm/MC/MCStreamer.h =================================================================== --- llvm/trunk/include/llvm/MC/MCStreamer.h +++ llvm/trunk/include/llvm/MC/MCStreamer.h @@ -183,6 +183,12 @@ /// PushSection. SmallVector, 4> SectionStack; + /// The next unique ID to use when creating a WinCFI-related section (.pdata + /// or .xdata). This ID ensures that we have a one-to-one mapping from + /// code section to unwind info section, which MSVC's incremental linker + /// requires. + unsigned NextWinCFIID = 0; + protected: MCStreamer(MCContext &Ctx); @@ -720,6 +726,14 @@ virtual void EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, bool Except); virtual void EmitWinEHHandlerData(); + /// Get the .pdata section used for the given section. Typically the given + /// section is either the main .text section or some other COMDAT .text + /// section, but it may be any section containing code. + MCSection *getAssociatedPDataSection(const MCSection *TextSec); + + /// Get the .xdata section used for the given section. + MCSection *getAssociatedXDataSection(const MCSection *TextSec); + virtual void EmitSyntaxDirective(); /// \brief Emit a .reloc directive. Index: llvm/trunk/include/llvm/MC/MCWinEH.h =================================================================== --- llvm/trunk/include/llvm/MC/MCWinEH.h +++ llvm/trunk/include/llvm/MC/MCWinEH.h @@ -13,11 +13,9 @@ #include namespace llvm { -class MCContext; class MCSection; class MCStreamer; class MCSymbol; -class StringRef; namespace WinEH { struct Instruction { @@ -31,50 +29,35 @@ }; struct FrameInfo { - const MCSymbol *Begin; - const MCSymbol *End; - const MCSymbol *ExceptionHandler; - const MCSymbol *Function; - const MCSymbol *PrologEnd; - const MCSymbol *Symbol; + const MCSymbol *Begin = nullptr; + const MCSymbol *End = nullptr; + const MCSymbol *ExceptionHandler = nullptr; + const MCSymbol *Function = nullptr; + const MCSymbol *PrologEnd = nullptr; + const MCSymbol *Symbol = nullptr; + const MCSection *TextSection = nullptr; - bool HandlesUnwind; - bool HandlesExceptions; + bool HandlesUnwind = false; + bool HandlesExceptions = false; - int LastFrameInst; - const FrameInfo *ChainedParent; + int LastFrameInst = -1; + const FrameInfo *ChainedParent = nullptr; std::vector Instructions; - FrameInfo() - : Begin(nullptr), End(nullptr), ExceptionHandler(nullptr), - Function(nullptr), PrologEnd(nullptr), Symbol(nullptr), - HandlesUnwind(false), HandlesExceptions(false), LastFrameInst(-1), - ChainedParent(nullptr), Instructions() {} + FrameInfo() = default; FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel) - : Begin(BeginFuncEHLabel), End(nullptr), ExceptionHandler(nullptr), - Function(Function), PrologEnd(nullptr), Symbol(nullptr), - HandlesUnwind(false), HandlesExceptions(false), LastFrameInst(-1), - ChainedParent(nullptr), Instructions() {} + : Begin(BeginFuncEHLabel), Function(Function) {} FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel, const FrameInfo *ChainedParent) - : Begin(BeginFuncEHLabel), End(nullptr), ExceptionHandler(nullptr), - Function(Function), PrologEnd(nullptr), Symbol(nullptr), - HandlesUnwind(false), HandlesExceptions(false), LastFrameInst(-1), - ChainedParent(ChainedParent), Instructions() {} + : Begin(BeginFuncEHLabel), Function(Function), + ChainedParent(ChainedParent) {} }; class UnwindEmitter { public: - static MCSection *getPDataSection(const MCSymbol *Function, - MCContext &Context); - static MCSection *getXDataSection(const MCSymbol *Function, - MCContext &Context); - - virtual ~UnwindEmitter() { } - - // - // This emits the unwind info sections (.pdata and .xdata in PE/COFF). - // + virtual ~UnwindEmitter(); + + /// This emits the unwind info sections (.pdata and .xdata in PE/COFF). virtual void Emit(MCStreamer &Streamer) const = 0; virtual void EmitUnwindInfo(MCStreamer &Streamer, FrameInfo *FI) const = 0; }; Index: llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp @@ -124,10 +124,9 @@ if (shouldEmitPersonality || shouldEmitLSDA) { Asm->OutStreamer->PushSection(); - // Just switch sections to the right xdata section. This use of CurrentFnSym - // assumes that we only emit the LSDA when ending the parent function. - MCSection *XData = WinEH::UnwindEmitter::getXDataSection(Asm->CurrentFnSym, - Asm->OutContext); + // Just switch sections to the right xdata section. + MCSection *XData = Asm->OutStreamer->getAssociatedXDataSection( + Asm->OutStreamer->getCurrentSectionOnly()); Asm->OutStreamer->SwitchSection(XData); // Emit the tables appropriate to the personality function in use. If we Index: llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp =================================================================== --- llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -316,7 +316,7 @@ Name.push_back('.'); TM.getNameWithPrefix(Name, GV, Mang, true); } - unsigned UniqueID = ~0; + unsigned UniqueID = MCContext::GenericSectionID; if (EmitUniqueSection && !UniqueSectionNames) { UniqueID = *NextUniqueID; (*NextUniqueID)++; @@ -924,10 +924,8 @@ Selection = 0; } } - return getContext().getCOFFSection(Name, - Characteristics, - Kind, - COMDATSymName, + + return getContext().getCOFFSection(Name, Characteristics, Kind, COMDATSymName, Selection); } @@ -968,16 +966,20 @@ else ComdatGV = GV; + unsigned UniqueID = MCContext::GenericSectionID; + if (EmitUniquedSection) + UniqueID = NextUniqueID++; + if (!ComdatGV->hasPrivateLinkage()) { MCSymbol *Sym = TM.getSymbol(ComdatGV, Mang); StringRef COMDATSymName = Sym->getName(); return getContext().getCOFFSection(Name, Characteristics, Kind, - COMDATSymName, Selection); + COMDATSymName, Selection, UniqueID); } else { SmallString<256> TmpData; Mang.getNameWithPrefix(TmpData, GV, /*CannotUsePrivateLabel=*/true); return getContext().getCOFFSection(Name, Characteristics, Kind, TmpData, - Selection); + Selection, UniqueID); } } @@ -1031,9 +1033,10 @@ const char *Name = getCOFFSectionNameForUniqueGlobal(Kind); unsigned Characteristics = getCOFFSectionFlags(Kind); Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT; + unsigned UniqueID = NextUniqueID++; return getContext().getCOFFSection(Name, Characteristics, Kind, COMDATSymName, - COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE); + COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE, UniqueID); } void TargetLoweringObjectFileCOFF:: @@ -1068,13 +1071,13 @@ MCSection *TargetLoweringObjectFileCOFF::getStaticCtorSection( unsigned Priority, const MCSymbol *KeySym) const { return getContext().getAssociativeCOFFSection( - cast(StaticCtorSection), KeySym); + cast(StaticCtorSection), KeySym, 0); } MCSection *TargetLoweringObjectFileCOFF::getStaticDtorSection( unsigned Priority, const MCSymbol *KeySym) const { return getContext().getAssociativeCOFFSection( - cast(StaticDtorSection), KeySym); + cast(StaticDtorSection), KeySym, 0); } void TargetLoweringObjectFileCOFF::emitLinkerFlagsForGlobal( Index: llvm/trunk/lib/MC/MCAsmStreamer.cpp =================================================================== --- llvm/trunk/lib/MC/MCAsmStreamer.cpp +++ llvm/trunk/lib/MC/MCAsmStreamer.cpp @@ -1288,8 +1288,8 @@ // We only do this so the section switch that terminates the handler // data block is visible. WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo(); - MCSection *XData = - WinEH::UnwindEmitter::getXDataSection(CurFrame->Function, getContext()); + MCSection *TextSec = &CurFrame->Function->getSection(); + MCSection *XData = getAssociatedXDataSection(TextSec); SwitchSectionNoChange(XData); OS << "\t.seh_handlerdata"; Index: llvm/trunk/lib/MC/MCContext.cpp =================================================================== --- llvm/trunk/lib/MC/MCContext.cpp +++ llvm/trunk/lib/MC/MCContext.cpp @@ -372,6 +372,7 @@ unsigned Characteristics, SectionKind Kind, StringRef COMDATSymName, int Selection, + unsigned UniqueID, const char *BeginSymName) { MCSymbol *COMDATSymbol = nullptr; if (!COMDATSymName.empty()) { @@ -379,8 +380,9 @@ COMDATSymName = COMDATSymbol->getName(); } + // Do the lookup, if we have a hit, return it. - COFFSectionKey T{Section, COMDATSymName, Selection}; + COFFSectionKey T{Section, COMDATSymName, Selection, UniqueID}; auto IterBool = COFFUniquingMap.insert(std::make_pair(T, nullptr)); auto Iter = IterBool.first; if (!IterBool.second) @@ -402,11 +404,12 @@ unsigned Characteristics, SectionKind Kind, const char *BeginSymName) { - return getCOFFSection(Section, Characteristics, Kind, "", 0, BeginSymName); + return getCOFFSection(Section, Characteristics, Kind, "", 0, GenericSectionID, + BeginSymName); } MCSectionCOFF *MCContext::getCOFFSection(StringRef Section) { - COFFSectionKey T{Section, "", 0}; + COFFSectionKey T{Section, "", 0, GenericSectionID}; auto Iter = COFFUniquingMap.find(T); if (Iter == COFFUniquingMap.end()) return nullptr; @@ -414,18 +417,24 @@ } MCSectionCOFF *MCContext::getAssociativeCOFFSection(MCSectionCOFF *Sec, - const MCSymbol *KeySym) { - // Return the normal section if we don't have to be associative. - if (!KeySym) + const MCSymbol *KeySym, + unsigned UniqueID) { + // Return the normal section if we don't have to be associative or unique. + if (!KeySym && UniqueID == GenericSectionID) return Sec; - // Make an associative section with the same name and kind as the normal - // section. - unsigned Characteristics = - Sec->getCharacteristics() | COFF::IMAGE_SCN_LNK_COMDAT; + // If we have a key symbol, make an associative section with the same name and + // kind as the normal section. + unsigned Characteristics = Sec->getCharacteristics(); + if (KeySym) { + Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT; + return getCOFFSection(Sec->getSectionName(), Characteristics, + Sec->getKind(), KeySym->getName(), + COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE, UniqueID); + } + return getCOFFSection(Sec->getSectionName(), Characteristics, Sec->getKind(), - KeySym->getName(), - COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE); + "", 0, UniqueID); } MCSubtargetInfo &MCContext::getSubtargetCopy(const MCSubtargetInfo &STI) { Index: llvm/trunk/lib/MC/MCStreamer.cpp =================================================================== --- llvm/trunk/lib/MC/MCStreamer.cpp +++ llvm/trunk/lib/MC/MCStreamer.cpp @@ -19,8 +19,10 @@ #include "llvm/MC/MCObjectFileInfo.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSection.h" +#include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCWin64EH.h" +#include "llvm/Support/COFF.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/raw_ostream.h" @@ -446,6 +448,7 @@ WinFrameInfos.push_back(new WinEH::FrameInfo(Symbol, StartProc)); CurrentWinFrameInfo = WinFrameInfos.back(); + CurrentWinFrameInfo->TextSection = getCurrentSectionOnly(); } void MCStreamer::EmitWinCFIEndProc() { @@ -467,6 +470,7 @@ WinFrameInfos.push_back(new WinEH::FrameInfo(CurrentWinFrameInfo->Function, StartProc, CurrentWinFrameInfo)); CurrentWinFrameInfo = WinFrameInfos.back(); + CurrentWinFrameInfo->TextSection = getCurrentSectionOnly(); } void MCStreamer::EmitWinCFIEndChained() { @@ -502,6 +506,38 @@ report_fatal_error("Chained unwind areas can't have handlers!"); } +static MCSection *getWinCFISection(MCContext &Context, unsigned *NextWinCFIID, + MCSection *MainCFISec, + const MCSection *TextSec) { + // If this is the main .text section, use the main unwind info section. + if (TextSec == Context.getObjectFileInfo()->getTextSection()) + return MainCFISec; + + const auto *TextSecCOFF = cast(TextSec); + unsigned UniqueID = TextSecCOFF->getOrAssignWinCFISectionID(NextWinCFIID); + + // If this section is COMDAT, this unwind section should be COMDAT associative + // with its group. + const MCSymbol *KeySym = nullptr; + if (TextSecCOFF->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) + KeySym = TextSecCOFF->getCOMDATSymbol(); + + return Context.getAssociativeCOFFSection(cast(MainCFISec), + KeySym, UniqueID); +} + +MCSection *MCStreamer::getAssociatedPDataSection(const MCSection *TextSec) { + return getWinCFISection(getContext(), &NextWinCFIID, + getContext().getObjectFileInfo()->getPDataSection(), + TextSec); +} + +MCSection *MCStreamer::getAssociatedXDataSection(const MCSection *TextSec) { + return getWinCFISection(getContext(), &NextWinCFIID, + getContext().getObjectFileInfo()->getXDataSection(), + TextSec); +} + void MCStreamer::EmitSyntaxDirective() {} void MCStreamer::EmitWinCFIPushReg(unsigned Register) { Index: llvm/trunk/lib/MC/MCWin64EH.cpp =================================================================== --- llvm/trunk/lib/MC/MCWin64EH.cpp +++ llvm/trunk/lib/MC/MCWin64EH.cpp @@ -17,7 +17,7 @@ #include "llvm/MC/MCSymbol.h" #include "llvm/Support/Win64EH.h" -namespace llvm { +using namespace llvm; // NOTE: All relocations generated here are 4-byte image-relative. @@ -218,35 +218,29 @@ } } -namespace Win64EH { -void UnwindEmitter::Emit(MCStreamer &Streamer) const { - MCContext &Context = Streamer.getContext(); - +void llvm::Win64EH::UnwindEmitter::Emit(MCStreamer &Streamer) const { // Emit the unwind info structs first. - for (const auto &CFI : Streamer.getWinFrameInfos()) { - MCSection *XData = getXDataSection(CFI->Function, Context); + for (WinEH::FrameInfo *CFI : Streamer.getWinFrameInfos()) { + MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection); Streamer.SwitchSection(XData); - EmitUnwindInfo(Streamer, CFI); + ::EmitUnwindInfo(Streamer, CFI); } // Now emit RUNTIME_FUNCTION entries. - for (const auto &CFI : Streamer.getWinFrameInfos()) { - MCSection *PData = getPDataSection(CFI->Function, Context); + for (WinEH::FrameInfo *CFI : Streamer.getWinFrameInfos()) { + MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection); Streamer.SwitchSection(PData); EmitRuntimeFunction(Streamer, CFI); } } -void UnwindEmitter::EmitUnwindInfo(MCStreamer &Streamer, - WinEH::FrameInfo *info) const { +void llvm::Win64EH::UnwindEmitter::EmitUnwindInfo( + MCStreamer &Streamer, WinEH::FrameInfo *info) const { // Switch sections (the static function above is meant to be called from // here and from Emit(). - MCContext &context = Streamer.getContext(); - MCSection *xdataSect = getXDataSection(info->Function, context); - Streamer.SwitchSection(xdataSect); + MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection); + Streamer.SwitchSection(XData); - llvm::EmitUnwindInfo(Streamer, info); -} + ::EmitUnwindInfo(Streamer, info); } -} // End of namespace llvm Index: llvm/trunk/lib/MC/MCWinEH.cpp =================================================================== --- llvm/trunk/lib/MC/MCWinEH.cpp +++ llvm/trunk/lib/MC/MCWinEH.cpp @@ -19,60 +19,7 @@ namespace llvm { namespace WinEH { -/// We can't have one section for all .pdata or .xdata because the Microsoft -/// linker seems to want all code relocations to refer to the same object file -/// section. If the code described is comdat, create a new comdat section -/// associated with that comdat. If the code described is not in the main .text -/// section, make a new section for it. Otherwise use the main unwind info -/// section. -static MCSection *getUnwindInfoSection(StringRef SecName, - MCSectionCOFF *UnwindSec, - const MCSymbol *Function, - MCContext &Context) { - if (Function && Function->isInSection()) { - // If Function is in a COMDAT, get or create an unwind info section in that - // COMDAT group. - const MCSectionCOFF *FunctionSection = - cast(&Function->getSection()); - if (FunctionSection->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) { - return Context.getAssociativeCOFFSection( - UnwindSec, FunctionSection->getCOMDATSymbol()); - } - - // If Function is in a section other than .text, create a new .pdata section. - // Otherwise use the plain .pdata section. - if (const auto *Section = dyn_cast(FunctionSection)) { - StringRef CodeSecName = Section->getSectionName(); - if (CodeSecName == ".text") - return UnwindSec; - - if (CodeSecName.startswith(".text$")) - CodeSecName = CodeSecName.substr(6); - - return Context.getCOFFSection((SecName + Twine('$') + CodeSecName).str(), - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getData()); - } - } - - return UnwindSec; - -} - -MCSection *UnwindEmitter::getPDataSection(const MCSymbol *Function, - MCContext &Context) { - MCSectionCOFF *PData = - cast(Context.getObjectFileInfo()->getPDataSection()); - return getUnwindInfoSection(".pdata", PData, Function, Context); -} - -MCSection *UnwindEmitter::getXDataSection(const MCSymbol *Function, - MCContext &Context) { - MCSectionCOFF *XData = - cast(Context.getObjectFileInfo()->getXDataSection()); - return getUnwindInfoSection(".xdata", XData, Function, Context); -} +UnwindEmitter::~UnwindEmitter() {} } } Index: llvm/trunk/test/MC/COFF/seh-section-2.s =================================================================== --- llvm/trunk/test/MC/COFF/seh-section-2.s +++ llvm/trunk/test/MC/COFF/seh-section-2.s @@ -0,0 +1,154 @@ +# RUN: llvm-mc -filetype=obj -triple x86_64-pc-win32 %s | llvm-readobj -symbols | FileCheck %s + +# This assembly should make an object with two .text sections, two .xdata +# sections, and two .pdata sections. + + .def f; + .scl 2; + .type 32; + .endef + .section .text,"xr",discard,f + .globl f + .p2align 4, 0x90 +f: # @f +.Ltmp0: +.seh_proc f +# BB#0: + subq $40, %rsp +.Ltmp1: + .seh_stackalloc 40 +.Ltmp2: + .seh_endprologue + callq g + nop + addq $40, %rsp + retq + .seh_handlerdata + .section .text,"xr",discard,f +.Ltmp3: + .seh_endproc + + .def g; + .scl 3; + .type 32; + .endef + .section .text,"xr",associative,f + .p2align 4, 0x90 +g: # @g +.Ltmp4: +.seh_proc g +# BB#0: +.Ltmp5: + .seh_endprologue + retq + .seh_handlerdata + .section .text,"xr",associative,f +.Ltmp6: + .seh_endproc + + +# CHECK: Symbols [ +# CHECK: Symbol { +# CHECK: Name: .text +# CHECK: Section: .text (4) +# CHECK: AuxSymbolCount: 1 +# CHECK: AuxSectionDef { +# CHECK: Length: 15 +# CHECK: RelocationCount: 1 +# CHECK: LineNumberCount: 0 +# CHECK: Checksum: 0xE17CBB7 +# CHECK: Number: 4 +# CHECK: Selection: Any (0x2) +# CHECK: } +# CHECK: } +# CHECK: Symbol { +# CHECK: Name: .xdata +# CHECK: Value: 0 +# CHECK: Section: .xdata (5) +# CHECK: BaseType: Null (0x0) +# CHECK: ComplexType: Null (0x0) +# CHECK: StorageClass: Static (0x3) +# CHECK: AuxSymbolCount: 1 +# CHECK: AuxSectionDef { +# CHECK: Length: 8 +# CHECK: RelocationCount: 0 +# CHECK: LineNumberCount: 0 +# CHECK: Checksum: 0xFC539D1 +# CHECK: Number: 4 +# CHECK: Selection: Associative (0x5) +# CHECK: AssocSection: .text (4) +# CHECK: } +# CHECK: } +# CHECK: Symbol { +# CHECK: Name: .text +# CHECK: Value: 0 +# CHECK: Section: .text (6) +# CHECK: BaseType: Null (0x0) +# CHECK: ComplexType: Null (0x0) +# CHECK: StorageClass: Static (0x3) +# CHECK: AuxSymbolCount: 1 +# CHECK: AuxSectionDef { +# CHECK: Length: 1 +# CHECK: RelocationCount: 0 +# CHECK: LineNumberCount: 0 +# CHECK: Checksum: 0x26D930A +# CHECK: Number: 4 +# CHECK: Selection: Associative (0x5) +# CHECK: AssocSection: .text (4) +# CHECK: } +# CHECK: } +# CHECK: Symbol { +# CHECK: Name: .xdata +# CHECK: Value: 0 +# CHECK: Section: .xdata (7) +# CHECK: BaseType: Null (0x0) +# CHECK: ComplexType: Null (0x0) +# CHECK: StorageClass: Static (0x3) +# CHECK: AuxSymbolCount: 1 +# CHECK: AuxSectionDef { +# CHECK: Length: 8 +# CHECK: RelocationCount: 0 +# CHECK: LineNumberCount: 0 +# CHECK: Checksum: 0xCCAA009E +# CHECK: Number: 4 +# CHECK: Selection: Associative (0x5) +# CHECK: AssocSection: .text (4) +# CHECK: } +# CHECK: } +# CHECK: Symbol { +# CHECK: Name: .pdata +# CHECK: Value: 0 +# CHECK: Section: .pdata (8) +# CHECK: BaseType: Null (0x0) +# CHECK: ComplexType: Null (0x0) +# CHECK: StorageClass: Static (0x3) +# CHECK: AuxSymbolCount: 1 +# CHECK: AuxSectionDef { +# CHECK: Length: 12 +# CHECK: RelocationCount: 3 +# CHECK: LineNumberCount: 0 +# CHECK: Checksum: 0xD92012AC +# CHECK: Number: 4 +# CHECK: Selection: Associative (0x5) +# CHECK: AssocSection: .text (4) +# CHECK: } +# CHECK: } +# CHECK: Symbol { +# CHECK: Name: .pdata +# CHECK: Value: 0 +# CHECK: Section: .pdata (9) +# CHECK: BaseType: Null (0x0) +# CHECK: ComplexType: Null (0x0) +# CHECK: StorageClass: Static (0x3) +# CHECK: AuxSymbolCount: 1 +# CHECK: AuxSectionDef { +# CHECK: Length: 12 +# CHECK: RelocationCount: 3 +# CHECK: LineNumberCount: 0 +# CHECK: Checksum: 0xCCAA009E +# CHECK: Number: 4 +# CHECK: Selection: Associative (0x5) +# CHECK: AssocSection: .text (4) +# CHECK: } +# CHECK: } +# CHECK: ] Index: llvm/trunk/test/MC/COFF/seh-section.s =================================================================== --- llvm/trunk/test/MC/COFF/seh-section.s +++ llvm/trunk/test/MC/COFF/seh-section.s @@ -1,10 +1,8 @@ // This test ensures functions in custom sections get unwind info emitted in a -// distinct .xdata section. Ideally we'd just emit a second .xdata section with -// the same name and characteristics, but MC uniques sections by name and -// characteristics, so that is not possible. +// distinct .xdata section. // RUN: llvm-mc -filetype=obj -triple x86_64-pc-win32 %s | llvm-readobj -s -sd | FileCheck %s -// CHECK: Name: .xdata$foo +// CHECK: Name: .xdata // CHECK-NEXT: VirtualSize // CHECK-NEXT: VirtualAddress // CHECK-NEXT: RawDataSize: 8 @@ -22,7 +20,7 @@ // CHECK-NEXT: 0000: 01050200 05500402 // CHECK-NEXT: ) -// CHECK: Name: .xdata$.mytext +// CHECK: Name: .xdata // CHECK-NEXT: VirtualSize // CHECK-NEXT: VirtualAddress // CHECK-NEXT: RawDataSize: 8