forked from OSchip/llvm-project
Update for llvm api change.
Now that llvm cannot represent alias cycles, we have to diagnose erros just before trying to close the cycle. This degrades the errors a bit. The real solution is what it was before: if we want to provide good errors for these cases, we have to be able to find a clang level decl given a mangled name and produce the error from Sema. llvm-svn: 209008
This commit is contained in:
parent
6b238633b7
commit
b2633b9793
|
@ -138,12 +138,12 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
|
|||
// which case the caller is responsible for ensuring the soundness
|
||||
// of these semantics.
|
||||
auto *Ref = cast<llvm::GlobalValue>(GetAddrOfGlobal(TargetDecl));
|
||||
llvm::Constant *Aliasee = Ref;
|
||||
if (Ref->getType() != AliasType)
|
||||
Aliasee = llvm::ConstantExpr::getBitCast(Ref, AliasType);
|
||||
auto *Aliasee = dyn_cast<llvm::GlobalObject>(Ref);
|
||||
if (!Aliasee)
|
||||
Aliasee = cast<llvm::GlobalAlias>(Ref)->getAliasee();
|
||||
|
||||
// Instead of creating as alias to a linkonce_odr, replace all of the uses
|
||||
// of the aliassee.
|
||||
// of the aliasee.
|
||||
if (llvm::GlobalValue::isDiscardableIfUnused(Linkage) &&
|
||||
(TargetLinkage != llvm::GlobalValue::AvailableExternallyLinkage ||
|
||||
!TargetDecl.getDecl()->hasAttr<AlwaysInlineAttr>())) {
|
||||
|
@ -152,7 +152,10 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
|
|||
// members with attribute "AlwaysInline" and expect no reference to
|
||||
// be generated. It is desirable to reenable this optimisation after
|
||||
// corresponding LLVM changes.
|
||||
Replacements[MangledName] = Aliasee;
|
||||
llvm::Constant *Replacement = Aliasee;
|
||||
if (Aliasee->getType() != AliasType)
|
||||
Replacement = llvm::ConstantExpr::getBitCast(Aliasee, AliasType);
|
||||
Replacements[MangledName] = Replacement;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -160,7 +163,7 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
|
|||
/// If we don't have a definition for the destructor yet, don't
|
||||
/// emit. We can't emit aliases to declarations; that's just not
|
||||
/// how aliases work.
|
||||
if (Ref->isDeclaration())
|
||||
if (Aliasee->isDeclaration())
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -238,46 +238,18 @@ void CodeGenModule::checkAliases() {
|
|||
llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
|
||||
auto *Alias = cast<llvm::GlobalAlias>(Entry);
|
||||
llvm::GlobalValue *GV = Alias->getAliasedGlobal();
|
||||
if (!GV) {
|
||||
Error = true;
|
||||
Diags.Report(AA->getLocation(), diag::err_cyclic_alias);
|
||||
} else if (GV->isDeclaration()) {
|
||||
if (GV->isDeclaration()) {
|
||||
Error = true;
|
||||
Diags.Report(AA->getLocation(), diag::err_alias_to_undefined);
|
||||
}
|
||||
|
||||
llvm::Constant *Aliasee = Alias->getAliasee();
|
||||
llvm::GlobalValue *AliaseeGV;
|
||||
if (auto CE = dyn_cast<llvm::ConstantExpr>(Aliasee)) {
|
||||
assert((CE->getOpcode() == llvm::Instruction::BitCast ||
|
||||
CE->getOpcode() == llvm::Instruction::AddrSpaceCast) &&
|
||||
"Unsupported aliasee");
|
||||
AliaseeGV = cast<llvm::GlobalValue>(CE->getOperand(0));
|
||||
} else {
|
||||
AliaseeGV = cast<llvm::GlobalValue>(Aliasee);
|
||||
}
|
||||
|
||||
llvm::GlobalObject *Aliasee = Alias->getAliasee();
|
||||
if (const SectionAttr *SA = D->getAttr<SectionAttr>()) {
|
||||
StringRef AliasSection = SA->getName();
|
||||
if (AliasSection != AliaseeGV->getSection())
|
||||
if (AliasSection != Aliasee->getSection())
|
||||
Diags.Report(SA->getLocation(), diag::warn_alias_with_section)
|
||||
<< AliasSection;
|
||||
}
|
||||
|
||||
// We have to handle alias to weak aliases in here. LLVM itself disallows
|
||||
// this since the object semantics would not match the IL one. For
|
||||
// compatibility with gcc we implement it by just pointing the alias
|
||||
// to its aliasee's aliasee. We also warn, since the user is probably
|
||||
// expecting the link to be weak.
|
||||
if (auto GA = dyn_cast<llvm::GlobalAlias>(AliaseeGV)) {
|
||||
if (GA->mayBeOverridden()) {
|
||||
Diags.Report(AA->getLocation(), diag::warn_alias_to_weak_alias)
|
||||
<< GA->getAliasedGlobal()->getName() << GA->getName();
|
||||
Aliasee = llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(
|
||||
GA->getAliasee(), Alias->getType());
|
||||
Alias->setAliasee(Aliasee);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!Error)
|
||||
return;
|
||||
|
@ -2246,6 +2218,29 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD,
|
|||
AddGlobalAnnotations(D, Fn);
|
||||
}
|
||||
|
||||
static llvm::GlobalObject &getGlobalObjectInExpr(DiagnosticsEngine &Diags,
|
||||
const AliasAttr *AA,
|
||||
llvm::Constant *C) {
|
||||
if (auto *GO = dyn_cast<llvm::GlobalObject>(C))
|
||||
return *GO;
|
||||
|
||||
auto *GA = dyn_cast<llvm::GlobalAlias>(C);
|
||||
if (GA) {
|
||||
if (GA->mayBeOverridden()) {
|
||||
Diags.Report(AA->getLocation(), diag::warn_alias_to_weak_alias)
|
||||
<< GA->getAliasee()->getName() << GA->getName();
|
||||
}
|
||||
|
||||
return *GA->getAliasee();
|
||||
}
|
||||
|
||||
auto *CE = cast<llvm::ConstantExpr>(C);
|
||||
assert(CE->getOpcode() == llvm::Instruction::BitCast ||
|
||||
CE->getOpcode() == llvm::Instruction::GetElementPtr ||
|
||||
CE->getOpcode() == llvm::Instruction::AddrSpaceCast);
|
||||
return *cast<llvm::GlobalObject>(CE->getOperand(0));
|
||||
}
|
||||
|
||||
void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
|
||||
const auto *D = cast<ValueDecl>(GD.getDecl());
|
||||
const AliasAttr *AA = D->getAttr<AliasAttr>();
|
||||
|
@ -2276,9 +2271,15 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) {
|
|||
// Create the new alias itself, but don't set a name yet.
|
||||
auto *GA = new llvm::GlobalAlias(
|
||||
cast<llvm::PointerType>(Aliasee->getType())->getElementType(),
|
||||
llvm::Function::ExternalLinkage, "", Aliasee, &getModule());
|
||||
llvm::Function::ExternalLinkage, "",
|
||||
&getGlobalObjectInExpr(Diags, AA, Aliasee), &getModule());
|
||||
|
||||
if (Entry) {
|
||||
if (GA->getAliasee() == Entry) {
|
||||
Diags.Report(AA->getLocation(), diag::err_cyclic_alias);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(Entry->isDeclaration());
|
||||
|
||||
// If there is a declaration in the module, then we had an extern followed
|
||||
|
@ -3196,9 +3197,9 @@ void CodeGenModule::EmitStaticExternCAliases() {
|
|||
IdentifierInfo *Name = I->first;
|
||||
llvm::GlobalValue *Val = I->second;
|
||||
if (Val && !getModule().getNamedValue(Name->getName()))
|
||||
addUsedGlobal(new llvm::GlobalAlias(Val->getType()->getElementType(),
|
||||
Val->getLinkage(), Name->getName(),
|
||||
Val, &getModule()));
|
||||
addUsedGlobal(new llvm::GlobalAlias(
|
||||
Val->getType()->getElementType(), Val->getLinkage(), Name->getName(),
|
||||
cast<llvm::GlobalObject>(Val), &getModule()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5213,7 +5213,7 @@ void MSP430TargetCodeGenInfo::SetTargetAttributes(const Decl *D,
|
|||
unsigned Num = attr->getNumber() / 2;
|
||||
new llvm::GlobalAlias(GV->getType()->getElementType(),
|
||||
llvm::Function::ExternalLinkage,
|
||||
"__isr_" + Twine(Num), GV, &M.getModule());
|
||||
"__isr_" + Twine(Num), F, &M.getModule());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,8 +14,8 @@ void f0(void) { }
|
|||
extern void f1(void);
|
||||
extern void f1(void) __attribute((alias("f0")));
|
||||
// CHECKBASIC-DAG: @f1 = alias void ()* @f0
|
||||
// CHECKBASIC-DAG: @test8_foo = alias weak bitcast (void ()* @test8_bar to void (...)*)
|
||||
// CHECKBASIC-DAG: @test8_zed = alias bitcast (void ()* @test8_bar to void (...)*)
|
||||
// CHECKBASIC-DAG: @test8_foo = alias weak void (...), void ()* @test8_bar
|
||||
// CHECKBASIC-DAG: @test8_zed = alias void (...), void ()* @test8_bar
|
||||
// CHECKBASIC-DAG: @test9_zed = alias void ()* @test9_bar
|
||||
// CHECKBASIC: define void @f0() [[NUW:#[0-9]+]] {
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ int t6 __attribute__((visibility("protected")));
|
|||
// CHECK: @t12 = global i32 0, section "SECT"
|
||||
int t12 __attribute__((section("SECT")));
|
||||
|
||||
// CHECK: @t9 = alias weak bitcast (void ()* @__t8 to void (...)*)
|
||||
// CHECK: @t9 = alias weak void (...), void ()* @__t8
|
||||
void __t8() {}
|
||||
void t9() __attribute__((weak, alias("__t8")));
|
||||
|
||||
|
|
|
@ -119,7 +119,7 @@ namespace test7 {
|
|||
|
||||
namespace test8 {
|
||||
// Test that we replace ~zed with ~bar which is an alias to ~foo.
|
||||
// CHECK-DAG: call i32 @__cxa_atexit({{.*}}@_ZN5test83barD2Ev
|
||||
// CHECK-DAG: call i32 @__cxa_atexit({{.*}}@_ZN5test83fooD2Ev
|
||||
// CHECK-DAG: @_ZN5test83barD2Ev = alias {{.*}} @_ZN5test83fooD2Ev
|
||||
struct foo {
|
||||
~foo();
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
// CHECK-DAG: @_ZN5test11MD2Ev = alias {{.*}} @_ZN5test11AD2Ev
|
||||
// CHECK-DAG: @_ZN5test11ND2Ev = alias {{.*}} @_ZN5test11AD2Ev
|
||||
// CHECK-DAG: @_ZN5test11OD2Ev = alias {{.*}} @_ZN5test11AD2Ev
|
||||
// CHECK-DAG: @_ZN5test11SD2Ev = alias bitcast {{.*}} @_ZN5test11AD2Ev
|
||||
// CHECK-DAG: @_ZN5test11SD2Ev = alias {{.*}} @_ZN5test11AD2Ev
|
||||
|
||||
// WIN32-DAG: @_ZN5test01AD1Ev = alias {{.*}} @_ZN5test01AD2Ev
|
||||
// WIN32-DAG: @_ZN5test11MD2Ev = alias {{.*}} @_ZN5test11AD2Ev
|
||||
// WIN32-DAG: @_ZN5test11ND2Ev = alias {{.*}} @_ZN5test11AD2Ev
|
||||
// WIN32-DAG: @_ZN5test11OD2Ev = alias {{.*}} @_ZN5test11AD2Ev
|
||||
// WIN32-DAG: @_ZN5test11SD2Ev = alias bitcast {{.*}} @_ZN5test11AD2Ev
|
||||
// WIN32-DAG: @_ZN5test11SD2Ev = alias {{.*}} @_ZN5test11AD2Ev
|
||||
|
||||
|
||||
struct A {
|
||||
|
|
|
@ -22,5 +22,5 @@ B::~B() {}
|
|||
void foo() {
|
||||
B b;
|
||||
}
|
||||
// CHECK-DAG: @"\01??1B@test2@@UAE@XZ" = alias bitcast (void (%"struct.test2::A"*)* @"\01??1A@test2@@UAE@XZ" to void (%"struct.test2::B"*)*)
|
||||
// CHECK-DAG: @"\01??1B@test2@@UAE@XZ" = alias void (%"struct.test2::B"*), void (%"struct.test2::A"*)* @"\01??1A@test2@@UAE@XZ"
|
||||
}
|
||||
|
|
|
@ -17,8 +17,8 @@ struct B : A {
|
|||
// CHECK: @_ZN1BD1Ev = alias {{.*}} @_ZN1BD2Ev
|
||||
|
||||
// (aliases from C)
|
||||
// CHECK: @_ZN1CD1Ev = alias {{.*}} @_ZN1CD2Ev
|
||||
// CHECK: @_ZN1CD2Ev = alias bitcast {{.*}} @_ZN1BD2Ev
|
||||
// CHECK: @_ZN1CD1Ev = alias {{.*}} @_ZN1BD2Ev
|
||||
// CHECK: @_ZN1CD2Ev = alias {{.*}} @_ZN1BD2Ev
|
||||
|
||||
// Base dtor: actually calls A's base dtor.
|
||||
// CHECK-LABEL: define void @_ZN1BD2Ev(%struct.B* %this) unnamed_addr
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
// RUN: %clang_cc1 -triple x86_64-pc-linux -fsyntax-only -verify -emit-llvm-only %s
|
||||
|
||||
// FIXME: The attributes use mangled names. Since we only keep a mapping from
|
||||
// mangled name to llvm GlobalValue, we don't see the clang level decl for
|
||||
// an alias target when constructing the alias. Given that and that alias cycles
|
||||
// are not representable in LLVM, we only note the issues when the cycle is
|
||||
// first formed.
|
||||
|
||||
// FIXME: This error is detected early in CodeGen. Once the first error is
|
||||
// found, Diags.hasErrorOccurred() returs true and we stop the codegen of the
|
||||
// file. The consequence is that we don't find any subsequent error.
|
||||
|
||||
void f1() __attribute__((alias("g1")));
|
||||
void g1() __attribute__((alias("f1"))); // expected-error {{alias definition is part of a cycle}}
|
||||
|
||||
void h1() __attribute__((alias("g1")));
|
|
@ -35,13 +35,6 @@ void h9() __attribute__((alias("f9")));
|
|||
void f9() __attribute__((alias("g9")));
|
||||
void g9() {}
|
||||
|
||||
void f10() __attribute__((alias("g10"))); // expected-error {{alias definition is part of a cycle}}
|
||||
void g10() __attribute__((alias("f10"))); // expected-error {{alias definition is part of a cycle}}
|
||||
|
||||
// FIXME: This could be a bit better, h10 is not part of the cycle, it points
|
||||
// to it.
|
||||
void h10() __attribute__((alias("g10"))); // expected-error {{alias definition is part of a cycle}}
|
||||
|
||||
extern int a1 __attribute__((alias("b1")));
|
||||
int b1 = 42;
|
||||
|
||||
|
|
Loading…
Reference in New Issue