From: Rafael Espindola Date: Sun, 29 Nov 2015 03:29:42 +0000 (+0000) Subject: Correctly handle llvm.global_ctors merging. X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=3e3383f5f71a3a28f73601dde8472c0bedae5999 Correctly handle llvm.global_ctors merging. We were not handling the case where an entry must be dropped and the destination module has no llvm.global_ctors. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@254241 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp index 4b1b9d21e42..58d2b84bd73 100644 --- a/lib/Linker/LinkModules.cpp +++ b/lib/Linker/LinkModules.cpp @@ -1314,54 +1314,57 @@ void ModuleLinker::upgradeMismatchedGlobals() { /// Return true on error. bool ModuleLinker::linkAppendingVarProto(GlobalVariable *DstGV, const GlobalVariable *SrcGV) { - - if (!SrcGV->hasAppendingLinkage() || !DstGV->hasAppendingLinkage()) - return emitError("Linking globals named '" + SrcGV->getName() + - "': can only link appending global with another appending global!"); - - ArrayType *DstTy = cast(DstGV->getType()->getElementType()); ArrayType *SrcTy = - cast(TypeMap.get(SrcGV->getType()->getElementType())); - Type *EltTy = DstTy->getElementType(); - - // Check to see that they two arrays agree on type. - if (EltTy != SrcTy->getElementType()) - return emitError("Appending variables with different element types!"); - if (DstGV->isConstant() != SrcGV->isConstant()) - return emitError("Appending variables linked with different const'ness!"); - - if (DstGV->getAlignment() != SrcGV->getAlignment()) - return emitError( - "Appending variables with different alignment need to be linked!"); - - if (DstGV->getVisibility() != SrcGV->getVisibility()) - return emitError( - "Appending variables with different visibility need to be linked!"); - - if (DstGV->hasUnnamedAddr() != SrcGV->hasUnnamedAddr()) - return emitError( - "Appending variables with different unnamed_addr need to be linked!"); - - if (StringRef(DstGV->getSection()) != SrcGV->getSection()) - return emitError( + cast(TypeMap.get(SrcGV->getType()->getElementType())); + Type *EltTy = SrcTy->getElementType(); + + uint64_t NewSize = SrcTy->getNumElements(); + if (DstGV) { + ArrayType *DstTy = cast(DstGV->getType()->getElementType()); + NewSize += DstTy->getNumElements(); + + if (!SrcGV->hasAppendingLinkage() || !DstGV->hasAppendingLinkage()) + return emitError( + "Linking globals named '" + SrcGV->getName() + + "': can only link appending global with another appending global!"); + + // Check to see that they two arrays agree on type. + if (EltTy != DstTy->getElementType()) + return emitError("Appending variables with different element types!"); + if (DstGV->isConstant() != SrcGV->isConstant()) + return emitError("Appending variables linked with different const'ness!"); + + if (DstGV->getAlignment() != SrcGV->getAlignment()) + return emitError( + "Appending variables with different alignment need to be linked!"); + + if (DstGV->getVisibility() != SrcGV->getVisibility()) + return emitError( + "Appending variables with different visibility need to be linked!"); + + if (DstGV->hasUnnamedAddr() != SrcGV->hasUnnamedAddr()) + return emitError( + "Appending variables with different unnamed_addr need to be linked!"); + + if (StringRef(DstGV->getSection()) != SrcGV->getSection()) + return emitError( "Appending variables with different section name need to be linked!"); + } - uint64_t NewSize = DstTy->getNumElements() + SrcTy->getNumElements(); ArrayType *NewType = ArrayType::get(EltTy, NewSize); // Create the new global variable. - GlobalVariable *NG = - new GlobalVariable(*DstGV->getParent(), NewType, SrcGV->isConstant(), - DstGV->getLinkage(), /*init*/nullptr, /*name*/"", DstGV, - DstGV->getThreadLocalMode(), - DstGV->getType()->getAddressSpace()); + GlobalVariable *NG = new GlobalVariable( + *DstM, NewType, SrcGV->isConstant(), SrcGV->getLinkage(), + /*init*/ nullptr, /*name*/ "", DstGV, SrcGV->getThreadLocalMode(), + SrcGV->getType()->getAddressSpace()); // Propagate alignment, visibility and section info. - copyGVAttributes(NG, DstGV); + copyGVAttributes(NG, SrcGV); AppendingVarInfo AVI; AVI.NewGV = NG; - AVI.DstInit = DstGV->getInitializer(); + AVI.DstInit = DstGV ? DstGV->getInitializer() : nullptr; AVI.SrcInit = SrcGV->getInitializer(); AppendingVars.push_back(AVI); @@ -1369,8 +1372,10 @@ bool ModuleLinker::linkAppendingVarProto(GlobalVariable *DstGV, // global. ValueMap[SrcGV] = ConstantExpr::getBitCast(NG, TypeMap.get(SrcGV->getType())); - DstGV->replaceAllUsesWith(ConstantExpr::getBitCast(NG, DstGV->getType())); - DstGV->eraseFromParent(); + if (DstGV) { + DstGV->replaceAllUsesWith(ConstantExpr::getBitCast(NG, DstGV->getType())); + DstGV->eraseFromParent(); + } // Track the source variable so we don't try to link it. DoNotLinkFromSource.insert(SrcGV); @@ -1391,8 +1396,8 @@ bool ModuleLinker::linkGlobalValueProto(GlobalValue *SGV) { DoNotLinkFromSource.insert(SGV); return false; } - if (DGV && DGV->hasAppendingLinkage()) - return linkAppendingVarProto(cast(DGV), + if (SGV->hasAppendingLinkage()) + return linkAppendingVarProto(cast_or_null(DGV), cast(SGV)); bool LinkFromSrc = true; @@ -1496,7 +1501,8 @@ static void getArrayElements(const Constant *C, void ModuleLinker::linkAppendingVarInit(AppendingVarInfo &AVI) { // Merge the initializer. SmallVector DstElements; - getArrayElements(AVI.DstInit, DstElements); + if (AVI.DstInit) + getArrayElements(AVI.DstInit, DstElements); SmallVector SrcElements; getArrayElements(AVI.SrcInit, SrcElements); diff --git a/test/Linker/Inputs/ctors2.ll b/test/Linker/Inputs/ctors2.ll new file mode 100644 index 00000000000..e2fe5ff429c --- /dev/null +++ b/test/Linker/Inputs/ctors2.ll @@ -0,0 +1,6 @@ +$foo = comdat any +@foo = global i8 1, comdat +@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @bar, i8* @foo }] +define void @bar() comdat($foo) { + ret void +} diff --git a/test/Linker/ctors2.ll b/test/Linker/ctors2.ll new file mode 100644 index 00000000000..9b7a70eb7cd --- /dev/null +++ b/test/Linker/ctors2.ll @@ -0,0 +1,7 @@ +; RUN: llvm-link -S %s %p/Inputs/ctors2.ll -o - | FileCheck %s + +$foo = comdat any +@foo = global i8 0, comdat + +; CHECK: @foo = global i8 0, comdat +; CHECK: @llvm.global_ctors = appending global [0 x { i32, void ()*, i8* }] zeroinitializer