Disallow aliases to available_externally.
authorRafael Espindola <rafael.espindola@gmail.com>
Thu, 26 Nov 2015 19:22:59 +0000 (19:22 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Thu, 26 Nov 2015 19:22:59 +0000 (19:22 +0000)
They are as much trouble as aliases to declarations. They are requiring
the code generator to define a symbol with the same value as another
symbol, but the second symbol is undefined.

If representing this is important for some optimization, we could add
support for available_externally aliases. They would be *required* to
point to a declaration (or available_externally definition).

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

lib/IR/Verifier.cpp
lib/Linker/LinkModules.cpp
lib/Transforms/IPO/ElimAvailExtern.cpp
test/Linker/funcimport.ll
test/Transforms/FunctionImport/funcimport.ll
test/Verifier/alias.ll

index cf7b4cac34243b379e04a8f95015fc5c24c6994e..617d965f4cfcad30f3db4c41e86db6e707a828cc 100644 (file)
@@ -571,7 +571,8 @@ void Verifier::visitAliaseeSubExpr(const GlobalAlias &GA, const Constant &C) {
 void Verifier::visitAliaseeSubExpr(SmallPtrSetImpl<const GlobalAlias*> &Visited,
                                    const GlobalAlias &GA, const Constant &C) {
   if (const auto *GV = dyn_cast<GlobalValue>(&C)) {
 void Verifier::visitAliaseeSubExpr(SmallPtrSetImpl<const GlobalAlias*> &Visited,
                                    const GlobalAlias &GA, const Constant &C) {
   if (const auto *GV = dyn_cast<GlobalValue>(&C)) {
-    Assert(!GV->isDeclaration(), "Alias must point to a definition", &GA);
+    Assert(!GV->isDeclarationForLinker(), "Alias must point to a definition",
+           &GA);
 
     if (const auto *GA2 = dyn_cast<GlobalAlias>(GV)) {
       Assert(Visited.insert(GA2).second, "Aliases cannot form a cycle", &GA);
 
     if (const auto *GA2 = dyn_cast<GlobalAlias>(GV)) {
       Assert(Visited.insert(GA2).second, "Aliases cannot form a cycle", &GA);
index 8970fe4461386106701f3cc89c1c84a3f3425ea2..bd445dd367f4848bd75d08e21e6e5f1fbcbc58f7 100644 (file)
@@ -655,7 +655,10 @@ bool ModuleLinker::doImportAsDefinition(const GlobalValue *SGV) {
   if (GA) {
     if (GA->hasWeakAnyLinkage())
       return false;
   if (GA) {
     if (GA->hasWeakAnyLinkage())
       return false;
-    return doImportAsDefinition(GA->getBaseObject());
+    const GlobalObject *GO = GA->getBaseObject();
+    if (!GO->hasLinkOnceODRLinkage())
+      return false;
+    return doImportAsDefinition(GO);
   }
   // Always import GlobalVariable definitions, except for the special
   // case of WeakAny which are imported as ExternalWeak declarations
   }
   // Always import GlobalVariable definitions, except for the special
   // case of WeakAny which are imported as ExternalWeak declarations
index 0e138cbbc7a10bdf28eb065e8aabbb26ed46b5d4..af313a6b001d751405f0e727ff2db65816ad382f 100644 (file)
@@ -49,46 +49,9 @@ ModulePass *llvm::createEliminateAvailableExternallyPass() {
   return new EliminateAvailableExternally();
 }
 
   return new EliminateAvailableExternally();
 }
 
-static void convertAliasToDeclaration(GlobalAlias &GA, Module &M) {
-  GlobalValue *GVal = GA.getBaseObject();
-  GlobalValue *NewGV;
-  if (auto *GVar = dyn_cast<GlobalVariable>(GVal)) {
-    GlobalVariable *NewGVar = new GlobalVariable(
-        M, GVar->getType()->getElementType(), GVar->isConstant(),
-        GVar->getLinkage(), /*init*/ nullptr, GA.getName(), GVar,
-        GVar->getThreadLocalMode(), GVar->getType()->getAddressSpace());
-    NewGV = NewGVar;
-    NewGV->copyAttributesFrom(GVar);
-  } else {
-    auto *F = dyn_cast<Function>(GVal);
-    assert(F);
-    Function *NewF = Function::Create(F->getFunctionType(), F->getLinkage(),
-                                      GA.getName(), &M);
-    NewGV = NewF;
-    NewGV->copyAttributesFrom(F);
-  }
-  GA.replaceAllUsesWith(ConstantExpr::getBitCast(NewGV, GA.getType()));
-  GA.eraseFromParent();
-}
-
 bool EliminateAvailableExternally::runOnModule(Module &M) {
   bool Changed = false;
 
 bool EliminateAvailableExternally::runOnModule(Module &M) {
   bool Changed = false;
 
-  // Convert any aliases that alias with an available externally
-  // value (which will be turned into declarations later on in this routine)
-  // into declarations themselves. All aliases must be definitions, and
-  // must alias with a definition. So this involves creating a declaration
-  // equivalent to the alias's base object.
-  for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E;) {
-    // Increment the iterator first since we may delete the current alias.
-    GlobalAlias &GA = *(I++);
-    GlobalValue *GVal = GA.getBaseObject();
-    if (!GVal->hasAvailableExternallyLinkage())
-      continue;
-    convertAliasToDeclaration(GA, M);
-    Changed = true;
-  }
-
   // Drop initializers of available externally global variables.
   for (GlobalVariable &GV : M.globals()) {
     if (!GV.hasAvailableExternallyLinkage())
   // Drop initializers of available externally global variables.
   for (GlobalVariable &GV : M.globals()) {
     if (!GV.hasAvailableExternallyLinkage())
index d6aa0502f260f1849069508d17c19c18e7c5b323..8a71e21d0ad13024509943ca23b467accb077c25 100644 (file)
@@ -36,7 +36,7 @@
 ; turned into a declaration, but that strong alias to an imported function
 ; is imported as alias.
 ; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=globalfunc2:%t.bc -S | FileCheck %s --check-prefix=IMPORTGLOB2
 ; turned into a declaration, but that strong alias to an imported function
 ; is imported as alias.
 ; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=globalfunc2:%t.bc -S | FileCheck %s --check-prefix=IMPORTGLOB2
-; IMPORTGLOB2-DAG: @analias = alias void (...), bitcast (void ()* @globalfunc2
+; IMPORTGLOB2-DAG: declare void @analias()
 ; IMPORTGLOB2-DAG: declare void @globalfunc1
 ; IMPORTGLOB2-DAG: define available_externally void @globalfunc2
 ; IMPORTGLOB2-DAG: declare extern_weak void @weakalias
 ; IMPORTGLOB2-DAG: declare void @globalfunc1
 ; IMPORTGLOB2-DAG: define available_externally void @globalfunc2
 ; IMPORTGLOB2-DAG: declare extern_weak void @weakalias
@@ -44,7 +44,7 @@
 ; Ensure that strong alias imported in second pass of importing ends up
 ; as an alias.
 ; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=globalfunc1:%t.bc -import=globalfunc2:%t.bc -S | FileCheck %s --check-prefix=IMPORTGLOB3
 ; Ensure that strong alias imported in second pass of importing ends up
 ; as an alias.
 ; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=globalfunc1:%t.bc -import=globalfunc2:%t.bc -S | FileCheck %s --check-prefix=IMPORTGLOB3
-; IMPORTGLOB3-DAG: @analias = alias void (...), bitcast (void ()* @globalfunc2
+; IMPORTGLOB3-DAG: declare void @analias()
 ; IMPORTGLOB3-DAG: define available_externally void @globalfunc1
 ; IMPORTGLOB3-DAG: define available_externally void @globalfunc2
 ; IMPORTGLOB3-DAG: declare extern_weak void @weakalias
 ; IMPORTGLOB3-DAG: define available_externally void @globalfunc1
 ; IMPORTGLOB3-DAG: define available_externally void @globalfunc2
 ; IMPORTGLOB3-DAG: declare extern_weak void @weakalias
 ; as an alias, and that seeing the alias definition during a second inlining
 ; pass is handled correctly.
 ; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=globalfunc2:%t.bc -import=globalfunc1:%t.bc -S | FileCheck %s --check-prefix=IMPORTGLOB4
 ; as an alias, and that seeing the alias definition during a second inlining
 ; pass is handled correctly.
 ; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=globalfunc2:%t.bc -import=globalfunc1:%t.bc -S | FileCheck %s --check-prefix=IMPORTGLOB4
-; IMPORTGLOB4-DAG: @analias = alias void (...), bitcast (void ()* @globalfunc2
+; IMPORTGLOB4-DAG: declare void @analias()
 ; IMPORTGLOB4-DAG: define available_externally void @globalfunc2
 ; IMPORTGLOB4-DAG: define available_externally void @globalfunc1
 ; IMPORTGLOB4-DAG: declare extern_weak void @weakalias
 
 ; IMPORTGLOB4-DAG: define available_externally void @globalfunc2
 ; IMPORTGLOB4-DAG: define available_externally void @globalfunc1
 ; IMPORTGLOB4-DAG: declare extern_weak void @weakalias
 
+; An alias to an imported function is imported as alias if the function is not
+; available_externally.
+; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=linkoncefunc:%t.bc -S | FileCheck %s --check-prefix=IMPORTGLOB5
+; IMPORTGLOB5-DAG: linkoncealias = alias void (...), bitcast (void ()* @linkoncefunc to void (...)*)
+; IMPORTGLOB5-DAG: define linkonce_odr void @linkoncefunc()
+
 ; Ensure that imported static variable and function references are correctly
 ; promoted and renamed (including static constant variable).
 ; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=referencestatics:%t.bc -S | FileCheck %s --check-prefix=IMPORTSTATIC
 ; Ensure that imported static variable and function references are correctly
 ; promoted and renamed (including static constant variable).
 ; RUN: llvm-link %t2.bc -functionindex=%t3.thinlto.bc -import=referencestatics:%t.bc -S | FileCheck %s --check-prefix=IMPORTSTATIC
index 57452b1ec53a6a01ee38b8ef1fa1e4cbf9b4e7fe..2c9164fdaa98b877292f14875f23bf173893b6ca 100644 (file)
@@ -14,6 +14,7 @@ define i32 @main() #0 {
 entry:
   call void (...) @weakalias()
   call void (...) @analias()
 entry:
   call void (...) @weakalias()
   call void (...) @analias()
+  call void (...) @linkoncealias()
   %call = call i32 (...) @referencestatics()
   %call1 = call i32 (...) @referenceglobals()
   %call2 = call i32 (...) @referencecommon()
   %call = call i32 (...) @referencestatics()
   %call1 = call i32 (...) @referenceglobals()
   %call2 = call i32 (...) @referencecommon()
@@ -27,11 +28,15 @@ entry:
 ; CHECK-DAG: declare extern_weak void @weakalias()
 declare void @weakalias(...) #1
 
 ; CHECK-DAG: declare extern_weak void @weakalias()
 declare void @weakalias(...) #1
 
-; Aliases import the aliasee function
-; CHECK-DAG: @analias = alias void (...), bitcast (void ()* @globalfunc2 to void (...)*)
-; CHECK-DAG: define available_externally void @globalfunc2()
+; Cannot create an alias to available_externally
+; CHECK-DAG: declare void @analias()
 declare void @analias(...) #1
 
 declare void @analias(...) #1
 
+; Aliases import the aliasee function
+declare void @linkoncealias(...) #1
+; CHECK-DAG: define linkonce_odr void @linkoncefunc()
+; CHECK-DAG: @linkoncealias = alias void (...), bitcast (void ()* @linkoncefunc to void (...)*
+
 ; INSTLIMDEF-DAG: define available_externally i32 @referencestatics(i32 %i)
 ; INSTLIM5-DAG: declare i32 @referencestatics(...)
 declare i32 @referencestatics(...) #1
 ; INSTLIMDEF-DAG: define available_externally i32 @referencestatics(i32 %i)
 ; INSTLIM5-DAG: declare i32 @referencestatics(...)
 declare i32 @referencestatics(...) #1
index 3fb140464ec439a33ec6187daded736ee498d665..1847c0d4214edaae7ffa367b5067e062518d6776 100644 (file)
@@ -11,6 +11,12 @@ declare void @f()
 ; CHECK: Alias must point to a definition
 ; CHECK-NEXT: @ga
 
 ; CHECK: Alias must point to a definition
 ; CHECK-NEXT: @ga
 
+define available_externally void @f2() {
+  ret void
+}
+@fa2 = alias void(), void()* @f2
+; CHECK: Alias must point to a definition
+; CHECK-NEXT: @fa2
 
 @test2_a = alias i32, i32* @test2_b
 @test2_b = alias i32, i32* @test2_a
 
 @test2_a = alias i32, i32* @test2_b
 @test2_b = alias i32, i32* @test2_a