diff --git a/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp b/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp --- a/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp @@ -15,20 +15,24 @@ #include "llvm/ADT/Twine.h" #include "llvm/ADT/iterator_range.h" #include "llvm/BinaryFormat/Dwarf.h" +#include "llvm/BinaryFormat/ELF.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineOperand.h" +#include "llvm/IR/Comdat.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCTargetOptions.h" #include "llvm/Support/Casting.h" #include "llvm/Support/LEB128.h" #include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" #include #include #include @@ -458,8 +462,30 @@ // Begin the exception table. // Sometimes we want not to emit the data into separate section (e.g. ARM // EHABI). In this case LSDASection will be NULL. - if (LSDASection) + if (LSDASection) { + const Function &F = MF->getFunction(); + if (Asm->TM.getTargetTriple().isOSBinFormatELF()) { + const MCSymbolELF *LinkedToSym = nullptr; + unsigned Flags = cast(LSDASection)->getFlags(); + StringRef Group; + if (F.hasComdat()) { + Group = F.getComdat()->getName(); + Flags |= ELF::SHF_GROUP; + } + if (F.hasComdat() || Asm->TM.getFunctionSections()) { + // Append the function name as the suffix like GCC. Note in the + // -fno-unique-section-names case we could use SHF_LINK_ORDER but that + // would require that we know the linker is a modern LLD (11.0 or + // later). + LSDASection = Asm->OutContext.getELFSection( + LSDASection->getName() + "." + F.getName(), ELF::SHT_PROGBITS, + Flags, 0, Group, MCSection::NonUniqueID, LinkedToSym); + } + // If neither COMDAT nor function sections, use the monolithic LSDA + // section. + } Asm->OutStreamer->SwitchSection(LSDASection); + } Asm->emitAlignment(Align(4)); // Emit the LSDA. diff --git a/llvm/test/CodeGen/X86/gcc_except_table-multi.ll b/llvm/test/CodeGen/X86/gcc_except_table-multi.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/gcc_except_table-multi.ll @@ -0,0 +1,47 @@ +; RUN: llc < %s -mtriple=x86_64 | FileCheck %s --check-prefixes=CHECK,NOSEPARATE +; RUN: llc < %s -mtriple=x86_64 -function-sections | FileCheck %s --check-prefixes=CHECK,SEPARATE +@_ZTIi = external constant i8* + +;; If the function is in a comdat group, the generated .gcc_except_table should +;; be placed in the same group, so that .gcc_except_table can be discarded if +;; the comdat is not prevailing. +$group = comdat any +define i32 @group() uwtable comdat personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { +; CHECK-LABEL: group: +; CHECK: .cfi_endproc +; CHECK-NEXT: .section .gcc_except_table.group,"aG",@progbits,group,comdat +entry: + invoke void @ext() to label %try.cont unwind label %lpad +lpad: + %0 = landingpad { i8*, i32 } catch i8* bitcast (i8** @_ZTIi to i8*) + br label %eh.resume +try.cont: + ret i32 0 +eh.resume: + resume { i8*, i32 } %0 +} + +;; If the function is not in a comdat group, use the monolithic .gcc_except_table +;; if function sections are not enabled. Otherwise, append the function name to +;; get a unique section name like GCC. This allows --gc-sections and STB_LOCAL +;; relocations referencing text sections if call-site code ranges are not +;; compile-time constant (RISC-V -mrelax or -fbasic-block-sections=). +define i32 @foo() uwtable personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { +; CHECK-LABEL: foo: +; CHECK: .cfi_endproc +; NOSEPARATE-NEXT: .section .gcc_except_table,"a",@progbits +; SEPARATE-NEXT: .section .gcc_except_table.foo,"a",@progbits +entry: + invoke void @ext() to label %try.cont unwind label %lpad +lpad: + %0 = landingpad { i8*, i32 } catch i8* bitcast (i8** @_ZTIi to i8*) + br label %eh.resume +try.cont: + ret i32 0 +eh.resume: + resume { i8*, i32 } %0 +} + +declare void @ext() + +declare i32 @__gxx_personality_v0(...)