1a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// RUN: %clang_cc1 -triple sparcv9-unknown-unknown -emit-llvm %s -o - | FileCheck %s
2a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen#include <stdarg.h>
3107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen
493ab6bf534fb6c26563c00f28a8fc5581bb71dfdStephen Lin// CHECK-LABEL: define void @f_void()
5107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesenvoid f_void(void) {}
6107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen
7107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen// Arguments and return values smaller than the word size are extended.
8107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen
993ab6bf534fb6c26563c00f28a8fc5581bb71dfdStephen Lin// CHECK-LABEL: define signext i32 @f_int_1(i32 signext %x)
10107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesenint f_int_1(int x) { return x; }
11107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen
1293ab6bf534fb6c26563c00f28a8fc5581bb71dfdStephen Lin// CHECK-LABEL: define zeroext i32 @f_int_2(i32 zeroext %x)
13107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesenunsigned f_int_2(unsigned x) { return x; }
14107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen
1593ab6bf534fb6c26563c00f28a8fc5581bb71dfdStephen Lin// CHECK-LABEL: define i64 @f_int_3(i64 %x)
16107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesenlong long f_int_3(long long x) { return x; }
17107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen
1893ab6bf534fb6c26563c00f28a8fc5581bb71dfdStephen Lin// CHECK-LABEL: define signext i8 @f_int_4(i8 signext %x)
19107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesenchar f_int_4(char x) { return x; }
20107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen
21651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines// CHECK-LABEL: define fp128 @f_ld(fp128 %x)
22651f13cea278ec967336033dd032faef0e9fc2ecStephen Hineslong double f_ld(long double x) { return x; }
23651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
24107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen// Small structs are passed in registers.
25107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesenstruct small {
26107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen  int *a, *b;
27107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen};
28107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen
2993ab6bf534fb6c26563c00f28a8fc5581bb71dfdStephen Lin// CHECK-LABEL: define %struct.small @f_small(i32* %x.coerce0, i32* %x.coerce1)
30107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesenstruct small f_small(struct small x) {
31107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen  x.a += *x.b;
32107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen  x.b = 0;
33107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen  return x;
34107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen}
35107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen
36107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen// Medium-sized structs are passed indirectly, but can be returned in registers.
37107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesenstruct medium {
38107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen  int *a, *b;
39107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen  int *c, *d;
40107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen};
41107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen
4293ab6bf534fb6c26563c00f28a8fc5581bb71dfdStephen Lin// CHECK-LABEL: define %struct.medium @f_medium(%struct.medium* %x)
43107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesenstruct medium f_medium(struct medium x) {
44107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen  x.a += *x.b;
45107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen  x.b = 0;
46107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen  return x;
47107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen}
48107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen
49107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen// Large structs are also returned indirectly.
50107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesenstruct large {
51107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen  int *a, *b;
52107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen  int *c, *d;
53107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen  int x;
54107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen};
55107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen
5693ab6bf534fb6c26563c00f28a8fc5581bb71dfdStephen Lin// CHECK-LABEL: define void @f_large(%struct.large* noalias sret %agg.result, %struct.large* %x)
57107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesenstruct large f_large(struct large x) {
58107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen  x.a += *x.b;
59107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen  x.b = 0;
60107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen  return x;
61107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen}
62107196cb219128bfddde53f4718e5c9aa3a41ba6Jakob Stoklund Olesen
63fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesen// A 64-bit struct fits in a register.
64fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesenstruct reg {
65fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesen  int a, b;
66fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesen};
67fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesen
6893ab6bf534fb6c26563c00f28a8fc5581bb71dfdStephen Lin// CHECK-LABEL: define i64 @f_reg(i64 %x.coerce)
69fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesenstruct reg f_reg(struct reg x) {
70fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesen  x.a += x.b;
71fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesen  return x;
72fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesen}
73fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesen
74fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesen// Structs with mixed int and float parts require the inreg attribute.
75fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesenstruct mixed {
76fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesen  int a;
77fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesen  float b;
78fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesen};
79fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesen
8093ab6bf534fb6c26563c00f28a8fc5581bb71dfdStephen Lin// CHECK-LABEL: define inreg %struct.mixed @f_mixed(i32 inreg %x.coerce0, float inreg %x.coerce1)
81fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesenstruct mixed f_mixed(struct mixed x) {
82fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesen  x.a += 1;
83fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesen  return x;
84fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesen}
85fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesen
86fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesen// Struct with padding.
87fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesenstruct mixed2 {
88fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesen  int a;
89fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesen  double b;
90fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesen};
91fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesen
927e9f52f1faacf5505476418411127c5b16e07533Jakob Stoklund Olesen// CHECK: define { i64, double } @f_mixed2(i64 %x.coerce0, double %x.coerce1)
937e9f52f1faacf5505476418411127c5b16e07533Jakob Stoklund Olesen// CHECK: store i64 %x.coerce0
947e9f52f1faacf5505476418411127c5b16e07533Jakob Stoklund Olesen// CHECK: store double %x.coerce1
95fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesenstruct mixed2 f_mixed2(struct mixed2 x) {
96fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesen  x.a += 1;
97fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesen  return x;
98fc782fbeb25ad880ec667f34997bd45d530aef86Jakob Stoklund Olesen}
997e9f52f1faacf5505476418411127c5b16e07533Jakob Stoklund Olesen
1007e9f52f1faacf5505476418411127c5b16e07533Jakob Stoklund Olesen// Struct with single element and padding in passed in the high bits of a
1017e9f52f1faacf5505476418411127c5b16e07533Jakob Stoklund Olesen// register.
1027e9f52f1faacf5505476418411127c5b16e07533Jakob Stoklund Olesenstruct tiny {
1037e9f52f1faacf5505476418411127c5b16e07533Jakob Stoklund Olesen  char a;
1047e9f52f1faacf5505476418411127c5b16e07533Jakob Stoklund Olesen};
1057e9f52f1faacf5505476418411127c5b16e07533Jakob Stoklund Olesen
10693ab6bf534fb6c26563c00f28a8fc5581bb71dfdStephen Lin// CHECK-LABEL: define i64 @f_tiny(i64 %x.coerce)
1077e9f52f1faacf5505476418411127c5b16e07533Jakob Stoklund Olesen// CHECK: %[[HB:[^ ]+]] = lshr i64 %x.coerce, 56
1087e9f52f1faacf5505476418411127c5b16e07533Jakob Stoklund Olesen// CHECK: = trunc i64 %[[HB]] to i8
1097e9f52f1faacf5505476418411127c5b16e07533Jakob Stoklund Olesenstruct tiny f_tiny(struct tiny x) {
1107e9f52f1faacf5505476418411127c5b16e07533Jakob Stoklund Olesen  x.a += 1;
1117e9f52f1faacf5505476418411127c5b16e07533Jakob Stoklund Olesen  return x;
1127e9f52f1faacf5505476418411127c5b16e07533Jakob Stoklund Olesen}
1137e9f52f1faacf5505476418411127c5b16e07533Jakob Stoklund Olesen
11493ab6bf534fb6c26563c00f28a8fc5581bb71dfdStephen Lin// CHECK-LABEL: define void @call_tiny()
1157e9f52f1faacf5505476418411127c5b16e07533Jakob Stoklund Olesen// CHECK: %[[XV:[^ ]+]] = zext i8 %{{[^ ]+}} to i64
1167e9f52f1faacf5505476418411127c5b16e07533Jakob Stoklund Olesen// CHECK: %[[HB:[^ ]+]] = shl i64 %[[XV]], 56
1177e9f52f1faacf5505476418411127c5b16e07533Jakob Stoklund Olesen// CHECK: = call i64 @f_tiny(i64 %[[HB]])
1187e9f52f1faacf5505476418411127c5b16e07533Jakob Stoklund Olesenvoid call_tiny() {
1197e9f52f1faacf5505476418411127c5b16e07533Jakob Stoklund Olesen  struct tiny x = { 1 };
1207e9f52f1faacf5505476418411127c5b16e07533Jakob Stoklund Olesen  f_tiny(x);
1217e9f52f1faacf5505476418411127c5b16e07533Jakob Stoklund Olesen}
122a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen
12393ab6bf534fb6c26563c00f28a8fc5581bb71dfdStephen Lin// CHECK-LABEL: define signext i32 @f_variable(i8* %f, ...)
124a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK: %ap = alloca i8*
125a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK: call void @llvm.va_start
126a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen//
127a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesenint f_variable(char *f, ...) {
128a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen  int s = 0;
129a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen  char c;
130a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen  va_list ap;
131a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen  va_start(ap, f);
132a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen  while ((c = *f++)) switch (c) {
133a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen
134a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK: %[[CUR:[^ ]+]] = load i8** %ap
135a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr i8* %[[CUR]], i32 8
136a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK-DAG: store i8* %[[NXT]], i8** %ap
137a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK-DAG: %[[EXT:[^ ]+]] = getelementptr i8* %[[CUR]], i32 4
138a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK-DAG: %[[ADR:[^ ]+]] = bitcast i8* %[[EXT]] to i32*
139a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK-DAG: load i32* %[[ADR]]
140a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK: br
141a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen  case 'i':
142a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen    s += va_arg(ap, int);
143a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen    break;
144a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen
145a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK: %[[CUR:[^ ]+]] = load i8** %ap
146a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr i8* %[[CUR]], i32 8
147a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK-DAG: store i8* %[[NXT]], i8** %ap
148a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK-DAG: %[[ADR:[^ ]+]] = bitcast i8* %[[CUR]] to i64*
149a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK-DAG: load i64* %[[ADR]]
150a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK: br
151a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen  case 'l':
152a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen    s += va_arg(ap, long);
153a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen    break;
154a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen
155a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK: %[[CUR:[^ ]+]] = load i8** %ap
156a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr i8* %[[CUR]], i32 8
157a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK-DAG: store i8* %[[NXT]], i8** %ap
158a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK-DAG: %[[ADR:[^ ]+]] = bitcast i8* %[[CUR]] to %struct.tiny*
159a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK: br
160a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen  case 't':
161a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen    s += va_arg(ap, struct tiny).a;
162a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen    break;
163a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen
164a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK: %[[CUR:[^ ]+]] = load i8** %ap
165a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr i8* %[[CUR]], i32 16
166a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK-DAG: store i8* %[[NXT]], i8** %ap
167a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK-DAG: %[[ADR:[^ ]+]] = bitcast i8* %[[CUR]] to %struct.small*
168a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK: br
169a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen  case 's':
170a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen    s += *va_arg(ap, struct small).a;
171a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen    break;
172a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen
173a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK: %[[CUR:[^ ]+]] = load i8** %ap
174a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr i8* %[[CUR]], i32 8
175a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK-DAG: store i8* %[[NXT]], i8** %ap
176a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK-DAG: %[[IND:[^ ]+]] = bitcast i8* %[[CUR]] to %struct.medium**
177a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK-DAG: %[[ADR:[^ ]+]] = load %struct.medium** %[[IND]]
178a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen// CHECK: br
179a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen  case 'm':
180a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen    s += *va_arg(ap, struct medium).a;
181a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen    break;
182a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen  }
183a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen  return s;
184a4b56d30389753cbde96ad410e86db4b4b86ac16Jakob Stoklund Olesen}
185