diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 409adafc786..fe48c254d24 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -156,19 +156,27 @@ static bool ConvertToString(ArrayRef Record, unsigned Idx, return false; } +static bool hasImplicitComdat(size_t Val) { + switch (Val) { + default: + return false; + case 1: // Old WeakAnyLinkage + case 4: // Old LinkOnceAnyLinkage + case 10: // Old WeakODRLinkage + case 11: // Old LinkOnceODRLinkage + return true; + } +} + static GlobalValue::LinkageTypes getDecodedLinkage(unsigned Val) { switch (Val) { default: // Map unknown/new linkages to external case 0: return GlobalValue::ExternalLinkage; - case 1: - return GlobalValue::WeakAnyLinkage; case 2: return GlobalValue::AppendingLinkage; case 3: return GlobalValue::InternalLinkage; - case 4: - return GlobalValue::LinkOnceAnyLinkage; case 5: return GlobalValue::ExternalLinkage; // Obsolete DLLImportLinkage case 6: @@ -179,10 +187,6 @@ static GlobalValue::LinkageTypes getDecodedLinkage(unsigned Val) { return GlobalValue::CommonLinkage; case 9: return GlobalValue::PrivateLinkage; - case 10: - return GlobalValue::WeakODRLinkage; - case 11: - return GlobalValue::LinkOnceODRLinkage; case 12: return GlobalValue::AvailableExternallyLinkage; case 13: @@ -191,6 +195,18 @@ static GlobalValue::LinkageTypes getDecodedLinkage(unsigned Val) { return GlobalValue::PrivateLinkage; // Obsolete LinkerPrivateWeakLinkage case 15: return GlobalValue::ExternalLinkage; // Obsolete LinkOnceODRAutoHideLinkage + case 1: // Old value with implicit comdat. + case 16: + return GlobalValue::WeakAnyLinkage; + case 10: // Old value with implicit comdat. + case 17: + return GlobalValue::WeakODRLinkage; + case 4: // Old value with implicit comdat. + case 18: + return GlobalValue::LinkOnceAnyLinkage; + case 11: // Old value with implicit comdat. + case 19: + return GlobalValue::LinkOnceODRLinkage; } } @@ -1118,6 +1134,10 @@ std::error_code BitcodeReader::ParseValueSymbolTable() { Value *V = ValueList[ValueID]; V->setName(StringRef(ValueName.data(), ValueName.size())); + if (auto *GO = dyn_cast(V)) { + if (GO->getComdat() == reinterpret_cast(1)) + GO->setComdat(TheModule->getOrInsertComdat(V->getName())); + } ValueName.clear(); break; } @@ -2140,7 +2160,8 @@ std::error_code BitcodeReader::ParseModule(bool Resume) { Ty = cast(Ty)->getElementType(); bool isConstant = Record[1]; - GlobalValue::LinkageTypes Linkage = getDecodedLinkage(Record[3]); + uint64_t RawLinkage = Record[3]; + GlobalValue::LinkageTypes Linkage = getDecodedLinkage(RawLinkage); unsigned Alignment = (1 << Record[4]) >> 1; std::string Section; if (Record[5]) { @@ -2178,7 +2199,7 @@ std::error_code BitcodeReader::ParseModule(bool Resume) { if (Record.size() > 10) NewGV->setDLLStorageClass(GetDecodedDLLStorageClass(Record[10])); else - UpgradeDLLImportExportLinkage(NewGV, Record[3]); + UpgradeDLLImportExportLinkage(NewGV, RawLinkage); ValueList.push_back(NewGV); @@ -2186,11 +2207,14 @@ std::error_code BitcodeReader::ParseModule(bool Resume) { if (unsigned InitID = Record[2]) GlobalInits.push_back(std::make_pair(NewGV, InitID-1)); - if (Record.size() > 11) + if (Record.size() > 11) { if (unsigned ComdatID = Record[11]) { assert(ComdatID <= ComdatList.size()); NewGV->setComdat(ComdatList[ComdatID - 1]); } + } else if (hasImplicitComdat(RawLinkage)) { + NewGV->setComdat(reinterpret_cast(1)); + } break; } // FUNCTION: [type, callingconv, isproto, linkage, paramattr, @@ -2214,7 +2238,8 @@ std::error_code BitcodeReader::ParseModule(bool Resume) { Func->setCallingConv(static_cast(Record[1])); bool isProto = Record[2]; - Func->setLinkage(getDecodedLinkage(Record[3])); + uint64_t RawLinkage = Record[3]; + Func->setLinkage(getDecodedLinkage(RawLinkage)); Func->setAttributes(getAttributes(Record[4])); Func->setAlignment((1 << Record[5]) >> 1); @@ -2242,13 +2267,16 @@ std::error_code BitcodeReader::ParseModule(bool Resume) { if (Record.size() > 11) Func->setDLLStorageClass(GetDecodedDLLStorageClass(Record[11])); else - UpgradeDLLImportExportLinkage(Func, Record[3]); + UpgradeDLLImportExportLinkage(Func, RawLinkage); - if (Record.size() > 12) + if (Record.size() > 12) { if (unsigned ComdatID = Record[12]) { assert(ComdatID <= ComdatList.size()); Func->setComdat(ComdatList[ComdatID - 1]); } + } else if (hasImplicitComdat(RawLinkage)) { + Func->setComdat(reinterpret_cast(1)); + } if (Record.size() > 13 && Record[13] != 0) FunctionPrefixes.push_back(std::make_pair(Func, Record[13]-1)); diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index 5e8c64ee9cd..960a7922cd8 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -480,13 +480,13 @@ static unsigned getEncodedLinkage(const GlobalValue &GV) { case GlobalValue::ExternalLinkage: return 0; case GlobalValue::WeakAnyLinkage: - return 1; + return 16; case GlobalValue::AppendingLinkage: return 2; case GlobalValue::InternalLinkage: return 3; case GlobalValue::LinkOnceAnyLinkage: - return 4; + return 18; case GlobalValue::ExternalWeakLinkage: return 7; case GlobalValue::CommonLinkage: @@ -494,9 +494,9 @@ static unsigned getEncodedLinkage(const GlobalValue &GV) { case GlobalValue::PrivateLinkage: return 9; case GlobalValue::WeakODRLinkage: - return 10; + return 17; case GlobalValue::LinkOnceODRLinkage: - return 11; + return 19; case GlobalValue::AvailableExternallyLinkage: return 12; } @@ -629,7 +629,7 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, Log2_32_Ceil(MaxGlobalType+1))); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Constant. Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Initializer. - Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // Linkage. + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 5)); // Linkage. if (MaxAlignment == 0) // Alignment. Abbv->Add(BitCodeAbbrevOp(0)); else { diff --git a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index 9f1e06b4725..b9a3ad23d1f 100644 --- a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -257,8 +257,7 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, // If this global is linkonce/weak and the target handles this by emitting it // into a 'uniqued' section name, create and return the section now. - if ((GV->isWeakForLinker() || EmitUniquedSection || GV->hasComdat()) && - !Kind.isCommon()) { + if ((EmitUniquedSection && !Kind.isCommon()) || GV->hasComdat()) { StringRef Prefix = getSectionPrefixForGlobal(Kind); SmallString<128> Name(Prefix); @@ -266,12 +265,9 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, StringRef Group = ""; unsigned Flags = getELFSectionFlags(Kind); - if (GV->isWeakForLinker() || GV->hasComdat()) { - if (const Comdat *C = getELFComdat(GV)) - Group = C->getName(); - else - Group = Name.substr(Prefix.size()); + if (const Comdat *C = getELFComdat(GV)) { Flags |= ELF::SHF_GROUP; + Group = C->getName(); } return getContext().getELFSection(Name.str(), @@ -801,7 +797,7 @@ const MCSection *TargetLoweringObjectFileCOFF::getExplicitSectionGlobal( unsigned Characteristics = getCOFFSectionFlags(Kind); StringRef Name = GV->getSection(); StringRef COMDATSymName = ""; - if ((GV->isWeakForLinker() || GV->hasComdat()) && !Kind.isCommon()) { + if (GV->hasComdat()) { Selection = getSelectionForCOFF(GV); const GlobalValue *ComdatGV; if (Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) @@ -848,12 +844,7 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, else EmitUniquedSection = TM.getDataSections(); - // If this global is linkonce/weak and the target handles this by emitting it - // into a 'uniqued' section name, create and return the section now. - // Section names depend on the name of the symbol which is not feasible if the - // symbol has private linkage. - if ((GV->isWeakForLinker() || EmitUniquedSection || GV->hasComdat()) && - !Kind.isCommon()) { + if ((EmitUniquedSection && !Kind.isCommon()) || GV->hasComdat()) { const char *Name = getCOFFSectionNameForUniqueGlobal(Kind); unsigned Characteristics = getCOFFSectionFlags(Kind); diff --git a/lib/Target/XCore/XCoreAsmPrinter.cpp b/lib/Target/XCore/XCoreAsmPrinter.cpp index 82e4e3690b4..3999f1254f6 100644 --- a/lib/Target/XCore/XCoreAsmPrinter.cpp +++ b/lib/Target/XCore/XCoreAsmPrinter.cpp @@ -105,7 +105,6 @@ void XCoreAsmPrinter::emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV) { OutContext)); if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()) { - // TODO Use COMDAT groups for LinkOnceLinkage OutStreamer.EmitSymbolAttribute(SymGlob, MCSA_Weak); } } @@ -140,7 +139,6 @@ void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { emitArrayBound(GVSym, GV); OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); - // TODO Use COMDAT groups for LinkOnceLinkage if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() || GV->hasCommonLinkage()) OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak); diff --git a/test/Bitcode/linkage-types-3.2.ll b/test/Bitcode/linkage-types-3.2.ll index e255b619f41..fb6cc5745fa 100644 --- a/test/Bitcode/linkage-types-3.2.ll +++ b/test/Bitcode/linkage-types-3.2.ll @@ -33,13 +33,13 @@ ; CHECK: @available_externally.var = available_externally constant i32 0{{$}} @linkonce.var = linkonce constant i32 0 -; CHECK: @linkonce.var = linkonce constant i32 0{{$}} +; CHECK: @linkonce.var = linkonce constant i32 0, comdat{{$}} @weak.var = weak constant i32 0 -; CHECK: @weak.var = weak constant i32 0{{$}} +; CHECK: @weak.var = weak constant i32 0, comdat{{$}} @linkonce_odr.var = linkonce_odr constant i32 0 -; CHECK: @linkonce_odr.var = linkonce_odr constant i32 0{{$}} +; CHECK: @linkonce_odr.var = linkonce_odr constant i32 0, comdat{{$}} @linkonce_odr_auto_hide.var = linkonce_odr_auto_hide constant i32 0 ; CHECK: @linkonce_odr_auto_hide.var = constant i32 0{{$}} @@ -90,19 +90,19 @@ define available_externally void @available_externally() } define linkonce void @linkonce() -; CHECK: define linkonce void @linkonce() { +; CHECK: define linkonce void @linkonce() comdat { { ret void } define weak void @weak() -; CHECK: define weak void @weak() { +; CHECK: define weak void @weak() comdat { { ret void } define linkonce_odr void @linkonce_odr() -; CHECK: define linkonce_odr void @linkonce_odr() { +; CHECK: define linkonce_odr void @linkonce_odr() comdat { { ret void } diff --git a/test/CodeGen/ARM/odr_comdat.ll b/test/CodeGen/ARM/odr_comdat.ll deleted file mode 100644 index e28b5788ef6..00000000000 --- a/test/CodeGen/ARM/odr_comdat.ll +++ /dev/null @@ -1,16 +0,0 @@ -; RUN: llc < %s -mtriple=arm-linux-gnueabi | FileCheck %s -check-prefix=ARMGNUEABI - -; Checking that a comdat group gets generated correctly for a static member -; of instantiated C++ templates. -; see http://sourcery.mentor.com/public/cxx-abi/abi.html#vague-itemplate -; section 5.2.6 Instantiated templates -; "Any static member data object is emitted in a COMDAT identified by its mangled -; name, in any object file with a reference to its name symbol." - -; Case 1: variable is not explicitly initialized, and ends up in a .bss section -; ARMGNUEABI: .section .bss._ZN1CIiE1iE,"aGw",%nobits,_ZN1CIiE1iE,comdat -@_ZN1CIiE1iE = weak_odr global i32 0, align 4 - -; Case 2: variable is explicitly initialized, and ends up in a .data section -; ARMGNUEABI: .section .data._ZN1CIiE1jE,"aGw",%progbits,_ZN1CIiE1jE,comdat -@_ZN1CIiE1jE = weak_odr global i32 12, align 4 diff --git a/test/CodeGen/ARM/section-name.ll b/test/CodeGen/ARM/section-name.ll index a0aad4733bc..a4c6054197f 100644 --- a/test/CodeGen/ARM/section-name.ll +++ b/test/CodeGen/ARM/section-name.ll @@ -16,7 +16,7 @@ entry: ret void } -; CHECK: .section .text.test3,"axG",%progbits,test3,comdat +; CHECK: .text ; CHECK: .weak test3 ; CHECK: .type test3,%function define linkonce_odr void @test3() { diff --git a/test/CodeGen/X86/dllexport-x86_64.ll b/test/CodeGen/X86/dllexport-x86_64.ll index c673f5d485f..25b88e56e45 100644 --- a/test/CodeGen/X86/dllexport-x86_64.ll +++ b/test/CodeGen/X86/dllexport-x86_64.ll @@ -17,19 +17,16 @@ define dllexport void @f2() unnamed_addr { ret void } -; CHECK: .section .text,"xr",discard,lnk1 ; CHECK: .globl lnk1 define linkonce_odr dllexport void @lnk1() { ret void } -; CHECK: .section .text,"xr",discard,lnk2 ; CHECK: .globl lnk2 define linkonce_odr dllexport void @lnk2() alwaysinline { ret void } -; CHECK: .section .text,"xr",discard,weak1 ; CHECK: .globl weak1 define weak_odr dllexport void @weak1() { ret void @@ -47,11 +44,9 @@ define weak_odr dllexport void @weak1() { ; CHECK: .comm Var3 @Var3 = common dllexport global i32 0, align 4 -; CHECK: .section .data,"wd",discard,WeakVar1 ; CHECK: .globl WeakVar1 @WeakVar1 = weak_odr dllexport global i32 1, align 4 -; CHECK: .section .rdata,"rd",discard,WeakVar2 ; CHECK: .globl WeakVar2 @WeakVar2 = weak_odr dllexport unnamed_addr constant i32 1 diff --git a/test/CodeGen/X86/dllexport.ll b/test/CodeGen/X86/dllexport.ll index 5035aa15330..e76591d7f5e 100644 --- a/test/CodeGen/X86/dllexport.ll +++ b/test/CodeGen/X86/dllexport.ll @@ -36,19 +36,16 @@ define dllexport x86_thiscallcc void @thisfun() nounwind { ret void } -; CHECK: .section .text,"xr",discard,_lnk1 ; CHECK: .globl _lnk1 define linkonce_odr dllexport void @lnk1() { ret void } -; CHECK: .section .text,"xr",discard,_lnk2 ; CHECK: .globl _lnk2 define linkonce_odr dllexport void @lnk2() alwaysinline { ret void } -; CHECK: .section .text,"xr",discard,_weak1 ; CHECK: .globl _weak1 define weak_odr dllexport void @weak1() { ret void @@ -66,11 +63,9 @@ define weak_odr dllexport void @weak1() { ; CHECK: .comm _Var3 @Var3 = common dllexport global i32 0, align 4 -; CHECK: .section .data,"wd",discard,_WeakVar1 ; CHECK: .globl _WeakVar1 @WeakVar1 = weak_odr dllexport global i32 1, align 4 -; CHECK: .section .rdata,"rd",discard,_WeakVar2 ; CHECK: .globl _WeakVar2 @WeakVar2 = weak_odr dllexport unnamed_addr constant i32 1 diff --git a/test/CodeGen/X86/global-sections.ll b/test/CodeGen/X86/global-sections.ll index fa1169d8a8e..24be27161f4 100644 --- a/test/CodeGen/X86/global-sections.ll +++ b/test/CodeGen/X86/global-sections.ll @@ -85,7 +85,6 @@ define void @F1() { @"foo bar" = linkonce global i32 42 ; LINUX: .type "foo bar",@object -; LINUX: .section ".data.foo bar","aGw",@progbits,"foo bar",comdat ; LINUX: .weak "foo bar" ; LINUX: "foo bar": @@ -98,7 +97,6 @@ define void @F1() { @G6 = weak_odr unnamed_addr constant [1 x i8] c"\01" ; LINUX: .type G6,@object -; LINUX: .section .rodata.G6,"aG",@progbits,G6,comdat ; LINUX: .weak G6 ; LINUX: G6: ; LINUX: .byte 1 diff --git a/test/CodeGen/X86/odr_comdat.ll b/test/CodeGen/X86/odr_comdat.ll deleted file mode 100644 index 547334c045a..00000000000 --- a/test/CodeGen/X86/odr_comdat.ll +++ /dev/null @@ -1,16 +0,0 @@ -; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s -check-prefix=X86LINUX - -; Checking that a comdat group gets generated correctly for a static member -; of instantiated C++ templates. -; see http://sourcery.mentor.com/public/cxx-abi/abi.html#vague-itemplate -; section 5.2.6 Instantiated templates -; "Any static member data object is emitted in a COMDAT identified by its mangled -; name, in any object file with a reference to its name symbol." - -; Case 1: variable is not explicitly initialized, and ends up in a .bss section -; X86LINUX: .section .bss._ZN1CIiE1iE,"aGw",@nobits,_ZN1CIiE1iE,comdat -@_ZN1CIiE1iE = weak_odr global i32 0, align 4 - -; Case 2: variable is explicitly initialized, and ends up in a .data section -; X86LINUX: .section .data._ZN1CIiE1jE,"aGw",@progbits,_ZN1CIiE1jE,comdat -@_ZN1CIiE1jE = weak_odr global i32 12, align 4 diff --git a/test/CodeGen/X86/pic_jumptable.ll b/test/CodeGen/X86/pic_jumptable.ll index bdd88593584..d66ff0c59db 100644 --- a/test/CodeGen/X86/pic_jumptable.ll +++ b/test/CodeGen/X86/pic_jumptable.ll @@ -10,7 +10,7 @@ declare void @_Z3bari(i32) -; CHECK-LINUX: .text._Z3fooILi1EEvi,"axG",@progbits,_Z3fooILi1EEvi,comdat +; CHECK-LINUX: _Z3fooILi1EEvi: define linkonce void @_Z3fooILi1EEvi(i32 %Y) nounwind { entry: ; CHECK: L0$pb diff --git a/test/MC/COFF/bss_section.ll b/test/MC/COFF/bss_section.ll index 1921eeb61a6..f80a0712b7e 100644 --- a/test/MC/COFF/bss_section.ll +++ b/test/MC/COFF/bss_section.ll @@ -5,5 +5,6 @@ @"\01?thingy@@3Ufoo@@B" = global %struct.foo zeroinitializer, align 4 ; CHECK: .bss -@thingy_linkonce = linkonce_odr global %struct.foo zeroinitializer, align 4 +$thingy_linkonce = comdat any +@thingy_linkonce = linkonce_odr global %struct.foo zeroinitializer, comdat, align 4 ; CHECK: .section .bss,"wb",discard,_thingy_linkonce diff --git a/test/MC/COFF/const-gv-with-rel-init.ll b/test/MC/COFF/const-gv-with-rel-init.ll index 7d3c5f63188..6a89e2faa68 100644 --- a/test/MC/COFF/const-gv-with-rel-init.ll +++ b/test/MC/COFF/const-gv-with-rel-init.ll @@ -8,4 +8,4 @@ define void @f() { ; CHECK: .section .CRT$XLB,"rd" @weak_array = weak_odr unnamed_addr constant [1 x i8*] [i8* bitcast (void ()* @f to i8*)] -; CHECK: .section .rdata,"rd",discard,weak_array +; CHECK: .section .rdata,"rd" diff --git a/test/MC/COFF/weak-symbol.ll b/test/MC/COFF/weak-symbol.ll deleted file mode 100644 index fd78307c1f2..00000000000 --- a/test/MC/COFF/weak-symbol.ll +++ /dev/null @@ -1,48 +0,0 @@ -; Test that weak functions and globals are placed into selectany COMDAT -; sections with the mangled name as suffix. Ensure that the weak linkage -; type is not ignored by the backend if the section was specialized. -; -; RUN: llc -mtriple=i686-pc-win32 %s -o - | FileCheck %s --check-prefix=X86 -; RUN: llc -mtriple=i686-pc-mingw32 %s -o - | FileCheck %s --check-prefix=X86 -; RUN: llc -mtriple=x86_64-pc-win32 %s -o - | FileCheck %s --check-prefix=X64 -; RUN: llc -mtriple=x86_64-pc-mingw32 %s -o - | FileCheck %s --check-prefix=X64 - -; Mangled function -; X86: .section .text,"xr",discard,__Z3foo -; X86: .globl __Z3foo -; -; X64: .section .text,"xr",discard,_Z3foo -; X64: .globl _Z3foo -define weak void @_Z3foo() { - ret void -} - -; Unmangled function -; X86: .section .sect,"xr",discard,_f -; X86: .globl _f -; -; X64: .section .sect,"xr",discard,f -; X64: .globl f -define weak void @f() section ".sect" { - ret void -} - -; Weak global -; X86: .section .data,"rd",discard,_a -; X86: .globl _a -; X86: .zero 12 -; -; X64: .section .data,"rd",discard,a -; X64: .globl a -; X64: .zero 12 -@a = weak unnamed_addr constant { i32, i32, i32 } { i32 0, i32 0, i32 0}, section ".data" - -; X86: .section .tls$,"wd",discard,_b -; X86: .globl _b -; X86: .long 0 -; -; X64: .section .tls$,"wd",discard,b -; X64: .globl b -; X64: .long 0 - -@b = weak_odr thread_local global i32 0, align 4