[IR] Allow available_externally GlobalAlias
GlobalVariable and Function can be available_externally. GlobalAlias is used similarly. Allowing available_externally is a natural extension and helps ThinLTO discard GlobalAlias in a non-prevailing COMDAT (see D135427). For now, available_externally GlobalAlias must point to an available_externally GlobalValue (not ConstantExpr). Differential Revision: https://reviews.llvm.org/D137441
This commit is contained in:
parent
ec224e3b68
commit
90ad3e3c02
|
@ -886,8 +886,9 @@ Syntax::
|
|||
[, partition "name"]
|
||||
|
||||
The linkage must be one of ``private``, ``internal``, ``linkonce``, ``weak``,
|
||||
``linkonce_odr``, ``weak_odr``, ``external``. Note that some system linkers
|
||||
might not correctly handle dropping a weak symbol that is aliased.
|
||||
``linkonce_odr``, ``weak_odr``, ``external``, ``available_externally``. Note
|
||||
that some system linkers might not correctly handle dropping a weak symbol that
|
||||
is aliased.
|
||||
|
||||
Aliases that are not ``unnamed_addr`` are guaranteed to have the same address as
|
||||
the aliasee expression. ``unnamed_addr`` ones are only guaranteed to point
|
||||
|
@ -906,8 +907,10 @@ some can only be checked when producing an object file:
|
|||
intermediate alias being overridden cannot be represented in an
|
||||
object file.
|
||||
|
||||
* No global value in the expression can be a declaration, since that
|
||||
would require a relocation, which is not possible.
|
||||
* If the alias has the ``available_externally`` linkage, the aliasee must be an
|
||||
``available_externally`` global value; otherwise the aliasee can be an
|
||||
expression but no global value in the expression can be a declaration, since
|
||||
that would require a relocation, which is not possible.
|
||||
|
||||
* If either the alias or the aliasee may be replaced by a symbol outside the
|
||||
module at link time or runtime, any optimization cannot replace the alias with
|
||||
|
|
|
@ -93,8 +93,8 @@ public:
|
|||
}
|
||||
|
||||
static bool isValidLinkage(LinkageTypes L) {
|
||||
return isExternalLinkage(L) || isLocalLinkage(L) ||
|
||||
isWeakLinkage(L) || isLinkOnceLinkage(L);
|
||||
return isExternalLinkage(L) || isLocalLinkage(L) || isWeakLinkage(L) ||
|
||||
isLinkOnceLinkage(L) || isAvailableExternallyLinkage(L);
|
||||
}
|
||||
|
||||
// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
|
|
|
@ -817,9 +817,18 @@ 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)) {
|
||||
Check(!GV->isDeclarationForLinker(), "Alias must point to a definition",
|
||||
if (GA.hasAvailableExternallyLinkage()) {
|
||||
Check(isa<GlobalValue>(C) &&
|
||||
cast<GlobalValue>(C).hasAvailableExternallyLinkage(),
|
||||
"available_externally alias must point to available_externally "
|
||||
"global value",
|
||||
&GA);
|
||||
}
|
||||
if (const auto *GV = dyn_cast<GlobalValue>(&C)) {
|
||||
if (!GA.hasAvailableExternallyLinkage()) {
|
||||
Check(!GV->isDeclarationForLinker(), "Alias must point to a definition",
|
||||
&GA);
|
||||
}
|
||||
|
||||
if (const auto *GA2 = dyn_cast<GlobalAlias>(GV)) {
|
||||
Check(Visited.insert(GA2).second, "Aliases cannot form a cycle", &GA);
|
||||
|
@ -848,7 +857,7 @@ void Verifier::visitAliaseeSubExpr(SmallPtrSetImpl<const GlobalAlias*> &Visited,
|
|||
void Verifier::visitGlobalAlias(const GlobalAlias &GA) {
|
||||
Check(GlobalAlias::isValidLinkage(GA.getLinkage()),
|
||||
"Alias should have private, internal, linkonce, weak, linkonce_odr, "
|
||||
"weak_odr, or external linkage!",
|
||||
"weak_odr, external, or available_externally linkage!",
|
||||
&GA);
|
||||
const Constant *Aliasee = GA.getAliasee();
|
||||
Check(Aliasee, "Aliasee cannot be NULL!", &GA);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
|
||||
; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s --implicit-check-not=alias --implicit-check-not=Alias
|
||||
|
||||
|
||||
declare void @f()
|
||||
|
@ -31,3 +31,15 @@ define available_externally void @f2() {
|
|||
@test3_c = alias i32, i32* @test3_b
|
||||
; CHECK: Alias cannot point to an interposable alias
|
||||
; CHECK-NEXT: i32* @test3_c
|
||||
|
||||
@test4_a = available_externally global i32 42
|
||||
@test4_b = available_externally alias i32, i32* @test4_a
|
||||
@test4_c = available_externally alias void(), void()* @f2
|
||||
@test4_d = available_externally alias i32, i32* @test4_b
|
||||
|
||||
@test4_e = available_externally alias i32, i32* @test3_a
|
||||
@test4_f = available_externally alias i32, inttoptr (i64 sub (i64 ptrtoint (i32* @test4_a to i64), i64 ptrtoint (i32* @test4_a to i64)) to i32*)
|
||||
; CHECK: available_externally alias must point to available_externally global value
|
||||
; CHECK-NEXT: i32* @test4_e
|
||||
; CHECK: available_externally alias must point to available_externally global value
|
||||
; CHECK-NEXT: i32* @test4_f
|
||||
|
|
Loading…
Reference in New Issue