mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 02:52:53 +02:00
Disallow aliases to available_externally.
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). llvm-svn: 254170
This commit is contained in:
parent
124c7bacb0
commit
d215bba299
@ -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)) {
|
||||
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);
|
||||
|
@ -655,7 +655,10 @@ bool ModuleLinker::doImportAsDefinition(const GlobalValue *SGV) {
|
||||
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
|
||||
|
@ -49,46 +49,9 @@ ModulePass *llvm::createEliminateAvailableExternallyPass() {
|
||||
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;
|
||||
|
||||
// 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())
|
||||
|
@ -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
|
||||
; 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
|
||||
@ -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
|
||||
; 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
|
||||
@ -53,11 +53,17 @@
|
||||
; 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
|
||||
|
||||
; 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
|
||||
|
@ -14,6 +14,7 @@ define i32 @main() #0 {
|
||||
entry:
|
||||
call void (...) @weakalias()
|
||||
call void (...) @analias()
|
||||
call void (...) @linkoncealias()
|
||||
%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
|
||||
|
||||
; 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
|
||||
|
||||
; 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
|
||||
|
@ -11,6 +11,12 @@ declare void @f()
|
||||
; 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
|
||||
|
Loading…
Reference in New Issue
Block a user