This adds back r204781.
Original message:
Aliases are just another name for a position in a file. As such, the
regular symbol resolutions are not applied. For example, given
define void @my_func() {
ret void
}
@my_alias = alias weak void ()* @my_func
@my_alias2 = alias void ()* @my_alias
We produce without this patch:
.weak my_alias
my_alias = my_func
.globl my_alias2
my_alias2 = my_alias
That is, in the resulting ELF file my_alias, my_func and my_alias are
just 3 names pointing to offset 0 of .text. That is *not* the
semantics of IR linking. For example, linking in a
@my_alias = alias void ()* @other_func
would require the strong my_alias to override the weak one and
my_alias2 would end up pointing to other_func.
There is no way to represent that with aliases being just another
name, so the best solution seems to be to just disallow it, converting
a miscompile into an error.
llvm-svn: 204934
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
Constant *getAliasee() {
return getOperand(0);
}
- /// getAliasedGlobal() - Aliasee can be either global or bitcast of
- /// global. This method retrives the global for both aliasee flavours.
+
+ /// 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.
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);
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->resolveAliasedGlobal(false));
+ GVar = dyn_cast_or_null<GlobalVariable>(GA->getAliasedGlobal());
}
unsigned Opc;
return TheJIT->getOrEmitGlobalVariable(GV);
if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V))
- return TheJIT->getPointerToGlobal(GA->resolveAliasedGlobal(false));
+ return TheJIT->getPointerToGlobal(GA->getAliasedGlobal());
// If we have already compiled the function, return a pointer to its body.
Function *F = cast<Function>(V);
setOperand(0, Aliasee);
}
-GlobalValue *GlobalAlias::getAliasedGlobal() {
- Constant *C = getAliasee();
- if (C == 0) return 0;
-
+static GlobalValue *getAliaseeGV(GlobalAlias *GA) {
+ Constant *C = GA->getAliasee();
+ assert(C && "Must alias something");
+
if (GlobalValue *GV = dyn_cast<GlobalValue>(C))
return GV;
CE->getOpcode() == Instruction::AddrSpaceCast ||
CE->getOpcode() == Instruction::GetElementPtr) &&
"Unsupported aliasee");
-
+
return cast<GlobalValue>(CE->getOperand(0));
}
-GlobalValue *GlobalAlias::resolveAliasedGlobal(bool stopOnWeak) {
+GlobalValue *GlobalAlias::getAliasedGlobal() {
SmallPtrSet<GlobalValue*, 3> Visited;
- // 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();
+ GlobalAlias *GA = this;
+ for (;;) {
+ GlobalValue *GV = getAliaseeGV(GA);
if (!Visited.insert(GV))
return 0;
- }
- return GV;
+ // Iterate over aliasing chain.
+ GA = dyn_cast<GlobalAlias>(GV);
+ if (!GA)
+ return GV;
+ }
}
}
}
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* Resolved = GA.resolveAliasedGlobal(/*stopOnWeak*/ false);
- Assert1(Resolved,
- "Aliasing chain should end with function or global variable", &GA);
+ const GlobalValue *AG = GA.getAliasedGlobal();
+ Assert1(AG, "Aliasing chain should end with function or global variable",
+ &GA);
visitGlobalValue(GA);
}
if (MO.isGlobal()) {
const GlobalValue *GValue = MO.getGlobal();
const GlobalAlias *GAlias = dyn_cast<GlobalAlias>(GValue);
- const GlobalValue *RealGValue = GAlias ?
- GAlias->resolveAliasedGlobal(false) : GValue;
+ const GlobalValue *RealGValue =
+ GAlias ? GAlias->getAliasedGlobal() : GValue;
MOSymbol = getSymbol(RealGValue);
const GlobalVariable *GVar = dyn_cast<GlobalVariable>(RealGValue);
IsExternal = GVar && !GVar->hasInitializer();
else if (MO.isGlobal()) {
const GlobalValue *GValue = MO.getGlobal();
const GlobalAlias *GAlias = dyn_cast<GlobalAlias>(GValue);
- const GlobalValue *RealGValue = GAlias ?
- GAlias->resolveAliasedGlobal(false) : GValue;
+ const GlobalValue *RealGValue =
+ GAlias ? GAlias->getAliasedGlobal() : GValue;
MOSymbol = getSymbol(RealGValue);
const GlobalVariable *GVar = dyn_cast<GlobalVariable>(RealGValue);
if (MO.isGlobal()) {
const GlobalValue *GValue = MO.getGlobal();
const GlobalAlias *GAlias = dyn_cast<GlobalAlias>(GValue);
- const GlobalValue *RealGValue = GAlias ?
- GAlias->resolveAliasedGlobal(false) : GValue;
+ const GlobalValue *RealGValue =
+ GAlias ? GAlias->getAliasedGlobal() : GValue;
MOSymbol = getSymbol(RealGValue);
const GlobalVariable *GVar = dyn_cast<GlobalVariable>(RealGValue);
IsExternal = GVar && !GVar->hasInitializer();
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->resolveAliasedGlobal(false));
+ GVar = dyn_cast_or_null<GlobalVariable>(GA->getAliasedGlobal());
}
// FIXME: We don't yet handle the complexity of TLS.
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(GA)) {
const GlobalValue *GValue = G->getGlobal();
const GlobalAlias *GAlias = dyn_cast<GlobalAlias>(GValue);
- const GlobalValue *RealGValue = GAlias ?
- GAlias->resolveAliasedGlobal(false) : GValue;
+ const GlobalValue *RealGValue =
+ GAlias ? GAlias->getAliasedGlobal() : GValue;
const GlobalVariable *GVar = dyn_cast<GlobalVariable>(RealGValue);
assert((GVar || isa<Function>(RealGValue)) &&
"Unexpected global value subclass!");
// If GV is an alias then use the aliasee for determining
// thread-localness.
if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
- GV = GA->resolveAliasedGlobal(false);
+ GV = GA->getAliasedGlobal();
const GlobalVariable *Var = cast<GlobalVariable>(GV);
bool isLocal = Var->hasLocalLinkage();
// it works...).
if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
if (const GlobalVariable *GVar =
- dyn_cast_or_null<GlobalVariable>(GA->resolveAliasedGlobal(false)))
+ dyn_cast_or_null<GlobalVariable>(GA->getAliasedGlobal()))
if (GVar->isThreadLocal())
return false;
// If GV is an alias then use the aliasee for determining
// thread-localness.
if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
- GV = GA->resolveAliasedGlobal(false);
+ GV = GA->getAliasedGlobal();
SDLoc dl(GA);
SDValue Chain = DAG.getEntryNode();
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->resolveAliasedGlobal();
+ UnderlyingGV = GA->getAliasedGlobal();
if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(UnderlyingGV)) {
if ( ( GVar->isConstant() &&
UnderlyingGV->isLocalLinkage(GV->getLinkage()) )
++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->resolveAliasedGlobal(/*stopOnWeak=*/false))) {
+ if (Function *F = dyn_cast<Function>(GA->getAliasedGlobal())) {
bool GAInst = isInstrumented(GA), FInst = isInstrumented(F);
if (GAInst && FInst) {
addGlobalNamePrefix(GA);
@alias2 = dllexport alias void()* @f1
; CHECK: .globl alias3
-; CHECK: alias3 = alias
+; CHECK: alias3 = notExported
@alias3 = dllexport alias void()* @alias
; CHECK: .weak weak_alias
@alias2 = dllexport alias void()* @f1
; CHECK: .globl _alias3
-; CHECK: _alias3 = _alias
+; CHECK: _alias3 = _notExported
@alias3 = dllexport alias void()* @alias
; CHECK: .weak _weak_alias
define i32 @foo_f() {
ret i32 0
}
-@bar_f = alias weak %FunTy* @foo_f
+@bar_f = alias weak_odr %FunTy* @foo_f
@bar_ff = alias i32()* @bar_f
@bar_i = alias internal i32* @bar
; RUN: opt < %s -globalopt -S | FileCheck %s
@foo1 = alias void ()* @foo2
-; CHECK: @foo1 = alias void ()* @foo2
+; CHECK: @foo1 = alias void ()* @bar2
-@foo2 = alias weak void()* @bar1
-; CHECK: @foo2 = alias weak void ()* @bar2
+@foo2 = alias void()* @bar1
+; CHECK: @foo2 = alias 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
}
define void @baz() {
entry:
call void @foo1()
-; CHECK: call void @foo2()
+; CHECK: call void @bar2()
call void @foo2()
-; CHECK: call void @foo2()
+; CHECK: call void @bar2()
call void @bar1()
; CHECK: call void @bar2()
+ call void @weak1()
+; CHECK: call void @weak1()
ret void
}