https://github.com/SharonXSharon updated https://github.com/llvm/llvm-project/pull/219261
>From dcb89b24bafaaac774a6a532f21230acc226b4f6 Mon Sep 17 00:00:00 2001 From: Sharon Xu <[email protected]> Date: Mon, 24 Aug 2026 13:52:01 -0700 Subject: [PATCH 1/2] [clang] Apply -funique-internal-linkage-names to internal global variables -funique-internal-linkage-names appends a `.__uniq.<module hash>` suffix to internal-linkage symbols so they are distinguishable across a build. Until now the suffix was applied only to functions; internal global variables were left alone, which was originally deferred until demanglers could cope with a suffix on a data symbol. Apply the suffix to internal-linkage variables as well. This lets profiling tools map a sampled data address back to the exact symbol that produced it, which is otherwise ambiguous when several translation units define same-named statics. LLVM's demangler handles suffixed data symbols today: $ llvm-cxxfilt _ZL8glob_foo.__uniq.123 glob_foo (.__uniq.123) GNU libiberty does not yet. Its clone-suffix handling only runs for symbols carrying a <bare-function-type>, so `nm -C`, `objdump -C` and gdb still print suffixed *data* symbols unchanged. This is a pre-existing libiberty limitation rather than something specific to this suffix -- `.part.N` on a data symbol fails the same way -- and it needs a separate fix in libiberty/cp-demangle.c. Since -funique-internal-linkage-names is opt-in, default builds are unaffected. The asm-label exclusion added in 774c4c9b098 is preserved and now applies to variables too: a static variable with an asm label keeps its label verbatim. --- clang/lib/AST/ItaniumMangle.cpp | 12 ++++----- clang/lib/CodeGen/CodeGenModule.cpp | 11 +++++--- .../CodeGen/unique-internal-linkage-names.cpp | 27 ++++++++++++------- .../unique-internal-linkage-names-dwarf.c | 6 ++--- .../unique-internal-linkage-names-dwarf.cpp | 14 +++++----- 5 files changed, 40 insertions(+), 30 deletions(-) diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 7fb162a68fe88..dad83fb12ece6 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -725,20 +725,18 @@ bool ItaniumMangleContextImpl::isInternalLinkageDecl(const NamedDecl *ND) { return false; } -// Check if this Function Decl needs a unique internal linkage name. +// Check if this Decl needs a unique internal linkage name. bool ItaniumMangleContextImpl::isUniqueInternalLinkageDecl( const NamedDecl *ND) { if (!NeedsUniqueInternalLinkageNames || !ND) return false; - const auto *FD = dyn_cast<FunctionDecl>(ND); - if (!FD) - return false; - // For C functions without prototypes, return false as their // names should not be mangled. - if (!FD->getType()->getAs<FunctionProtoType>()) - return false; + if (const auto *FD = dyn_cast<FunctionDecl>(ND)) { + if (!FD->getType()->getAs<FunctionProtoType>()) + return false; + } if (isInternalLinkageDecl(ND)) return true; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 435f67542268a..25c6c3d2bf63d 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -2460,14 +2460,17 @@ static void AppendCPUSpecificCPUDispatchMangling(const CodeGenModule &CGM, Out << ".resolver"; } -// Returns true if GD is a function decl with internal linkage and +// Returns true if GD is a function/var decl with internal linkage and // needs a unique suffix after the mangled name. static bool isUniqueInternalLinkageDecl(GlobalDecl GD, CodeGenModule &CGM) { const Decl *D = GD.getDecl(); - return !CGM.getModuleNameHash().empty() && isa<FunctionDecl>(D) && - !D->hasAttr<AsmLabelAttr>() && - (CGM.getFunctionLinkage(GD) == llvm::GlobalValue::InternalLinkage); + if (CGM.getModuleNameHash().empty() || D->hasAttr<AsmLabelAttr>()) + return false; + return (isa<FunctionDecl>(D) && + CGM.getFunctionLinkage(GD) == llvm::GlobalValue::InternalLinkage) || + (isa<VarDecl>(D) && CGM.getContext().GetGVALinkageForVariable( + cast<VarDecl>(D)) == GVA_Internal); } static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD, diff --git a/clang/test/CodeGen/unique-internal-linkage-names.cpp b/clang/test/CodeGen/unique-internal-linkage-names.cpp index b5c4824575372..a65813a6fb338 100644 --- a/clang/test/CodeGen/unique-internal-linkage-names.cpp +++ b/clang/test/CodeGen/unique-internal-linkage-names.cpp @@ -64,8 +64,13 @@ static int asm_label() asm("custom_label"); static int asm_label() { return 0; } int call_asm_label() { return asm_label(); } +// Likewise for a static variable with an asm label. +static int asm_label_var asm("custom_var_label"); +int read_asm_label_var() { return asm_label_var; } + // PLAIN: @_ZL4glob = internal global // PLAIN: @_ZZ8retAnonMvE5fGlob = internal global +// PLAIN: @custom_var_label = internal global // PLAIN: @_ZN12_GLOBAL__N_16anon_mE = internal global // PLAIN: define internal noundef i32 @_ZL3foov() // PLAIN: define internal noundef i32 @_ZN12_GLOBAL__N_14getMEv @@ -76,10 +81,11 @@ int call_asm_label() { return asm_label(); } // PLAIN: define internal noundef i32 @_ZL4mverv() // PLAIN: define internal noundef i32 @_ZL4mverv.sse4.2() // PLAIN-NOT: "sample-profile-suffix-elision-policy" -// UNIQUE: @_ZL4glob = internal global -// UNIQUE: @_ZZ8retAnonMvE5fGlob = internal global -// UNIQUE: @_ZN12_GLOBAL__N_16anon_mE = internal global -// UNIQUE: define internal noundef i32 @_ZL3foov.[[MODHASH:__uniq.[0-9]+]]() #[[#ATTR:]] { +// UNIQUE: @_ZL4glob.[[MODHASH:__uniq.[0-9]+]] = internal global +// UNIQUE: @_ZZ8retAnonMvE5fGlob.[[MODHASH]] = internal global +// UNIQUE: @custom_var_label = internal global +// UNIQUE: @_ZN12_GLOBAL__N_16anon_mE.[[MODHASH]] = internal global +// UNIQUE: define internal noundef i32 @_ZL3foov.[[MODHASH]]() #[[#ATTR:]] { // UNIQUE: define internal noundef i32 @_ZN12_GLOBAL__N_14getMEv.[[MODHASH]] // UNIQUE: define internal ptr @_ZL4mverv.[[MODHASH]].resolver() // UNIQUE: define internal void @_ZN12_GLOBAL__N_11AC1Ev.__uniq.68358509610070717889884130747296293671 @@ -92,9 +98,10 @@ int call_asm_label() { return asm_label(); } // Expected module path and unique ID // /repro/src/path/unique-internal-linkage-names.cpp => __uniq.5283619504002921413211664429594652319 -// UNIQUE-PATH-MAP-LINUX: @_ZL4glob = internal global -// UNIQUE-PATH-MAP-LINUX: @_ZZ8retAnonMvE5fGlob = internal global -// UNIQUE-PATH-MAP-LINUX: @_ZN12_GLOBAL__N_16anon_mE = internal global +// UNIQUE-PATH-MAP-LINUX: @_ZL4glob.__uniq.5283619504002921413211664429594652319 = internal global +// UNIQUE-PATH-MAP-LINUX: @_ZZ8retAnonMvE5fGlob.__uniq.5283619504002921413211664429594652319 = internal global +// UNIQUE-PATH-MAP-LINUX: @custom_var_label = internal global +// UNIQUE-PATH-MAP-LINUX: @_ZN12_GLOBAL__N_16anon_mE.__uniq.5283619504002921413211664429594652319 = internal global // UNIQUE-PATH-MAP-LINUX: define internal noundef i32 @_ZL3foov.__uniq.5283619504002921413211664429594652319() #[[#ATTR:]] { // UNIQUE-PATH-MAP-LINUX: define internal noundef i32 @_ZN12_GLOBAL__N_14getMEv.__uniq.5283619504002921413211664429594652319 // UNIQUE-PATH-MAP-LINUX: define internal ptr @_ZL4mverv.__uniq.5283619504002921413211664429594652319.resolver() @@ -107,9 +114,11 @@ int call_asm_label() { return asm_label(); } // Expected module path and unique ID // \repro\src\path\unique-internal-linkage-names.cpp => __uniq.68451533753012730514350177221027644473 +// Note: 'glob' is not mangled under the MS ABI, so it gets no unique suffix. // UNIQUE-PATH-MAP-WINDOWS: @glob = internal global -// UNIQUE-PATH-MAP-WINDOWS: @"?fGlob@?1??retAnonM@@YAHXZ@4HA" = internal global -// UNIQUE-PATH-MAP-WINDOWS: @"?anon_m@?{{.*}}@@3HA" = internal global +// UNIQUE-PATH-MAP-WINDOWS: @"?fGlob@?1??retAnonM@@YAHXZ@4HA.__uniq.68451533753012730514350177221027644473" = internal global +// UNIQUE-PATH-MAP-WINDOWS: @custom_var_label = internal global +// UNIQUE-PATH-MAP-WINDOWS: @"?anon_m@?{{.*}}@@3HA.__uniq.68451533753012730514350177221027644473" = internal global // UNIQUE-PATH-MAP-WINDOWS: ret ptr @"?foo@@YAHXZ.__uniq.68451533753012730514350177221027644473" // UNIQUE-PATH-MAP-WINDOWS: define internal noundef i32 @"?foo@@YAHXZ.__uniq.68451533753012730514350177221027644473" // UNIQUE-PATH-MAP-WINDOWS: define internal i32 @"?mver@@YAHXZ.__uniq.68451533753012730514350177221027644473.resolver"() diff --git a/clang/test/DebugInfo/Generic/unique-internal-linkage-names-dwarf.c b/clang/test/DebugInfo/Generic/unique-internal-linkage-names-dwarf.c index 5a401182450ab..8f9dc143654c9 100644 --- a/clang/test/DebugInfo/Generic/unique-internal-linkage-names-dwarf.c +++ b/clang/test/DebugInfo/Generic/unique-internal-linkage-names-dwarf.c @@ -33,9 +33,9 @@ void baz(void) { // PLAIN: distinct !DISubprogram(name: "bar"{{.*}}) // PLAIN-NOT: linkageName: // -// UNIQUE: @glob = internal global i32 -// UNIQUE: define internal i32 @_ZL3foov.[[MODHASH:__uniq.[0-9]+]]() +// UNIQUE: @_ZL4glob.[[MODHASH:__uniq.[0-9]+]] = internal global i32 +// UNIQUE: define internal i32 @_ZL3foov.[[MODHASH]]() // UNIQUE: define internal i32 @_ZL3bari.[[MODHASH]](i32 noundef %a) -// UNIQUE: distinct !DIGlobalVariable(name: "glob"{{.*}}) +// UNIQUE: distinct !DIGlobalVariable(name: "glob", linkageName: "_ZL4glob.[[MODHASH]]"{{.*}}) // UNIQUE: distinct !DISubprogram(name: "foo", linkageName: "_ZL3foov.[[MODHASH]]"{{.*}}) // UNIQUE: distinct !DISubprogram(name: "bar", linkageName: "_ZL3bari.[[MODHASH]]"{{.*}}) diff --git a/clang/test/DebugInfo/Generic/unique-internal-linkage-names-dwarf.cpp b/clang/test/DebugInfo/Generic/unique-internal-linkage-names-dwarf.cpp index cdd7062a3a009..e49fe5736092d 100644 --- a/clang/test/DebugInfo/Generic/unique-internal-linkage-names-dwarf.cpp +++ b/clang/test/DebugInfo/Generic/unique-internal-linkage-names-dwarf.cpp @@ -46,15 +46,15 @@ void baz() { // PLAIN-DAG: distinct !DIGlobalVariable(name: "glob_zip", linkageName: "_ZL8glob_zip"{{.*}}) // PLAIN-DAG: distinct !DISubprogram(name: "zip", linkageName: "_ZL3zipv"{{.*}}) -// UNIQUE-DAG: @_ZL8glob_foo = internal global i32 -// UNIQUE-DAG: define internal noundef i32 @_ZL3foov.[[MODHASH:__uniq\.[0-9]+]]() -// UNIQUE-DAG: distinct !DIGlobalVariable(name: "glob_foo", linkageName: "_ZL8glob_foo"{{.*}}) +// UNIQUE-DAG: @_ZL8glob_foo.[[MODHASH:__uniq\.[0-9]+]] = internal global i32 +// UNIQUE-DAG: define internal noundef i32 @_ZL3foov.[[MODHASH]]() +// UNIQUE-DAG: distinct !DIGlobalVariable(name: "glob_foo", linkageName: "_ZL8glob_foo.[[MODHASH]]"{{.*}}) // UNIQUE-DAG: distinct !DISubprogram(name: "foo", linkageName: "_ZL3foov.[[MODHASH]]"{{.*}}) -// UNIQUE-DAG: @_ZN12_GLOBAL__N_18glob_barE = internal global i32 +// UNIQUE-DAG: @_ZN12_GLOBAL__N_18glob_barE.[[MODHASH]] = internal global i32 // UNIQUE-DAG: define internal noundef i32 @_ZN12_GLOBAL__N_13barEv.[[MODHASH]]() -// UNIQUE-DAG: distinct !DIGlobalVariable(name: "glob_bar", linkageName: "_ZN12_GLOBAL__N_18glob_barE"{{.*}}) +// UNIQUE-DAG: distinct !DIGlobalVariable(name: "glob_bar", linkageName: "_ZN12_GLOBAL__N_18glob_barE.[[MODHASH]]"{{.*}}) // UNIQUE-DAG: distinct !DISubprogram(name: "bar", linkageName: "_ZN12_GLOBAL__N_13barEv.[[MODHASH]]"{{.*}}) -// UNIQUE-DAG: @_ZL8glob_zip = internal global i32 +// UNIQUE-DAG: @_ZL8glob_zip.[[MODHASH]] = internal global i32 // UNIQUE-DAG: define internal noundef i32 @_ZL3zipv.[[MODHASH]]() -// UNIQUE-DAG: distinct !DIGlobalVariable(name: "glob_zip", linkageName: "_ZL8glob_zip"{{.*}}) +// UNIQUE-DAG: distinct !DIGlobalVariable(name: "glob_zip", linkageName: "_ZL8glob_zip.[[MODHASH]]"{{.*}}) // UNIQUE-DAG: distinct !DISubprogram(name: "zip", linkageName: "_ZL3zipv.[[MODHASH]]"{{.*}}) >From 2714a9763911851f11ef2f927d1be7e45c2c4de4 Mon Sep 17 00:00:00 2001 From: Sharon Xu <[email protected]> Date: Fri, 4 Sep 2026 13:49:28 -0700 Subject: [PATCH 2/2] add documentation --- clang/docs/ReleaseNotes.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index ca0dbfa2af229..7b06d0ebd34a0 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -228,6 +228,14 @@ features cannot lower the translation-unit ABI level; - All options of the `-fzero-call-used-regs` compiler flag are now allowed on RISC-V. +- `-funique-internal-linkage-names` now gives internal global variables a + unique `.__uniq.<module-hash>` suffix, as it already does for functions. This + helps profiling tools distinguish static variables with the same name in + different source files. LLVM can demangle these suffixes for both functions + and data symbols. GNU libiberty can demangle suffixed function symbols, but + leaves suffixed data symbols unchanged. The option remains opt-in, and + variables with explicit assembly labels keep their original names. + ### Removed Compiler Flags ### Attribute Changes in Clang _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
