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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@217176 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Reid Kleckner 2014-09-04 17:42:03 +00:00
parent 54dfc533fc
commit b9cb76d3f3
8 changed files with 162 additions and 49 deletions

View File

@ -284,6 +284,13 @@ namespace llvm {
const MCSectionCOFF *getCOFFSection(StringRef Section);
/// Gets or creates a section equivalent to Sec that is associated with the
/// 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.
const MCSectionCOFF *getAssociativeCOFFSection(const MCSectionCOFF *Sec,
const MCSymbol *KeySym);
/// @}
/// @name Dwarf Management

View File

@ -65,9 +65,10 @@ struct FrameInfo {
class UnwindEmitter {
public:
static StringRef GetSectionSuffix(const MCSymbol *Function);
static const MCSection *GetPDataSection(StringRef Suffix, MCContext &Context);
static const MCSection *GetXDataSection(StringRef Suffix, MCContext &Context);
static const MCSection *getPDataSection(const MCSymbol *Function,
MCContext &Context);
static const MCSection *getXDataSection(const MCSymbol *Function,
MCContext &Context);
virtual ~UnwindEmitter() { }

View File

@ -967,29 +967,14 @@ emitModuleFlags(MCStreamer &Streamer,
}
}
static const MCSection *getAssociativeCOFFSection(MCContext &Ctx,
const MCSection *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.
const MCSectionCOFF *SecCOFF = cast<MCSectionCOFF>(Sec);
unsigned Characteristics =
SecCOFF->getCharacteristics() | COFF::IMAGE_SCN_LNK_COMDAT;
return Ctx.getCOFFSection(SecCOFF->getSectionName(), Characteristics,
SecCOFF->getKind(), KeySym->getName(),
COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE);
}
const MCSection *TargetLoweringObjectFileCOFF::getStaticCtorSection(
unsigned Priority, const MCSymbol *KeySym) const {
return getAssociativeCOFFSection(getContext(), StaticCtorSection, KeySym);
return getContext().getAssociativeCOFFSection(
cast<MCSectionCOFF>(StaticCtorSection), KeySym);
}
const MCSection *TargetLoweringObjectFileCOFF::getStaticDtorSection(
unsigned Priority, const MCSymbol *KeySym) const {
return getAssociativeCOFFSection(getContext(), StaticDtorSection, KeySym);
return getContext().getAssociativeCOFFSection(
cast<MCSectionCOFF>(StaticDtorSection), KeySym);
}

View File

@ -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";

View File

@ -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
//===----------------------------------------------------------------------===//

View File

@ -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);

View File

@ -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);
}
}
}

View File

@ -0,0 +1,85 @@
// RUN: llvm-mc -triple x86_64-pc-win32 -filetype=obj %s | llvm-readobj -sections -section-symbols | FileCheck %s
.text
.def weak_func;
.scl 2;
.type 32;
.endef
.section .text,"xr",discard,weak_func
.globl weak_func
.align 16, 0x90
weak_func: # @weak_func
.Ltmp0:
.seh_proc weak_func
# BB#0: # %entry
pushq %rbp
.Ltmp1:
.seh_pushreg 5
movq %rsp, %rbp
.Ltmp2:
.seh_setframe 5, 0
.Ltmp3:
.seh_endprologue
xorl %eax, %eax
popq %rbp
retq
.Leh_func_end0:
.Ltmp4:
.seh_endproc
// CHECK: Sections [
// CHECK: Section {
// CHECK: Name: .text
// CHECK: }
// CHECK: Section {
// CHECK: Name: .data
// CHECK: }
// CHECK: Section {
// CHECK: Name: .bss
// CHECK: }
// CHECK: Section {
// CHECK: Number: [[TEXT_SECNUM:[0-9]+]]
// CHECK: Name: .text
// CHECK: Characteristics [
// CHECK: IMAGE_SCN_LNK_COMDAT
// CHECK: ]
// CHECK: }
// CHECK: Section {
// CHECK: Number: [[XDATA_SECNUM:[0-9]+]]
// CHECK: Name: .xdata
// CHECK: Characteristics [
// CHECK: IMAGE_SCN_LNK_COMDAT
// CHECK: ]
// CHECK: Symbols [
// CHECK: Symbol {
// CHECK: Name: .xdata
// CHECK: Section: .xdata ([[XDATA_SECNUM]])
// CHECK: StorageClass: Static (0x3)
// CHECK: AuxSymbolCount: 1
// CHECK: AuxSectionDef {
// CHECK: Selection: Associative (0x5)
// CHECK: AssocSection: .text ([[TEXT_SECNUM]])
// CHECK: }
// CHECK: }
// CHECK: ]
// CHECK: }
// CHECK: Section {
// CHECK: Number: [[PDATA_SECNUM:[0-9]+]]
// CHECK: Name: .pdata
// CHECK: Characteristics [
// CHECK: IMAGE_SCN_LNK_COMDAT
// CHECK: ]
// CHECK: Symbols [
// CHECK: Symbol {
// CHECK: Name: .pdata
// CHECK: Section: .pdata ([[PDATA_SECNUM]])
// CHECK: StorageClass: Static (0x3)
// CHECK: AuxSymbolCount: 1
// CHECK: AuxSectionDef {
// CHECK: Selection: Associative (0x5)
// CHECK: AssocSection: .text ([[TEXT_SECNUM]])
// CHECK: }
// CHECK: }
// CHECK: ]
// CHECK: }
// CHECK: ]