mirror of
https://github.com/RPCS3/llvm.git
synced 2025-03-05 00:59:19 +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);
|
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
|
/// @name Dwarf Management
|
||||||
|
@ -65,9 +65,10 @@ struct FrameInfo {
|
|||||||
|
|
||||||
class UnwindEmitter {
|
class UnwindEmitter {
|
||||||
public:
|
public:
|
||||||
static StringRef GetSectionSuffix(const MCSymbol *Function);
|
static const MCSection *getPDataSection(const MCSymbol *Function,
|
||||||
static const MCSection *GetPDataSection(StringRef Suffix, MCContext &Context);
|
MCContext &Context);
|
||||||
static const MCSection *GetXDataSection(StringRef Suffix, MCContext &Context);
|
static const MCSection *getXDataSection(const MCSymbol *Function,
|
||||||
|
MCContext &Context);
|
||||||
|
|
||||||
virtual ~UnwindEmitter() { }
|
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(
|
const MCSection *TargetLoweringObjectFileCOFF::getStaticCtorSection(
|
||||||
unsigned Priority, const MCSymbol *KeySym) const {
|
unsigned Priority, const MCSymbol *KeySym) const {
|
||||||
return getAssociativeCOFFSection(getContext(), StaticCtorSection, KeySym);
|
return getContext().getAssociativeCOFFSection(
|
||||||
|
cast<MCSectionCOFF>(StaticCtorSection), KeySym);
|
||||||
}
|
}
|
||||||
|
|
||||||
const MCSection *TargetLoweringObjectFileCOFF::getStaticDtorSection(
|
const MCSection *TargetLoweringObjectFileCOFF::getStaticDtorSection(
|
||||||
unsigned Priority, const MCSymbol *KeySym) const {
|
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
|
// We only do this so the section switch that terminates the handler
|
||||||
// data block is visible.
|
// data block is visible.
|
||||||
WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo();
|
WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo();
|
||||||
StringRef Suffix = WinEH::UnwindEmitter::GetSectionSuffix(CurFrame->Function);
|
if (const MCSection *XData = WinEH::UnwindEmitter::getXDataSection(
|
||||||
if (const MCSection *XData =
|
CurFrame->Function, getContext()))
|
||||||
WinEH::UnwindEmitter::GetXDataSection(Suffix, getContext()))
|
|
||||||
SwitchSectionNoChange(XData);
|
SwitchSectionNoChange(XData);
|
||||||
|
|
||||||
OS << "\t.seh_handlerdata";
|
OS << "\t.seh_handlerdata";
|
||||||
|
@ -317,6 +317,22 @@ const MCSectionCOFF *MCContext::getCOFFSection(StringRef Section) {
|
|||||||
return Iter->second;
|
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
|
// Dwarf Management
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -225,7 +225,7 @@ void UnwindEmitter::Emit(MCStreamer &Streamer) const {
|
|||||||
// Emit the unwind info structs first.
|
// Emit the unwind info structs first.
|
||||||
for (const auto &CFI : Streamer.getWinFrameInfos()) {
|
for (const auto &CFI : Streamer.getWinFrameInfos()) {
|
||||||
const MCSection *XData =
|
const MCSection *XData =
|
||||||
GetXDataSection(GetSectionSuffix(CFI->Function), Context);
|
getXDataSection(CFI->Function, Context);
|
||||||
Streamer.SwitchSection(XData);
|
Streamer.SwitchSection(XData);
|
||||||
EmitUnwindInfo(Streamer, CFI);
|
EmitUnwindInfo(Streamer, CFI);
|
||||||
}
|
}
|
||||||
@ -233,7 +233,7 @@ void UnwindEmitter::Emit(MCStreamer &Streamer) const {
|
|||||||
// Now emit RUNTIME_FUNCTION entries.
|
// Now emit RUNTIME_FUNCTION entries.
|
||||||
for (const auto &CFI : Streamer.getWinFrameInfos()) {
|
for (const auto &CFI : Streamer.getWinFrameInfos()) {
|
||||||
const MCSection *PData =
|
const MCSection *PData =
|
||||||
GetPDataSection(GetSectionSuffix(CFI->Function), Context);
|
getPDataSection(CFI->Function, Context);
|
||||||
Streamer.SwitchSection(PData);
|
Streamer.SwitchSection(PData);
|
||||||
EmitRuntimeFunction(Streamer, CFI);
|
EmitRuntimeFunction(Streamer, CFI);
|
||||||
}
|
}
|
||||||
@ -245,7 +245,7 @@ void UnwindEmitter::EmitUnwindInfo(MCStreamer &Streamer,
|
|||||||
// here and from Emit().
|
// here and from Emit().
|
||||||
MCContext &context = Streamer.getContext();
|
MCContext &context = Streamer.getContext();
|
||||||
const MCSection *xdataSect =
|
const MCSection *xdataSect =
|
||||||
GetXDataSection(GetSectionSuffix(info->Function), context);
|
getXDataSection(info->Function, context);
|
||||||
Streamer.SwitchSection(xdataSect);
|
Streamer.SwitchSection(xdataSect);
|
||||||
|
|
||||||
llvm::EmitUnwindInfo(Streamer, info);
|
llvm::EmitUnwindInfo(Streamer, info);
|
||||||
|
@ -17,27 +17,7 @@
|
|||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
namespace WinEH {
|
namespace WinEH {
|
||||||
const MCSection *UnwindEmitter::GetPDataSection(StringRef Suffix,
|
static StringRef getSectionSuffix(const MCSymbol *Function) {
|
||||||
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) {
|
|
||||||
if (!Function || !Function->isInSection())
|
if (!Function || !Function->isInSection())
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
@ -59,6 +39,46 @@ StringRef UnwindEmitter::GetSectionSuffix(const MCSymbol *Function) {
|
|||||||
|
|
||||||
return "";
|
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…
x
Reference in New Issue
Block a user