Skip to content

Commit a79f5dc

Browse files
committed
[PtrAuth] Add ConstantPtrAuth comparator to FunctionComparator.cpp
When building rustc std for arm64e, the optimizations result in devirtualization of indirect calls. This can happen during function merging so I modified FunctionComparator.cpp as the ConstantPtrAuth value would go unchecked in the switch statement.
1 parent d2f67c3 commit a79f5dc

File tree

2 files changed

+120
-0
lines changed

2 files changed

+120
-0
lines changed

llvm/lib/Transforms/Utils/FunctionComparator.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,23 @@ int FunctionComparator::cmpConstants(const Constant *L,
354354
if (!L->isNullValue() && R->isNullValue())
355355
return -1;
356356

357+
// Handle authenticated pointer constants produced by ConstantPtrAuth::get.
358+
if (auto *PA1 = dyn_cast<ConstantPtrAuth>(L)) {
359+
auto *PA2 = dyn_cast<ConstantPtrAuth>(R);
360+
if (!PA2)
361+
return cmpNumbers(L->getValueID(), R->getValueID());
362+
363+
if (int Res = cmpConstants(PA1->getPointer(), PA2->getPointer()))
364+
return Res;
365+
if (int Res = cmpConstants(PA1->getKey(), PA2->getKey()))
366+
return Res;
367+
if (int Res =
368+
cmpConstants(PA1->getDiscriminator(), PA2->getDiscriminator()))
369+
return Res;
370+
return cmpConstants(PA1->getAddrDiscriminator(),
371+
PA2->getAddrDiscriminator());
372+
}
373+
357374
auto GlobalValueL = const_cast<GlobalValue *>(dyn_cast<GlobalValue>(L));
358375
auto GlobalValueR = const_cast<GlobalValue *>(dyn_cast<GlobalValue>(R));
359376
if (GlobalValueL && GlobalValueR) {
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
; RUN: opt -passes=mergefunc -S %s | FileCheck %s
2+
; Ensure MergeFunc handles ConstantPtrAuth correctly and does not
3+
; merge when any ptrauth operand differs (ptr, key, int disc, addr disc).
4+
5+
target triple = "arm64e-apple-ios14.0.0"
6+
7+
declare void @baz()
8+
@ADDR = external global i8
9+
10+
declare void @callee0(ptr)
11+
declare void @callee1(ptr)
12+
declare void @callee2(ptr)
13+
declare void @callee3(ptr)
14+
15+
; different base pointer (null vs @baz)
16+
17+
define void @f_ptr_null() {
18+
; CHECK-LABEL: define void @f_ptr_null()
19+
; CHECK: call void @callee0(ptr ptrauth (ptr null, i32 0))
20+
entry:
21+
call void @callee0(ptr ptrauth (ptr null, i32 0))
22+
ret void
23+
}
24+
25+
define void @g_ptr_baz() {
26+
; CHECK-LABEL: define void @g_ptr_baz()
27+
; CHECK: call void @callee0(ptr ptrauth (ptr @baz, i32 0))
28+
entry:
29+
call void @callee0(ptr ptrauth (ptr @baz, i32 0))
30+
ret void
31+
}
32+
33+
; different key (i32 0 vs i32 1)
34+
35+
define void @f_key0() {
36+
; CHECK-LABEL: define void @f_key0()
37+
; CHECK: call void @callee1(ptr ptrauth (ptr @baz, i32 0))
38+
entry:
39+
call void @callee1(ptr ptrauth (ptr @baz, i32 0))
40+
ret void
41+
}
42+
43+
define void @g_key1() {
44+
; CHECK-LABEL: define void @g_key1()
45+
; CHECK: call void @callee1(ptr ptrauth (ptr @baz, i32 1))
46+
entry:
47+
call void @callee1(ptr ptrauth (ptr @baz, i32 1))
48+
ret void
49+
}
50+
51+
; different integer disc (i64 0 vs i64 7)
52+
53+
define void @f_disc0() {
54+
; CHECK-LABEL: define void @f_disc0()
55+
; CHECK: call void @callee2(ptr ptrauth (ptr @baz, i32 0))
56+
entry:
57+
call void @callee2(ptr ptrauth (ptr @baz, i32 0))
58+
ret void
59+
}
60+
61+
define void @g_disc7() {
62+
; CHECK-LABEL: define void @g_disc7()
63+
; CHECK: call void @callee2(ptr ptrauth (ptr @baz, i32 0, i64 7))
64+
entry:
65+
call void @callee2(ptr ptrauth (ptr @baz, i32 0, i64 7))
66+
ret void
67+
}
68+
69+
; different addr disc (ptr null vs @ADDR)
70+
71+
define void @f_addr_null() {
72+
; CHECK-LABEL: define void @f_addr_null()
73+
; CHECK: call void @callee3(ptr ptrauth (ptr @baz, i32 0))
74+
entry:
75+
call void @callee3(ptr ptrauth (ptr @baz, i32 0))
76+
ret void
77+
}
78+
79+
define void @g_addr_ADDR() {
80+
; CHECK-LABEL: define void @g_addr_ADDR()
81+
; CHECK: call void @callee3(ptr ptrauth (ptr @baz, i32 0, i64 0, ptr @ADDR))
82+
entry:
83+
call void @callee3(ptr ptrauth (ptr @baz, i32 0, i64 0, ptr @ADDR))
84+
ret void
85+
}
86+
87+
; positive test: identical ptrauth operands, should be merged
88+
89+
define void @merge_ptrauth_a() {
90+
; CHECK-LABEL: define void @merge_ptrauth_a()
91+
; CHECK: call void @callee1(ptr ptrauth (ptr @baz, i32 0, i64 0, ptr @ADDR))
92+
entry:
93+
call void @callee1(ptr ptrauth (ptr @baz, i32 0, i64 0, ptr @ADDR))
94+
ret void
95+
}
96+
97+
define void @merge_ptrauth_b() {
98+
; CHECK-LABEL: define void @merge_ptrauth_b()
99+
; CHECK: tail call void @merge_ptrauth_a()
100+
entry:
101+
call void @callee1(ptr ptrauth (ptr @baz, i32 0, i64 0, ptr @ADDR))
102+
ret void
103+
}

0 commit comments

Comments
 (0)