diff --git a/clang/include/clang/AST/Mangle.h b/clang/include/clang/AST/Mangle.h --- a/clang/include/clang/AST/Mangle.h +++ b/clang/include/clang/AST/Mangle.h @@ -110,6 +110,12 @@ virtual bool isDeviceMangleContext() const { return false; } virtual void setDeviceMangleContext(bool) {} + virtual bool isUniqueInternalLinkageDecl(const NamedDecl *ND) { + return false; + } + + virtual void needsUniqueInternalLinkageNames() { } + // FIXME: consider replacing raw_ostream & with something like SmallString &. void mangleName(GlobalDecl GD, raw_ostream &); virtual void mangleCXXName(GlobalDecl GD, raw_ostream &) = 0; diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -126,6 +126,7 @@ llvm::DenseMap Uniquifier; bool IsDevCtx = false; + bool NeedsUniqueInternalLinkageNames = false; public: explicit ItaniumMangleContextImpl(ASTContext &Context, @@ -140,6 +141,11 @@ return false; } + bool isUniqueInternalLinkageDecl(const NamedDecl *ND) override; + void needsUniqueInternalLinkageNames() override { + NeedsUniqueInternalLinkageNames = true; + } + bool isDeviceMangleContext() const override { return IsDevCtx; } void setDeviceMangleContext(bool IsDev) override { IsDevCtx = IsDev; } @@ -613,6 +619,33 @@ } +static bool isInternalLinkageDecl(const NamedDecl *ND) { + if (ND && ND->getFormalLinkage() == InternalLinkage && + !ND->isExternallyVisible() && + getEffectiveDeclContext(ND)->isFileContext() && + !ND->isInAnonymousNamespace()) + return true; + return false; +} + +// Check if this Decl needs a unique internal linkage name. +bool ItaniumMangleContextImpl::isUniqueInternalLinkageDecl( + const NamedDecl *ND) { + if (!NeedsUniqueInternalLinkageNames || !ND) + return false; + + // For C functions without prototypes, return false as their + // names should not be mangled. + if (auto *FD = dyn_cast(ND)) { + if (!FD->getType()->getAs()) + return false; + } + + if (isInternalLinkageDecl(ND)) + return true; + return false; +} + bool ItaniumMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) { const FunctionDecl *FD = dyn_cast(D); if (FD) { @@ -1376,10 +1409,7 @@ // 12_GLOBAL__N_1 mangling is quite sufficient there, and this better // matches GCC anyway, because GCC does not treat anonymous namespaces as // implying internal linkage. - if (ND && ND->getFormalLinkage() == InternalLinkage && - !ND->isExternallyVisible() && - getEffectiveDeclContext(ND)->isFileContext() && - !ND->isInAnonymousNamespace()) + if (isInternalLinkageDecl(ND)) Out << 'L'; auto *FD = dyn_cast(ND); diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp --- a/clang/lib/AST/Mangle.cpp +++ b/clang/lib/AST/Mangle.cpp @@ -116,6 +116,12 @@ if (!D->hasExternalFormalLinkage() && D->getOwningModuleForLinkage()) return true; + // C functions with internal linkage have to be mangled with option + // -funique-internal-linkage-names. + if (!getASTContext().getLangOpts().CPlusPlus && + isUniqueInternalLinkageDecl(D)) + return true; + // In C, functions with no attributes never need to be mangled. Fastpath them. if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs()) return false; diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -84,7 +84,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; @@ -817,12 +816,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) @@ -1256,7 +1249,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); diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -2150,6 +2150,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) { diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -28,6 +28,7 @@ #include "clang/Basic/NoSanitizeList.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); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -180,6 +180,34 @@ // 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. The "__uniq" is the + // pre-determined prefix that is used to tell tools that this symbol was + // created with -funique-internal-linakge-symbols and the tools can strip or + // keep the prefix as needed. + ModuleNameHash = (Twine(".__uniq.") + + Twine(IntHash.toString(/* Radix = */ 10, /* Signed = */false))).str(); + } } CodeGenModule::~CodeGenModule() {} @@ -1147,13 +1175,30 @@ } } -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)) + if (!CGM.getModuleNameHash().empty()) + MC.needsUniqueInternalLinkageNames(); + bool ShouldMangle = MC.shouldMangleDeclName(ND); + if (ShouldMangle) MC.mangleName(GD.getWithDecl(ND), Out); else { IdentifierInfo *II = ND->getIdentifier(); @@ -1171,6 +1216,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()) { diff --git a/clang/test/CodeGen/unique-internal-linkage-names-dwarf.c b/clang/test/CodeGen/unique-internal-linkage-names-dwarf.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/unique-internal-linkage-names-dwarf.c @@ -0,0 +1,28 @@ +// 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-llvm -o - %s | FileCheck %s --check-prefix=PLAIN +// RUN: %clang_cc1 -triple x86_64-unknown-linux -debug-info-kind=limited -dwarf-version=4 -funique-internal-linkage-names -emit-llvm -o - %s | FileCheck %s --check-prefix=UNIQUE +// +// RUN: %clang_cc1 -triple x86_64-unknown-linux -debug-info-kind=limited -dwarf-version=5 -emit-llvm -o - %s | FileCheck %s --check-prefix=PLAIN +// RUN: %clang_cc1 -triple x86_64-unknown-linux -debug-info-kind=limited -dwarf-version=5 -funique-internal-linkage-names -emit-llvm -o - %s | FileCheck %s --check-prefix=UNIQUE + +static int glob; +static int foo(void) { + return glob; +} + +void baz() { + foo(); +} + +// PLAIN: @glob = internal global i32 +// PLAIN: define internal i32 @foo() +// PLAIN: distinct !DIGlobalVariable(name: "glob"{{.*}}) +// PLAIN: distinct !DISubprogram(name: "foo"{{.*}}) +// PLAIN-NOT: linkageName: +// +// UNIQUE: @_ZL4glob.[[MODHASH:__uniq.[0-9]+]] = internal global i32 +// UNIQUE: define internal i32 @_ZL3foov.[[MODHASH]]() +// UNIQUE: distinct !DIGlobalVariable(name: "glob", linkageName: "_ZL4glob.[[MODHASH]]"{{.*}}) +// UNIQUE: distinct !DISubprogram(name: "foo", linkageName: "_ZL3foov.[[MODHASH]]"{{.*}}) diff --git a/clang/test/CodeGen/unique-internal-linkage-names-dwarf.cpp b/clang/test/CodeGen/unique-internal-linkage-names-dwarf.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/unique-internal-linkage-names-dwarf.cpp @@ -0,0 +1,60 @@ +// 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-llvm -o - %s | FileCheck %s --check-prefix=PLAIN +// RUN: %clang_cc1 -triple x86_64-unknown-linux -debug-info-kind=limited -dwarf-version=4 -funique-internal-linkage-names -emit-llvm -o - %s | FileCheck %s --check-prefix=UNIQUE +// RUN: %clang_cc1 -triple x86_64-unknown-linux -debug-info-kind=limited -dwarf-version=5 -emit-llvm -o - %s | FileCheck %s --check-prefix=PLAIN +// RUN: %clang_cc1 -triple x86_64-unknown-linux -debug-info-kind=limited -dwarf-version=5 -funique-internal-linkage-names -emit-llvm -o - %s | FileCheck %s --check-prefix=UNIQUE + +static int glob_foo = 5; +static int foo(void) { + __builtin_printf("%p", &glob_foo); + return glob_foo; +} + +// Anonymous namespaces generate internal linkage symbols. +namespace { + int glob_bar; + int bar() { + return glob_bar; + } +} + +extern "C" { + static int glob_zip; + static int zip(void) { + return glob_zip; + } +} + +void baz() { + foo(); + bar(); + zip(); +} + +// PLAIN-DAG: @_ZL8glob_foo = internal global i32 +// PLAIN-DAG: define internal i32 @_ZL3foov() +// PLAIN-DAG: distinct !DIGlobalVariable(name: "glob_foo", linkageName: "_ZL8glob_foo"{{.*}}) +// PLAIN-DAG: distinct !DISubprogram(name: "foo", linkageName: "_ZL3foov"{{.*}}) +// PLAIN-DAG: @_ZN12_GLOBAL__N_18glob_barE = internal global i32 +// PLAIN-DAG: define internal i32 @_ZN12_GLOBAL__N_13barEv() +// PLAIN-DAG: distinct !DIGlobalVariable(name: "glob_bar", linkageName: "_ZN12_GLOBAL__N_18glob_barE"{{.*}}) +// PLAIN-DAG: distinct !DISubprogram(name: "bar", linkageName: "_ZN12_GLOBAL__N_13barEv"{{.*}}) +// PLAIN-DAG: @_ZL8glob_zip = internal global i32 +// PLAIN-DAG: define internal i32 @_ZL3zipv() +// PLAIN-DAG: distinct !DIGlobalVariable(name: "glob_zip", linkageName: "_ZL8glob_zip"{{.*}}) +// PLAIN-DAG: distinct !DISubprogram(name: "zip", linkageName: "_ZL3zipv"{{.*}}) + +// UNIQUE-DAG: @_ZL8glob_foo.[[MODHASH:__uniq\.[0-9]+]] = internal global i32 +// UNIQUE-DAG: define internal 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.[[MODHASH]] = internal global i32 +// UNIQUE-DAG: define internal i32 @_ZN12_GLOBAL__N_13barEv.[[MODHASH]]() +// 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.[[MODHASH]] = internal global i32 +// UNIQUE-DAG: define internal i32 @_ZL3zipv.[[MODHASH]]() +// UNIQUE-DAG: distinct !DIGlobalVariable(name: "glob_zip", linkageName: "_ZL8glob_zip.[[MODHASH]]"{{.*}}) +// UNIQUE-DAG: distinct !DISubprogram(name: "zip", linkageName: "_ZL3zipv.[[MODHASH]]"{{.*}}) diff --git a/clang/test/CodeGen/unique-internal-linkage-names.cpp b/clang/test/CodeGen/unique-internal-linkage-names.cpp --- a/clang/test/CodeGen/unique-internal-linkage-names.cpp +++ b/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 @_ZL3foov.__uniq.{{[0-9]+}}() #[[#ATTR:]] { // 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: attributes #[[#ATTR]] = { {{.*}}"sample-profile-suffix-elision-policy"{{.*}} }