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