From 8eeedf74d346d6797236544847ebaa45e14d7703 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Thu, 12 Feb 2015 17:16:46 +0000 Subject: [PATCH] Put each jump table in an independent section if the function is too. This allows the linker to GC both, fixing pr22557. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@228937 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../CodeGen/TargetLoweringObjectFileImpl.h | 4 +++ .../llvm/Target/TargetLoweringObjectFile.h | 4 +++ lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 7 ++-- lib/CodeGen/TargetLoweringObjectFileImpl.cpp | 22 +++++++++++++ lib/Target/TargetLoweringObjectFile.cpp | 5 +++ test/CodeGen/X86/global-sections-comdat.ll | 33 ++++++++++++++++++- test/CodeGen/X86/global-sections.ll | 31 ++++++++++++++++- 7 files changed, 100 insertions(+), 6 deletions(-) diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index abf6a2a2467..0dc04100616 100644 --- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -56,6 +56,10 @@ public: SectionKind Kind, Mangler &Mang, const TargetMachine &TM) const override; + const MCSection * + getSectionForJumpTable(const Function &F, Mangler &Mang, + const TargetMachine &TM) const override; + /// Return an MCExpr to use for a reference to the specified type info global /// variable from exception handling information. const MCExpr * diff --git a/include/llvm/Target/TargetLoweringObjectFile.h b/include/llvm/Target/TargetLoweringObjectFile.h index 73bf56f018e..ec29283bbe4 100644 --- a/include/llvm/Target/TargetLoweringObjectFile.h +++ b/include/llvm/Target/TargetLoweringObjectFile.h @@ -94,6 +94,10 @@ public: return SectionForGlobal(GV, getKindForGlobal(GV, TM), Mang, TM); } + virtual const MCSection * + getSectionForJumpTable(const Function &F, Mangler &Mang, + const TargetMachine &TM) const; + /// Targets should implement this method to assign a section to globals with /// an explicit section specfied. The implementation of this method can /// assume that GV->hasSection() is true. diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 7fb84605071..aacc486aa14 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1177,6 +1177,7 @@ void AsmPrinter::EmitJumpTableInfo() { // Pick the directive to use to print the jump table entries, and switch to // the appropriate section. const Function *F = MF->getFunction(); + const TargetLoweringObjectFile &TLOF = getObjFileLowering(); bool JTInDiffSection = false; if (// In PIC mode, we need to emit the jump table to the same section as the // function body itself, otherwise the label differences won't make sense. @@ -1187,13 +1188,11 @@ void AsmPrinter::EmitJumpTableInfo() { // FIXME: this isn't the right predicate, should be based on the MCSection // for the function. F->isWeakForLinker()) { - OutStreamer.SwitchSection( - getObjFileLowering().SectionForGlobal(F, *Mang, TM)); + OutStreamer.SwitchSection(TLOF.SectionForGlobal(F, *Mang, TM)); } else { // Otherwise, drop it in the readonly section. const MCSection *ReadOnlySection = - getObjFileLowering().getSectionForConstant(SectionKind::getReadOnly(), - /*C=*/nullptr); + TLOF.getSectionForJumpTable(*F, *Mang, TM); OutStreamer.SwitchSection(ReadOnlySection); JTInDiffSection = true; } diff --git a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index eac1245d829..0a49f5ff9fe 100644 --- a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -334,6 +334,28 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, return DataRelROSection; } +const MCSection *TargetLoweringObjectFileELF::getSectionForJumpTable( + const Function &F, Mangler &Mang, const TargetMachine &TM) const { + // If the function can be removed, produce a unique section so that + // the table doesn't prevent the removal. + const Comdat *C = F.getComdat(); + bool EmitUniqueSection = TM.getFunctionSections() || C; + if (!EmitUniqueSection) + return ReadOnlySection; + + SmallString<128> Name(".rodata."); + TM.getNameWithPrefix(Name, &F, Mang, true); + + unsigned Flags = ELF::SHF_ALLOC; + StringRef Group = ""; + if (C) { + Flags |= ELF::SHF_GROUP; + Group = C->getName(); + } + + return getContext().getELFSection(Name, ELF::SHT_PROGBITS, Flags, 0, Group); +} + /// getSectionForConstant - Given a mergeable constant with the /// specified size and relocation information, return a section that it /// should be placed in. diff --git a/lib/Target/TargetLoweringObjectFile.cpp b/lib/Target/TargetLoweringObjectFile.cpp index 25b898c1aee..c098035a5aa 100644 --- a/lib/Target/TargetLoweringObjectFile.cpp +++ b/lib/Target/TargetLoweringObjectFile.cpp @@ -270,6 +270,11 @@ SectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler &Mang, return SelectSectionForGlobal(GV, Kind, Mang, TM); } +const MCSection *TargetLoweringObjectFile::getSectionForJumpTable( + const Function &F, Mangler &Mang, const TargetMachine &TM) const { + return getSectionForConstant(SectionKind::getReadOnly(), /*C=*/nullptr); +} + /// getSectionForConstant - Given a mergable constant with the /// specified size and relocation information, return a section that it /// should be placed in. diff --git a/test/CodeGen/X86/global-sections-comdat.ll b/test/CodeGen/X86/global-sections-comdat.ll index a4804a7c5cf..0557d9a0ee1 100644 --- a/test/CodeGen/X86/global-sections-comdat.ll +++ b/test/CodeGen/X86/global-sections-comdat.ll @@ -1,5 +1,36 @@ ; RUN: llc < %s -mtriple=i386-unknown-linux | FileCheck %s -check-prefix=LINUX -; RUN: llc < %s -mtriple=i386-unknown-linux -data-sections | FileCheck %s -check-prefix=LINUX-SECTIONS +; RUN: llc < %s -mtriple=i386-unknown-linux -data-sections -function-sections | FileCheck %s -check-prefix=LINUX-SECTIONS + +$F1 = comdat any +define void @F1(i32 %y) comdat { +bb0: +switch i32 %y, label %bb5 [ + i32 1, label %bb1 + i32 2, label %bb2 + i32 3, label %bb3 + i32 4, label %bb4 + ] +bb1: + ret void +bb2: + ret void +bb3: + ret void +bb4: + ret void +bb5: + ret void +} + +; LINUX: .section .text.F1,"axG",@progbits,F1,comdat +; LINUX: .size F1, +; LINUX-NEXT: .cfi_endproc +; LINUX-NEXT: .section .rodata.F1,"aG",@progbits,F1,comdat + +; LINUX-SECTIONS: .section .text.F1,"axG",@progbits,F1,comdat +; LINUX-SECTIONS: .size F1, +; LINUX-SECTIONS-NEXT: .cfi_endproc +; LINUX-SECTIONS-NEXT: .section .rodata.F1,"aG",@progbits,F1,comdat $G16 = comdat any @G16 = unnamed_addr constant i32 42, comdat diff --git a/test/CodeGen/X86/global-sections.ll b/test/CodeGen/X86/global-sections.ll index 0502582cb1f..4dc0f7d04c6 100644 --- a/test/CodeGen/X86/global-sections.ll +++ b/test/CodeGen/X86/global-sections.ll @@ -2,7 +2,7 @@ ; RUN: llc < %s -mtriple=i386-apple-darwin9.7 | FileCheck %s -check-prefix=DARWIN ; RUN: llc < %s -mtriple=i386-apple-darwin10 -relocation-model=static | FileCheck %s -check-prefix=DARWIN-STATIC ; RUN: llc < %s -mtriple=x86_64-apple-darwin10 | FileCheck %s -check-prefix=DARWIN64 -; RUN: llc < %s -mtriple=i386-unknown-linux-gnu -data-sections | FileCheck %s -check-prefix=LINUX-SECTIONS +; RUN: llc < %s -mtriple=i386-unknown-linux-gnu -data-sections -function-sections | FileCheck %s -check-prefix=LINUX-SECTIONS ; RUN: llc < %s -mtriple=i686-pc-win32 -data-sections -function-sections | FileCheck %s -check-prefix=WIN32-SECTIONS define void @F1() { @@ -12,6 +12,35 @@ define void @F1() { ; WIN32-SECTIONS: .section .text,"xr",one_only,_F1 ; WIN32-SECTIONS: .globl _F1 +define void @F2(i32 %y) { +bb0: +switch i32 %y, label %bb5 [ + i32 1, label %bb1 + i32 2, label %bb2 + i32 3, label %bb3 + i32 4, label %bb4 + ] +bb1: + ret void +bb2: + ret void +bb3: + ret void +bb4: + ret void +bb5: + ret void +} + +; LINUX: .size F2, +; LINUX-NEX: .cfi_endproc +; LINUX-NEX: .section .rodata,"a",@progbits + +; LINUX-SECTIONS: .section .text.F2,"ax",@progbits +; LINUX-SECTIONS: .size F2, +; LINUX-SECTIONS-NEXT: .cfi_endproc +; LINUX-SECTIONS-NEXT: .section .rodata.F2,"a",@progbits + ; int G1; @G1 = common global i32 0 -- 2.34.1