Skip to content

Commit 6c862f2

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 c3678c4 commit 6c862f2

File tree

2 files changed

+144
-0
lines changed

2 files changed

+144
-0
lines changed

llvm/lib/Transforms/Utils/FunctionComparator.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,20 @@ int FunctionComparator::cmpConstants(const Constant *L,
518518
const auto *REquiv = cast<DSOLocalEquivalent>(R);
519519
return cmpGlobalValues(LEquiv->getGlobalValue(), REquiv->getGlobalValue());
520520
}
521+
case Value::ConstantPtrAuthVal: {
522+
// Handle authenticated pointer constants produced by ConstantPtrAuth::get.
523+
const ConstantPtrAuth *LPA = cast<ConstantPtrAuth>(L);
524+
const ConstantPtrAuth *RPA = cast<ConstantPtrAuth>(R);
525+
if (int Res = cmpConstants(LPA->getPointer(), RPA->getPointer()))
526+
return Res;
527+
if (int Res = cmpConstants(LPA->getKey(), RPA->getKey()))
528+
return Res;
529+
if (int Res =
530+
cmpConstants(LPA->getDiscriminator(), RPA->getDiscriminator()))
531+
return Res;
532+
return cmpConstants(LPA->getAddrDiscriminator(),
533+
RPA->getAddrDiscriminator());
534+
}
521535
default: // Unknown constant, abort.
522536
LLVM_DEBUG(dbgs() << "Looking at valueID " << L->getValueID() << "\n");
523537
llvm_unreachable("Constant ValueID not recognized.");
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
2+
; RUN: opt -passes=mergefunc -S < %s | FileCheck %s
3+
; Ensure MergeFunc handles ConstantPtrAuth correctly and does not
4+
; merge when any ptrauth operand differs (ptr, key, int disc, addr disc).
5+
6+
target triple = "arm64e-apple-ios14.0.0"
7+
8+
declare void @baz()
9+
@ADDR = external global i8
10+
11+
declare void @callee(ptr)
12+
13+
; different base pointer (null vs @baz)
14+
15+
define i32 @f_ptr_null() {
16+
; CHECK-LABEL: define i32 @f_ptr_null() {
17+
; CHECK-NEXT: [[ENTRY:.*:]]
18+
; CHECK-NEXT: call void @callee(ptr ptrauth (ptr null, i32 0))
19+
; CHECK-NEXT: ret i32 1
20+
;
21+
entry:
22+
call void @callee(ptr ptrauth (ptr null, i32 0))
23+
ret i32 1
24+
}
25+
26+
define i32 @g_ptr_baz() {
27+
; CHECK-LABEL: define i32 @g_ptr_baz() {
28+
; CHECK-NEXT: [[ENTRY:.*:]]
29+
; CHECK-NEXT: call void @callee(ptr ptrauth (ptr @baz, i32 0))
30+
; CHECK-NEXT: ret i32 2
31+
;
32+
entry:
33+
call void @callee(ptr ptrauth (ptr @baz, i32 0))
34+
ret i32 2
35+
}
36+
37+
; different key (i32 0 vs i32 1)
38+
39+
define i32 @f_key0() {
40+
; CHECK-LABEL: define i32 @f_key0() {
41+
; CHECK-NEXT: [[ENTRY:.*:]]
42+
; CHECK-NEXT: call void @callee(ptr ptrauth (ptr @baz, i32 0))
43+
; CHECK-NEXT: ret i32 3
44+
;
45+
entry:
46+
call void @callee(ptr ptrauth (ptr @baz, i32 0))
47+
ret i32 3
48+
}
49+
50+
define i32 @g_key1() {
51+
; CHECK-LABEL: define i32 @g_key1() {
52+
; CHECK-NEXT: [[ENTRY:.*:]]
53+
; CHECK-NEXT: call void @callee(ptr ptrauth (ptr @baz, i32 1))
54+
; CHECK-NEXT: ret i32 4
55+
;
56+
entry:
57+
call void @callee(ptr ptrauth (ptr @baz, i32 1))
58+
ret i32 4
59+
}
60+
61+
; different integer disc (i64 0 vs i64 7)
62+
63+
define i32 @f_disc0() {
64+
; CHECK-LABEL: define i32 @f_disc0() {
65+
; CHECK-NEXT: [[ENTRY:.*:]]
66+
; CHECK-NEXT: call void @callee(ptr ptrauth (ptr @baz, i32 0))
67+
; CHECK-NEXT: ret i32 5
68+
;
69+
entry:
70+
call void @callee(ptr ptrauth (ptr @baz, i32 0))
71+
ret i32 5
72+
}
73+
74+
define i32 @g_disc7() {
75+
; CHECK-LABEL: define i32 @g_disc7() {
76+
; CHECK-NEXT: [[ENTRY:.*:]]
77+
; CHECK-NEXT: call void @callee(ptr ptrauth (ptr @baz, i32 0, i64 7))
78+
; CHECK-NEXT: ret i32 6
79+
;
80+
entry:
81+
call void @callee(ptr ptrauth (ptr @baz, i32 0, i64 7))
82+
ret i32 6
83+
}
84+
85+
; different addr disc (ptr null vs @ADDR)
86+
87+
define i32 @f_addr_null() {
88+
; CHECK-LABEL: define i32 @f_addr_null() {
89+
; CHECK-NEXT: [[ENTRY:.*:]]
90+
; CHECK-NEXT: call void @callee(ptr ptrauth (ptr @baz, i32 0))
91+
; CHECK-NEXT: ret i32 7
92+
;
93+
entry:
94+
call void @callee(ptr ptrauth (ptr @baz, i32 0))
95+
ret i32 7
96+
}
97+
98+
define i32 @g_addr_ADDR() {
99+
; CHECK-LABEL: define i32 @g_addr_ADDR() {
100+
; CHECK-NEXT: [[ENTRY:.*:]]
101+
; CHECK-NEXT: call void @callee(ptr ptrauth (ptr @baz, i32 0, i64 0, ptr @ADDR))
102+
; CHECK-NEXT: ret i32 8
103+
;
104+
entry:
105+
call void @callee(ptr ptrauth (ptr @baz, i32 0, i64 0, ptr @ADDR))
106+
ret i32 8
107+
}
108+
109+
; positive test: identical ptrauth operands, should be merged
110+
111+
define void @merge_ptrauth_a() {
112+
; CHECK-LABEL: define void @merge_ptrauth_a() {
113+
; CHECK-NEXT: [[ENTRY:.*:]]
114+
; CHECK-NEXT: call void @callee(ptr ptrauth (ptr @baz, i32 0, i64 0, ptr @ADDR))
115+
; CHECK-NEXT: ret void
116+
;
117+
entry:
118+
call void @callee(ptr ptrauth (ptr @baz, i32 0, i64 0, ptr @ADDR))
119+
ret void
120+
}
121+
122+
define void @merge_ptrauth_b() {
123+
; CHECK-LABEL: define void @merge_ptrauth_b() {
124+
; CHECK-NEXT: tail call void @merge_ptrauth_a()
125+
; CHECK-NEXT: ret void
126+
;
127+
entry:
128+
call void @callee(ptr ptrauth (ptr @baz, i32 0, i64 0, ptr @ADDR))
129+
ret void
130+
}

0 commit comments

Comments
 (0)