From: Rafael Espindola Date: Fri, 5 Sep 2014 21:27:52 +0000 (+0000) Subject: Fix pr20078. X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=e8b19acded1d944918a35c6196d8336916dde735 Fix pr20078. When linking llvm.global_ctors with the optional third element we have to handle it specially and only copy the elements whose keys were also copied. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@217281 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp index 5c26b2610b1..98114ca2e2f 100644 --- a/lib/Linker/LinkModules.cpp +++ b/lib/Linker/LinkModules.cpp @@ -1223,14 +1223,34 @@ static void getArrayElements(Constant *C, SmallVectorImpl &Dest) { void ModuleLinker::linkAppendingVarInit(const AppendingVarInfo &AVI) { // Merge the initializer. - SmallVector Elements; - getArrayElements(AVI.DstInit, Elements); + SmallVector DstElements; + getArrayElements(AVI.DstInit, DstElements); - Constant *SrcInit = MapValue(AVI.SrcInit, ValueMap, RF_None, &TypeMap, &ValMaterializer); - getArrayElements(SrcInit, Elements); + SmallVector SrcElements; + getArrayElements(AVI.SrcInit, SrcElements); ArrayType *NewType = cast(AVI.NewGV->getType()->getElementType()); - AVI.NewGV->setInitializer(ConstantArray::get(NewType, Elements)); + + StringRef Name = AVI.NewGV->getName(); + bool IsNewStructor = + (Name == "llvm.global_ctors" || Name == "llvm.global_dtors") && + cast(NewType->getElementType())->getNumElements() == 3; + + for (auto *V : SrcElements) { + if (IsNewStructor) { + Constant *Key = V->getAggregateElement(2); + if (DoNotLinkFromSource.count(Key)) + continue; + } + DstElements.push_back( + MapValue(V, ValueMap, RF_None, &TypeMap, &ValMaterializer)); + } + if (IsNewStructor) { + NewType = ArrayType::get(NewType->getElementType(), DstElements.size()); + AVI.NewGV->mutateType(PointerType::get(NewType, 0)); + } + + AVI.NewGV->setInitializer(ConstantArray::get(NewType, DstElements)); } /// linkGlobalInits - Update the initializers in the Dest module now that all diff --git a/test/Linker/Inputs/ctors.ll b/test/Linker/Inputs/ctors.ll new file mode 100644 index 00000000000..f3307bc554e --- /dev/null +++ b/test/Linker/Inputs/ctors.ll @@ -0,0 +1,6 @@ +@v = weak global i8 1 +@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @f, i8* @v}] + +define weak void @f() { + ret void +} diff --git a/test/Linker/ctors.ll b/test/Linker/ctors.ll new file mode 100644 index 00000000000..67bf4563718 --- /dev/null +++ b/test/Linker/ctors.ll @@ -0,0 +1,15 @@ +; RUN: llvm-link %s %p/Inputs/ctors.ll -S -o - | \ +; RUN: FileCheck --check-prefix=ALL --check-prefix=CHECK1 %s +; RUN: llvm-link %p/Inputs/ctors.ll %s -S -o - | \ +; RUN: FileCheck --check-prefix=ALL --check-prefix=CHECK2 %s + +@v = weak global i8 0 +; CHECK1: @v = weak global i8 0 +; CHECK2: @v = weak global i8 1 + +@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @f, i8* @v }] +; ALL: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @f, i8* @v }] + +define weak void @f() { + ret void +}