diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -2052,6 +2052,10 @@ return getNumOperands() > 10 ? getOperandAs(10) : nullptr; } + void replaceRawLinkageName(MDString *LinkageName) { + replaceOperandWith(3, LinkageName); + } + /// Check if this subprogram describes the given function. /// /// FIXME: Should this be looking through bitcasts? diff --git a/llvm/lib/Transforms/Utils/UniqueInternalLinkageNames.cpp b/llvm/lib/Transforms/Utils/UniqueInternalLinkageNames.cpp --- a/llvm/lib/Transforms/Utils/UniqueInternalLinkageNames.cpp +++ b/llvm/lib/Transforms/Utils/UniqueInternalLinkageNames.cpp @@ -13,8 +13,11 @@ #include "llvm/Transforms/Utils/UniqueInternalLinkageNames.h" #include "llvm/ADT/SmallString.h" +#include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/MDBuilder.h" #include "llvm/IR/Module.h" #include "llvm/InitializePasses.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/MD5.h" #include "llvm/Transforms/Utils/ModuleUtils.h" @@ -34,11 +37,23 @@ // this symbol is of internal linkage type. std::string ModuleNameHash = (Twine(".__uniq.") + Twine(IntHash.toString(10, false))).str(); bool Changed = false; + MDBuilder MDB(M.getContext()); // Append the module hash to all internal linkage functions. for (auto &F : M) { if (F.hasInternalLinkage()) { F.setName(F.getName() + ModuleNameHash); + // Replace linkage names in the debug metadata. + if (DISubprogram *SP = F.getSubprogram()) { + if (SP->getRawLinkageName()) { + auto *Name = MDB.createString(F.getName()); + SP->replaceRawLinkageName(Name); + if (DISubprogram *SPDecl = SP->getDeclaration()) { + if (SPDecl->getRawLinkageName()) + SPDecl->replaceRawLinkageName(Name); + } + } + } Changed = true; } } diff --git a/llvm/test/Transforms/UniqueInternalLinkageNames/unique-internal-linkage-names.ll b/llvm/test/Transforms/UniqueInternalLinkageNames/unique-internal-linkage-names.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/UniqueInternalLinkageNames/unique-internal-linkage-names.ll @@ -0,0 +1,50 @@ +; RUN: opt -S -passes='default' -new-pm-pseudo-probe-for-profiling -new-pm-unique-internal-linkage-names -debug-pass-manager < %s 2>&1 | FileCheck %s --check-prefix=O0 --check-prefix=UNIQUE +; RUN: opt -S -passes='default' -new-pm-pseudo-probe-for-profiling -new-pm-unique-internal-linkage-names -debug-pass-manager < %s 2>&1 | FileCheck %s --check-prefix=O2 --check-prefix=UNIQUE +; RUN: opt -S -passes='default' -new-pm-pseudo-probe-for-profiling -new-pm-unique-internal-linkage-names -debug-pass-manager < %s 2>&1 | FileCheck %s --check-prefix=O2 --check-prefix=UNIQUE +; RUN: opt -S -passes='thinlto-pre-link' -new-pm-pseudo-probe-for-profiling -new-pm-unique-internal-linkage-names -debug-pass-manager < %s 2>&1 | FileCheck %s --check-prefix=O2 --check-prefix=UNIQUE +; RUN: opt -S -passes='thinlto-pre-link' -new-pm-pseudo-probe-for-profiling -new-pm-unique-internal-linkage-names -debug-pass-manager < %s 2>&1 | FileCheck %s --check-prefix=O2 --check-prefix=UNIQUE +; RUN: opt -S -passes=unique-internal-linkage-names < %s -o - | FileCheck %s --check-prefix=DBG + +define internal i32 @foo() !dbg !15 { +entry: + ret i32 0 +} + +define dso_local i32 (...)* @bar() { +entry: + ret i32 (...)* bitcast (i32 ()* @foo to i32 (...)*) +} + +define internal i32 @go() !dbg !19 { +entry: + ret i32 0 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, enums: !2) +!1 = !DIFile(filename: "test.c", directory: "") +!2 = !{} +!3 = !{i32 7, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!15 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: !1, file: !1, line: 5, type: !16, scopeLine: 5, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !0, declaration: !18, retainedNodes: !2) +!16 = !DISubroutineType(types: !17) +!17 = !{!13} +!18 = !DISubprogram(name: "foo", linkageName: "foo", scope: !1, isDefinition: false, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized) +!19 = distinct !DISubprogram(name: "go", scope: !1, file: !1, line: 5, type: !16, scopeLine: 5, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !0, declaration: !18, retainedNodes: !2) + +; O0: Running pass: UniqueInternalLinkageNamesPass + +;; Check UniqueInternalLinkageNamesPass is scheduled before SampleProfileProbePass. +; O2: Running pass: UniqueInternalLinkageNamesPass +; O2: Running pass: SampleProfileProbePass + +; UNIQUE: define internal i32 @foo.__uniq.{{[0-9]+}}() +; UNIQUE: ret {{.*}} @foo.__uniq.{{[0-9]+}} {{.*}} + +; DBG: distinct !DISubprogram(name: "foo", linkageName: "foo.__uniq.{{[0-9]+}}", scope: ![[#]] +; DBG: !DISubprogram(name: "foo", linkageName: "foo.__uniq.{{[0-9]+}}", scope: ![[#]] +; DBG: distinct !DISubprogram(name: "go", scope: ![[#]] diff --git a/llvm/test/Transforms/UniqueLinkageNames/unique-internal-linkage-names.ll b/llvm/test/Transforms/UniqueLinkageNames/unique-internal-linkage-names.ll deleted file mode 100644 --- a/llvm/test/Transforms/UniqueLinkageNames/unique-internal-linkage-names.ll +++ /dev/null @@ -1,24 +0,0 @@ -; RUN: opt -S -passes='default' -new-pm-pseudo-probe-for-profiling -new-pm-unique-internal-linkage-names -debug-pass-manager < %s 2>&1 | FileCheck %s --check-prefix=O0 --check-prefix=UNIQUE -; RUN: opt -S -passes='default' -new-pm-pseudo-probe-for-profiling -new-pm-unique-internal-linkage-names -debug-pass-manager < %s 2>&1 | FileCheck %s --check-prefix=O2 --check-prefix=UNIQUE -; RUN: opt -S -passes='default' -new-pm-pseudo-probe-for-profiling -new-pm-unique-internal-linkage-names -debug-pass-manager < %s 2>&1 | FileCheck %s --check-prefix=O2 --check-prefix=UNIQUE -; RUN: opt -S -passes='thinlto-pre-link' -new-pm-pseudo-probe-for-profiling -new-pm-unique-internal-linkage-names -debug-pass-manager < %s 2>&1 | FileCheck %s --check-prefix=O2 --check-prefix=UNIQUE -; RUN: opt -S -passes='thinlto-pre-link' -new-pm-pseudo-probe-for-profiling -new-pm-unique-internal-linkage-names -debug-pass-manager < %s 2>&1 | FileCheck %s --check-prefix=O2 --check-prefix=UNIQUE - -define internal i32 @foo() { -entry: - ret i32 0 -} - -define dso_local i32 (...)* @bar() { -entry: - ret i32 (...)* bitcast (i32 ()* @foo to i32 (...)*) -} - -; O0: Running pass: UniqueInternalLinkageNamesPass - -;; Check UniqueInternalLinkageNamesPass is scheduled before SampleProfileProbePass. -; O2: Running pass: UniqueInternalLinkageNamesPass -; O2: Running pass: SampleProfileProbePass - -; UNIQUE: define internal i32 @foo.__uniq.{{[0-9a-f]+}}() -; UNIQUE: ret {{.*}} @foo.__uniq.{{[0-9a-f]+}} {{.*}}