From 70c7eda21fd736f29ed4132cdcc656228d6ea952 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 16 May 2014 19:35:48 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@209008 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGCXX.cpp | 15 ++-- lib/CodeGen/CodeGenModule.cpp | 71 ++++++++++--------- lib/CodeGen/TargetInfo.cpp | 2 +- test/CodeGen/alias.c | 4 +- test/CodeGen/attributes.c | 2 +- test/CodeGenCXX/ctor-dtor-alias.cpp | 2 +- test/CodeGenCXX/destructors.cpp | 4 +- .../microsoft-abi-structors-alias.cpp | 2 +- test/CodeGenCXX/virtual-destructor-calls.cpp | 4 +- test/Sema/attr-alias-cycle.c | 16 +++++ test/Sema/attr-alias-elf.c | 7 -- 11 files changed, 71 insertions(+), 58 deletions(-) create mode 100644 test/Sema/attr-alias-cycle.c diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 08b74a3c30..0a73550c7a 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -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(GetAddrOfGlobal(TargetDecl)); - llvm::Constant *Aliasee = Ref; - if (Ref->getType() != AliasType) - Aliasee = llvm::ConstantExpr::getBitCast(Ref, AliasType); + auto *Aliasee = dyn_cast(Ref); + if (!Aliasee) + Aliasee = cast(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())) { @@ -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; } diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 769b01c825..fa9ddf0222 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -238,46 +238,18 @@ void CodeGenModule::checkAliases() { llvm::GlobalValue *Entry = GetGlobalValue(MangledName); auto *Alias = cast(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(Aliasee)) { - assert((CE->getOpcode() == llvm::Instruction::BitCast || - CE->getOpcode() == llvm::Instruction::AddrSpaceCast) && - "Unsupported aliasee"); - AliaseeGV = cast(CE->getOperand(0)); - } else { - AliaseeGV = cast(Aliasee); - } - + llvm::GlobalObject *Aliasee = Alias->getAliasee(); if (const SectionAttr *SA = D->getAttr()) { 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(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(C)) + return *GO; + + auto *GA = dyn_cast(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(C); + assert(CE->getOpcode() == llvm::Instruction::BitCast || + CE->getOpcode() == llvm::Instruction::GetElementPtr || + CE->getOpcode() == llvm::Instruction::AddrSpaceCast); + return *cast(CE->getOperand(0)); +} + void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) { const auto *D = cast(GD.getDecl()); const AliasAttr *AA = D->getAttr(); @@ -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(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(Val), &getModule())); } } diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index 0ed23ed371..9e5849328b 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -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()); } } } diff --git a/test/CodeGen/alias.c b/test/CodeGen/alias.c index 98449d36ed..5aafd95fde 100644 --- a/test/CodeGen/alias.c +++ b/test/CodeGen/alias.c @@ -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]+]] { diff --git a/test/CodeGen/attributes.c b/test/CodeGen/attributes.c index 356a17996a..388ea822f0 100644 --- a/test/CodeGen/attributes.c +++ b/test/CodeGen/attributes.c @@ -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"))); diff --git a/test/CodeGenCXX/ctor-dtor-alias.cpp b/test/CodeGenCXX/ctor-dtor-alias.cpp index d869a2bfd5..87793119d0 100644 --- a/test/CodeGenCXX/ctor-dtor-alias.cpp +++ b/test/CodeGenCXX/ctor-dtor-alias.cpp @@ -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(); diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp index 5c430480bc..3d6e6038a2 100644 --- a/test/CodeGenCXX/destructors.cpp +++ b/test/CodeGenCXX/destructors.cpp @@ -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 { diff --git a/test/CodeGenCXX/microsoft-abi-structors-alias.cpp b/test/CodeGenCXX/microsoft-abi-structors-alias.cpp index f977556aa5..59ced74093 100644 --- a/test/CodeGenCXX/microsoft-abi-structors-alias.cpp +++ b/test/CodeGenCXX/microsoft-abi-structors-alias.cpp @@ -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" } diff --git a/test/CodeGenCXX/virtual-destructor-calls.cpp b/test/CodeGenCXX/virtual-destructor-calls.cpp index 3e7fa8293a..46a446bc9b 100644 --- a/test/CodeGenCXX/virtual-destructor-calls.cpp +++ b/test/CodeGenCXX/virtual-destructor-calls.cpp @@ -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 diff --git a/test/Sema/attr-alias-cycle.c b/test/Sema/attr-alias-cycle.c new file mode 100644 index 0000000000..ce024c3bd8 --- /dev/null +++ b/test/Sema/attr-alias-cycle.c @@ -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"))); diff --git a/test/Sema/attr-alias-elf.c b/test/Sema/attr-alias-elf.c index 04d13924ac..82ab076782 100644 --- a/test/Sema/attr-alias-elf.c +++ b/test/Sema/attr-alias-elf.c @@ -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; -- 2.40.0