OSDN Git Service

Fix pr20078.
authorRafael Espindola <rafael.espindola@gmail.com>
Fri, 5 Sep 2014 21:27:52 +0000 (21:27 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Fri, 5 Sep 2014 21:27:52 +0000 (21:27 +0000)
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

lib/Linker/LinkModules.cpp
test/Linker/Inputs/ctors.ll [new file with mode: 0644]
test/Linker/ctors.ll [new file with mode: 0644]

index 5c26b26..98114ca 100644 (file)
@@ -1223,14 +1223,34 @@ static void getArrayElements(Constant *C, SmallVectorImpl<Constant*> &Dest) {
 
 void ModuleLinker::linkAppendingVarInit(const AppendingVarInfo &AVI) {
   // Merge the initializer.
-  SmallVector<Constant*, 16> Elements;
-  getArrayElements(AVI.DstInit, Elements);
+  SmallVector<Constant *, 16> DstElements;
+  getArrayElements(AVI.DstInit, DstElements);
 
-  Constant *SrcInit = MapValue(AVI.SrcInit, ValueMap, RF_None, &TypeMap, &ValMaterializer);
-  getArrayElements(SrcInit, Elements);
+  SmallVector<Constant *, 16> SrcElements;
+  getArrayElements(AVI.SrcInit, SrcElements);
 
   ArrayType *NewType = cast<ArrayType>(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<StructType>(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 (file)
index 0000000..f3307bc
--- /dev/null
@@ -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 (file)
index 0000000..67bf456
--- /dev/null
@@ -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
+}