[clang] [Clang] Allow vanilla C function symbol name to be used in __attribute__((alias)) when -funique-internal-linkage-names is specified (PR #145652)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jul 9 08:04:52 PDT 2025
https://github.com/HighW4y2H3ll updated https://github.com/llvm/llvm-project/pull/145652
>From 9a29dd6fa3f28bf507f047a22597f8510bd096b3 Mon Sep 17 00:00:00 2001
From: h2h <h2h at meta.com>
Date: Tue, 24 Jun 2025 23:24:32 -0700
Subject: [PATCH 1/7] [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 <h2h at meta.com>
Date: Wed, 25 Jun 2025 16:22:49 -0700
Subject: [PATCH 2/7] 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 <h2h at meta.com>
Date: Thu, 3 Jul 2025 13:33:44 -0700
Subject: [PATCH 3/7] 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 <h2h at meta.com>
Date: Sun, 6 Jul 2025 13:17:35 -0700
Subject: [PATCH 4/7] 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 <h2h at meta.com>
Date: Mon, 7 Jul 2025 13:50:33 -0700
Subject: [PATCH 5/7] 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 <h2h at meta.com>
Date: Tue, 8 Jul 2025 02:39:13 -0700
Subject: [PATCH 6/7] 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();
>From cab9bf6dde61ee8f337f33aac47fbd14ae33ce8f Mon Sep 17 00:00:00 2001
From: h2h <h2h at meta.com>
Date: Tue, 8 Jul 2025 21:43:17 -0700
Subject: [PATCH 7/7] Check static __always_inline/inline functions to avoid
inline assembly breakages
---
clang/lib/CodeGen/CodeGenModule.cpp | 68 ++++++++++++++++++++++++++---
clang/lib/CodeGen/CodeGenModule.h | 12 +++++
2 files changed, 75 insertions(+), 5 deletions(-)
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index e7258197936ed..47d4603bcc6d7 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -775,6 +775,7 @@ void CodeGenModule::clear() {
DeferredAnnotations.clear();
if (OpenMPRuntime)
OpenMPRuntime->clear();
+ DeferredMaybeInlineFunctions.clear();
}
void InstrProfStats::reportDiagnostics(DiagnosticsEngine &Diags,
@@ -940,6 +941,7 @@ void CodeGenModule::Release() {
emitAtAvailableLinkGuard();
if (Context.getTargetInfo().getTriple().isWasm())
EmitMainVoidAlias();
+ FixupMaybeInlineFunctions();
if (getTriple().isAMDGPU() ||
(getTriple().isSPIRV() && getTriple().getVendor() == llvm::Triple::AMD)) {
@@ -6213,6 +6215,10 @@ void CodeGenModule::HandleCXXStaticMemberVarInstantiation(VarDecl *VD) {
EmitTopLevelDecl(VD);
}
+static bool hasInlineAttr(const FunctionDecl *Decl) {
+ return Decl->hasAttr<AlwaysInlineAttr>() || Decl->hasAttr<GNUInlineAttr>();
+}
+
void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD,
llvm::GlobalValue *GV) {
const auto *D = cast<FunctionDecl>(GD.getDecl());
@@ -6239,7 +6245,7 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD,
getModule().getNamedValue(II->getName())) {
GVDef->replaceAllUsesWith(GV);
GVDef->eraseFromParent();
- } else if (!D->hasAttr<GNUInlineAttr>()) {
+ } else {
// Create a GlobalAlias to the original symbol in case it was
// referenced in the inline assembly
unsigned AS = GV->getType()->getPointerAddressSpace();
@@ -6294,22 +6300,43 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD,
// __attribute__((error)).
for (auto BB = Fn->begin(); GA && BB != Fn->end(); BB++) {
for (auto &I : *BB) {
- if (auto *CI = dyn_cast<llvm::CallInst>(&I)) {
+ bool shouldEraseAlias = false;
+ if (auto *CI = dyn_cast<llvm::CallBase>(&I)) {
if (auto *Callee = CI->getCalledFunction()) {
- if (Callee->hasFnAttribute("dontcall-error")) {
- GA->eraseFromParent();
+ if (MustInlinedFunctions.contains(Callee->getName())) {
+ // Callee is a known always inline, inline assembly
+ if (hasInlineAttr(D))
+ MustInlinedFunctions.insert(Fn->getName());
+ shouldEraseAlias = true;
+ } else if (Callee->hasFnAttribute("dontcall-error")) {
+ // Callee has Error Attribute
+ shouldEraseAlias = true;
+ } else if (Callee->isDeclaration() && !Callee->isIntrinsic() &&
+ hasInlineAttr(D)) {
+ // Callee has not emitted. Defer this check to a later stage
+ DeferredMaybeInlineFunctions[GD] = Callee;
GA = nullptr;
break;
}
+ } else if (CI->isInlineAsm() && hasInlineAttr(D)) {
+ // Avoid alias towards always inline assembly to allow inlining
+ MustInlinedFunctions.insert(Fn->getName());
+ shouldEraseAlias = true;
}
}
+ if (shouldEraseAlias) {
+ GA->eraseFromParent();
+ GA = nullptr;
+ break;
+ }
}
}
- // Set Attributes to perserve the internal GlobalAlias
+ // Set Attributes to perserve the internal GlobalValues
if (GA) {
SetCommonAttributes(GD, GA);
addUsedOrCompilerUsedGlobal(GA);
+ addUsedOrCompilerUsedGlobal(GV);
}
if (const ConstructorAttr *CA = D->getAttr<ConstructorAttr>())
@@ -7592,6 +7619,37 @@ void CodeGenModule::EmitMainVoidAlias() {
}
}
+void CodeGenModule::FixupMaybeInlineFunctions() {
+ // Check if GlobalAlias need to be removed
+ unsigned long sz = 0;
+ while (sz != DeferredMaybeInlineFunctions.size()) {
+ sz = DeferredMaybeInlineFunctions.size();
+ for (auto I = DeferredMaybeInlineFunctions.begin(); I != DeferredMaybeInlineFunctions.end();) {
+ const auto *D = cast<FunctionDecl>(I->first.getDecl());
+ auto *GA = GetGlobalValue(D->getName());
+ StringRef MangledName = getMangledName(I->first);
+ if (GA && MustInlinedFunctions.contains(I->second->getName())) {
+ MustInlinedFunctions.insert(MangledName);
+ GA->eraseFromParent();
+ I = DeferredMaybeInlineFunctions.erase(I);
+ } else
+ I++;
+ }
+ }
+ // Fixup attributes
+ for (auto &[Decl, Callee] : DeferredMaybeInlineFunctions) {
+ const auto *D = cast<FunctionDecl>(Decl.getDecl());
+ auto *GA = GetGlobalValue(D->getName());
+ StringRef MangledName = getMangledName(Decl);
+ auto *GV = GetGlobalValue(MangledName);
+ if (!GA || !GV)
+ continue;
+ SetCommonAttributes(Decl, GA);
+ addUsedOrCompilerUsedGlobal(GA);
+ addUsedOrCompilerUsedGlobal(GV);
+ }
+}
+
/// Turns the given pointer into a constant.
static llvm::Constant *GetPointerConstant(llvm::LLVMContext &Context,
const void *Ptr) {
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index e7d3f0276566c..bb05bdb8ca538 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -464,6 +464,14 @@ class CodeGenModule : public CodeGenTypeCache {
std::vector<llvm::WeakTrackingVH> LLVMUsed;
std::vector<llvm::WeakTrackingVH> LLVMCompilerUsed;
+ /// Set of function names that must be inlined. e.g.
+ /// __always_inline void foo() { asm (...); }
+ llvm::DenseSet<StringRef> MustInlinedFunctions;
+
+ /// Deferred always inline functions that has a generated GlobalAlias due to
+ /// -funique-internal-linkage-names
+ llvm::MapVector<GlobalDecl, llvm::Function *> DeferredMaybeInlineFunctions;
+
/// Store the list of global constructors and their respective priorities to
/// be emitted when the translation unit is complete.
CtorList GlobalCtors;
@@ -1257,6 +1265,10 @@ class CodeGenModule : public CodeGenTypeCache {
/// Emit an alias for "main" if it has no arguments (needed for wasm).
void EmitMainVoidAlias();
+ /// Fixup attributes or remove GlobalAlias for always inline functions due to
+ /// -funique-internal-linkage-names
+ void FixupMaybeInlineFunctions();
+
/// Tell the consumer that this variable has been instantiated.
void HandleCXXStaticMemberVarInstantiation(VarDecl *VD);
More information about the cfe-commits
mailing list