Skip to content

Commit dcec3ea

Browse files
dobbelaj-snpsmemfrob
authored andcommitted
[remangleIntrinsicFunction] Detect and resolve name clash
It is possible that the remangled name for an intrinsic already exists with a different (and wrong) prototype within the module. As the bitcode reader keeps both versions of all remangled intrinsics around for a longer time, this can result in a crash, as can be seen in https://bugs.llvm.org/show_bug.cgi?id=50923 This patch makes 'remangleIntrinsicFunction' aware of this situation. When it is detected, it moves the version with the wrong prototype to a different name. That version will be removed anyway once the module is completely loaded. With thanks to @asbirlea for reporting this issue when trying out an lto build with the full restrict patches, and @efriedma for suggesting a sane resolution mechanism. Reviewed By: apilipenko Differential Revision: https://reviews.llvm.org/D105118
1 parent e7703e8 commit dcec3ea

File tree

6 files changed

+144
-3
lines changed

6 files changed

+144
-3
lines changed

llvm/include/llvm/IR/Intrinsics.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,8 @@ namespace Intrinsic {
244244

245245
// Checks if the intrinsic name matches with its signature and if not
246246
// returns the declaration with the same signature and remangled name.
247+
// An existing GlobalValue with the wanted name but with a wrong prototype
248+
// or of the wrong kind will be renamed by adding ".renamed" to the name.
247249
llvm::Optional<Function*> remangleIntrinsicFunction(Function *F);
248250

249251
} // End Intrinsic namespace

llvm/lib/IR/Function.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1676,11 +1676,26 @@ Optional<Function *> Intrinsic::remangleIntrinsicFunction(Function *F) {
16761676

16771677
Intrinsic::ID ID = F->getIntrinsicID();
16781678
StringRef Name = F->getName();
1679-
if (Name ==
1680-
Intrinsic::getName(ID, ArgTys, F->getParent(), F->getFunctionType()))
1679+
std::string WantedName =
1680+
Intrinsic::getName(ID, ArgTys, F->getParent(), F->getFunctionType());
1681+
if (Name == WantedName)
16811682
return None;
16821683

1683-
auto NewDecl = Intrinsic::getDeclaration(F->getParent(), ID, ArgTys);
1684+
Function *NewDecl = [&] {
1685+
if (auto *ExistingGV = F->getParent()->getNamedValue(WantedName)) {
1686+
if (auto *ExistingF = dyn_cast<Function>(ExistingGV))
1687+
if (ExistingF->getFunctionType() == F->getFunctionType())
1688+
return ExistingF;
1689+
1690+
// The name already exists, but is not a function or has the wrong
1691+
// prototype. Make place for the new one by renaming the old version.
1692+
// Either this old version will be removed later on or the module is
1693+
// invalid and we'll get an error.
1694+
ExistingGV->setName(WantedName + ".renamed");
1695+
}
1696+
return Intrinsic::getDeclaration(F->getParent(), ID, ArgTys);
1697+
}();
1698+
16841699
NewDecl->setCallingConv(F->getCallingConv());
16851700
assert(NewDecl->getFunctionType() == F->getFunctionType() &&
16861701
"Shouldn't change the signature");

llvm/test/Assembler/remangle.ll

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
; RUN: opt %s -S -o - | FileCheck %s
2+
3+
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
4+
target triple = "x86_64-unknown-linux-gnu"
5+
6+
; Note: this test mimics how the naming could have been after parsing in IR in
7+
; a LLVMContext where some types were already available; but before the
8+
; remangleIntrinsicFunctions has happened:
9+
; The @llvm.ssa.copy intrinsics will have to be remangled.
10+
; In certain cases (as shown here) the remangling can result in a name clash.
11+
; This is also related to the llvm/test/tools/llvm-linker/remangle.ll testcase that checks
12+
; a similar situation in the bitcode reader.
13+
14+
%fum = type { %aab, i8, [7 x i8] }
15+
%aab = type { %aba }
16+
%aba = type { [8 x i8] }
17+
%fum.1 = type { %abb, i8, [7 x i8] }
18+
%abb = type { %abc }
19+
%abc = type { [4 x i8] }
20+
21+
declare void @foo(%fum*)
22+
23+
; Will be remagled to @"llvm.ssa.copy.p0p0s_fum.1s"
24+
declare %fum.1** @"llvm.ssa.copy.p0p0s_fums"(%fum.1**)
25+
26+
; Will be remagled to @"llvm.ssa.copy.p0p0s_fums"
27+
declare %fum** @"llvm.ssa.copy.p0p0s_fum.1s"(%fum**)
28+
29+
define void @foo1(%fum** %a, %fum.1 ** %b) {
30+
%b.copy = call %fum.1** @"llvm.ssa.copy.p0p0s_fums"(%fum.1** %b)
31+
%a.copy = call %fum** @"llvm.ssa.copy.p0p0s_fum.1s"(%fum** %a)
32+
ret void
33+
}
34+
35+
define void @foo2(%fum.1 ** %b, %fum** %a) {
36+
%a.copy = call %fum** @"llvm.ssa.copy.p0p0s_fum.1s"(%fum** %a)
37+
%b.copy = call %fum.1** @"llvm.ssa.copy.p0p0s_fums"(%fum.1** %b)
38+
ret void
39+
}
40+
41+
; CHECK-DAG: %fum = type { %aab, i8, [7 x i8] }
42+
; CHECK-DAG: %aab = type { %aba }
43+
; CHECK-DAG: %aba = type { [8 x i8] }
44+
; CHECK-DAG: %fum.1 = type { %abb, i8, [7 x i8] }
45+
; CHECK-DAG: %abb = type { %abc }
46+
; CHECK-DAG: %abc = type { [4 x i8] }
47+
48+
; CHECK-LABEL: define void @foo1(%fum** %a, %fum.1** %b) {
49+
; CHECK-NEXT: %b.copy = call %fum.1** @llvm.ssa.copy.p0p0s_fum.1s(%fum.1** %b)
50+
; CHECK-NEXT: %a.copy = call %fum** @llvm.ssa.copy.p0p0s_fums(%fum** %a)
51+
; CHECK-NEXT: ret void
52+
53+
; CHECK-LABEL: define void @foo2(%fum.1** %b, %fum** %a) {
54+
; CHECK-NEXT: %a.copy = call %fum** @llvm.ssa.copy.p0p0s_fums(%fum** %a)
55+
; CHECK-NEXT: %b.copy = call %fum.1** @llvm.ssa.copy.p0p0s_fum.1s(%fum.1** %b)
56+
; CHECK-NEXT: ret void
57+
58+
; CHECK: declare %fum.1** @llvm.ssa.copy.p0p0s_fum.1s(%fum.1** returned)
59+
60+
; CHECK: declare %fum** @llvm.ssa.copy.p0p0s_fums(%fum** returned)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
2+
target triple = "x86_64-unknown-linux-gnu"
3+
4+
%aaa = type <{ %aab, i32, [4 x i8] }>
5+
%aab = type { i64 }
6+
%fum = type { %aac, i8, [7 x i8] }
7+
%aac = type { [8 x i8] }
8+
9+
declare void @bar01(%aaa*)
10+
declare void @bar02(%fum*)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
2+
target triple = "x86_64-unknown-linux-gnu"
3+
4+
%fum = type { %aab, i8, [7 x i8] }
5+
%aab = type { %aba }
6+
%aba = type { [8 x i8] }
7+
%fum.1 = type { %abb, i8, [7 x i8] }
8+
%abb = type { %abc }
9+
%abc = type { [4 x i8] }
10+
11+
declare void @foo(%fum*)
12+
13+
declare %fum.1** @"llvm.ssa.copy.p0p0s_fum.1s"(%fum.1**)
14+
15+
declare %fum** @"llvm.ssa.copy.p0p0s_fums"(%fum**)
16+
17+
define void @foo1(%fum** %a, %fum.1 ** %b) {
18+
%b.copy = call %fum.1** @"llvm.ssa.copy.p0p0s_fum.1s"(%fum.1** %b)
19+
%a.copy = call %fum** @"llvm.ssa.copy.p0p0s_fums"(%fum** %a)
20+
ret void
21+
}
22+
23+
define void @foo2(%fum.1 ** %b, %fum** %a) {
24+
%a.copy = call %fum** @"llvm.ssa.copy.p0p0s_fums"(%fum** %a)
25+
%b.copy = call %fum.1** @"llvm.ssa.copy.p0p0s_fum.1s"(%fum.1** %b)
26+
ret void
27+
}

llvm/test/tools/llvm-link/remangle.ll

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# RUN: llvm-as %S/Inputs/remangle1.ll -o %t.remangle1.bc
2+
# RUN: llvm-as %S/Inputs/remangle2.ll -o %t.remangle2.bc
3+
# RUN: llvm-link %t.remangle1.bc %t.remangle2.bc -o %t.remangle.linked.bc
4+
# RUN: llvm-dis %t.remangle.linked.bc -o - | FileCheck %s
5+
6+
; CHECK-DAG: %fum.1 = type { %aab.0, i8, [7 x i8] }
7+
; CHECK-DAG: %aab.0 = type { %aba }
8+
; CHECK-DAG: %aba = type { [8 x i8] }
9+
; CHECK-DAG: %fum.1.2 = type { %abb, i8, [7 x i8] }
10+
; CHECK-DAG: %abb = type { %abc }
11+
; CHECK-DAG: %abc = type { [4 x i8] }
12+
13+
; CHECK-LABEL: define void @foo1(%fum.1** %a, %fum.1.2** %b) {
14+
; CHECK-NEXT: %b.copy = call %fum.1.2** @llvm.ssa.copy.p0p0s_fum.1.2s(%fum.1.2** %b)
15+
; CHECK-NEXT: %a.copy = call %fum.1** @llvm.ssa.copy.p0p0s_fum.1s(%fum.1** %a)
16+
; CHECK-NEXT: ret void
17+
18+
; CHECK: declare %fum.1.2** @llvm.ssa.copy.p0p0s_fum.1.2s(%fum.1.2** returned)
19+
20+
; CHECK: declare %fum.1** @llvm.ssa.copy.p0p0s_fum.1s(%fum.1** returned)
21+
22+
; CHECK-LABEL: define void @foo2(%fum.1.2** %b, %fum.1** %a) {
23+
; CHECK-NEXT: %a.copy = call %fum.1** @llvm.ssa.copy.p0p0s_fum.1s(%fum.1** %a)
24+
; CHECK-NEXT: %b.copy = call %fum.1.2** @llvm.ssa.copy.p0p0s_fum.1.2s(%fum.1.2** %b)
25+
; CHECK-NEXT: ret void
26+
27+

0 commit comments

Comments
 (0)