[llvm] r254241 - Correctly handle llvm.global_ctors merging.

Rafael Espindola via llvm-commits llvm-commits at lists.llvm.org
Sat Nov 28 19:29:42 PST 2015


Author: rafael
Date: Sat Nov 28 21:29:42 2015
New Revision: 254241

URL: http://llvm.org/viewvc/llvm-project?rev=254241&view=rev
Log:
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.

Added:
    llvm/trunk/test/Linker/Inputs/ctors2.ll
    llvm/trunk/test/Linker/ctors2.ll
Modified:
    llvm/trunk/lib/Linker/LinkModules.cpp

Modified: llvm/trunk/lib/Linker/LinkModules.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Linker/LinkModules.cpp?rev=254241&r1=254240&r2=254241&view=diff
==============================================================================
--- llvm/trunk/lib/Linker/LinkModules.cpp (original)
+++ llvm/trunk/lib/Linker/LinkModules.cpp Sat Nov 28 21:29:42 2015
@@ -1314,54 +1314,57 @@ void ModuleLinker::upgradeMismatchedGlob
 /// 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();
+      cast<ArrayType>(TypeMap.get(SrcGV->getType()->getElementType()));
+  Type *EltTy = SrcTy->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!");
+  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(
+    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
   // 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(
     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 Const
 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);

Added: llvm/trunk/test/Linker/Inputs/ctors2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/Inputs/ctors2.ll?rev=254241&view=auto
==============================================================================
--- llvm/trunk/test/Linker/Inputs/ctors2.ll (added)
+++ llvm/trunk/test/Linker/Inputs/ctors2.ll Sat Nov 28 21:29:42 2015
@@ -0,0 +1,6 @@
+$foo = comdat any
+ at foo = global i8 1, comdat
+ at 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
+}

Added: llvm/trunk/test/Linker/ctors2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/ctors2.ll?rev=254241&view=auto
==============================================================================
--- llvm/trunk/test/Linker/ctors2.ll (added)
+++ llvm/trunk/test/Linker/ctors2.ll Sat Nov 28 21:29:42 2015
@@ -0,0 +1,7 @@
+; RUN: llvm-link -S %s %p/Inputs/ctors2.ll -o - | FileCheck %s
+
+$foo = comdat any
+ at foo = global i8 0, comdat
+
+; CHECK: @foo = global i8 0, comdat
+; CHECK: @llvm.global_ctors = appending global [0 x { i32, void ()*, i8* }] zeroinitializer




More information about the llvm-commits mailing list