1 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
2 // RUN: %cheri_purecap_cc1 -o - -emit-llvm -O0 %s | FileCheck %s
3 // RUN: %cheri_cc1 -o - -emit-llvm -O0 %s | FileCheck %s -check-prefix HYBRID
4 // CHECK-LABEL: @var_annotation(
5 // CHECK-NEXT:  entry:
6 // CHECK-NEXT:    [[B:%.*]] = alloca i32, align 4, addrspace(200)
7 // CHECK-NEXT:    [[B1:%.*]] = bitcast i32 addrspace(200)* [[B]] to i8 addrspace(200)*
8 // CHECK-NEXT:    call void @llvm.var.annotation.p200i8(i8 addrspace(200)* [[B1]], i8 addrspace(200)* getelementptr inbounds ([4 x i8], [4 x i8] addrspace(200)* @.str, i32 0, i32 0),
9 // CHECK-SAME:  i8 addrspace(200)* getelementptr inbounds ([[FILENAME_ARRAY:\[[0-9]+ x i8\]]],
10 // CHECK-SAME:  [[FILENAME_ARRAY]] addrspace(200)* @.str.1, i32 0, i32 0),
11 // CHECK-SAME:  i32 [[@LINE+13]])
12 // CHECK-NEXT:    ret void
13 // HYBRID-LABEL: @var_annotation(
14 // HYBRID-NEXT:  entry:
15 // HYBRID-NEXT:    [[B:%.*]] = alloca i32, align 4
16 // HYBRID-NEXT:    [[B1:%.*]] = bitcast i32* [[B]] to i8*
17 // HYBRID-NEXT:    call void @llvm.var.annotation.p0i8(i8* [[B1]], i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0),
18 // HYBRID-SAME:  i8* getelementptr inbounds ([[FILENAME_ARRAY:\[[0-9]+ x i8\]]],
19 // HYBRID-SAME:  [[FILENAME_ARRAY]]* @.str.1, i32 0, i32 0),
20 // HYBRID-SAME:  i32 [[@LINE+4]])
21 // HYBRID-NEXT:    ret void
22 //
var_annotation(void)23 void var_annotation(void) {
24   __attribute__((annotate("foo"))) int b;
25 }
26 
27 // Should be overloaded and args in AS200
28 // CHECK: declare void @llvm.var.annotation.p200i8(i8 addrspace(200)*, i8 addrspace(200)*, i8 addrspace(200)*, i32) addrspace(200)
29 // HYBRID: declare void @llvm.var.annotation.p0i8(i8*, i8*, i8*, i32)
30 
31 // CHECK-LABEL: @ptr_annotation(
32 // CHECK-NEXT:  entry:
33 // CHECK-NEXT:    [[VAR:%.*]] = alloca [[STRUCT_ANON:%.*]], align 4, addrspace(200)
34 // CHECK-NEXT:    [[U:%.*]] = getelementptr inbounds [[STRUCT_ANON]], [[STRUCT_ANON]] addrspace(200)* [[VAR]], i32 0, i32 0
35 // CHECK-NEXT:    store i32 0, i32 addrspace(200)* [[U]], align 4
36 // CHECK-NEXT:    [[V:%.*]] = getelementptr inbounds [[STRUCT_ANON]], [[STRUCT_ANON]] addrspace(200)* [[VAR]], i32 0, i32 1
37 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast i32 addrspace(200)* [[V]] to i8 addrspace(200)*
38 // CHECK-NEXT:    [[TMP1:%.*]] = call i8 addrspace(200)* @llvm.ptr.annotation.p200i8.p200i8(i8 addrspace(200)* [[TMP0]], i8 addrspace(200)* getelementptr inbounds ([13 x i8], [13 x i8] addrspace(200)* @.str.2, i32 0, i32 0), i8 addrspace(200)* getelementptr inbounds ([[FILENAME_ARRAY]], [[FILENAME_ARRAY]] addrspace(200)* @.str.1, i32 0, i32 0), i32 [[@LINE+19]])
39 // CHECK-NEXT:    [[TMP2:%.*]] = bitcast i8 addrspace(200)* [[TMP1]] to i32 addrspace(200)*
40 // CHECK-NEXT:    store i32 0, i32 addrspace(200)* [[TMP2]], align 4
41 // CHECK-NEXT:    ret i32 0
42 // HYBRID-LABEL: @ptr_annotation(
43 // HYBRID-NEXT:  entry:
44 // HYBRID-NEXT:    [[VAR:%.*]] = alloca [[STRUCT_ANON:%.*]], align 4
45 // HYBRID-NEXT:    [[U:%.*]] = getelementptr inbounds [[STRUCT_ANON]], %struct.anon* [[VAR]], i32 0, i32 0
46 // HYBRID-NEXT:    store i32 0, i32* [[U]], align 4
47 // HYBRID-NEXT:    [[V:%.*]] = getelementptr inbounds [[STRUCT_ANON]], %struct.anon* [[VAR]], i32 0, i32 1
48 // HYBRID-NEXT:    [[TMP0:%.*]] = bitcast i32* [[V]] to i8*
49 // HYBRID-NEXT:    [[TMP1:%.*]] = call i8* @llvm.ptr.annotation.p0i8.p0i8(i8* [[TMP0]], i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.2, i32 0, i32 0), i8* getelementptr inbounds ([[FILENAME_ARRAY]], [[FILENAME_ARRAY]]* @.str.1, i32 0, i32 0), i32 [[@LINE+8]])
50 // HYBRID-NEXT:    [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32*
51 // HYBRID-NEXT:    store i32 0, i32* [[TMP2]], align 4
52 // HYBRID-NEXT:    ret i32 0
53 //
ptr_annotation(void)54 int ptr_annotation(void) {
55   struct {
56     int u;
57     __attribute__((annotate("myannotation"))) int v;
58   } var;
59   var.u = 0;
60   var.v = 0;
61   return (0);
62 }
63 
64 // Should be overloaded and args in AS200
65 // CHECK: declare i8 addrspace(200)* @llvm.ptr.annotation.p200i8.p200i8(i8 addrspace(200)*, i8 addrspace(200)*, i8 addrspace(200)*, i32) addrspace(200)
66 // HYBRID: declare i8* @llvm.ptr.annotation.p0i8.p0i8(i8*, i8*, i8*, i32)
67 
68 // CHECK-LABEL: @builtin_annotation(
69 // CHECK-NEXT:  entry:
70 // CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i64, align 8, addrspace(200)
71 // CHECK-NEXT:    [[Y:%.*]] = alloca i64, align 8, addrspace(200)
72 // CHECK-NEXT:    store i64 [[X:%.*]], i64 addrspace(200)* [[X_ADDR]], align 8
73 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, i64 addrspace(200)* [[X_ADDR]], align 8
74 // CHECK-NEXT:    [[TMP1:%.*]] = call i64 @llvm.annotation.i64.p200i8(i64 [[TMP0]], i8 addrspace(200)* getelementptr inbounds ([13 x i8], [13 x i8] addrspace(200)* @.str.3, i32 0, i32 0), i8 addrspace(200)* getelementptr inbounds ([[FILENAME_ARRAY]], [[FILENAME_ARRAY]] addrspace(200)* @.str.1, i32 0, i32 0), i32 [[@LINE+22]])
75 // CHECK-NEXT:    store i64 [[TMP1]], i64 addrspace(200)* [[Y]], align 8
76 // CHECK-NEXT:    [[TMP2:%.*]] = load i64, i64 addrspace(200)* [[X_ADDR]], align 8
77 // CHECK-NEXT:    [[TMP3:%.*]] = load i64, i64 addrspace(200)* [[Y]], align 8
78 // CHECK-NEXT:    [[ADD:%.*]] = add nsw i64 [[TMP2]], [[TMP3]]
79 // CHECK-NEXT:    [[CONV:%.*]] = trunc i64 [[ADD]] to i32
80 // CHECK-NEXT:    ret i32 [[CONV]]
81 // HYBRID-LABEL: @builtin_annotation(
82 // HYBRID-NEXT:  entry:
83 // HYBRID-NEXT:    [[X_ADDR:%.*]] = alloca i64, align 8
84 // HYBRID-NEXT:    [[Y:%.*]] = alloca i64, align 8
85 // HYBRID-NEXT:    store i64 [[X:%.*]], i64* [[X_ADDR]], align 8
86 // HYBRID-NEXT:    [[TMP0:%.*]] = load i64, i64* [[X_ADDR]], align 8
87 // HYBRID-NEXT:    [[TMP1:%.*]] = call i64 @llvm.annotation.i64.p0i8(i64 [[TMP0]], i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.3, i32 0, i32 0), i8* getelementptr inbounds ([[FILENAME_ARRAY]], [[FILENAME_ARRAY]]* @.str.1, i32 0, i32 0), i32 [[@LINE+9]])
88 // HYBRID-NEXT:    store i64 [[TMP1]], i64* [[Y]], align 8
89 // HYBRID-NEXT:    [[TMP2:%.*]] = load i64, i64* [[X_ADDR]], align 8
90 // HYBRID-NEXT:    [[TMP3:%.*]] = load i64, i64* [[Y]], align 8
91 // HYBRID-NEXT:    [[ADD:%.*]] = add nsw i64 [[TMP2]], [[TMP3]]
92 // HYBRID-NEXT:    [[CONV:%.*]] = trunc i64 [[ADD]] to i32
93 // HYBRID-NEXT:    ret i32 [[CONV]]
94 //
builtin_annotation(long x)95 int builtin_annotation(long x) {
96   long y = __builtin_annotation(x, "annotation_a");
97   return x + y;
98 }
99 
100 // Should be overloaded and args in AS200
101 // CHECK: declare i64 @llvm.annotation.i64.p200i8(i64, i8 addrspace(200)*, i8 addrspace(200)*, i32) addrspace(200)
102 // HYBRID: declare i64 @llvm.annotation.i64.p0i8(i64, i8*, i8*, i32)
103 
104 // https://github.com/CTSRD-CHERI/llvm-project/issues/327
issue327(void)105 void issue327(void) {
106   struct {
107     __attribute__((annotate("myannotation"))) int u;
108   } var, *__capability x;
109   x = &var;
110   x->u = x->u;
111 }
112 
113 // CHECK: define void @issue327() addrspace(200)
114 // CHECK: call i8 addrspace(200)* @llvm.ptr.annotation.p200i8.p200i8(i8 addrspace(200)* %{{.+}}, i8 addrspace(200)* getelementptr inbounds ([13 x i8], [13 x i8] addrspace(200)* @.str.2, i32 0, i32 0),
115 // CHECK-SAME: i8 addrspace(200)* getelementptr inbounds ([[FILENAME_ARRAY]], [[FILENAME_ARRAY]] addrspace(200)* @.str.1, i32 0, i32 0),
116 // CHECK-SAME: i32 [[MYANNOTATION_LINE:107]])
117 // CHECK: call i8 addrspace(200)* @llvm.ptr.annotation.p200i8.p200i8(i8 addrspace(200)* %{{.+}}, i8 addrspace(200)* getelementptr inbounds ([13 x i8], [13 x i8] addrspace(200)* @.str.2, i32 0, i32 0),
118 // CHECK-SAME: i8 addrspace(200)* getelementptr inbounds ([[FILENAME_ARRAY]], [[FILENAME_ARRAY]] addrspace(200)* @.str.1, i32 0, i32 0),
119 // CHECK-SAME: i32 [[MYANNOTATION_LINE]])
120 
121 // HYBRID: define void @issue327()
122 // HYBRID: call i8* @llvm.ptr.annotation.p0i8.p0i8(i8* %{{.+}}, i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.2, i32 0, i32 0),
123 // HYBRID-SAME: i8* getelementptr inbounds ([[FILENAME_ARRAY]], [[FILENAME_ARRAY]]* @.str.1, i32 0, i32 0),
124 // HYBRID-SAME: i32 [[MYANNOTATION_LINE:107]])
125 // HYBRID: call i8* @llvm.ptr.annotation.p0i8.p0i8(i8* %{{.+}}, i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.2, i32 0, i32 0),
126 // HYBRID-SAME: i8* getelementptr inbounds ([[FILENAME_ARRAY]], [[FILENAME_ARRAY]]* @.str.1, i32 0, i32 0),
127 // HYBRID-SAME: i32 [[MYANNOTATION_LINE]])
128