Correctly handle llvm.global_ctors merging.
authorRafael Espindola <rafael.espindola@gmail.com>
Sun, 29 Nov 2015 03:29:42 +0000 (03:29 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Sun, 29 Nov 2015 03:29:42 +0000 (03:29 +0000)
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

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

index 4b1b9d2..58d2b84 100644 (file)
@@ -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<ArrayType>(DstGV->getType()->getElementType());
   ArrayType *SrcTy =
-    cast<ArrayType>(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<ArrayType>(TypeMap.get(SrcGV->getType()->getElementType()));
+  Type *EltTy = SrcTy->getElementType();
+
+  uint64_t NewSize = SrcTy->getNumElements();
+  if (DstGV) {
+    ArrayType *DstTy = cast<ArrayType>(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<GlobalVariable>(DGV),
+  if (SGV->hasAppendingLinkage())
+    return linkAppendingVarProto(cast_or_null<GlobalVariable>(DGV),
                                  cast<GlobalVariable>(SGV));
 
   bool LinkFromSrc = true;
@@ -1496,7 +1501,8 @@ static void getArrayElements(const Constant *C,
 void ModuleLinker::linkAppendingVarInit(AppendingVarInfo &AVI) {
   // Merge the initializer.
   SmallVector<Constant *, 16> DstElements;
-  getArrayElements(AVI.DstInit, DstElements);
+  if (AVI.DstInit)
+    getArrayElements(AVI.DstInit, DstElements);
 
   SmallVector<Constant *, 16> SrcElements;
   getArrayElements(AVI.SrcInit, SrcElements);
diff --git a/test/Linker/Inputs/ctors2.ll b/test/Linker/Inputs/ctors2.ll
new file mode 100644 (file)
index 0000000..e2fe5ff
--- /dev/null
@@ -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 (file)
index 0000000..9b7a70e
--- /dev/null
@@ -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