Index: clang/include/clang/Basic/Attr.td =================================================================== --- clang/include/clang/Basic/Attr.td +++ clang/include/clang/Basic/Attr.td @@ -2156,6 +2156,17 @@ let Documentation = [Undocumented]; } +def UniqueInternalLinkageSuffix : Attr { + // This attribute has no spellings as it is only ever created implicitly. + // It is used to tag function decls that are 'C' functions and have + // internal linkage along with the unique suffix. Such names must be + // mangled and this attribute is used to denote that. + let Spellings = []; + let Subjects = SubjectList<[Function], ErrorDiag>; + let SemaHandler = 0; + let Documentation = [Undocumented]; +} + def Packed : InheritableAttr { let Spellings = [GCC<"packed">]; // let Subjects = [Tag, Field]; Index: clang/lib/AST/ItaniumMangle.cpp =================================================================== --- clang/lib/AST/ItaniumMangle.cpp +++ clang/lib/AST/ItaniumMangle.cpp @@ -621,6 +621,10 @@ if (FD->hasAttr()) return true; + // Unique Internal Linkage functions with suffixes need mangling. + if (FD->hasAttr()) + return true; + // "main" is not mangled. if (FD->isMain()) return false; Index: clang/lib/CodeGen/BackendUtil.cpp =================================================================== --- clang/lib/CodeGen/BackendUtil.cpp +++ clang/lib/CodeGen/BackendUtil.cpp @@ -83,7 +83,6 @@ #include "llvm/Transforms/Utils/EntryExitInstrumenter.h" #include "llvm/Transforms/Utils/NameAnonGlobals.h" #include "llvm/Transforms/Utils/SymbolRewriter.h" -#include "llvm/Transforms/Utils/UniqueInternalLinkageNames.h" #include using namespace clang; using namespace llvm; @@ -790,12 +789,6 @@ if (!CodeGenOpts.RewriteMapFiles.empty()) addSymbolRewriterPass(CodeGenOpts, &MPM); - // Add UniqueInternalLinkageNames Pass which renames internal linkage symbols - // with unique names. - if (CodeGenOpts.UniqueInternalLinkageNames) { - MPM.add(createUniqueInternalLinkageNamesPass()); - } - if (Optional Options = getGCOVOptions(CodeGenOpts, LangOpts)) { MPM.add(createGCOVProfilerPass(*Options)); if (CodeGenOpts.getDebugInfo() == codegenoptions::NoDebugInfo) @@ -1148,7 +1141,6 @@ // non-integrated assemblers don't recognize .cgprofile section. PTO.CallGraphProfile = !CodeGenOpts.DisableIntegratedAS; PTO.Coroutines = LangOpts.Coroutines; - PTO.UniqueLinkageNames = CodeGenOpts.UniqueInternalLinkageNames; PassInstrumentationCallbacks PIC; StandardInstrumentations SI(CodeGenOpts.DebugPassManager); Index: clang/lib/CodeGen/CGCall.cpp =================================================================== --- clang/lib/CodeGen/CGCall.cpp +++ clang/lib/CodeGen/CGCall.cpp @@ -2085,6 +2085,16 @@ } } + // Add "sample-profile-suffix-elision-policy" attribute for internal linkage + // functions with -funique-internal-linkage-names. + if (TargetDecl && CodeGenOpts.UniqueInternalLinkageNames) { + if (auto *Fn = dyn_cast(TargetDecl)) { + if (this->getFunctionLinkage(Fn) == llvm::GlobalValue::InternalLinkage) + FuncAttrs.addAttribute("sample-profile-suffix-elision-policy", + "selected"); + } + } + // Collect non-call-site function IR attributes from declaration-specific // information. if (!AttrOnCallSite) { Index: clang/lib/CodeGen/CodeGenModule.h =================================================================== --- clang/lib/CodeGen/CodeGenModule.h +++ clang/lib/CodeGen/CodeGenModule.h @@ -28,6 +28,7 @@ #include "clang/Basic/SanitizerBlacklist.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/XRayLists.h" +#include "clang/Lex/PreprocessorOptions.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" @@ -72,7 +73,6 @@ class LangOptions; class CodeGenOptions; class HeaderSearchOptions; -class PreprocessorOptions; class DiagnosticsEngine; class AnnotateAttr; class CXXDestructorDecl; @@ -311,6 +311,7 @@ const TargetInfo &Target; std::unique_ptr ABI; llvm::LLVMContext &VMContext; + std::string ModuleNameHash = ""; std::unique_ptr TBAA; @@ -586,6 +587,8 @@ /// Return true iff an Objective-C runtime has been configured. bool hasObjCRuntime() { return !!ObjCRuntime; } + const std::string &getModuleNameHash() const { return ModuleNameHash; } + /// Return a reference to the configured OpenCL runtime. CGOpenCLRuntime &getOpenCLRuntime() { assert(OpenCLRuntime != nullptr); Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -180,6 +180,31 @@ // CoverageMappingModuleGen object. if (CodeGenOpts.CoverageMapping) CoverageMapping.reset(new CoverageMappingModuleGen(*this, *CoverageInfo)); + + // Generate the module name hash here if needed. + if (CodeGenOpts.UniqueInternalLinkageNames && + !getModule().getSourceFileName().empty()) { + std::string Path = getModule().getSourceFileName(); + // Check if a path substitution is needed from the MacroPrefixMap. + for (const auto &Entry : PPO.MacroPrefixMap) + if (Path.rfind(Entry.first, 0) != std::string::npos) { + Path = Entry.second + Path.substr(Entry.first.size()); + break; + } + llvm::MD5 Md5; + Md5.update(Path); + llvm::MD5::MD5Result R; + Md5.final(R); + SmallString<32> Str; + llvm::MD5::stringifyResult(R, Str); + // Convert MD5hash to Decimal. Demangler suffixes can either contain + // numbers or characters but not both. + llvm::APInt IntHash(128, Str.str(), 16); + // Prepend "__uniq" before the hash for tools like profilers to understand + // that this symbol is of internal linkage type. + ModuleNameHash = (Twine(".__uniq.") + + Twine(IntHash.toString(10, false))).str(); + } } CodeGenModule::~CodeGenModule() {} @@ -1142,13 +1167,28 @@ } } -static std::string getMangledNameImpl(const CodeGenModule &CGM, GlobalDecl GD, +// 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(); + if (!CGM.getModuleNameHash().empty() && + ((isa(D) && + CGM.getFunctionLinkage(GD) == llvm::GlobalValue::InternalLinkage) || + (isa(D) && CGM.getContext().GetGVALinkageForVariable( + cast(D)) == GVA_Internal))) + return true; + return false; +} + +static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD, const NamedDecl *ND, bool OmitMultiVersionMangling = false) { SmallString<256> Buffer; llvm::raw_svector_ostream Out(Buffer); MangleContext &MC = CGM.getCXXABI().getMangleContext(); - if (MC.shouldMangleDeclName(ND)) + bool ShouldMangle = MC.shouldMangleDeclName(ND); + if (ShouldMangle) MC.mangleName(GD.getWithDecl(ND), Out); else { IdentifierInfo *II = ND->getIdentifier(); @@ -1166,6 +1206,20 @@ } } + // Check if the module name hash should be appended for internal linkage + // symbols. This should come before multi-version target suffixes are + // appended. This is to keep the name and module hash suffix of the + // internal linkage function together. The unique suffix should only be + // added when name mangling is done to make sure that the final name can + // be properly demangled. For example, for C functions without prototypes, + // name mangling is not done and the unique suffix should not be appeneded + // then. + if (ShouldMangle && isUniqueInternalLinkageDecl(GD, CGM)) { + assert(CGM.getCodeGenOpts().UniqueInternalLinkageNames && + "Hash computed when not explicitly requested"); + Out << CGM.getModuleNameHash(); + } + if (const auto *FD = dyn_cast(ND)) if (FD->isMultiVersion() && !OmitMultiVersionMangling) { switch (FD->getMultiVersionKind()) { @@ -5500,6 +5554,17 @@ if (FD->isConsteval()) return; + // In C, functions with internal linkage which need unique suffix names need + // to be mangled. Add the UniqueInternalLinkageAttr to this decl so that the + // mangler does the right thing. Check if the function has a prototype as + // the mangler will not do the right thing without one. + if (D->getKind() == Decl::Function && !getLangOpts().CPlusPlus && + cast(D)->getType()->getAs() && + isUniqueInternalLinkageDecl(cast(D), *this)) { + D->addAttr(UniqueInternalLinkageSuffixAttr::CreateImplicit( + getCXXABI().getMangleContext().getASTContext())); + } + switch (D->getKind()) { case Decl::CXXConversion: case Decl::CXXMethod: Index: clang/test/CodeGen/unique-internal-linkage-names-dwarf.c =================================================================== --- /dev/null +++ clang/test/CodeGen/unique-internal-linkage-names-dwarf.c @@ -0,0 +1,31 @@ +// This test checks if C functions with internal linkage names are mangled +// and the module hash suffixes attached including emitting DW_AT_linkage_name. +// +// RUN: %clang_cc1 -triple x86_64-unknown-linux -debug-info-kind=limited -dwarf-version=4 -emit-obj -o %t.o %s +// RUN: llvm-nm %t.o | FileCheck %s --check-prefix=PLAIN-NM +// RUN: llvm-dwarfdump %t.o | FileCheck %s --check-prefix=PLAIN-DWARF +// RUN: %clang_cc1 -triple x86_64-unknown-linux -debug-info-kind=limited -dwarf-version=4 -funique-internal-linkage-names -emit-obj -o %t.o %s +// RUN: llvm-nm %t.o | FileCheck %s --check-prefix=UNIQUE-NM +// RUN: llvm-dwarfdump %t.o | FileCheck %s --check-prefix=UNIQUE-DWARF + +// RUN: %clang_cc1 -triple x86_64-unknown-linux -debug-info-kind=limited -dwarf-version=5 -emit-obj -o %t.o %s +// RUN: llvm-nm %t.o | FileCheck %s --check-prefix=PLAIN-NM +// RUN: llvm-dwarfdump %t.o | FileCheck %s --check-prefix=PLAIN-DWARF +// RUN: %clang_cc1 -triple x86_64-unknown-linux -debug-info-kind=limited -dwarf-version=5 -funique-internal-linkage-names -emit-obj -o %t.o %s +// RUN: llvm-nm %t.o | FileCheck %s --check-prefix=UNIQUE-NM +// RUN: llvm-dwarfdump %t.o | FileCheck %s --check-prefix=UNIQUE-DWARF + +static int foo(void) { + return 0; +} + +void baz() { + foo(); +} + +// PLAIN-NM: foo{{$}} +// PLAIN-DWARF: DW_AT_name{{.*}}("foo") +// PLAIN-DWARF-NOT: DW_AT_linkage_name +// UNIQUE-NM: _ZL3foov.__uniq.{{[0-9]+}} +// UNIQUE-DWARF-DAG: DW_AT_name{{.*}}("foo") +// UNIQUE-DWARF-DAG: DW_AT_linkage_name{{.*}}("_ZL3foov.__uniq.{{[0-9]+}}") Index: clang/test/CodeGen/unique-internal-linkage-names-dwarf.cpp =================================================================== --- /dev/null +++ clang/test/CodeGen/unique-internal-linkage-names-dwarf.cpp @@ -0,0 +1,31 @@ +// This test checks if C++ functions with internal linkage names are mangled +// and the module hash suffixes attached including emitting DW_AT_linkage_name. +// +// RUN: %clang_cc1 -triple x86_64-unknown-linux -debug-info-kind=limited -dwarf-version=4 -emit-obj -o %t.o %s +// RUN: llvm-nm %t.o | FileCheck %s --check-prefix=PLAIN-NM +// RUN: llvm-dwarfdump %t.o | FileCheck %s --check-prefix=PLAIN-DWARF +// RUN: %clang_cc1 -triple x86_64-unknown-linux -debug-info-kind=limited -dwarf-version=4 -funique-internal-linkage-names -emit-obj -o %t.o %s +// RUN: llvm-nm %t.o | FileCheck %s --check-prefix=UNIQUE-NM +// RUN: llvm-dwarfdump %t.o | FileCheck %s --check-prefix=UNIQUE-DWARF + +// RUN: %clang_cc1 -triple x86_64-unknown-linux -debug-info-kind=limited -dwarf-version=5 -emit-obj -o %t.o %s +// RUN: llvm-nm %t.o | FileCheck %s --check-prefix=PLAIN-NM +// RUN: llvm-dwarfdump %t.o | FileCheck %s --check-prefix=PLAIN-DWARF +// RUN: %clang_cc1 -triple x86_64-unknown-linux -debug-info-kind=limited -dwarf-version=5 -funique-internal-linkage-names -emit-obj -o %t.o %s +// RUN: llvm-nm %t.o | FileCheck %s --check-prefix=UNIQUE-NM +// RUN: llvm-dwarfdump %t.o | FileCheck %s --check-prefix=UNIQUE-DWARF + +static int foo(void) { + return 0; +} + +void baz() { + foo(); +} + +// PLAIN-NM: _ZL3foov{{$}} +// PLAIN-DWARF-DAG: DW_AT_name{{.*}}("foo") +// PLAIN-DWARF-DAG: DW_AT_linkage_name{{.*}}("_ZL3foov") +// UNIQUE-NM: _ZL3foov.__uniq.{{[0-9]+}} +// UNIQUE-DWARF-DAG: DW_AT_name{{.*}}("foo") +// UNIQUE-DWARF-DAG: DW_AT_linkage_name{{.*}}("_ZL3foov.__uniq.{{[0-9]+}}") Index: clang/test/CodeGen/unique-internal-linkage-names.cpp =================================================================== --- clang/test/CodeGen/unique-internal-linkage-names.cpp +++ clang/test/CodeGen/unique-internal-linkage-names.cpp @@ -1,10 +1,7 @@ // This test checks if internal linkage symbols get unique names with // -funique-internal-linkage-names option. // RUN: %clang_cc1 -triple x86_64 -x c++ -S -emit-llvm -o - < %s | FileCheck %s --check-prefix=PLAIN -// RUN: %clang_cc1 -triple x86_64 -x c++ -O0 -S -emit-llvm -funique-internal-linkage-names -o - < %s | FileCheck %s --check-prefix=UNIQUE -// RUN: %clang_cc1 -triple x86_64 -x c++ -O1 -S -emit-llvm -funique-internal-linkage-names -o - < %s | FileCheck %s --check-prefix=UNIQUEO1 -// RUN: %clang_cc1 -triple x86_64 -x c++ -O0 -S -emit-llvm -fexperimental-new-pass-manager -funique-internal-linkage-names -o - < %s | FileCheck %s --check-prefix=UNIQUE -// RUN: %clang_cc1 -triple x86_64 -x c++ -O1 -S -emit-llvm -fexperimental-new-pass-manager -funique-internal-linkage-names -o - < %s | FileCheck %s --check-prefix=UNIQUEO1 +// RUN: %clang_cc1 -triple x86_64 -x c++ -S -emit-llvm -funique-internal-linkage-names -o - < %s | FileCheck %s --check-prefix=UNIQUE static int glob; static int foo() { @@ -53,15 +50,13 @@ // PLAIN: define weak_odr i32 ()* @_ZL4mverv.resolver() // PLAIN: define internal i32 @_ZL4mverv() // PLAIN: define internal i32 @_ZL4mverv.sse4.2() +// PLAIN-NOT: "sample-profile-suffix-elision-policy" // UNIQUE: @_ZL4glob.__uniq.{{[0-9]+}} = internal global // UNIQUE: @_ZZ8retAnonMvE5fGlob.__uniq.{{[0-9]+}} = internal global // UNIQUE: @_ZN12_GLOBAL__N_16anon_mE.__uniq.{{[0-9]+}} = internal global // UNIQUE: define internal i32 @_ZL3foov.__uniq.{{[0-9]+}}() // UNIQUE: define internal i32 @_ZN12_GLOBAL__N_14getMEv.__uniq.{{[0-9]+}} -// UNIQUE: define weak_odr i32 ()* @_ZL4mverv.resolver() +// UNIQUE: define weak_odr i32 ()* @_ZL4mverv.__uniq.{{[0-9]+}}.resolver() // UNIQUE: define internal i32 @_ZL4mverv.__uniq.{{[0-9]+}}() -// UNIQUE: define internal i32 @_ZL4mverv.sse4.2.__uniq.{{[0-9]+}} -// UNIQUEO1: define internal i32 @_ZL3foov.__uniq.{{[0-9]+}}() -// UNIQUEO1: define weak_odr i32 ()* @_ZL4mverv.resolver() -// UNIQUEO1: define internal i32 @_ZL4mverv.__uniq.{{[0-9]+}}() -// UNIQUEO1: define internal i32 @_ZL4mverv.sse4.2.__uniq.{{[0-9]+}} +// UNIQUE: define internal i32 @_ZL4mverv.__uniq.{{[0-9]+}}.sse4.2 +// UNIQUE: "sample-profile-suffix-elision-policy"