Skip to content

Commit ee5d1a0

Browse files
committed
[AsmPrinter] Split up .gcc_except_table
MC currently produces monolithic .gcc_except_table section. GCC can split up .gcc_except_table: * if comdat: `.section .gcc_except_table._Z6comdatv,"aG",@progbits,_Z6comdatv,comdat` * otherwise, if -ffunction-sections: `.section .gcc_except_table._Z3fooi,"a",@progbits` This ensures that (a) non-prevailing copies are discarded and (b) .gcc_except_table associated to discarded text sections can be discarded by a .gcc_except_table-aware linker (GNU ld, but not gold or LLD) This patches matches the GCC behavior. If -fno-unique-section-names is specified, we don't append the suffix. If -ffunction-sections is additionally specified, use `.section ...,unique`. Note, if clang driver communicates that the linker is LLD and we know it is new (11.0.0 or later) we can use SHF_LINK_ORDER to avoid string table costs, at least in the -fno-unique-section-names case. We cannot use it on GNU ld because as of binutils 2.35 it does not support mixed SHF_LINK_ORDER & non-SHF_LINK_ORDER components in an output section https://sourceware.org/bugzilla/show_bug.cgi?id=26256 For RISC-V -mrelax, this patch additionally fixes an assembler-linker interaction problem: because a section is shrinkable, the length of a call-site code range is not a constant. Relocations referencing the associated text section (STT_SECTION) are needed. However, a STB_LOCAL relocation referencing a discarded section group member from outside the group is disallowed by the ELF specification (PR46675): ``` // a.cc inline int comdat() { try { throw 1; } catch (int) { return 1; } return 0; } int main() { return comdat(); } // b.cc inline int comdat() { try { throw 1; } catch (int) { return 1; } return 0; } int foo() { return comdat(); } clang++ -target riscv64-linux -c a.cc b.cc -fPIC -mno-relax ld.lld -shared a.o b.o => ld.lld: error: relocation refers to a symbol in a discarded section: ``` -fbasic-block-sections= is similar to RISC-V -mrelax: there are outstanding relocations. Reviewed By: jrtc27, rahmanl Differential Revision: https://reviews.llvm.org/D83655
1 parent 1fcd5d5 commit ee5d1a0

File tree

6 files changed

+102
-2
lines changed

6 files changed

+102
-2
lines changed

llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h

+2
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
6363

6464
MCSection *getSectionForJumpTable(const Function &F,
6565
const TargetMachine &TM) const override;
66+
MCSection *getSectionForLSDA(const Function &F,
67+
const TargetMachine &TM) const override;
6668

6769
MCSection *
6870
getSectionForMachineBasicBlock(const Function &F,

llvm/include/llvm/MC/MCObjectFileInfo.h

-1
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,6 @@ class MCObjectFileInfo {
250250
MCSection *getDataSection() const { return DataSection; }
251251
MCSection *getBSSSection() const { return BSSSection; }
252252
MCSection *getReadOnlySection() const { return ReadOnlySection; }
253-
MCSection *getLSDASection() const { return LSDASection; }
254253
MCSection *getCompactUnwindSection() const { return CompactUnwindSection; }
255254
MCSection *getDwarfAbbrevSection() const { return DwarfAbbrevSection; }
256255
MCSection *getDwarfInfoSection() const { return DwarfInfoSection; }

llvm/include/llvm/Target/TargetLoweringObjectFile.h

+4
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ class TargetLoweringObjectFile : public MCObjectFileInfo {
118118

119119
virtual MCSection *getSectionForJumpTable(const Function &F,
120120
const TargetMachine &TM) const;
121+
virtual MCSection *getSectionForLSDA(const Function &F,
122+
const TargetMachine &TM) const {
123+
return LSDASection;
124+
}
121125

122126
virtual bool shouldPutJumpTableInFunctionSection(bool UsesLabelDifference,
123127
const Function &F) const;

llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,8 @@ MCSymbol *EHStreamer::emitExceptionTable() {
417417
bool HaveTTData = !TypeInfos.empty() || !FilterIds.empty();
418418

419419
// Type infos.
420-
MCSection *LSDASection = Asm->getObjFileLowering().getLSDASection();
420+
MCSection *LSDASection =
421+
Asm->getObjFileLowering().getSectionForLSDA(MF->getFunction(), Asm->TM);
421422
unsigned TTypeEncoding;
422423

423424
if (!HaveTTData) {

llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp

+36
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,42 @@ MCSection *TargetLoweringObjectFileELF::getSectionForJumpTable(
833833
/* AssociatedSymbol */ nullptr);
834834
}
835835

836+
MCSection *
837+
TargetLoweringObjectFileELF::getSectionForLSDA(const Function &F,
838+
const TargetMachine &TM) const {
839+
// If neither COMDAT nor function sections, use the monolithic LSDA section.
840+
if (!F.hasComdat() && !TM.getFunctionSections())
841+
return LSDASection;
842+
843+
const auto *LSDA = cast<MCSectionELF>(LSDASection);
844+
unsigned Flags = LSDA->getFlags();
845+
StringRef Group;
846+
if (F.hasComdat()) {
847+
Group = F.getComdat()->getName();
848+
Flags |= ELF::SHF_GROUP;
849+
}
850+
851+
// Append the function name as the suffix like GCC, assuming
852+
// -funique-section-names applies to .gcc_except_table sections.
853+
if (TM.getUniqueSectionNames())
854+
return getContext().getELFSection(LSDA->getName() + "." + F.getName(),
855+
LSDA->getType(), Flags, 0, Group,
856+
MCSection::NonUniqueID, nullptr);
857+
858+
// Allocate a unique ID if function sections && (integrated assembler or GNU
859+
// as>=2.35). Note we could use SHF_LINK_ORDER to facilitate --gc-sections but
860+
// that would require that we know the linker is a modern LLD (12.0 or later).
861+
// GNU ld as of 2.35 does not support mixed SHF_LINK_ORDER &
862+
// non-SHF_LINK_ORDER components in an output section
863+
// https://sourceware.org/bugzilla/show_bug.cgi?id=26256
864+
unsigned ID = TM.getFunctionSections() &&
865+
getContext().getAsmInfo()->useIntegratedAssembler()
866+
? NextUniqueID++
867+
: MCSection::NonUniqueID;
868+
return getContext().getELFSection(LSDA->getName(), LSDA->getType(), Flags, 0,
869+
Group, ID, nullptr);
870+
}
871+
836872
bool TargetLoweringObjectFileELF::shouldPutJumpTableInFunctionSection(
837873
bool UsesLabelDifference, const Function &F) const {
838874
// We can always create relative relocations, so use another section
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
; RUN: llc < %s -mtriple=x86_64 | FileCheck %s --check-prefixes=CHECK,NORMAL
2+
; RUN: llc < %s -mtriple=x86_64 -unique-section-names=false | FileCheck %s --check-prefixes=CHECK,NOUNIQUE
3+
; RUN: llc < %s -mtriple=x86_64 -function-sections | FileCheck %s --check-prefixes=CHECK,SEP
4+
; RUN: llc < %s -mtriple=x86_64 -function-sections -unique-section-names=false | FileCheck %s --check-prefixes=CHECK,SEP_NOUNIQUE
5+
6+
;; Don't use `,unique` if GNU as<2.35.
7+
; RUN: llc < %s -mtriple=x86_64 -function-sections -unique-section-names=false -no-integrated-as | FileCheck %s --check-prefixes=CHECK,SEP_NOUNIQUE_GAS
8+
9+
@_ZTIi = external constant i8*
10+
11+
;; If the function is in a comdat group, the generated .gcc_except_table should
12+
;; be placed in the same group, so that .gcc_except_table can be discarded if
13+
;; the comdat is not prevailing. If -funique-section-names, append the function name.
14+
$group = comdat any
15+
define i32 @group() uwtable comdat personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
16+
; CHECK-LABEL: group:
17+
; CHECK: .cfi_endproc
18+
; NORMAL-NEXT: .section .gcc_except_table.group,"aG",@progbits,group,comdat{{$}}
19+
; NOUNIQUE-NEXT: .section .gcc_except_table,"aG",@progbits,group,comdat{{$}}
20+
; SEP-NEXT: .section .gcc_except_table.group,"aG",@progbits,group,comdat{{$}}
21+
; SEP_NOUNIQUE-NEXT: .section .gcc_except_table,"aG",@progbits,group,comdat,unique,2
22+
; SEP_NOUNIQUE_GAS-NEXT: .section .gcc_except_table,"aG",@progbits,group,comdat{{$}}
23+
entry:
24+
invoke void @ext() to label %try.cont unwind label %lpad
25+
lpad:
26+
%0 = landingpad { i8*, i32 } catch i8* bitcast (i8** @_ZTIi to i8*)
27+
br label %eh.resume
28+
try.cont:
29+
ret i32 0
30+
eh.resume:
31+
resume { i8*, i32 } %0
32+
}
33+
34+
;; If the function is not in a comdat group, but function sections is enabled,
35+
;; use a separate section by either using a unique ID (integrated assembler) or
36+
;; a suffix (GNU as<2.35).
37+
define i32 @foo() uwtable personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
38+
; CHECK-LABEL: foo:
39+
; CHECK: .cfi_endproc
40+
; NORMAL-NEXT: .section .gcc_except_table,"a",@progbits{{$}}
41+
; NOUNIQUE-NEXT: .section .gcc_except_table,"a",@progbits{{$}}
42+
; SEP-NEXT: .section .gcc_except_table.foo,"a",@progbits{{$}}
43+
; SEP_NOUNIQUE-NEXT: .section .gcc_except_table,"a",@progbits,unique,4
44+
; SEP_NOUNIQUE_GAS-NEXT: .section .gcc_except_table,"a",@progbits{{$}}
45+
entry:
46+
invoke void @ext() to label %try.cont unwind label %lpad
47+
lpad:
48+
%0 = landingpad { i8*, i32 } catch i8* bitcast (i8** @_ZTIi to i8*)
49+
br label %eh.resume
50+
try.cont:
51+
ret i32 0
52+
eh.resume:
53+
resume { i8*, i32 } %0
54+
}
55+
56+
declare void @ext()
57+
58+
declare i32 @__gxx_personality_v0(...)

0 commit comments

Comments
 (0)