1 | // RUN: %clang_cc1 -triple x86_64-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-X86-64 |
2 | // RUN: %clang_cc1 -triple arm64-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ARM |
3 | // RUN: %clang_cc1 -triple armv7-linux-gnu -target-abi apcs-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ARM |
4 | |
5 | // CHECK-NOT: @sp = common global |
6 | |
7 | #if defined(__x86_64__) |
8 | register unsigned long current_stack_pointer asm("rsp"); |
9 | #else |
10 | register unsigned long current_stack_pointer asm("sp"); |
11 | #endif |
12 | |
13 | struct p4_Thread { |
14 | struct { |
15 | int len; |
16 | } word; |
17 | }; |
18 | // Testing pointer types as well |
19 | #if defined(__x86_64__) |
20 | register struct p4_Thread *p4TH asm("rsp"); |
21 | #else |
22 | register struct p4_Thread *p4TH asm("sp"); |
23 | #endif |
24 | |
25 | // CHECK: define{{.*}} i[[bits:[0-9]+]] @get_stack_pointer_addr() |
26 | // CHECK: [[ret:%[0-9]+]] = call i[[bits]] @llvm.read_register.i[[bits]](metadata !0) |
27 | // CHECK: ret i[[bits]] [[ret]] |
28 | unsigned long get_stack_pointer_addr() { |
29 | return current_stack_pointer; |
30 | } |
31 | // CHECK: declare{{.*}} i[[bits]] @llvm.read_register.i[[bits]](metadata) |
32 | |
33 | // CHECK: define{{.*}} void @set_stack_pointer_addr(i[[bits]] %addr) #0 { |
34 | // CHECK: [[sto:%[0-9]+]] = load i[[bits]], i[[bits]]* % |
35 | // CHECK: call void @llvm.write_register.i[[bits]](metadata !0, i[[bits]] [[sto]]) |
36 | // CHECK: ret void |
37 | void set_stack_pointer_addr(unsigned long addr) { |
38 | current_stack_pointer = addr; |
39 | } |
40 | // CHECK: declare{{.*}} void @llvm.write_register.i[[bits]](metadata, i[[bits]]) |
41 | |
42 | // CHECK: define {{.*}}@fn1 |
43 | int fn1() { |
44 | return (*p4TH).word.len; |
45 | } |
46 | // CHECK: %[[regr:[0-9]+]] = call i[[bits]] @llvm.read_register.i[[bits]](metadata !0) |
47 | // CHECK: inttoptr i[[bits]] %[[regr]] to %struct.p4_Thread* |
48 | |
49 | // CHECK: define {{.*}}@fn2 |
50 | void fn2(struct p4_Thread *val) { |
51 | p4TH = val; |
52 | } |
53 | // CHECK: %[[regw:[0-9]+]] = ptrtoint %struct.p4_Thread* %{{.*}} to i[[bits]] |
54 | // CHECK: call void @llvm.write_register.i[[bits]](metadata !0, i[[bits]] %[[regw]]) |
55 | |
56 | // CHECK-X86-64: !llvm.named.register.rsp = !{!0} |
57 | // CHECK-X86-64: !0 = !{!"rsp"} |
58 | // CHECK-ARM: !llvm.named.register.sp = !{!0} |
59 | // CHECK-ARM: !0 = !{!"sp"} |
60 | |