Bring r226038 back.

No change in this commit, but clang was changed to also produce trivial comdats when
needed.

Original message:

Don't create new comdats in CodeGen.

This patch stops the implicit creation of comdats during codegen.

Clang now sets the comdat explicitly when it is required. With this patch clang and gcc
now produce the same result in pr19848.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@226467 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Rafael Espindola 2015-01-19 15:16:06 +00:00
parent 10b853882c
commit 4b678bff4e
15 changed files with 63 additions and 137 deletions

View File

@ -156,19 +156,27 @@ static bool ConvertToString(ArrayRef<uint64_t> Record, unsigned Idx,
return false; 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) { static GlobalValue::LinkageTypes getDecodedLinkage(unsigned Val) {
switch (Val) { switch (Val) {
default: // Map unknown/new linkages to external default: // Map unknown/new linkages to external
case 0: case 0:
return GlobalValue::ExternalLinkage; return GlobalValue::ExternalLinkage;
case 1:
return GlobalValue::WeakAnyLinkage;
case 2: case 2:
return GlobalValue::AppendingLinkage; return GlobalValue::AppendingLinkage;
case 3: case 3:
return GlobalValue::InternalLinkage; return GlobalValue::InternalLinkage;
case 4:
return GlobalValue::LinkOnceAnyLinkage;
case 5: case 5:
return GlobalValue::ExternalLinkage; // Obsolete DLLImportLinkage return GlobalValue::ExternalLinkage; // Obsolete DLLImportLinkage
case 6: case 6:
@ -179,10 +187,6 @@ static GlobalValue::LinkageTypes getDecodedLinkage(unsigned Val) {
return GlobalValue::CommonLinkage; return GlobalValue::CommonLinkage;
case 9: case 9:
return GlobalValue::PrivateLinkage; return GlobalValue::PrivateLinkage;
case 10:
return GlobalValue::WeakODRLinkage;
case 11:
return GlobalValue::LinkOnceODRLinkage;
case 12: case 12:
return GlobalValue::AvailableExternallyLinkage; return GlobalValue::AvailableExternallyLinkage;
case 13: case 13:
@ -191,6 +195,18 @@ static GlobalValue::LinkageTypes getDecodedLinkage(unsigned Val) {
return GlobalValue::PrivateLinkage; // Obsolete LinkerPrivateWeakLinkage return GlobalValue::PrivateLinkage; // Obsolete LinkerPrivateWeakLinkage
case 15: case 15:
return GlobalValue::ExternalLinkage; // Obsolete LinkOnceODRAutoHideLinkage 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]; Value *V = ValueList[ValueID];
V->setName(StringRef(ValueName.data(), ValueName.size())); V->setName(StringRef(ValueName.data(), ValueName.size()));
if (auto *GO = dyn_cast<GlobalObject>(V)) {
if (GO->getComdat() == reinterpret_cast<Comdat *>(1))
GO->setComdat(TheModule->getOrInsertComdat(V->getName()));
}
ValueName.clear(); ValueName.clear();
break; break;
} }
@ -2140,7 +2160,8 @@ std::error_code BitcodeReader::ParseModule(bool Resume) {
Ty = cast<PointerType>(Ty)->getElementType(); Ty = cast<PointerType>(Ty)->getElementType();
bool isConstant = Record[1]; 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; unsigned Alignment = (1 << Record[4]) >> 1;
std::string Section; std::string Section;
if (Record[5]) { if (Record[5]) {
@ -2178,7 +2199,7 @@ std::error_code BitcodeReader::ParseModule(bool Resume) {
if (Record.size() > 10) if (Record.size() > 10)
NewGV->setDLLStorageClass(GetDecodedDLLStorageClass(Record[10])); NewGV->setDLLStorageClass(GetDecodedDLLStorageClass(Record[10]));
else else
UpgradeDLLImportExportLinkage(NewGV, Record[3]); UpgradeDLLImportExportLinkage(NewGV, RawLinkage);
ValueList.push_back(NewGV); ValueList.push_back(NewGV);
@ -2186,11 +2207,14 @@ std::error_code BitcodeReader::ParseModule(bool Resume) {
if (unsigned InitID = Record[2]) if (unsigned InitID = Record[2])
GlobalInits.push_back(std::make_pair(NewGV, InitID-1)); GlobalInits.push_back(std::make_pair(NewGV, InitID-1));
if (Record.size() > 11) if (Record.size() > 11) {
if (unsigned ComdatID = Record[11]) { if (unsigned ComdatID = Record[11]) {
assert(ComdatID <= ComdatList.size()); assert(ComdatID <= ComdatList.size());
NewGV->setComdat(ComdatList[ComdatID - 1]); NewGV->setComdat(ComdatList[ComdatID - 1]);
} }
} else if (hasImplicitComdat(RawLinkage)) {
NewGV->setComdat(reinterpret_cast<Comdat *>(1));
}
break; break;
} }
// FUNCTION: [type, callingconv, isproto, linkage, paramattr, // FUNCTION: [type, callingconv, isproto, linkage, paramattr,
@ -2214,7 +2238,8 @@ std::error_code BitcodeReader::ParseModule(bool Resume) {
Func->setCallingConv(static_cast<CallingConv::ID>(Record[1])); Func->setCallingConv(static_cast<CallingConv::ID>(Record[1]));
bool isProto = Record[2]; bool isProto = Record[2];
Func->setLinkage(getDecodedLinkage(Record[3])); uint64_t RawLinkage = Record[3];
Func->setLinkage(getDecodedLinkage(RawLinkage));
Func->setAttributes(getAttributes(Record[4])); Func->setAttributes(getAttributes(Record[4]));
Func->setAlignment((1 << Record[5]) >> 1); Func->setAlignment((1 << Record[5]) >> 1);
@ -2242,13 +2267,16 @@ std::error_code BitcodeReader::ParseModule(bool Resume) {
if (Record.size() > 11) if (Record.size() > 11)
Func->setDLLStorageClass(GetDecodedDLLStorageClass(Record[11])); Func->setDLLStorageClass(GetDecodedDLLStorageClass(Record[11]));
else else
UpgradeDLLImportExportLinkage(Func, Record[3]); UpgradeDLLImportExportLinkage(Func, RawLinkage);
if (Record.size() > 12) if (Record.size() > 12) {
if (unsigned ComdatID = Record[12]) { if (unsigned ComdatID = Record[12]) {
assert(ComdatID <= ComdatList.size()); assert(ComdatID <= ComdatList.size());
Func->setComdat(ComdatList[ComdatID - 1]); Func->setComdat(ComdatList[ComdatID - 1]);
} }
} else if (hasImplicitComdat(RawLinkage)) {
Func->setComdat(reinterpret_cast<Comdat *>(1));
}
if (Record.size() > 13 && Record[13] != 0) if (Record.size() > 13 && Record[13] != 0)
FunctionPrefixes.push_back(std::make_pair(Func, Record[13]-1)); FunctionPrefixes.push_back(std::make_pair(Func, Record[13]-1));

View File

@ -480,13 +480,13 @@ static unsigned getEncodedLinkage(const GlobalValue &GV) {
case GlobalValue::ExternalLinkage: case GlobalValue::ExternalLinkage:
return 0; return 0;
case GlobalValue::WeakAnyLinkage: case GlobalValue::WeakAnyLinkage:
return 1; return 16;
case GlobalValue::AppendingLinkage: case GlobalValue::AppendingLinkage:
return 2; return 2;
case GlobalValue::InternalLinkage: case GlobalValue::InternalLinkage:
return 3; return 3;
case GlobalValue::LinkOnceAnyLinkage: case GlobalValue::LinkOnceAnyLinkage:
return 4; return 18;
case GlobalValue::ExternalWeakLinkage: case GlobalValue::ExternalWeakLinkage:
return 7; return 7;
case GlobalValue::CommonLinkage: case GlobalValue::CommonLinkage:
@ -494,9 +494,9 @@ static unsigned getEncodedLinkage(const GlobalValue &GV) {
case GlobalValue::PrivateLinkage: case GlobalValue::PrivateLinkage:
return 9; return 9;
case GlobalValue::WeakODRLinkage: case GlobalValue::WeakODRLinkage:
return 10; return 17;
case GlobalValue::LinkOnceODRLinkage: case GlobalValue::LinkOnceODRLinkage:
return 11; return 19;
case GlobalValue::AvailableExternallyLinkage: case GlobalValue::AvailableExternallyLinkage:
return 12; return 12;
} }
@ -629,7 +629,7 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE,
Log2_32_Ceil(MaxGlobalType+1))); Log2_32_Ceil(MaxGlobalType+1)));
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Constant. Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Constant.
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Initializer. 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. if (MaxAlignment == 0) // Alignment.
Abbv->Add(BitCodeAbbrevOp(0)); Abbv->Add(BitCodeAbbrevOp(0));
else { else {

View File

@ -257,8 +257,7 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
// If this global is linkonce/weak and the target handles this by emitting it // 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. // into a 'uniqued' section name, create and return the section now.
if ((GV->isWeakForLinker() || EmitUniquedSection || GV->hasComdat()) && if ((EmitUniquedSection && !Kind.isCommon()) || GV->hasComdat()) {
!Kind.isCommon()) {
StringRef Prefix = getSectionPrefixForGlobal(Kind); StringRef Prefix = getSectionPrefixForGlobal(Kind);
SmallString<128> Name(Prefix); SmallString<128> Name(Prefix);
@ -266,12 +265,9 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
StringRef Group = ""; StringRef Group = "";
unsigned Flags = getELFSectionFlags(Kind); unsigned Flags = getELFSectionFlags(Kind);
if (GV->isWeakForLinker() || GV->hasComdat()) { if (const Comdat *C = getELFComdat(GV)) {
if (const Comdat *C = getELFComdat(GV))
Group = C->getName();
else
Group = Name.substr(Prefix.size());
Flags |= ELF::SHF_GROUP; Flags |= ELF::SHF_GROUP;
Group = C->getName();
} }
return getContext().getELFSection(Name.str(), return getContext().getELFSection(Name.str(),
@ -801,7 +797,7 @@ const MCSection *TargetLoweringObjectFileCOFF::getExplicitSectionGlobal(
unsigned Characteristics = getCOFFSectionFlags(Kind); unsigned Characteristics = getCOFFSectionFlags(Kind);
StringRef Name = GV->getSection(); StringRef Name = GV->getSection();
StringRef COMDATSymName = ""; StringRef COMDATSymName = "";
if ((GV->isWeakForLinker() || GV->hasComdat()) && !Kind.isCommon()) { if (GV->hasComdat()) {
Selection = getSelectionForCOFF(GV); Selection = getSelectionForCOFF(GV);
const GlobalValue *ComdatGV; const GlobalValue *ComdatGV;
if (Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) if (Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE)
@ -848,12 +844,7 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
else else
EmitUniquedSection = TM.getDataSections(); EmitUniquedSection = TM.getDataSections();
// If this global is linkonce/weak and the target handles this by emitting it if ((EmitUniquedSection && !Kind.isCommon()) || GV->hasComdat()) {
// 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()) {
const char *Name = getCOFFSectionNameForUniqueGlobal(Kind); const char *Name = getCOFFSectionNameForUniqueGlobal(Kind);
unsigned Characteristics = getCOFFSectionFlags(Kind); unsigned Characteristics = getCOFFSectionFlags(Kind);

View File

@ -106,7 +106,6 @@ void XCoreAsmPrinter::emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV) {
OutContext)); OutContext));
if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() || if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() ||
GV->hasCommonLinkage()) { GV->hasCommonLinkage()) {
// TODO Use COMDAT groups for LinkOnceLinkage
OutStreamer.EmitSymbolAttribute(SymGlob, MCSA_Weak); OutStreamer.EmitSymbolAttribute(SymGlob, MCSA_Weak);
} }
} }
@ -141,7 +140,6 @@ void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
emitArrayBound(GVSym, GV); emitArrayBound(GVSym, GV);
OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global);
// TODO Use COMDAT groups for LinkOnceLinkage
if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() || if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() ||
GV->hasCommonLinkage()) GV->hasCommonLinkage())
OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak); OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak);

View File

@ -33,13 +33,13 @@
; CHECK: @available_externally.var = available_externally constant i32 0{{$}} ; CHECK: @available_externally.var = available_externally constant i32 0{{$}}
@linkonce.var = linkonce 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 @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 @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 @linkonce_odr_auto_hide.var = linkonce_odr_auto_hide constant i32 0
; CHECK: @linkonce_odr_auto_hide.var = 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() define linkonce void @linkonce()
; CHECK: define linkonce void @linkonce() { ; CHECK: define linkonce void @linkonce() comdat {
{ {
ret void ret void
} }
define weak void @weak() define weak void @weak()
; CHECK: define weak void @weak() { ; CHECK: define weak void @weak() comdat {
{ {
ret void ret void
} }
define linkonce_odr void @linkonce_odr() define linkonce_odr void @linkonce_odr()
; CHECK: define linkonce_odr void @linkonce_odr() { ; CHECK: define linkonce_odr void @linkonce_odr() comdat {
{ {
ret void ret void
} }

View File

@ -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

View File

@ -16,7 +16,7 @@ entry:
ret void ret void
} }
; CHECK: .section .text.test3,"axG",%progbits,test3,comdat ; CHECK: .text
; CHECK: .weak test3 ; CHECK: .weak test3
; CHECK: .type test3,%function ; CHECK: .type test3,%function
define linkonce_odr void @test3() { define linkonce_odr void @test3() {

View File

@ -17,19 +17,16 @@ define dllexport void @f2() unnamed_addr {
ret void ret void
} }
; CHECK: .section .text,"xr",discard,lnk1
; CHECK: .globl lnk1 ; CHECK: .globl lnk1
define linkonce_odr dllexport void @lnk1() { define linkonce_odr dllexport void @lnk1() {
ret void ret void
} }
; CHECK: .section .text,"xr",discard,lnk2
; CHECK: .globl lnk2 ; CHECK: .globl lnk2
define linkonce_odr dllexport void @lnk2() alwaysinline { define linkonce_odr dllexport void @lnk2() alwaysinline {
ret void ret void
} }
; CHECK: .section .text,"xr",discard,weak1
; CHECK: .globl weak1 ; CHECK: .globl weak1
define weak_odr dllexport void @weak1() { define weak_odr dllexport void @weak1() {
ret void ret void
@ -47,11 +44,9 @@ define weak_odr dllexport void @weak1() {
; CHECK: .comm Var3 ; CHECK: .comm Var3
@Var3 = common dllexport global i32 0, align 4 @Var3 = common dllexport global i32 0, align 4
; CHECK: .section .data,"wd",discard,WeakVar1
; CHECK: .globl WeakVar1 ; CHECK: .globl WeakVar1
@WeakVar1 = weak_odr dllexport global i32 1, align 4 @WeakVar1 = weak_odr dllexport global i32 1, align 4
; CHECK: .section .rdata,"rd",discard,WeakVar2
; CHECK: .globl WeakVar2 ; CHECK: .globl WeakVar2
@WeakVar2 = weak_odr dllexport unnamed_addr constant i32 1 @WeakVar2 = weak_odr dllexport unnamed_addr constant i32 1

View File

@ -36,19 +36,16 @@ define dllexport x86_thiscallcc void @thisfun() nounwind {
ret void ret void
} }
; CHECK: .section .text,"xr",discard,_lnk1
; CHECK: .globl _lnk1 ; CHECK: .globl _lnk1
define linkonce_odr dllexport void @lnk1() { define linkonce_odr dllexport void @lnk1() {
ret void ret void
} }
; CHECK: .section .text,"xr",discard,_lnk2
; CHECK: .globl _lnk2 ; CHECK: .globl _lnk2
define linkonce_odr dllexport void @lnk2() alwaysinline { define linkonce_odr dllexport void @lnk2() alwaysinline {
ret void ret void
} }
; CHECK: .section .text,"xr",discard,_weak1
; CHECK: .globl _weak1 ; CHECK: .globl _weak1
define weak_odr dllexport void @weak1() { define weak_odr dllexport void @weak1() {
ret void ret void
@ -66,11 +63,9 @@ define weak_odr dllexport void @weak1() {
; CHECK: .comm _Var3 ; CHECK: .comm _Var3
@Var3 = common dllexport global i32 0, align 4 @Var3 = common dllexport global i32 0, align 4
; CHECK: .section .data,"wd",discard,_WeakVar1
; CHECK: .globl _WeakVar1 ; CHECK: .globl _WeakVar1
@WeakVar1 = weak_odr dllexport global i32 1, align 4 @WeakVar1 = weak_odr dllexport global i32 1, align 4
; CHECK: .section .rdata,"rd",discard,_WeakVar2
; CHECK: .globl _WeakVar2 ; CHECK: .globl _WeakVar2
@WeakVar2 = weak_odr dllexport unnamed_addr constant i32 1 @WeakVar2 = weak_odr dllexport unnamed_addr constant i32 1

View File

@ -85,7 +85,6 @@ define void @F1() {
@"foo bar" = linkonce global i32 42 @"foo bar" = linkonce global i32 42
; LINUX: .type "foo bar",@object ; LINUX: .type "foo bar",@object
; LINUX: .section ".data.foo bar","aGw",@progbits,"foo bar",comdat
; LINUX: .weak "foo bar" ; LINUX: .weak "foo bar"
; LINUX: "foo bar": ; LINUX: "foo bar":
@ -98,7 +97,6 @@ define void @F1() {
@G6 = weak_odr unnamed_addr constant [1 x i8] c"\01" @G6 = weak_odr unnamed_addr constant [1 x i8] c"\01"
; LINUX: .type G6,@object ; LINUX: .type G6,@object
; LINUX: .section .rodata.G6,"aG",@progbits,G6,comdat
; LINUX: .weak G6 ; LINUX: .weak G6
; LINUX: G6: ; LINUX: G6:
; LINUX: .byte 1 ; LINUX: .byte 1

View File

@ -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

View File

@ -10,7 +10,7 @@
declare void @_Z3bari(i32) declare void @_Z3bari(i32)
; CHECK-LINUX: .text._Z3fooILi1EEvi,"axG",@progbits,_Z3fooILi1EEvi,comdat ; CHECK-LINUX: _Z3fooILi1EEvi:
define linkonce void @_Z3fooILi1EEvi(i32 %Y) nounwind { define linkonce void @_Z3fooILi1EEvi(i32 %Y) nounwind {
entry: entry:
; CHECK: L0$pb ; CHECK: L0$pb

View File

@ -5,5 +5,6 @@
@"\01?thingy@@3Ufoo@@B" = global %struct.foo zeroinitializer, align 4 @"\01?thingy@@3Ufoo@@B" = global %struct.foo zeroinitializer, align 4
; CHECK: .bss ; 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 ; CHECK: .section .bss,"wb",discard,_thingy_linkonce

View File

@ -8,4 +8,4 @@ define void @f() {
; CHECK: .section .CRT$XLB,"rd" ; CHECK: .section .CRT$XLB,"rd"
@weak_array = weak_odr unnamed_addr constant [1 x i8*] [i8* bitcast (void ()* @f to i8*)] @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"

View File

@ -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