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