diff options
author | Reid Kleckner <reid@kleckner.net> | 2014-09-04 17:42:03 +0000 |
---|---|---|
committer | Reid Kleckner <reid@kleckner.net> | 2014-09-04 17:42:03 +0000 |
commit | 7c4059eb8929eb2819ff81137033e190b1b550dd (patch) | |
tree | ba73a0bc6df98b5579e89a72bc14bac4f88e47c5 /llvm/lib/MC | |
parent | 84897b8b7d01f5ccf7cb51e153f29c8bbb4f9191 (diff) | |
download | bcm5719-llvm-7c4059eb8929eb2819ff81137033e190b1b550dd.tar.gz bcm5719-llvm-7c4059eb8929eb2819ff81137033e190b1b550dd.zip |
MC Win64: Put unwind info for COMDAT code into the same COMDAT group
Summary:
This fixes a long standing issue where we would emit many little .text
sections and only one .pdata and .xdata section. Now we generate one
.pdata / .xdata pair per .text section and associate them correctly.
Fixes PR19667.
Reviewers: majnemer
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D5181
llvm-svn: 217176
Diffstat (limited to 'llvm/lib/MC')
-rw-r--r-- | llvm/lib/MC/MCAsmStreamer.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/MC/MCContext.cpp | 16 | ||||
-rw-r--r-- | llvm/lib/MC/MCWin64EH.cpp | 6 | ||||
-rw-r--r-- | llvm/lib/MC/MCWinEH.cpp | 62 |
4 files changed, 62 insertions, 27 deletions
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp index fcf39b836fc..f60c7fc5041 100644 --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -1095,9 +1095,8 @@ void MCAsmStreamer::EmitWinEHHandlerData() { // We only do this so the section switch that terminates the handler // data block is visible. WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo(); - StringRef Suffix = WinEH::UnwindEmitter::GetSectionSuffix(CurFrame->Function); - if (const MCSection *XData = - WinEH::UnwindEmitter::GetXDataSection(Suffix, getContext())) + if (const MCSection *XData = WinEH::UnwindEmitter::getXDataSection( + CurFrame->Function, getContext())) SwitchSectionNoChange(XData); OS << "\t.seh_handlerdata"; diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp index 7702da3540c..4266759b1f0 100644 --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -317,6 +317,22 @@ const MCSectionCOFF *MCContext::getCOFFSection(StringRef Section) { return Iter->second; } +const MCSectionCOFF * +MCContext::getAssociativeCOFFSection(const MCSectionCOFF *Sec, + const MCSymbol *KeySym) { + // Return the normal section if we don't have to be associative. + if (!KeySym) + 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; + return getCOFFSection(Sec->getSectionName(), Characteristics, Sec->getKind(), + KeySym->getName(), + COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE); +} + //===----------------------------------------------------------------------===// // Dwarf Management //===----------------------------------------------------------------------===// diff --git a/llvm/lib/MC/MCWin64EH.cpp b/llvm/lib/MC/MCWin64EH.cpp index 7394ba848bc..dfadb3cc42b 100644 --- a/llvm/lib/MC/MCWin64EH.cpp +++ b/llvm/lib/MC/MCWin64EH.cpp @@ -225,7 +225,7 @@ void UnwindEmitter::Emit(MCStreamer &Streamer) const { // Emit the unwind info structs first. for (const auto &CFI : Streamer.getWinFrameInfos()) { const MCSection *XData = - GetXDataSection(GetSectionSuffix(CFI->Function), Context); + getXDataSection(CFI->Function, Context); Streamer.SwitchSection(XData); EmitUnwindInfo(Streamer, CFI); } @@ -233,7 +233,7 @@ void UnwindEmitter::Emit(MCStreamer &Streamer) const { // Now emit RUNTIME_FUNCTION entries. for (const auto &CFI : Streamer.getWinFrameInfos()) { const MCSection *PData = - GetPDataSection(GetSectionSuffix(CFI->Function), Context); + getPDataSection(CFI->Function, Context); Streamer.SwitchSection(PData); EmitRuntimeFunction(Streamer, CFI); } @@ -245,7 +245,7 @@ void UnwindEmitter::EmitUnwindInfo(MCStreamer &Streamer, // here and from Emit(). MCContext &context = Streamer.getContext(); const MCSection *xdataSect = - GetXDataSection(GetSectionSuffix(info->Function), context); + getXDataSection(info->Function, context); Streamer.SwitchSection(xdataSect); llvm::EmitUnwindInfo(Streamer, info); diff --git a/llvm/lib/MC/MCWinEH.cpp b/llvm/lib/MC/MCWinEH.cpp index 8faf70737bf..f0c354feb61 100644 --- a/llvm/lib/MC/MCWinEH.cpp +++ b/llvm/lib/MC/MCWinEH.cpp @@ -17,27 +17,7 @@ namespace llvm { namespace WinEH { -const MCSection *UnwindEmitter::GetPDataSection(StringRef Suffix, - MCContext &Context) { - if (Suffix.empty()) - return Context.getObjectFileInfo()->getPDataSection(); - return Context.getCOFFSection((".pdata" + Suffix).str(), - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getDataRel()); -} - -const MCSection *UnwindEmitter::GetXDataSection(StringRef Suffix, - MCContext &Context) { - if (Suffix.empty()) - return Context.getObjectFileInfo()->getXDataSection(); - return Context.getCOFFSection((".xdata" + Suffix).str(), - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getDataRel()); -} - -StringRef UnwindEmitter::GetSectionSuffix(const MCSymbol *Function) { +static StringRef getSectionSuffix(const MCSymbol *Function) { if (!Function || !Function->isInSection()) return ""; @@ -59,6 +39,46 @@ StringRef UnwindEmitter::GetSectionSuffix(const MCSymbol *Function) { return ""; } + +static const MCSection *getUnwindInfoSection( + StringRef SecName, const MCSectionCOFF *UnwindSec, const MCSymbol *Function, + MCContext &Context) { + // If Function is in a COMDAT, get or create an unwind info section in that + // COMDAT group. + if (Function && Function->isInSection()) { + const MCSectionCOFF *FunctionSection = + cast<MCSectionCOFF>(&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. + StringRef Suffix = getSectionSuffix(Function); + if (Suffix.empty()) + return UnwindSec; + return Context.getCOFFSection((SecName + Suffix).str(), + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getDataRel()); +} + +const MCSection *UnwindEmitter::getPDataSection(const MCSymbol *Function, + MCContext &Context) { + const MCSectionCOFF *PData = + cast<MCSectionCOFF>(Context.getObjectFileInfo()->getPDataSection()); + return getUnwindInfoSection(".pdata", PData, Function, Context); +} + +const MCSection *UnwindEmitter::getXDataSection(const MCSymbol *Function, + MCContext &Context) { + const MCSectionCOFF *XData = + cast<MCSectionCOFF>(Context.getObjectFileInfo()->getXDataSection()); + return getUnwindInfoSection(".xdata", XData, Function, Context); +} + } } |