Skip to content

Commit bd44558

Browse files
[AArch64][GlobalISel] Implement __builtin_return_address for PAC-RET
This patch implements stripping of the PAC in the return address for GlobalISel. Implementation for when not using GLobalISel is in https://reviews.llvm.org/D75044 The analogous GCC patch is https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=a70d5d81c41048556fd86eaa1036018a6bfba115 Differential Revision: https://reviews.llvm.org/D84502
1 parent 08d145e commit bd44558

File tree

4 files changed

+159
-31
lines changed

4 files changed

+159
-31
lines changed

llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4881,21 +4881,22 @@ bool AArch64InstructionSelector::selectIntrinsic(MachineInstr &I,
48814881
RBI.constrainGenericRegister(DstReg, AArch64::GPR64RegClass, MRI);
48824882

48834883
if (Depth == 0 && IntrinID == Intrinsic::returnaddress) {
4884-
if (MFReturnAddr) {
4885-
MIRBuilder.buildCopy({DstReg}, MFReturnAddr);
4886-
I.eraseFromParent();
4887-
return true;
4884+
if (!MFReturnAddr) {
4885+
// Insert the copy from LR/X30 into the entry block, before it can be
4886+
// clobbered by anything.
4887+
MFI.setReturnAddressIsTaken(true);
4888+
MFReturnAddr = getFunctionLiveInPhysReg(MF, TII, AArch64::LR,
4889+
AArch64::GPR64RegClass);
48884890
}
48894891

4890-
MFI.setReturnAddressIsTaken(true);
4891-
4892-
// Insert the copy from LR/X30 into the entry block, before it can be
4893-
// clobbered by anything.
4894-
Register LiveInLR = getFunctionLiveInPhysReg(MF, TII, AArch64::LR,
4895-
AArch64::GPR64spRegClass);
4896-
MIRBuilder.buildCopy(DstReg, LiveInLR);
4892+
if (STI.hasV8_3aOps()) {
4893+
MIRBuilder.buildInstr(AArch64::XPACI, {DstReg}, {MFReturnAddr});
4894+
} else {
4895+
MIRBuilder.buildCopy({Register(AArch64::LR)}, {MFReturnAddr});
4896+
MIRBuilder.buildInstr(AArch64::XPACLRI);
4897+
MIRBuilder.buildCopy({DstReg}, {Register(AArch64::LR)});
4898+
}
48974899

4898-
MFReturnAddr = LiveInLR;
48994900
I.eraseFromParent();
49004901
return true;
49014902
}
@@ -4915,7 +4916,16 @@ bool AArch64InstructionSelector::selectIntrinsic(MachineInstr &I,
49154916
MIRBuilder.buildCopy({DstReg}, {FrameAddr});
49164917
else {
49174918
MFI.setReturnAddressIsTaken(true);
4918-
MIRBuilder.buildInstr(AArch64::LDRXui, {DstReg}, {FrameAddr}).addImm(1);
4919+
4920+
if (STI.hasV8_3aOps()) {
4921+
Register TmpReg = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
4922+
MIRBuilder.buildInstr(AArch64::LDRXui, {TmpReg}, {FrameAddr}).addImm(1);
4923+
MIRBuilder.buildInstr(AArch64::XPACI, {DstReg}, {TmpReg});
4924+
} else {
4925+
MIRBuilder.buildInstr(AArch64::LDRXui, {Register(AArch64::LR)}, {FrameAddr}).addImm(1);
4926+
MIRBuilder.buildInstr(AArch64::XPACLRI);
4927+
MIRBuilder.buildCopy({DstReg}, {Register(AArch64::LR)});
4928+
}
49194929
}
49204930

49214931
I.eraseFromParent();
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
;; RUN: llc -mtriple aarch64 -global-isel -O0 %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-NOP
2+
;; RUN: llc -mtriple aarch64 -mattr=+v8.3a -global-isel -O0 %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-V83
3+
declare void @g0() #1
4+
declare void @g1(i8*) #1
5+
declare void @g2(i32, i8*) #1
6+
7+
declare i8* @llvm.returnaddress(i32 immarg) #2
8+
9+
define i8* @f0() #0 {
10+
entry:
11+
%0 = call i8* @llvm.returnaddress(i32 0)
12+
call void @g1(i8* %0)
13+
%1 = call i8* @llvm.returnaddress(i32 1)
14+
call void @g2(i32 1, i8* %1)
15+
%2 = call i8* @llvm.returnaddress(i32 2)
16+
ret i8* %2
17+
}
18+
;; CHECK-LABEL: f0:
19+
;; CHECK-NOT: {{(mov|ldr)}} x30
20+
;; CHECK-NOP: hint #7
21+
;; CHECK-V83: xpaci x30
22+
;; CHECK: bl g1
23+
;; CHECK: ldr x[[T0:[0-9]+]], [x29]
24+
;; CHECK-NOP-NEXT: ldr x30, [x[[T0]], #8]
25+
;; CHECK-NOP-NEXT: hint #7
26+
;; CHECK-V83-NEXT: ldr x[[T0]], [x[[T0]], #8]
27+
;; CHECK-V83-NEXT: xpaci x[[T0]]
28+
;; CHECK: bl g2
29+
;; CHECK: ldr x[[T1:[0-9]+]], [x29]
30+
;; CHECK-NEXT: ldr x[[T1]], [x[[T1]]]
31+
;; CHECK-NOP-NEXT: ldr x30, [x[[T1]], #8]
32+
;; CHECK-NOP-NEXT: hint #7
33+
;; CHECK-NOP-NEXT: mov x0, x30
34+
;; CHECK-V83-NEXT: ldr x[[T1]], [x[[T1]], #8]
35+
;; CHECK-V83-NEXT: xpaci x[[T1]]
36+
;; CHECK-V83-NEXT: mov x0, x[[T1]]
37+
38+
define i8* @f1() #0 {
39+
entry:
40+
%0 = call i8* @llvm.returnaddress(i32 1)
41+
call void @g1(i8* %0)
42+
%1 = call i8* @llvm.returnaddress(i32 2)
43+
call void @g2(i32 1, i8* %1)
44+
%2 = call i8* @llvm.returnaddress(i32 0)
45+
ret i8* %2
46+
}
47+
;; CHECK-LABEL: f1:
48+
;; CHECK-DAG: ldr x[[T0:[0-9]+]], [x29]
49+
;; CHECK-NOP-DAG: str x30, [sp, #[[OFF:[0-9]+]]
50+
;; CHECK-NOP: ldr x30, [x[[T0]], #8]
51+
;; CHECK-NOP-NEXT: hint #7
52+
;; CHECK-V83: ldr x[[T0]], [x[[T0]], #8]
53+
;; CHECK-V83-NEXT: xpaci x[[T0]]
54+
;; CHECK-V83: str x30, [sp, #[[OFF:[0-9]+]]
55+
;; CHECK: bl g1
56+
;; CHECK: ldr x[[T1:[0-9]+]], [x29]
57+
;; CHECK-NEXT: ldr x[[T1]], [x[[T1]]]
58+
;; CHECK-NOP-NEXT: ldr x30, [x[[T1]], #8]
59+
;; CHECK-NOP-NEXT: hint #7
60+
;; CHECK-V83-NEXT: ldr x[[T1]], [x[[T1]], #8]
61+
;; CHECK-V83-NEXT: xpaci x[[T1]]
62+
;; CHECK: bl g2
63+
;; CHECK: ldr x[[T2:[0-9]+]], [sp, #[[OFF]]]
64+
;; CHECK-NOP-NEXT: mov x30, x[[T2]]
65+
;; CHECK-NOP-NEXT: hint #7
66+
;; CHECK-NOP-NEXT: mov x0, x30
67+
;; CHECK-V83-NEXT: xpaci x[[T2]]
68+
;; CHECK-V83-NEXT: mov x0, x[[T2]]
69+
;; CHECK-NOT: x0
70+
;; CHECK: ret
71+
72+
define i8* @f2() #0 {
73+
entry:
74+
call void bitcast (void ()* @g0 to void ()*)()
75+
%0 = call i8* @llvm.returnaddress(i32 0)
76+
ret i8* %0
77+
}
78+
;; CHECK-LABEL: f2
79+
;; CHECK: bl g0
80+
;; CHECK: ldr x[[T0:[0-9]+]], [sp,
81+
;; CHECK-NOP-NEXT: mov x30, x[[T2]]
82+
;; CHECK-NOP-NEXT: hint #7
83+
;; CHECK-NOP-NEXT: mov x0, x30
84+
;; CHECK-V83-NEXT: xpaci x[[T2]]
85+
;; CHECK-V83-NEXT: mov x0, x[[T2]]
86+
;; CHECK-NOT: x0
87+
;; CHECK: ret
88+
89+
define i8* @f3() #0 {
90+
entry:
91+
%0 = call i8* @llvm.returnaddress(i32 0)
92+
ret i8* %0
93+
}
94+
;; CHECK-LABEL: f3:
95+
;; CHECK: str x30, [sp,
96+
;; CHECK-NOP-NEXT: hint #7
97+
;; CHECK-V83-NEXT: xpaci x30
98+
;; CHECK-NEXT: mov x0, x30
99+
;; CHECK-NOT: x0
100+
;; CHECK: ret
101+
attributes #0 = { nounwind }
102+
attributes #1 = { nounwind }
103+
attributes #2 = { nounwind readnone }

llvm/test/CodeGen/AArch64/GlobalISel/select-returnaddr.ll

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,24 @@
33
define i8* @rt0(i32 %x) nounwind readnone {
44
entry:
55
; CHECK-LABEL: rt0:
6-
; CHECK-NOT: stp
7-
; CHECK: mov x0, x30
6+
; CHECK: hint #7
7+
; CHECK-NEXT: mov x0, x30
88
%0 = tail call i8* @llvm.returnaddress(i32 0)
99
ret i8* %0
1010
}
1111

1212
define i8* @rt0_call_clobber(i32 %x) nounwind readnone {
1313
entry:
1414
; CHECK-LABEL: rt0_call_clobber:
15-
; CHECK: stp x20, x19, [sp, #-32]!
16-
; CHECK: stp x29, x30, [sp, #16]
17-
; CHECK: mov x19, x30
18-
; CHECK: bl _foo
19-
; CHECK: ldp x29, x30, [sp, #16]
20-
; CHECK: mov x0, x19
15+
; CHECK: stp x20, x19, [sp, #-32]!
16+
; CHECK: stp x29, x30, [sp, #16]
17+
; CHECK: mov x19, x30
18+
; CHECK: bl _foo
19+
; CHECK: mov x30, x19
20+
; CHECK-NEXT: hint #7
21+
; CHECK-NEXT: mov x0, x30
22+
; CHECK-NOT: x0
23+
; CHECK: ret
2124
%ret = call i32 @foo()
2225
%0 = tail call i8* @llvm.returnaddress(i32 0)
2326
ret i8* %0
@@ -26,9 +29,13 @@ entry:
2629
define i8* @rt2() nounwind readnone {
2730
entry:
2831
; CHECK-LABEL: rt2:
29-
; CHECK: ldr x[[reg:[0-9]+]], [x29]
30-
; CHECK: ldr x[[reg]], [x[[reg]]]
31-
; CHECK: ldr x0, [x[[reg]], #8]
32+
; CHECK: ldr x[[reg:[0-9]+]], [x29]
33+
; CHECK: ldr x[[reg]], [x[[reg]]]
34+
; CHECK: ldr x30, [x[[reg]], #8]
35+
; CHECK: hint #7
36+
; CHECK: mov x0, x30
37+
; CHECK-NOT: x0
38+
; CHECK: ret
3239
%0 = tail call i8* @llvm.returnaddress(i32 2)
3340
ret i8* %0
3441
}

llvm/test/CodeGen/AArch64/GlobalISel/select-returnaddress-liveins.mir

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ body: |
1818
; CHECK: bb.0:
1919
; CHECK: successors: %bb.1(0x80000000)
2020
; CHECK: liveins: $w0, $x0, $lr
21-
; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $lr
21+
; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $lr
2222
; CHECK: bb.1:
23-
; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY [[COPY]]
23+
; CHECK: $lr = COPY [[COPY]]
24+
; CHECK: XPACLRI implicit-def $lr, implicit $lr
25+
; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY $lr
2426
; CHECK: $x0 = COPY [[COPY1]]
2527
; CHECK: RET_ReallyLR implicit $x0
2628
; LR should be added as a livein to the entry block.
@@ -45,9 +47,11 @@ body: |
4547
; CHECK: bb.0:
4648
; CHECK: successors: %bb.1(0x80000000)
4749
; CHECK: liveins: $w0, $x0, $lr
48-
; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $lr
50+
; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $lr
4951
; CHECK: bb.1:
50-
; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY [[COPY]]
52+
; CHECK: $lr = COPY [[COPY]]
53+
; CHECK: XPACLRI implicit-def $lr, implicit $lr
54+
; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY $lr
5155
; CHECK: $x0 = COPY [[COPY1]]
5256
; CHECK: RET_ReallyLR implicit $x0
5357
; We should not have LR listed as a livein twice.
@@ -74,11 +78,15 @@ body: |
7478
; CHECK: bb.0:
7579
; CHECK: successors: %bb.1(0x80000000)
7680
; CHECK: liveins: $w0, $x0, $lr
77-
; CHECK: [[COPY:%[0-9]+]]:gpr64sp = COPY $lr
78-
; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY [[COPY]]
81+
; CHECK: [[COPY:%[0-9]+]]:gpr64 = COPY $lr
82+
; CHECK: $lr = COPY [[COPY]]
83+
; CHECK: XPACLRI implicit-def $lr, implicit $lr
84+
; CHECK: [[COPY1:%[0-9]+]]:gpr64 = COPY $lr
7985
; CHECK: bb.1:
8086
; CHECK: $x0 = COPY [[COPY1]]
81-
; CHECK: [[COPY2:%[0-9]+]]:gpr64 = COPY [[COPY]]
87+
; CHECK: $lr = COPY [[COPY]]
88+
; CHECK: XPACLRI implicit-def $lr, implicit $lr
89+
; CHECK: [[COPY2:%[0-9]+]]:gpr64 = COPY $lr
8290
; CHECK: RET_ReallyLR implicit [[COPY2]]
8391
bb.0:
8492
liveins: $w0, $x0, $lr

0 commit comments

Comments
 (0)