OSDN Git Service

Preserve extern_weak linkage in CloneModule.
authorEvgeniy Stepanov <eugeni.stepanov@gmail.com>
Thu, 31 Mar 2016 20:21:31 +0000 (20:21 +0000)
committerEvgeniy Stepanov <eugeni.stepanov@gmail.com>
Thu, 31 Mar 2016 20:21:31 +0000 (20:21 +0000)
Only force "extern" linkage if the function used to be a definition
in the source module. Declarations keep their original linkage.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@265043 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Utils/CloneModule.cpp
test/tools/llvm-split/extern_linkage.ll [new file with mode: 0644]

index 929f51b..6fb86da 100644 (file)
@@ -109,6 +109,9 @@ std::unique_ptr<Module> llvm::CloneModule(
   //
   for (Module::const_global_iterator I = M->global_begin(), E = M->global_end();
        I != E; ++I) {
+    if (I->isDeclaration())
+      continue;
+
     GlobalVariable *GV = cast<GlobalVariable>(VMap[&*I]);
     if (!ShouldCloneDefinition(&*I)) {
       // Skip after setting the correct linkage for an external reference.
@@ -122,6 +125,9 @@ std::unique_ptr<Module> llvm::CloneModule(
   // Similarly, copy over function bodies now...
   //
   for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) {
+    if (I->isDeclaration())
+      continue;
+
     Function *F = cast<Function>(VMap[&*I]);
     if (!ShouldCloneDefinition(&*I)) {
       // Skip after setting the correct linkage for an external reference.
@@ -130,18 +136,17 @@ std::unique_ptr<Module> llvm::CloneModule(
       F->setPersonalityFn(nullptr);
       continue;
     }
-    if (!I->isDeclaration()) {
-      Function::arg_iterator DestI = F->arg_begin();
-      for (Function::const_arg_iterator J = I->arg_begin(); J != I->arg_end();
-           ++J) {
-        DestI->setName(J->getName());
-        VMap[&*J] = &*DestI++;
-      }
-
-      SmallVector<ReturnInst*, 8> Returns;  // Ignore returns cloned.
-      CloneFunctionInto(F, &*I, VMap, /*ModuleLevelChanges=*/true, Returns);
+
+    Function::arg_iterator DestI = F->arg_begin();
+    for (Function::const_arg_iterator J = I->arg_begin(); J != I->arg_end();
+         ++J) {
+      DestI->setName(J->getName());
+      VMap[&*J] = &*DestI++;
     }
 
+    SmallVector<ReturnInst *, 8> Returns; // Ignore returns cloned.
+    CloneFunctionInto(F, &*I, VMap, /*ModuleLevelChanges=*/true, Returns);
+
     if (I->hasPersonalityFn())
       F->setPersonalityFn(MapValue(I->getPersonalityFn(), VMap));
   }
diff --git a/test/tools/llvm-split/extern_linkage.ll b/test/tools/llvm-split/extern_linkage.ll
new file mode 100644 (file)
index 0000000..d8dde79
--- /dev/null
@@ -0,0 +1,12 @@
+; Test that extern_weak linkage is preserved.
+; RUN: llvm-split -o %t %s
+; RUN: llvm-dis -o - %t0 | FileCheck %s
+; RUN: llvm-dis -o - %t1 | FileCheck %s
+
+; Both declarations are extern_weak in all partitions.
+
+; CHECK: @x = extern_weak global i32, align 4
+@x = extern_weak global i32, align 4
+
+; CHECK: declare extern_weak void @f(...)
+declare extern_weak void @f(...)