Index: llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h =================================================================== --- llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -13,11 +13,13 @@ #ifndef LLVM_CODEGEN_TARGETLOWERINGOBJECTFILEIMPL_H #define LLVM_CODEGEN_TARGETLOWERINGOBJECTFILEIMPL_H - + +#include "llvm/BinaryFormat/ELF.h" #include "llvm/BinaryFormat/XCOFF.h" #include "llvm/IR/Module.h" #include "llvm/MC/MCExpr.h" #include "llvm/Target/TargetLoweringObjectFile.h" +#include namespace llvm { @@ -33,6 +35,30 @@ bool UseInitArray = false; mutable unsigned NextUniqueID = 1; // ID 0 is reserved for execute-only sections + // Mergeable globals must be assigned to a section with a compatible entry + // size. This map is used to assign unique IDs to mergeable sections to + // distinguish between sections with identical names but incompatible entry + // sizes. This is required if mergeable globals are explicitly assigned to a + // section, e.g. via _attribute_((section("myname"))). + struct ELFEntrySizeKey { + std::string SectionName; + unsigned Flags; + unsigned EntrySize; + + ELFEntrySizeKey(StringRef SectionName, unsigned Flags, unsigned EntrySize) + : SectionName(SectionName), Flags(Flags), EntrySize(EntrySize) {} + + bool operator<(const ELFEntrySizeKey &Other) const { + if (SectionName != Other.SectionName) + return SectionName < Other.SectionName; + if ((Flags & ELF::SHF_STRINGS) != (Other.Flags & ELF::SHF_STRINGS)) + return (Other.Flags & ELF::SHF_STRINGS); + return EntrySize < Other.EntrySize; + } + }; + + mutable std::map ELFEntrySizeMap; + protected: MCSymbolRefExpr::VariantKind PLTRelativeVariantKind = MCSymbolRefExpr::VK_None; Index: llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp =================================================================== --- llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -594,15 +594,35 @@ if (AssociatedSymbol) { UniqueID = NextUniqueID++; Flags |= ELF::SHF_LINK_ORDER; + } else { + // Mergeable globals must be placed into sections with compatible entry + // sizes. Put the global into the correct existing section or create a + // new uniqued section. + if (Flags & ELF::SHF_MERGE) { + auto i = ELFEntrySizeMap.insert(std::make_pair( + ELFEntrySizeKey{SectionName, Flags, getEntrySizeForKind(Kind)}, + NextUniqueID)); + if (i.second) + NextUniqueID++; + UniqueID = i.first->second; + } } MCSectionELF *Section = getContext().getELFSection( SectionName, getELFSectionType(SectionName, Kind), Flags, getEntrySizeForKind(Kind), Group, UniqueID, AssociatedSymbol); + // Make sure that we did not get some other section with incompatible sh_link. // This should not be possible due to UniqueID code above. assert(Section->getAssociatedSymbol() == AssociatedSymbol && "Associated symbol mismatch between sections"); + + // Make sure that a mergeable global is not assigned to a section with an + // incompatible entry size. This should not be possible due to the UniqueID + // code above. + assert((getELFSectionFlags(Kind) & ELF::SHF_MERGE) && + (Section->getEntrySize() == getEntrySizeForKind(Kind))); + return Section; } Index: llvm/test/CodeGen/X86/explict-section-mergeable.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/X86/explict-section-mergeable.ll @@ -0,0 +1,173 @@ +; RUN: llc < %s -mtriple=x86_64-linux-gnu -unique-section-names=0 -data-sections 2>&1 \ +; RUN: | FileCheck %s + +;; Test implicit section assignment for globals +; CHECK: .section .data,"aw",@progbits,unique,1 +; CHECK-NOT: .section +; CHECK: uniqified1: +; CHECK: .section .rodata.cst4,"aM",@progbits,4 +; CHECK-NOT: .section +; CHECK: implicit1: +; CHECK: .section .rodata.cst8,"aM",@progbits,8 +; CHECK-NOT: .section +; CHECK: implicit2: +; CHECK: .section .rodata.str4.4,"aMS",@progbits,4 +; CHECK-NOT: .section +; CHECK: implicit3: + +;; Check that the globals have been placed into distinct sections with +;; the same name, but different entry sizes. +; CHECK: .section .explicit,"aM",@progbits,4,unique,2 +; CHECK-NOT: .section +; CHECK: explicit1: +; CHECK: explicit2: +; CHECK: .section .explicit,"aM",@progbits,8,unique,3 +; CHECK-NOT: .section +; CHECK: explicit3: +; CHECK: explicit4: +; CHECK: .section .explicit,"aMS",@progbits,4,unique,4 +; CHECK-NOT: .section +; CHECK: explicit5: +; CHECK: explicit6: + +@uniqified1 = global i32 1 + +@implicit1 = unnamed_addr constant [2 x i16] [i16 1, i16 1] +@implicit2 = unnamed_addr constant [2 x i32] [i32 1, i32 1] +@implicit3 = unnamed_addr constant [2 x i32] [i32 1, i32 0] + +@explicit1 = unnamed_addr constant [2 x i16] [i16 1, i16 1], section ".explicit" +@explicit2 = unnamed_addr constant [2 x i16] [i16 1, i16 1] "rodata-section"=".explicit" +@explicit3 = unnamed_addr constant [2 x i32] [i32 1, i32 1], section ".explicit" +@explicit4 = unnamed_addr constant [2 x i32] [i32 1, i32 1] "rodata-section"=".explicit" +@explicit5 = unnamed_addr constant [2 x i32] [i32 1, i32 0], section ".explicit" +@explicit6 = unnamed_addr constant [2 x i32] [i32 1, i32 0] "rodata-section"=".explicit" + +;; Test implicit section assignment for globals with associated globals +; CHECK: .section .rodata.cst4,"aMo",@progbits,4,implicit1,unique,5 +; CHECK-NOT: .section +; CHECK: implicit4: +; CHECK: .section .rodata.cst8,"aMo",@progbits,8,implicit1,unique,6 +; CHECK-NOT: .section +; CHECK: implicit5: +; CHECK: .section .rodata.str4.4,"aMSo",@progbits,4,implicit1,unique,7 +; CHECK-NOT: .section +; CHECK: implicit6: + +;; Check that globals with associated globals that are explicitly assigned +;; to a section have been placed into distinct sections with the same name, but +;; different entry sizes. +; CHECK: .section .explicit,"aMo",@progbits,4,implicit1,unique,8 +; CHECK-NOT: .section +; CHECK: explicit7: +; CHECK: .section .explicit,"aMo",@progbits,4,implicit1,unique,9 +; CHECK-NOT: .section +; CHECK: explicit8: +; CHECK: .section .explicit,"aMo",@progbits,8,implicit1,unique,10 +; CHECK-NOT: .section +; CHECK: explicit9: +; CHECK: .section .explicit,"aMo",@progbits,8,implicit1,unique,11 +; CHECK-NOT: .section +; CHECK: explicit10: +; CHECK: .section .explicit,"aMSo",@progbits,4,implicit1,unique,12 +; CHECK-NOT: .section +; CHECK: explicit11: +; CHECK: .section .explicit,"aMSo",@progbits,4,implicit1,unique,13 +; CHECK-NOT: .section +; CHECK: explicit12: + +@implicit4 = unnamed_addr constant [2 x i16] [i16 1, i16 1], !associated !4 +@implicit5 = unnamed_addr constant [2 x i32] [i32 1, i32 1], !associated !4 +@implicit6 = unnamed_addr constant [2 x i32] [i32 1, i32 0], !associated !4 + +@explicit7 = unnamed_addr constant [2 x i16] [i16 1, i16 1], section ".explicit", !associated !4 +@explicit8 = unnamed_addr constant [2 x i16] [i16 1, i16 1], !associated !4 "rodata-section"=".explicit" +@explicit9 = unnamed_addr constant [2 x i32] [i32 1, i32 1], section ".explicit", !associated !4 +@explicit10 = unnamed_addr constant [2 x i32] [i32 1, i32 1], !associated !4 "rodata-section"=".explicit" +@explicit11 = unnamed_addr constant [2 x i32] [i32 1, i32 0], section ".explicit", !associated !4 +@explicit12 = unnamed_addr constant [2 x i32] [i32 1, i32 0], !associated !4 "rodata-section"=".explicit" + +!4 = !{[2 x i16]* @implicit1} + +;; Test implicit section assignment for globals in distinct comdat groups +; CHECK: .section .rodata.cst4,"aGM",@progbits,4,f,comdat,unique,14 +; CHECK-NOT: .section +; CHECK: implicit7: +; CHECK: .section .rodata.cst8,"aGM",@progbits,8,g,comdat,unique,15 +; CHECK-NOT: .section +; CHECK: implicit8: +; CHECK: .section .rodata.str4.4,"aGMS",@progbits,4,h,comdat,unique,16 +; CHECK-NOT: .section +; CHECK: implicit9: + +;; Check that globals in distinct comdat groups that are explicitly assigned +;; to a section have been placed into distinct sections with the same name, but +;; different entry sizes. Due to the way that MC currently works the unique ID +;; does not have any effect here, although it appears in the assembly. +; CHECK: .section .explicit,"aGM",@progbits,4,f,comdat,unique,2 +; CHECK-NOT: .section +; CHECK: explicit13: +; CHECK: explicit14: +; CHECK: .section .explicit,"aGM",@progbits,8,g,comdat,unique,3 +; CHECK-NOT: .section +; CHECK: explicit15: +; CHECK: explicit16: +; CHECK: .section .explicit,"aGMS",@progbits,4,h,comdat,unique,4 +; CHECK-NOT: .section +; CHECK: explicit17: +; CHECK: explicit18: + +$f = comdat any +$g = comdat any +$h = comdat any + +@implicit7 = unnamed_addr constant [2 x i16] [i16 1, i16 1], comdat($f) +@implicit8 = unnamed_addr constant [2 x i32] [i32 1, i32 1], comdat($g) +@implicit9 = unnamed_addr constant [2 x i32] [i32 1, i32 0], comdat($h) + +@explicit13 = unnamed_addr constant [2 x i16] [i16 1, i16 1], section ".explicit", comdat($f) +@explicit14 = unnamed_addr constant [2 x i16] [i16 1, i16 1], comdat($f) "rodata-section"=".explicit" +@explicit15 = unnamed_addr constant [2 x i32] [i32 1, i32 1], section ".explicit", comdat($g) +@explicit16 = unnamed_addr constant [2 x i32] [i32 1, i32 1], comdat($g) "rodata-section"=".explicit" +@explicit17 = unnamed_addr constant [2 x i32] [i32 1, i32 0], section ".explicit", comdat($h) +@explicit18 = unnamed_addr constant [2 x i32] [i32 1, i32 0], comdat($h) "rodata-section"=".explicit" + +;; Test implicit section assignment for globals in the same comdat group +; CHECK: .section .rodata.cst4,"aGM",@progbits,4,i,comdat,unique,17 +; CHECK-NOT: .section +; CHECK: implicit10: +; CHECK: .section .rodata.cst8,"aGM",@progbits,8,i,comdat,unique,18 +; CHECK-NOT: .section +; CHECK: implicit11: +; CHECK: .section .rodata.str4.4,"aGMS",@progbits,4,i,comdat,unique,19 +; CHECK-NOT: .section +; CHECK: implicit12: + +;; Check that globals in the same comdat group that are explicitly assigned +;; to a section have been placed into distinct sections with the same name, but +;; different entry sizes. +; CHECK: .section .explicit,"aGM",@progbits,4,i,comdat,unique,2 +; CHECK-NOT: .section +; CHECK: explicit19: +; CHECK: explicit20: +; CHECK: .section .explicit,"aGM",@progbits,8,i,comdat,unique,3 +; CHECK-NOT: .section +; CHECK: explicit21: +; CHECK: explicit22: +; CHECK: .section .explicit,"aGMS",@progbits,4,i,comdat,unique,4 +; CHECK-NOT: .section +; CHECK: explicit23: +; CHECK: explicit24: + +$i = comdat any + +@implicit10 = unnamed_addr constant [2 x i16] [i16 1, i16 1], comdat($i) +@implicit11 = unnamed_addr constant [2 x i32] [i32 1, i32 1], comdat($i) +@implicit12 = unnamed_addr constant [2 x i32] [i32 1, i32 0], comdat($i) + +@explicit19 = unnamed_addr constant [2 x i16] [i16 1, i16 1], section ".explicit", comdat($i) +@explicit20 = unnamed_addr constant [2 x i16] [i16 1, i16 1], comdat($i) "rodata-section"=".explicit" +@explicit21 = unnamed_addr constant [2 x i32] [i32 1, i32 1], section ".explicit", comdat($i) +@explicit22 = unnamed_addr constant [2 x i32] [i32 1, i32 1], comdat($i) "rodata-section"=".explicit" +@explicit23 = unnamed_addr constant [2 x i32] [i32 1, i32 0], section ".explicit", comdat($i) +@explicit24 = unnamed_addr constant [2 x i32] [i32 1, i32 0], comdat($i) "rodata-section"=".explicit" Index: llvm/unittests/ExecutionEngine/Orc/LegacyRTDyldObjectLinkingLayerTest.cpp =================================================================== --- llvm/unittests/ExecutionEngine/Orc/LegacyRTDyldObjectLinkingLayerTest.cpp +++ llvm/unittests/ExecutionEngine/Orc/LegacyRTDyldObjectLinkingLayerTest.cpp @@ -77,10 +77,12 @@ LLVMContext Context; auto M = std::make_unique("", Context); M->setTargetTriple("x86_64-unknown-linux-gnu"); - Type *Int32Ty = IntegerType::get(Context, 32); - GlobalVariable *GV = - new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage, - ConstantInt::get(Int32Ty, 42), "foo"); + Constant *StrConstant = ConstantDataArray::getString(Context, "forty-two"); + auto *GV = + new GlobalVariable(*M, StrConstant->getType(), true, + GlobalValue::ExternalLinkage, StrConstant, "foo"); + GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); + GV->setAlignment(1); GV->setSection(".debug_str"); Index: llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp =================================================================== --- llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp +++ llvm/unittests/ExecutionEngine/Orc/RTDyldObjectLinkingLayerTest.cpp @@ -73,10 +73,12 @@ LLVMContext Context; auto M = std::make_unique("", Context); M->setTargetTriple("x86_64-unknown-linux-gnu"); - Type *Int32Ty = IntegerType::get(Context, 32); - GlobalVariable *GV = - new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage, - ConstantInt::get(Int32Ty, 42), "foo"); + Constant *StrConstant = ConstantDataArray::getString(Context, "forty-two"); + auto *GV = + new GlobalVariable(*M, StrConstant->getType(), true, + GlobalValue::ExternalLinkage, StrConstant, "foo"); + GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); + GV->setAlignment(1); GV->setSection(".debug_str");