1; RUN: llc --force-dwarf-frame-section %s -o - | FileCheck %s
2; RUN: llc --filetype=obj %s -o - | llvm-readelf -s --unwind - | FileCheck %s --check-prefix=UNWIND
3target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64"
4target triple = "thumbv8m.main-none-none-eabi"
5
6; int g(int);
7;
8; #if __ARM_FEATURE_CMSE == 3
9; #define ENTRY __attribute__((cmse_nonsecure_entry))
10; #else
11; #define ENTRY
12; #endif
13;
14; ENTRY int f(int x) {
15;     return 1 + g(x - 1);
16; }
17
18define hidden i32 @f0(i32 %x) local_unnamed_addr {
19entry:
20  %sub = add nsw i32 %x, -1
21  %call = tail call i32 @g(i32 %sub)
22  %add = add nsw i32 %call, 1
23  ret i32 %add
24}
25
26; CHECK-LABEL: f0:
27; CHECK:       pac     r12, lr, sp
28; CHECK-NEXT:  .save   {r7, lr}
29; CHECK-NEXT:  push    {r7, lr}
30; CHECK-NEXT: .cfi_def_cfa_offset 8
31; CHECK-NEXT: .cfi_offset lr, -4
32; CHECK-NEXT: .cfi_offset r7, -8
33; CHECK-NEXT: .save   {ra_auth_code}
34; CHECK-NEXT:  str     r12, [sp, #-4]!
35; CHECK-NEXT: .cfi_def_cfa_offset 12
36; CHECK-NEXT: .cfi_offset ra_auth_code, -12
37; CHECK-NEXT: .pad    #4
38; CHECK-NEXT:  sub     sp, #4
39; ...
40; CHECK:       add     sp, #4
41; CHECK-NEXT:  ldr     r12, [sp], #4
42; CHECK-NEXT:  pop.w   {r7, lr}
43; CHECK-NEXT:  aut     r12, lr, sp
44; CHECK-NEXT:  bx      lr
45
46define hidden i32 @f1(i32 %x) local_unnamed_addr #0 {
47entry:
48  %sub = add nsw i32 %x, -1
49  %call = tail call i32 @g(i32 %sub)
50  %add = add nsw i32 %call, 1
51  ret i32 %add
52}
53
54; CHECK-LABEL: f1:
55; CHECK:       pac     r12, lr, sp
56; CHECK-NEXT:  vstr    fpcxtns, [sp, #-4]!
57; CHECK-NEXT:  .cfi_def_cfa_offset 4
58; CHECK-NEXT:  .save    {r7, lr}
59; CHECK-NEXT:  push    {r7, lr}
60; CHECK:       vldr    fpcxtns, [sp], #4
61; CHECK:       aut     r12, lr, sp
62
63define hidden i32 @f2(i32 %x) local_unnamed_addr #1 {
64entry:
65  %sub = add nsw i32 %x, -1
66  %call = tail call i32 @g(i32 %sub)
67  %add = add nsw i32 %call, 1
68  ret i32 %add
69}
70; CHECK-LABEL: f2:
71; CHECK:       pac    r12, lr, sp
72; CHECK-NEXT:  .save  {r7, lr}
73; CHECK-NEXT:  push   {r7, lr}
74; CHECK-NEXT: .cfi_def_cfa_offset 8
75; CHECK-NEXT: .cfi_offset lr, -4
76; CHECK-NEXT: .cfi_offset r7, -8
77; CHECK-NEXT:  .save  {ra_auth_code}
78; CHECK-NEXT:  str    r12, [sp, #-4]!
79; CHECK-NEXT: .cfi_def_cfa_offset 12
80; CHECK-NEXT: .cfi_offset ra_auth_code, -12
81; CHECK-NEXT:  .pad   #4
82; CHECK-NEXT:  sub    sp, #4
83; CHECK-NEXT:  .cfi_def_cfa_offset 16
84; ...
85; CHECK:       add    sp, #4
86; CHECK-NEXT:  ldr    r12, [sp], #4
87; CHECK-NEXT:  pop.w  {r7, lr}
88; CHECK-NEXT:  aut    r12, lr, sp
89; CHECK-NEXT:  mrs    r12, control
90; ...
91; CHECK:       bxns    lr
92
93declare dso_local i32 @g(i32) local_unnamed_addr
94
95attributes #0 = { "cmse_nonsecure_entry" "target-features"="+8msecext,+armv8.1-m.main"}
96attributes #1 = { "cmse_nonsecure_entry" "target-features"="+8msecext,+armv8-m.main,+fp-armv8d16"}
97
98!llvm.module.flags = !{!0, !1, !2}
99
100!0 = !{i32 8, !"branch-target-enforcement", i32 0}
101!1 = !{i32 8, !"sign-return-address", i32 1}
102!2 = !{i32 8, !"sign-return-address-all", i32 0}
103
104; UNWIND-LABEL: FunctionAddress: 0x0
105; UNWIND:       0x00      ; vsp = vsp + 4
106; UNWIND-NEXT:  0xB4      ; pop ra_auth_code
107; UNWIND-NEXT:  0x84 0x08 ; pop {r7, lr}
108; UNWIND-NEXT:  0xB0      ; finish
109; UNWIND-NEXT:  0xB0      ; finish
110
111; UNWIND-LABEL: FunctionAddress: 0x24
112; UNWIND:       0xB4      ; pop ra_auth_code
113; UNWIND-NEXT:  0x84 0x08 ; pop {r7, lr}
114
115; UNWIND-LABEL: FunctionAddress: 0x54
116; UNWIND:       0x00      ; vsp = vsp + 4
117; UNWIND-NEXT:  0xB4      ; pop ra_auth_code
118; UNWIND-NEXT:  0x84 0x08 ; pop {r7, lr}
119; UNWIND-NEXT:  0xB0      ; finish
120; UNWIND-NEXT:  0xB0      ; finish
121
122; UNWIND-LABEL: 00000001 {{.*}} f0
123; UNWIND-LABEL: 00000025 {{.*}} f1
124; UNWIND-LABEL: 00000055 {{.*}} f2
125