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