summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/LangRef.rst4
-rw-r--r--include/llvm/IR/GlobalAlias.h16
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAG.cpp2
-rw-r--r--lib/ExecutionEngine/JIT/JITEmitter.cpp2
-rw-r--r--lib/IR/Globals.cpp35
-rw-r--r--lib/IR/Verifier.cpp10
-rw-r--r--lib/Target/PowerPC/PPCAsmPrinter.cpp12
-rw-r--r--lib/Target/PowerPC/PPCFastISel.cpp2
-rw-r--r--lib/Target/PowerPC/PPCISelDAGToDAG.cpp4
-rw-r--r--lib/Target/TargetMachine.cpp2
-rw-r--r--lib/Target/X86/X86FastISel.cpp2
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp2
-rw-r--r--lib/Target/XCore/XCoreISelLowering.cpp2
-rw-r--r--lib/Transforms/Instrumentation/DataFlowSanitizer.cpp3
-rw-r--r--test/CodeGen/X86/dllexport-x86_64.ll2
-rw-r--r--test/CodeGen/X86/dllexport.ll2
-rw-r--r--test/Feature/aliases.ll2
-rw-r--r--test/Transforms/GlobalOpt/alias-resolve.ll15
18 files changed, 61 insertions, 58 deletions
diff --git a/docs/LangRef.rst b/docs/LangRef.rst
index b0b8bfebee..c959f56ef1 100644
--- a/docs/LangRef.rst
+++ b/docs/LangRef.rst
@@ -681,10 +681,6 @@ the aliasee.
The aliasee must be a definition.
-Aliases are not allowed to point to aliases with linkages that can be
-overridden. Since they are only a second name, the possibility of the
-intermediate alias being overridden cannot be represented in an object file.
-
.. _namedmetadatastructure:
Named Metadata
diff --git a/include/llvm/IR/GlobalAlias.h b/include/llvm/IR/GlobalAlias.h
index 2ca481a515..81777af386 100644
--- a/include/llvm/IR/GlobalAlias.h
+++ b/include/llvm/IR/GlobalAlias.h
@@ -64,15 +64,23 @@ public:
Constant *getAliasee() {
return getOperand(0);
}
-
- /// This method tries to ultimately resolve the alias by going through the
- /// aliasing chain and trying to find the very last global. Returns NULL if a
- /// cycle was found.
+ /// getAliasedGlobal() - Aliasee can be either global or bitcast of
+ /// global. This method retrives the global for both aliasee flavours.
GlobalValue *getAliasedGlobal();
const GlobalValue *getAliasedGlobal() const {
return const_cast<GlobalAlias *>(this)->getAliasedGlobal();
}
+ /// resolveAliasedGlobal() - This method tries to ultimately resolve the alias
+ /// by going through the aliasing chain and trying to find the very last
+ /// global. Returns NULL if a cycle was found. If stopOnWeak is false, then
+ /// the whole chain aliasing chain is traversed, otherwise - only strong
+ /// aliases.
+ GlobalValue *resolveAliasedGlobal(bool stopOnWeak = true);
+ const GlobalValue *resolveAliasedGlobal(bool stopOnWeak = true) const {
+ return const_cast<GlobalAlias *>(this)->resolveAliasedGlobal(stopOnWeak);
+ }
+
static bool isValidLinkage(LinkageTypes L) {
return isExternalLinkage(L) || isLocalLinkage(L) ||
isWeakLinkage(L) || isLinkOnceLinkage(L);
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 52806235fd..61961d8ca2 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -1172,7 +1172,7 @@ SDValue SelectionDAG::getGlobalAddress(const GlobalValue *GV, SDLoc DL,
if (!GVar) {
// If GV is an alias then use the aliasee for determining thread-localness.
if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
- GVar = dyn_cast_or_null<GlobalVariable>(GA->getAliasedGlobal());
+ GVar = dyn_cast_or_null<GlobalVariable>(GA->resolveAliasedGlobal(false));
}
unsigned Opc;
diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp
index 9d215ec96a..4b2f012eaf 100644
--- a/lib/ExecutionEngine/JIT/JITEmitter.cpp
+++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp
@@ -688,7 +688,7 @@ void *JITEmitter::getPointerToGlobal(GlobalValue *V, void *Reference,
return TheJIT->getOrEmitGlobalVariable(GV);
if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V))
- return TheJIT->getPointerToGlobal(GA->getAliasedGlobal());
+ return TheJIT->getPointerToGlobal(GA->resolveAliasedGlobal(false));
// If we have already compiled the function, return a pointer to its body.
Function *F = cast<Function>(V);
diff --git a/lib/IR/Globals.cpp b/lib/IR/Globals.cpp
index f338dd76aa..11152d5d6c 100644
--- a/lib/IR/Globals.cpp
+++ b/lib/IR/Globals.cpp
@@ -236,10 +236,10 @@ void GlobalAlias::setAliasee(Constant *Aliasee) {
setOperand(0, Aliasee);
}
-static GlobalValue *getAliaseeGV(GlobalAlias *GA) {
- Constant *C = GA->getAliasee();
- assert(C && "Must alias something");
-
+GlobalValue *GlobalAlias::getAliasedGlobal() {
+ Constant *C = getAliasee();
+ if (C == 0) return 0;
+
if (GlobalValue *GV = dyn_cast<GlobalValue>(C))
return GV;
@@ -248,23 +248,30 @@ static GlobalValue *getAliaseeGV(GlobalAlias *GA) {
CE->getOpcode() == Instruction::AddrSpaceCast ||
CE->getOpcode() == Instruction::GetElementPtr) &&
"Unsupported aliasee");
-
+
return cast<GlobalValue>(CE->getOperand(0));
}
-GlobalValue *GlobalAlias::getAliasedGlobal() {
+GlobalValue *GlobalAlias::resolveAliasedGlobal(bool stopOnWeak) {
SmallPtrSet<GlobalValue*, 3> Visited;
- GlobalAlias *GA = this;
+ // Check if we need to stop early.
+ if (stopOnWeak && mayBeOverridden())
+ return this;
+
+ GlobalValue *GV = getAliasedGlobal();
+ Visited.insert(GV);
+
+ // Iterate over aliasing chain, stopping on weak alias if necessary.
+ while (GlobalAlias *GA = dyn_cast<GlobalAlias>(GV)) {
+ if (stopOnWeak && GA->mayBeOverridden())
+ break;
+
+ GV = GA->getAliasedGlobal();
- for (;;) {
- GlobalValue *GV = getAliaseeGV(GA);
if (!Visited.insert(GV))
return 0;
-
- // Iterate over aliasing chain.
- GA = dyn_cast<GlobalAlias>(GV);
- if (!GA)
- return GV;
}
+
+ return GV;
}
diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp
index f5c8ac623b..50c6ae204e 100644
--- a/lib/IR/Verifier.cpp
+++ b/lib/IR/Verifier.cpp
@@ -502,14 +502,10 @@ void Verifier::visitGlobalAlias(const GlobalAlias &GA) {
}
}
Assert1(!GV->isDeclaration(), "Alias must point to a definition", &GA);
- if (const GlobalAlias *GAAliasee = dyn_cast<GlobalAlias>(GV)) {
- Assert1(!GAAliasee->mayBeOverridden(), "Alias cannot point to a weak alias",
- &GA);
- }
- const GlobalValue *AG = GA.getAliasedGlobal();
- Assert1(AG, "Aliasing chain should end with function or global variable",
- &GA);
+ const GlobalValue* Resolved = GA.resolveAliasedGlobal(/*stopOnWeak*/ false);
+ Assert1(Resolved,
+ "Aliasing chain should end with function or global variable", &GA);
visitGlobalValue(GA);
}
diff --git a/lib/Target/PowerPC/PPCAsmPrinter.cpp b/lib/Target/PowerPC/PPCAsmPrinter.cpp
index 9ce8ea911c..daf90c86ef 100644
--- a/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -381,8 +381,8 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
if (MO.isGlobal()) {
const GlobalValue *GValue = MO.getGlobal();
const GlobalAlias *GAlias = dyn_cast<GlobalAlias>(GValue);
- const GlobalValue *RealGValue =
- GAlias ? GAlias->getAliasedGlobal() : GValue;
+ const GlobalValue *RealGValue = GAlias ?
+ GAlias->resolveAliasedGlobal(false) : GValue;
MOSymbol = getSymbol(RealGValue);
const GlobalVariable *GVar = dyn_cast<GlobalVariable>(RealGValue);
IsExternal = GVar && !GVar->hasInitializer();
@@ -428,8 +428,8 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
else if (MO.isGlobal()) {
const GlobalValue *GValue = MO.getGlobal();
const GlobalAlias *GAlias = dyn_cast<GlobalAlias>(GValue);
- const GlobalValue *RealGValue =
- GAlias ? GAlias->getAliasedGlobal() : GValue;
+ const GlobalValue *RealGValue = GAlias ?
+ GAlias->resolveAliasedGlobal(false) : GValue;
MOSymbol = getSymbol(RealGValue);
const GlobalVariable *GVar = dyn_cast<GlobalVariable>(RealGValue);
@@ -463,8 +463,8 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
if (MO.isGlobal()) {
const GlobalValue *GValue = MO.getGlobal();
const GlobalAlias *GAlias = dyn_cast<GlobalAlias>(GValue);
- const GlobalValue *RealGValue =
- GAlias ? GAlias->getAliasedGlobal() : GValue;
+ const GlobalValue *RealGValue = GAlias ?
+ GAlias->resolveAliasedGlobal(false) : GValue;
MOSymbol = getSymbol(RealGValue);
const GlobalVariable *GVar = dyn_cast<GlobalVariable>(RealGValue);
IsExternal = GVar && !GVar->hasInitializer();
diff --git a/lib/Target/PowerPC/PPCFastISel.cpp b/lib/Target/PowerPC/PPCFastISel.cpp
index dd45683032..4753160e09 100644
--- a/lib/Target/PowerPC/PPCFastISel.cpp
+++ b/lib/Target/PowerPC/PPCFastISel.cpp
@@ -1863,7 +1863,7 @@ unsigned PPCFastISel::PPCMaterializeGV(const GlobalValue *GV, MVT VT) {
if (!GVar) {
// If GV is an alias, use the aliasee for determining thread-locality.
if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
- GVar = dyn_cast_or_null<GlobalVariable>(GA->getAliasedGlobal());
+ GVar = dyn_cast_or_null<GlobalVariable>(GA->resolveAliasedGlobal(false));
}
// FIXME: We don't yet handle the complexity of TLS.
diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
index 0e75bb4575..5b09588e0f 100644
--- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
+++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
@@ -1413,8 +1413,8 @@ SDNode *PPCDAGToDAGISel::Select(SDNode *N) {
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(GA)) {
const GlobalValue *GValue = G->getGlobal();
const GlobalAlias *GAlias = dyn_cast<GlobalAlias>(GValue);
- const GlobalValue *RealGValue =
- GAlias ? GAlias->getAliasedGlobal() : GValue;
+ const GlobalValue *RealGValue = GAlias ?
+ GAlias->resolveAliasedGlobal(false) : GValue;
const GlobalVariable *GVar = dyn_cast<GlobalVariable>(RealGValue);
assert((GVar || isa<Function>(RealGValue)) &&
"Unexpected global value subclass!");
diff --git a/lib/Target/TargetMachine.cpp b/lib/Target/TargetMachine.cpp
index fe3c870c98..f8a58ec292 100644
--- a/lib/Target/TargetMachine.cpp
+++ b/lib/Target/TargetMachine.cpp
@@ -129,7 +129,7 @@ TLSModel::Model TargetMachine::getTLSModel(const GlobalValue *GV) const {
// If GV is an alias then use the aliasee for determining
// thread-localness.
if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
- GV = GA->getAliasedGlobal();
+ GV = GA->resolveAliasedGlobal(false);
const GlobalVariable *Var = cast<GlobalVariable>(GV);
bool isLocal = Var->hasLocalLinkage();
diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp
index 9c57f0d1f1..c3e002082d 100644
--- a/lib/Target/X86/X86FastISel.cpp
+++ b/lib/Target/X86/X86FastISel.cpp
@@ -363,7 +363,7 @@ bool X86FastISel::handleConstantAddresses(const Value *V, X86AddressMode &AM) {
// it works...).
if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
if (const GlobalVariable *GVar =
- dyn_cast_or_null<GlobalVariable>(GA->getAliasedGlobal()))
+ dyn_cast_or_null<GlobalVariable>(GA->resolveAliasedGlobal(false)))
if (GVar->isThreadLocal())
return false;
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp
index 630fba0151..ec923ba7aa 100644
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -8509,7 +8509,7 @@ X86TargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const {
// If GV is an alias then use the aliasee for determining
// thread-localness.
if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
- GV = GA->getAliasedGlobal();
+ GV = GA->resolveAliasedGlobal(false);
SDLoc dl(GA);
SDValue Chain = DAG.getEntryNode();
diff --git a/lib/Target/XCore/XCoreISelLowering.cpp b/lib/Target/XCore/XCoreISelLowering.cpp
index 1b74013ac1..079e886457 100644
--- a/lib/Target/XCore/XCoreISelLowering.cpp
+++ b/lib/Target/XCore/XCoreISelLowering.cpp
@@ -277,7 +277,7 @@ getGlobalAddressWrapper(SDValue GA, const GlobalValue *GV,
const GlobalValue *UnderlyingGV = GV;
// If GV is an alias then use the aliasee to determine the wrapper type
if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
- UnderlyingGV = GA->getAliasedGlobal();
+ UnderlyingGV = GA->resolveAliasedGlobal();
if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(UnderlyingGV)) {
if ( ( GVar->isConstant() &&
UnderlyingGV->isLocalLinkage(GV->getLinkage()) )
diff --git a/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp b/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
index df1549d405..0249df1c6d 100644
--- a/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
+++ b/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp
@@ -554,7 +554,8 @@ bool DataFlowSanitizer::runOnModule(Module &M) {
++i;
// Don't stop on weak. We assume people aren't playing games with the
// instrumentedness of overridden weak aliases.
- if (Function *F = dyn_cast<Function>(GA->getAliasedGlobal())) {
+ if (Function *F = dyn_cast<Function>(
+ GA->resolveAliasedGlobal(/*stopOnWeak=*/false))) {
bool GAInst = isInstrumented(GA), FInst = isInstrumented(F);
if (GAInst && FInst) {
addGlobalNamePrefix(GA);
diff --git a/test/CodeGen/X86/dllexport-x86_64.ll b/test/CodeGen/X86/dllexport-x86_64.ll
index a38c2d8f8a..1fadfec254 100644
--- a/test/CodeGen/X86/dllexport-x86_64.ll
+++ b/test/CodeGen/X86/dllexport-x86_64.ll
@@ -65,7 +65,7 @@ define weak_odr dllexport void @weak1() {
@alias2 = dllexport alias void()* @f1
; CHECK: .globl alias3
-; CHECK: alias3 = notExported
+; CHECK: alias3 = alias
@alias3 = dllexport alias void()* @alias
; CHECK: .weak weak_alias
diff --git a/test/CodeGen/X86/dllexport.ll b/test/CodeGen/X86/dllexport.ll
index 1b34d23869..7f0dadb6a2 100644
--- a/test/CodeGen/X86/dllexport.ll
+++ b/test/CodeGen/X86/dllexport.ll
@@ -80,7 +80,7 @@ define weak_odr dllexport void @weak1() {
@alias2 = dllexport alias void()* @f1
; CHECK: .globl _alias3
-; CHECK: _alias3 = _notExported
+; CHECK: _alias3 = _alias
@alias3 = dllexport alias void()* @alias
; CHECK: .weak _weak_alias
diff --git a/test/Feature/aliases.ll b/test/Feature/aliases.ll
index 7fe9d0b374..7ffa5f2601 100644
--- a/test/Feature/aliases.ll
+++ b/test/Feature/aliases.ll
@@ -14,7 +14,7 @@
define i32 @foo_f() {
ret i32 0
}
-@bar_f = alias weak_odr %FunTy* @foo_f
+@bar_f = alias weak %FunTy* @foo_f
@bar_ff = alias i32()* @bar_f
@bar_i = alias internal i32* @bar
diff --git a/test/Transforms/GlobalOpt/alias-resolve.ll b/test/Transforms/GlobalOpt/alias-resolve.ll
index 2d5a956d14..64e3d88af8 100644
--- a/test/Transforms/GlobalOpt/alias-resolve.ll
+++ b/test/Transforms/GlobalOpt/alias-resolve.ll
@@ -1,17 +1,14 @@
; RUN: opt < %s -globalopt -S | FileCheck %s
@foo1 = alias void ()* @foo2
-; CHECK: @foo1 = alias void ()* @bar2
+; CHECK: @foo1 = alias void ()* @foo2
-@foo2 = alias void()* @bar1
-; CHECK: @foo2 = alias void ()* @bar2
+@foo2 = alias weak void()* @bar1
+; CHECK: @foo2 = alias weak void ()* @bar2
@bar1 = alias void ()* @bar2
; CHECK: @bar1 = alias void ()* @bar2
-@weak1 = alias weak void ()* @bar2
-; CHECK: @weak1 = alias weak void ()* @bar2
-
define void @bar2() {
ret void
}
@@ -20,16 +17,14 @@ define void @bar2() {
define void @baz() {
entry:
call void @foo1()
-; CHECK: call void @bar2()
+; CHECK: call void @foo2()
call void @foo2()
-; CHECK: call void @bar2()
+; CHECK: call void @foo2()
call void @bar1()
; CHECK: call void @bar2()
- call void @weak1()
-; CHECK: call void @weak1()
ret void
}