mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-14 15:39:06 +00:00
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:
parent
54dfc533fc
commit
b9cb76d3f3
@ -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
|
||||
|
@ -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() { }
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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";
|
||||
|
@ -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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
85
test/MC/COFF/seh-linkonce.s
Normal file
85
test/MC/COFF/seh-linkonce.s
Normal 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: ]
|
Loading…
Reference in New Issue
Block a user