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;
llvm::DenseMap<const NamedDecl*, unsigned> Uniquifier;
bool IsDevCtx = false;
+ bool NeedsUniqueInternalLinkageNames = false;
public:
explicit ItaniumMangleContextImpl(ASTContext &Context,
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; }
}
+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<FunctionDecl>(ND)) {
+ if (!FD->getType()->getAs<FunctionProtoType>())
+ return false;
+ }
+
+ if (isInternalLinkageDecl(ND))
+ return true;
+ return false;
+}
+
bool ItaniumMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
if (FD) {
// 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<FunctionDecl>(ND);
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;
#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 <memory>
using namespace clang;
using namespace llvm;
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<GCOVOptions> Options = getGCOVOptions(CodeGenOpts, LangOpts)) {
MPM.add(createGCOVProfilerPass(*Options));
if (CodeGenOpts.getDebugInfo() == codegenoptions::NoDebugInfo)
// 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);
}
}
+ // 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<FunctionDecl>(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) {
// 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() {}
}
}
-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<FunctionDecl>(D) &&
+ CGM.getFunctionLinkage(GD) == llvm::GlobalValue::InternalLinkage) ||
+ (isa<VarDecl>(D) && CGM.getContext().GetGVALinkageForVariable(
+ cast<VarDecl>(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();
}
}
+ // 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<FunctionDecl>(ND))
if (FD->isMultiVersion() && !OmitMultiVersionMangling) {
switch (FD->getMultiVersionKind()) {
#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"
class LangOptions;
class CodeGenOptions;
class HeaderSearchOptions;
-class PreprocessorOptions;
class DiagnosticsEngine;
class AnnotateAttr;
class CXXDestructorDecl;
const TargetInfo &Target;
std::unique_ptr<CGCXXABI> ABI;
llvm::LLVMContext &VMContext;
+ std::string ModuleNameHash = "";
std::unique_ptr<CodeGenTBAA> TBAA;
/// 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);
--- /dev/null
+// 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]]"{{.*}})
--- /dev/null
+// 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]]"{{.*}})
// 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() {
// 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"{{.*}} }