https://github.com/HighW4y2H3ll updated https://github.com/llvm/llvm-project/pull/145652
>From 9a29dd6fa3f28bf507f047a22597f8510bd096b3 Mon Sep 17 00:00:00 2001 From: h2h <h...@meta.com> Date: Tue, 24 Jun 2025 23:24:32 -0700 Subject: [PATCH 1/6] [Clang] Allow vanilla C function symbol name to be used in __attribute__((alias)) when -funique-internal-linkage-names is specified --- clang/lib/CodeGen/CodeGenModule.cpp | 48 +++++++++++++++++-- .../unique-internal-linkage-names-alias.c | 10 ++++ 2 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 clang/test/CodeGen/unique-internal-linkage-names-alias.c diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 16688810d0685..90f02220ec306 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -588,8 +588,9 @@ static const llvm::GlobalValue *getAliasedGlobal(const llvm::GlobalValue *GV) { } static bool checkAliasedGlobal( - const ASTContext &Context, DiagnosticsEngine &Diags, SourceLocation Location, - bool IsIFunc, const llvm::GlobalValue *Alias, const llvm::GlobalValue *&GV, + const CodeGenModule *CGM, const ASTContext &Context, + DiagnosticsEngine &Diags, SourceLocation Location, bool IsIFunc, + const llvm::GlobalValue *Alias, const llvm::GlobalValue *&GV, const llvm::MapVector<GlobalDecl, StringRef> &MangledDeclNames, SourceRange AliasRange) { GV = getAliasedGlobal(Alias); @@ -598,6 +599,23 @@ static bool checkAliasedGlobal( return false; } + // Only resolve unique internal linkage symbols for C code + if (!CGM->getLangOpts().CPlusPlus) { + for (const auto &[Decl, Name] : MangledDeclNames) { + if (const auto *ND = dyn_cast<NamedDecl>(Decl.getDecl())) { + IdentifierInfo *II = ND->getIdentifier(); + if (II && II->getName() == GV->getName() && + Name.contains(llvm::FunctionSamples::UniqSuffix)) { + GlobalDecl GD; + if (CGM->lookupRepresentativeDecl(Name, GD)) { + GV = CGM->getModule().getNamedValue(Name); + break; + } + } + } + } + } + if (GV->hasCommonLinkage()) { const llvm::Triple &Triple = Context.getTargetInfo().getTriple(); if (Triple.getObjectFormat() == llvm::Triple::XCOFF) { @@ -687,8 +705,8 @@ void CodeGenModule::checkAliases() { StringRef MangledName = getMangledName(GD); llvm::GlobalValue *Alias = GetGlobalValue(MangledName); const llvm::GlobalValue *GV = nullptr; - if (!checkAliasedGlobal(getContext(), Diags, Location, IsIFunc, Alias, GV, - MangledDeclNames, Range)) { + if (!checkAliasedGlobal(this, getContext(), Diags, Location, IsIFunc, Alias, + GV, MangledDeclNames, Range)) { Error = true; continue; } @@ -4038,6 +4056,7 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { CXXGlobalInits.push_back(nullptr); } + const auto *ND = dyn_cast<NamedDecl>(GD.getDecl()); StringRef MangledName = getMangledName(GD); if (GetGlobalValue(MangledName) != nullptr) { // The value has already been used and should therefore be emitted. @@ -4046,6 +4065,12 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { // The value must be emitted, but cannot be emitted eagerly. assert(!MayBeEmittedEagerly(Global)); addDeferredDeclToEmit(GD); + } else if (!getLangOpts().CPlusPlus && ND && + GetGlobalValue(ND->getName()) != nullptr && + MangledName.contains(llvm::FunctionSamples::UniqSuffix)) { + // Emit static C function that is mangled with + // -funique-internal-linkage-names. + addDeferredDeclToEmit(GD); } else { // Otherwise, remember that we saw a deferred decl with this name. The // first use of the mangled name will cause it to move into @@ -6189,6 +6214,21 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD, /*DontDefer=*/true, ForDefinition)); + if (!getLangOpts().CPlusPlus && + getCXXABI().getMangleContext().shouldMangleDeclName(D)) { + // -funique-internal-linkage-names may change the symbol name of C function. + // Replace all uses of old symbol with the emitted global value. + if (IdentifierInfo *II = D->getIdentifier()) { + if (II->getName() != GV->getName() && + GV->getName().contains(llvm::FunctionSamples::UniqSuffix)) { + if (llvm::GlobalValue *GVDef = + getModule().getNamedValue(D->getName())) { + GVDef->replaceAllUsesWith(GV); + } + } + } + } + // Already emitted. if (!GV->isDeclaration()) return; diff --git a/clang/test/CodeGen/unique-internal-linkage-names-alias.c b/clang/test/CodeGen/unique-internal-linkage-names-alias.c new file mode 100644 index 0000000000000..14bfea08367d3 --- /dev/null +++ b/clang/test/CodeGen/unique-internal-linkage-names-alias.c @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 %s -emit-llvm -funique-internal-linkage-names -o - | FileCheck %s + +struct A; +static long foo(const struct A*p); + +long bar(const struct A*p); +long bar(const struct A*p) __attribute__((__alias__("foo"))); + +// CHECK: define internal i64 @_ZL3fooPK1A.__uniq.[[ATTR:[0-9]+]](ptr noundef %p) #1 { +static long foo(const struct A*p) {return 1;} >From aedff8d00362405ad73880eccf4bd7006f6facb2 Mon Sep 17 00:00:00 2001 From: h2h <h...@meta.com> Date: Wed, 25 Jun 2025 16:22:49 -0700 Subject: [PATCH 2/6] Check Itanium mangling only --- clang/test/CodeGen/unique-internal-linkage-names-alias.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/CodeGen/unique-internal-linkage-names-alias.c b/clang/test/CodeGen/unique-internal-linkage-names-alias.c index 14bfea08367d3..85345233ad507 100644 --- a/clang/test/CodeGen/unique-internal-linkage-names-alias.c +++ b/clang/test/CodeGen/unique-internal-linkage-names-alias.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -emit-llvm -funique-internal-linkage-names -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux %s -emit-llvm -funique-internal-linkage-names -o - | FileCheck %s struct A; static long foo(const struct A*p); >From 80e7bda91ae783ce02e8c3491a88e65779a1e01c Mon Sep 17 00:00:00 2001 From: h2h <h...@meta.com> Date: Thu, 3 Jul 2025 13:33:44 -0700 Subject: [PATCH 3/6] Fix frontend crash with extern_weak when using __attribute__((weak, alias())) --- clang/lib/CodeGen/CodeGenModule.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 90f02220ec306..83515a4488256 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -4066,7 +4066,6 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { assert(!MayBeEmittedEagerly(Global)); addDeferredDeclToEmit(GD); } else if (!getLangOpts().CPlusPlus && ND && - GetGlobalValue(ND->getName()) != nullptr && MangledName.contains(llvm::FunctionSamples::UniqSuffix)) { // Emit static C function that is mangled with // -funique-internal-linkage-names. >From 1e116a9b6a7964a78ae1b795bc2ac80ec9f46be1 Mon Sep 17 00:00:00 2001 From: h2h <h...@meta.com> Date: Sun, 6 Jul 2025 13:17:35 -0700 Subject: [PATCH 4/6] Fix missed aliasee function emit when function alias is used after the definitation of the aliasee function --- clang/lib/CodeGen/CodeGenModule.cpp | 33 +++++++++++++++++-- clang/lib/CodeGen/CodeGenModule.h | 1 + .../unique-internal-linkage-names-alias.c | 2 +- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 83515a4488256..1c9c9c04b6d4a 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -3902,6 +3902,22 @@ bool CodeGenModule::shouldEmitCUDAGlobalVar(const VarDecl *Global) const { Global->getType()->isCUDADeviceBuiltinTextureType(); } +bool CodeGenModule::shouldEmitUniqLinkageName(GlobalDecl GD) { + const auto *ND = dyn_cast<FunctionDecl>(GD.getDecl()); + if (!ND || !getCXXABI().getMangleContext().shouldMangleDeclName(ND)) + return false; + StringRef MangledName = getMangledName(GD); + if (!MangledName.contains(llvm::FunctionSamples::UniqSuffix)) + return false; + for (const GlobalDecl &AD : Aliases) { + const auto *D = cast<ValueDecl>(AD.getDecl()); + const AliasAttr *AA = D->getAttr<AliasAttr>(); + if (AA && AA->getAliasee() == ND->getName()) + return true; + } + return false; +} + void CodeGenModule::EmitGlobal(GlobalDecl GD) { const auto *Global = cast<ValueDecl>(GD.getDecl()); @@ -4056,7 +4072,6 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { CXXGlobalInits.push_back(nullptr); } - const auto *ND = dyn_cast<NamedDecl>(GD.getDecl()); StringRef MangledName = getMangledName(GD); if (GetGlobalValue(MangledName) != nullptr) { // The value has already been used and should therefore be emitted. @@ -4065,8 +4080,7 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { // The value must be emitted, but cannot be emitted eagerly. assert(!MayBeEmittedEagerly(Global)); addDeferredDeclToEmit(GD); - } else if (!getLangOpts().CPlusPlus && ND && - MangledName.contains(llvm::FunctionSamples::UniqSuffix)) { + } else if (!getLangOpts().CPlusPlus && shouldEmitUniqLinkageName(GD)) { // Emit static C function that is mangled with // -funique-internal-linkage-names. addDeferredDeclToEmit(GD); @@ -6223,6 +6237,7 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD, if (llvm::GlobalValue *GVDef = getModule().getNamedValue(D->getName())) { GVDef->replaceAllUsesWith(GV); + GVDef->removeFromParent(); } } } @@ -6287,6 +6302,18 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) { return; } + // Deferred emit for aliased C function when __attribute__((alias)) might be + // used after the definition of aliasee function + if (!getLangOpts().CPlusPlus) { + for (const auto &[Name, Decl] : DeferredDecls) { + const auto *FD = dyn_cast<FunctionDecl>(Decl.getDecl()); + if (FD && FD->getName() == AA->getAliasee() && + Name.contains(llvm::FunctionSamples::UniqSuffix)) { + addDeferredDeclToEmit(Decl); + } + } + } + // If there is a definition in the module, then it wins over the alias. // This is dubious, but allow it to be safe. Just ignore the alias. llvm::GlobalValue *Entry = GetGlobalValue(MangledName); diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 1b67d4354efc0..e7d3f0276566c 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -613,6 +613,7 @@ class CodeGenModule : public CodeGenTypeCache { // related attributes. bool shouldEmitCUDAGlobalVar(const VarDecl *VD) const; bool shouldOpportunisticallyEmitVTables(); + bool shouldEmitUniqLinkageName(GlobalDecl GD); /// Map used to be sure we don't emit the same CompoundLiteral twice. llvm::DenseMap<const CompoundLiteralExpr *, llvm::GlobalVariable *> EmittedCompoundLiterals; diff --git a/clang/test/CodeGen/unique-internal-linkage-names-alias.c b/clang/test/CodeGen/unique-internal-linkage-names-alias.c index 85345233ad507..e9cedc9dd8957 100644 --- a/clang/test/CodeGen/unique-internal-linkage-names-alias.c +++ b/clang/test/CodeGen/unique-internal-linkage-names-alias.c @@ -6,5 +6,5 @@ static long foo(const struct A*p); long bar(const struct A*p); long bar(const struct A*p) __attribute__((__alias__("foo"))); -// CHECK: define internal i64 @_ZL3fooPK1A.__uniq.[[ATTR:[0-9]+]](ptr noundef %p) #1 { +// CHECK: define internal i64 @_ZL3fooPK1A.__uniq.[[ATTR:[0-9]+]](ptr noundef %p) #0 { static long foo(const struct A*p) {return 1;} >From 3beeb6a17ba5e3e1cc8be455505633aec89e9d94 Mon Sep 17 00:00:00 2001 From: h2h <h...@meta.com> Date: Mon, 7 Jul 2025 13:50:33 -0700 Subject: [PATCH 5/6] Make the original function GlobalAlias to avoid broken references in the inline assembly --- clang/lib/CodeGen/CGCall.cpp | 18 +++++++++++++++ clang/lib/CodeGen/CodeGenModule.cpp | 35 +++++++++++++++++++++++++++-- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index fd75de42515da..e44d9d3c6691c 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -5741,6 +5741,24 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, IRFuncTy = OrigFn->getFunctionType(); } + // Propogate Error Attribute if Callee is declared within the function body + // e.g. + // void foo() { + // __extern__ void nocall(void) __attribute__((__error__(msg))); + // if (nobranch) + // nocall(); + // } + if (CalleePtr && CalleeDecl) { + if (const auto *EA = CalleeDecl->getAttr<ErrorAttr>()) { + if (EA->isError()) + dyn_cast<llvm::Function>(CalleePtr)->addFnAttr("dontcall-error", + EA->getUserDiagnostic()); + else if (EA->isWarning()) + dyn_cast<llvm::Function>(CalleePtr)->addFnAttr("dontcall-warn", + EA->getUserDiagnostic()); + } + } + // 3. Perform the actual call. // Deactivate any cleanups that we're supposed to do immediately before diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 1c9c9c04b6d4a..ae4273efcb4da 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -6227,6 +6227,7 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD, /*DontDefer=*/true, ForDefinition)); + llvm::GlobalAlias *GA = nullptr; if (!getLangOpts().CPlusPlus && getCXXABI().getMangleContext().shouldMangleDeclName(D)) { // -funique-internal-linkage-names may change the symbol name of C function. @@ -6235,9 +6236,17 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD, if (II->getName() != GV->getName() && GV->getName().contains(llvm::FunctionSamples::UniqSuffix)) { if (llvm::GlobalValue *GVDef = - getModule().getNamedValue(D->getName())) { + getModule().getNamedValue(II->getName())) { GVDef->replaceAllUsesWith(GV); - GVDef->removeFromParent(); + GVDef->eraseFromParent(); + } else if (!D->hasAttr<AlwaysInlineAttr>() && + !D->hasAttr<GNUInlineAttr>()) { + // Create a GlobalAlias to the original symbol in case it was + // referenced in the inline assembly + unsigned AS = GV->getType()->getPointerAddressSpace(); + GA = llvm::GlobalAlias::create(GV->getValueType(), AS, + llvm::GlobalValue::InternalLinkage, + II->getName(), GV, &getModule()); } } } @@ -6282,6 +6291,28 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD, SetLLVMFunctionAttributesForDefinition(D, Fn); + // Avoid extra uses of the internal GlobalAlias if Callee has + // __attribute__((error)). + for (auto BB = Fn->begin(); GA && BB != Fn->end(); BB++) { + for (auto &I : *BB) { + if (auto *CI = dyn_cast<llvm::CallInst>(&I)) { + if (auto *Callee = CI->getCalledFunction()) { + if (Callee->hasFnAttribute("dontcall-error")) { + GA->eraseFromParent(); + GA = nullptr; + break; + } + } + } + } + } + + // Set Attributes to perserve the internal GlobalAlias + if (GA) { + SetCommonAttributes(GD, GA); + addUsedOrCompilerUsedGlobal(GA); + } + if (const ConstructorAttr *CA = D->getAttr<ConstructorAttr>()) AddGlobalCtor(Fn, CA->getPriority()); if (const DestructorAttr *DA = D->getAttr<DestructorAttr>()) >From 0003a3f53bbaad91b1222f3549bf020ff0087772 Mon Sep 17 00:00:00 2001 From: h2h <h...@meta.com> Date: Tue, 8 Jul 2025 02:39:13 -0700 Subject: [PATCH 6/6] Create GlobalAlias for AlwaysInline internal functions --- clang/lib/CodeGen/CodeGenModule.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index ae4273efcb4da..e7258197936ed 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -6239,8 +6239,7 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD, getModule().getNamedValue(II->getName())) { GVDef->replaceAllUsesWith(GV); GVDef->eraseFromParent(); - } else if (!D->hasAttr<AlwaysInlineAttr>() && - !D->hasAttr<GNUInlineAttr>()) { + } else if (!D->hasAttr<GNUInlineAttr>()) { // Create a GlobalAlias to the original symbol in case it was // referenced in the inline assembly unsigned AS = GV->getType()->getPointerAddressSpace(); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits