1 // REQUIRES: mips-registered-target
2
3 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
4 // RUN: %cheri_purecap_cc1 -std=c11 %s -emit-llvm -o - -O0 | %cheri_FileCheck %s
5 // RUN: %cheri_purecap_cc1 -std=c11 %s -emit-llvm -o - -O2 | %cheri_FileCheck %s -check-prefixes OPT,NULL_INVALID-OPT
6 // RUN: %cheri_purecap_cc1 -std=c11 %s -emit-llvm -o - -O2 -fno-delete-null-pointer-checks | %cheri_FileCheck %s -check-prefixes OPT,NO_DELETE_NULL-OPT
7 // Check that we can generate assembly without crashing
8 // RUN: %cheri_purecap_cc1 -mllvm -cheri-cap-table-abi=plt -std=c11 %s -S -o - -O2 -fno-delete-null-pointer-checks | FileCheck %s -check-prefix ASM
9
10 // This previously crashed in codegen when generating the *p
11 // CHECK-LABEL: @main(
12 // CHECK-NEXT: entry:
13 // CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4, addrspace(200)
14 // CHECK-NEXT: [[P:%.*]] = alloca i32 addrspace(200)*, align [[#CAP_SIZE]], addrspace(200)
15 // CHECK-NEXT: store i32 0, i32 addrspace(200)* [[RETVAL]], align 4
16 // CHECK-NEXT: store i32 addrspace(200)* null, i32 addrspace(200)* addrspace(200)* [[P]], align [[#CAP_SIZE]]
17 // CHECK-NEXT: [[ATOMIC_LOAD:%.*]] = load atomic i32 addrspace(200)*, i32 addrspace(200)* addrspace(200)* [[P]] seq_cst, align [[#CAP_SIZE]]
18 // CHECK-NEXT: [[TMP0:%.*]] = load i32, i32 addrspace(200)* [[ATOMIC_LOAD]], align 4
19 // CHECK-NEXT: ret i32 [[TMP0]]
20 //
21 // OPT-LABEL: @main(
22 // OPT-NEXT: entry:
23 // Now clang can tell that it is dereferncing a null pointer an returns undef
24 // NULL_INVALID-OPT-NEXT: ret i32 undef
25 // This uses a crazy alignment value (the maximum) because it is loading a null pointer, not a bug!
26 // NO_DELETE_NULL-OPT-NEXT: [[TMP0:%.*]] = load i32, i32 addrspace(200)* null, align 536870912, !tbaa !2
27 // NO_DELETE_NULL-OPT-NEXT: ret i32 [[TMP0]]
main(void)28 int main(void) {
29 _Atomic(int*) p = (int*)0;
30 return *p;
31
32 // TODO: why is this not going in the delay slot?
33 // ASM-LABEL: main:
34 // ASM: cgetnull $c1
35 // ASM-NEXT: clw $2, $zero, 0($c1)
36 // ASM-NEXT: cjr $c17
37 // ASM-NEXT: nop
38 }
39
40 // This previously crashed in codegen when generating the *p
41 // CHECK-LABEL: @main2(
42 // CHECK-NEXT: entry:
43 // CHECK-NEXT: [[P_ADDR:%.*]] = alloca i32 addrspace(200)*, align [[#CAP_SIZE]], addrspace(200)
44 // CHECK-NEXT: store i32 addrspace(200)* [[P:%.*]], i32 addrspace(200)* addrspace(200)* [[P_ADDR]], align [[#CAP_SIZE]]
45 // CHECK-NEXT: [[ATOMIC_LOAD:%.*]] = load atomic i32 addrspace(200)*, i32 addrspace(200)* addrspace(200)* [[P_ADDR]] seq_cst, align [[#CAP_SIZE]]
46 // CHECK-NEXT: [[TMP0:%.*]] = load i32, i32 addrspace(200)* [[ATOMIC_LOAD]], align 4
47 // CHECK-NEXT: ret i32 [[TMP0]]
48 //
49 // OPT-LABEL: @main2(
50 // OPT-NEXT: entry:
51 // OPT-NEXT: [[TMP0:%.*]] = load i32, i32 addrspace(200)* [[P:%.*]], align 4, !tbaa !2
52 // OPT-NEXT: ret i32 [[TMP0]]
53 //
main2(_Atomic (int *)p)54 int main2(_Atomic(int*) p) {
55 return *p;
56 // ASM-LABEL: main2:
57 // TODO: why is this not going in the delay slot?
58 // ASM: clw $2, $zero, 0($c3)
59 // ASM-NEXT: cjr $c17
60 // ASM-NEXT: nop
61 }
62
63
64 // This was also crashing:
65 _Atomic(int *) a;
66 // CHECK-LABEL: @test_store(
67 // CHECK-NEXT: entry:
68 // CHECK-NEXT: store atomic i32 addrspace(200)* bitcast (i8 addrspace(200)* getelementptr (i8, i8 addrspace(200)* null, i64 1) to i32 addrspace(200)*), i32 addrspace(200)* addrspace(200)* @a seq_cst, align [[#CAP_SIZE]]
69 // CHECK-NEXT: ret void
70 //
71 // OPT-LABEL: @test_store(
72 // OPT-NEXT: entry:
73 // OPT-NEXT: store atomic i32 addrspace(200)* bitcast (i8 addrspace(200)* getelementptr (i8, i8 addrspace(200)* null, i64 1) to i32 addrspace(200)*), i32 addrspace(200)* addrspace(200)* @a seq_cst, align [[#CAP_SIZE]], !tbaa !6
74 // OPT-NEXT: ret void
75 //
test_store()76 void test_store() {
77 a = (void *)1;
78 // ASM-LABEL: test_store:
79 // TODO: why is this not going in the delay slot?
80 // ASM: clcbi $c1, %captab20(a)($c26)
81 // ASM-NEXT: sync
82 // ASM-NEXT: cincoffset $c2, $cnull, 1
83 // ASM-NEXT: csc $c2, $zero, 0($c1)
84 // ASM-NEXT: sync
85 // ASM-NEXT: cjr $c17
86 // ASM-NEXT: nop
87 }
88