xref: /minix3/external/bsd/llvm/dist/clang/test/CodeGen/sparcv9-abi.c (revision 0b98e8aad89f2bd4ba80b523d73cf29e9dd82ce1)
1 // RUN: %clang_cc1 -triple sparcv9-unknown-unknown -emit-llvm %s -o - | FileCheck %s
2 #include <stdarg.h>
3 
4 // CHECK-LABEL: define void @f_void()
5 void f_void(void) {}
6 
7 // Arguments and return values smaller than the word size are extended.
8 
9 // CHECK-LABEL: define signext i32 @f_int_1(i32 signext %x)
10 int f_int_1(int x) { return x; }
11 
12 // CHECK-LABEL: define zeroext i32 @f_int_2(i32 zeroext %x)
13 unsigned f_int_2(unsigned x) { return x; }
14 
15 // CHECK-LABEL: define i64 @f_int_3(i64 %x)
16 long long f_int_3(long long x) { return x; }
17 
18 // CHECK-LABEL: define signext i8 @f_int_4(i8 signext %x)
19 char f_int_4(char x) { return x; }
20 
21 // Small structs are passed in registers.
22 struct small {
23   int *a, *b;
24 };
25 
26 // CHECK-LABEL: define %struct.small @f_small(i32* %x.coerce0, i32* %x.coerce1)
27 struct small f_small(struct small x) {
28   x.a += *x.b;
29   x.b = 0;
30   return x;
31 }
32 
33 // Medium-sized structs are passed indirectly, but can be returned in registers.
34 struct medium {
35   int *a, *b;
36   int *c, *d;
37 };
38 
39 // CHECK-LABEL: define %struct.medium @f_medium(%struct.medium* %x)
40 struct medium f_medium(struct medium x) {
41   x.a += *x.b;
42   x.b = 0;
43   return x;
44 }
45 
46 // Large structs are also returned indirectly.
47 struct large {
48   int *a, *b;
49   int *c, *d;
50   int x;
51 };
52 
53 // CHECK-LABEL: define void @f_large(%struct.large* noalias sret %agg.result, %struct.large* %x)
54 struct large f_large(struct large x) {
55   x.a += *x.b;
56   x.b = 0;
57   return x;
58 }
59 
60 // A 64-bit struct fits in a register.
61 struct reg {
62   int a, b;
63 };
64 
65 // CHECK-LABEL: define i64 @f_reg(i64 %x.coerce)
66 struct reg f_reg(struct reg x) {
67   x.a += x.b;
68   return x;
69 }
70 
71 // Structs with mixed int and float parts require the inreg attribute.
72 struct mixed {
73   int a;
74   float b;
75 };
76 
77 // CHECK-LABEL: define inreg %struct.mixed @f_mixed(i32 inreg %x.coerce0, float inreg %x.coerce1)
78 struct mixed f_mixed(struct mixed x) {
79   x.a += 1;
80   return x;
81 }
82 
83 // Struct with padding.
84 struct mixed2 {
85   int a;
86   double b;
87 };
88 
89 // CHECK: define { i64, double } @f_mixed2(i64 %x.coerce0, double %x.coerce1)
90 // CHECK: store i64 %x.coerce0
91 // CHECK: store double %x.coerce1
92 struct mixed2 f_mixed2(struct mixed2 x) {
93   x.a += 1;
94   return x;
95 }
96 
97 // Struct with single element and padding in passed in the high bits of a
98 // register.
99 struct tiny {
100   char a;
101 };
102 
103 // CHECK-LABEL: define i64 @f_tiny(i64 %x.coerce)
104 // CHECK: %[[HB:[^ ]+]] = lshr i64 %x.coerce, 56
105 // CHECK: = trunc i64 %[[HB]] to i8
106 struct tiny f_tiny(struct tiny x) {
107   x.a += 1;
108   return x;
109 }
110 
111 // CHECK-LABEL: define void @call_tiny()
112 // CHECK: %[[XV:[^ ]+]] = zext i8 %{{[^ ]+}} to i64
113 // CHECK: %[[HB:[^ ]+]] = shl i64 %[[XV]], 56
114 // CHECK: = call i64 @f_tiny(i64 %[[HB]])
115 void call_tiny() {
116   struct tiny x = { 1 };
117   f_tiny(x);
118 }
119 
120 // CHECK-LABEL: define signext i32 @f_variable(i8* %f, ...)
121 // CHECK: %ap = alloca i8*
122 // CHECK: call void @llvm.va_start
123 //
124 int f_variable(char *f, ...) {
125   int s = 0;
126   char c;
127   va_list ap;
128   va_start(ap, f);
129   while ((c = *f++)) switch (c) {
130 
131 // CHECK: %[[CUR:[^ ]+]] = load i8** %ap
132 // CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr i8* %[[CUR]], i32 8
133 // CHECK-DAG: store i8* %[[NXT]], i8** %ap
134 // CHECK-DAG: %[[EXT:[^ ]+]] = getelementptr i8* %[[CUR]], i32 4
135 // CHECK-DAG: %[[ADR:[^ ]+]] = bitcast i8* %[[EXT]] to i32*
136 // CHECK-DAG: load i32* %[[ADR]]
137 // CHECK: br
138   case 'i':
139     s += va_arg(ap, int);
140     break;
141 
142 // CHECK: %[[CUR:[^ ]+]] = load i8** %ap
143 // CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr i8* %[[CUR]], i32 8
144 // CHECK-DAG: store i8* %[[NXT]], i8** %ap
145 // CHECK-DAG: %[[ADR:[^ ]+]] = bitcast i8* %[[CUR]] to i64*
146 // CHECK-DAG: load i64* %[[ADR]]
147 // CHECK: br
148   case 'l':
149     s += va_arg(ap, long);
150     break;
151 
152 // CHECK: %[[CUR:[^ ]+]] = load i8** %ap
153 // CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr i8* %[[CUR]], i32 8
154 // CHECK-DAG: store i8* %[[NXT]], i8** %ap
155 // CHECK-DAG: %[[ADR:[^ ]+]] = bitcast i8* %[[CUR]] to %struct.tiny*
156 // CHECK: br
157   case 't':
158     s += va_arg(ap, struct tiny).a;
159     break;
160 
161 // CHECK: %[[CUR:[^ ]+]] = load i8** %ap
162 // CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr i8* %[[CUR]], i32 16
163 // CHECK-DAG: store i8* %[[NXT]], i8** %ap
164 // CHECK-DAG: %[[ADR:[^ ]+]] = bitcast i8* %[[CUR]] to %struct.small*
165 // CHECK: br
166   case 's':
167     s += *va_arg(ap, struct small).a;
168     break;
169 
170 // CHECK: %[[CUR:[^ ]+]] = load i8** %ap
171 // CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr i8* %[[CUR]], i32 8
172 // CHECK-DAG: store i8* %[[NXT]], i8** %ap
173 // CHECK-DAG: %[[IND:[^ ]+]] = bitcast i8* %[[CUR]] to %struct.medium**
174 // CHECK-DAG: %[[ADR:[^ ]+]] = load %struct.medium** %[[IND]]
175 // CHECK: br
176   case 'm':
177     s += *va_arg(ap, struct medium).a;
178     break;
179   }
180   return s;
181 }
182