blob: bf447198cdfcf52472efa0ebdc1ae21dbbdbb376 [file] [log] [blame]
Jakob Stoklund Olesena4b56d32013-06-05 03:00:18 +00001// RUN: %clang_cc1 -triple sparcv9-unknown-unknown -emit-llvm %s -o - | FileCheck %s
2#include <stdarg.h>
Jakob Stoklund Olesen107196c2013-05-27 21:48:25 +00003
Stephen Lin93ab6bf2013-08-15 06:47:53 +00004// CHECK-LABEL: define void @f_void()
Jakob Stoklund Olesen107196c2013-05-27 21:48:25 +00005void f_void(void) {}
6
7// Arguments and return values smaller than the word size are extended.
8
Stephen Lin93ab6bf2013-08-15 06:47:53 +00009// CHECK-LABEL: define signext i32 @f_int_1(i32 signext %x)
Jakob Stoklund Olesen107196c2013-05-27 21:48:25 +000010int f_int_1(int x) { return x; }
11
Stephen Lin93ab6bf2013-08-15 06:47:53 +000012// CHECK-LABEL: define zeroext i32 @f_int_2(i32 zeroext %x)
Jakob Stoklund Olesen107196c2013-05-27 21:48:25 +000013unsigned f_int_2(unsigned x) { return x; }
14
Stephen Lin93ab6bf2013-08-15 06:47:53 +000015// CHECK-LABEL: define i64 @f_int_3(i64 %x)
Jakob Stoklund Olesen107196c2013-05-27 21:48:25 +000016long long f_int_3(long long x) { return x; }
17
Stephen Lin93ab6bf2013-08-15 06:47:53 +000018// CHECK-LABEL: define signext i8 @f_int_4(i8 signext %x)
Jakob Stoklund Olesen107196c2013-05-27 21:48:25 +000019char f_int_4(char x) { return x; }
20
Stephen Hines651f13c2014-04-23 16:59:28 -070021// CHECK-LABEL: define fp128 @f_ld(fp128 %x)
22long double f_ld(long double x) { return x; }
23
Jakob Stoklund Olesen107196c2013-05-27 21:48:25 +000024// Small structs are passed in registers.
25struct small {
26 int *a, *b;
27};
28
Stephen Lin93ab6bf2013-08-15 06:47:53 +000029// CHECK-LABEL: define %struct.small @f_small(i32* %x.coerce0, i32* %x.coerce1)
Jakob Stoklund Olesen107196c2013-05-27 21:48:25 +000030struct small f_small(struct small x) {
31 x.a += *x.b;
32 x.b = 0;
33 return x;
34}
35
36// Medium-sized structs are passed indirectly, but can be returned in registers.
37struct medium {
38 int *a, *b;
39 int *c, *d;
40};
41
Stephen Lin93ab6bf2013-08-15 06:47:53 +000042// CHECK-LABEL: define %struct.medium @f_medium(%struct.medium* %x)
Jakob Stoklund Olesen107196c2013-05-27 21:48:25 +000043struct medium f_medium(struct medium x) {
44 x.a += *x.b;
45 x.b = 0;
46 return x;
47}
48
49// Large structs are also returned indirectly.
50struct large {
51 int *a, *b;
52 int *c, *d;
53 int x;
54};
55
Stephen Lin93ab6bf2013-08-15 06:47:53 +000056// CHECK-LABEL: define void @f_large(%struct.large* noalias sret %agg.result, %struct.large* %x)
Jakob Stoklund Olesen107196c2013-05-27 21:48:25 +000057struct large f_large(struct large x) {
58 x.a += *x.b;
59 x.b = 0;
60 return x;
61}
62
Jakob Stoklund Olesenfc782fb2013-05-28 04:57:37 +000063// A 64-bit struct fits in a register.
64struct reg {
65 int a, b;
66};
67
Stephen Lin93ab6bf2013-08-15 06:47:53 +000068// CHECK-LABEL: define i64 @f_reg(i64 %x.coerce)
Jakob Stoklund Olesenfc782fb2013-05-28 04:57:37 +000069struct reg f_reg(struct reg x) {
70 x.a += x.b;
71 return x;
72}
73
74// Structs with mixed int and float parts require the inreg attribute.
75struct mixed {
76 int a;
77 float b;
78};
79
Stephen Lin93ab6bf2013-08-15 06:47:53 +000080// CHECK-LABEL: define inreg %struct.mixed @f_mixed(i32 inreg %x.coerce0, float inreg %x.coerce1)
Jakob Stoklund Olesenfc782fb2013-05-28 04:57:37 +000081struct mixed f_mixed(struct mixed x) {
82 x.a += 1;
83 return x;
84}
85
86// Struct with padding.
87struct mixed2 {
88 int a;
89 double b;
90};
91
Jakob Stoklund Olesen7e9f52f2013-06-05 03:00:13 +000092// CHECK: define { i64, double } @f_mixed2(i64 %x.coerce0, double %x.coerce1)
93// CHECK: store i64 %x.coerce0
94// CHECK: store double %x.coerce1
Jakob Stoklund Olesenfc782fb2013-05-28 04:57:37 +000095struct mixed2 f_mixed2(struct mixed2 x) {
96 x.a += 1;
97 return x;
98}
Jakob Stoklund Olesen7e9f52f2013-06-05 03:00:13 +000099
100// Struct with single element and padding in passed in the high bits of a
101// register.
102struct tiny {
103 char a;
104};
105
Stephen Lin93ab6bf2013-08-15 06:47:53 +0000106// CHECK-LABEL: define i64 @f_tiny(i64 %x.coerce)
Jakob Stoklund Olesen7e9f52f2013-06-05 03:00:13 +0000107// CHECK: %[[HB:[^ ]+]] = lshr i64 %x.coerce, 56
108// CHECK: = trunc i64 %[[HB]] to i8
109struct tiny f_tiny(struct tiny x) {
110 x.a += 1;
111 return x;
112}
113
Stephen Lin93ab6bf2013-08-15 06:47:53 +0000114// CHECK-LABEL: define void @call_tiny()
Jakob Stoklund Olesen7e9f52f2013-06-05 03:00:13 +0000115// CHECK: %[[XV:[^ ]+]] = zext i8 %{{[^ ]+}} to i64
116// CHECK: %[[HB:[^ ]+]] = shl i64 %[[XV]], 56
117// CHECK: = call i64 @f_tiny(i64 %[[HB]])
118void call_tiny() {
119 struct tiny x = { 1 };
120 f_tiny(x);
121}
Jakob Stoklund Olesena4b56d32013-06-05 03:00:18 +0000122
Stephen Lin93ab6bf2013-08-15 06:47:53 +0000123// CHECK-LABEL: define signext i32 @f_variable(i8* %f, ...)
Jakob Stoklund Olesena4b56d32013-06-05 03:00:18 +0000124// CHECK: %ap = alloca i8*
125// CHECK: call void @llvm.va_start
126//
127int f_variable(char *f, ...) {
128 int s = 0;
129 char c;
130 va_list ap;
131 va_start(ap, f);
132 while ((c = *f++)) switch (c) {
133
Pirama Arumuga Nainar3ea9e332015-04-08 08:57:32 -0700134// CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap
135// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr i8, i8* %[[CUR]], i32 8
Jakob Stoklund Olesena4b56d32013-06-05 03:00:18 +0000136// CHECK-DAG: store i8* %[[NXT]], i8** %ap
Pirama Arumuga Nainar3ea9e332015-04-08 08:57:32 -0700137// CHECK-DAG: %[[EXT:[^ ]+]] = getelementptr i8, i8* %[[CUR]], i32 4
Jakob Stoklund Olesena4b56d32013-06-05 03:00:18 +0000138// CHECK-DAG: %[[ADR:[^ ]+]] = bitcast i8* %[[EXT]] to i32*
Pirama Arumuga Nainar3ea9e332015-04-08 08:57:32 -0700139// CHECK-DAG: load i32, i32* %[[ADR]]
Jakob Stoklund Olesena4b56d32013-06-05 03:00:18 +0000140// CHECK: br
141 case 'i':
142 s += va_arg(ap, int);
143 break;
144
Pirama Arumuga Nainar3ea9e332015-04-08 08:57:32 -0700145// CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap
146// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr i8, i8* %[[CUR]], i32 8
Jakob Stoklund Olesena4b56d32013-06-05 03:00:18 +0000147// CHECK-DAG: store i8* %[[NXT]], i8** %ap
148// CHECK-DAG: %[[ADR:[^ ]+]] = bitcast i8* %[[CUR]] to i64*
Pirama Arumuga Nainar3ea9e332015-04-08 08:57:32 -0700149// CHECK-DAG: load i64, i64* %[[ADR]]
Jakob Stoklund Olesena4b56d32013-06-05 03:00:18 +0000150// CHECK: br
151 case 'l':
152 s += va_arg(ap, long);
153 break;
154
Pirama Arumuga Nainar3ea9e332015-04-08 08:57:32 -0700155// CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap
156// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr i8, i8* %[[CUR]], i32 8
Jakob Stoklund Olesena4b56d32013-06-05 03:00:18 +0000157// CHECK-DAG: store i8* %[[NXT]], i8** %ap
158// CHECK-DAG: %[[ADR:[^ ]+]] = bitcast i8* %[[CUR]] to %struct.tiny*
159// CHECK: br
160 case 't':
161 s += va_arg(ap, struct tiny).a;
162 break;
163
Pirama Arumuga Nainar3ea9e332015-04-08 08:57:32 -0700164// CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap
165// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr i8, i8* %[[CUR]], i32 16
Jakob Stoklund Olesena4b56d32013-06-05 03:00:18 +0000166// CHECK-DAG: store i8* %[[NXT]], i8** %ap
167// CHECK-DAG: %[[ADR:[^ ]+]] = bitcast i8* %[[CUR]] to %struct.small*
168// CHECK: br
169 case 's':
170 s += *va_arg(ap, struct small).a;
171 break;
172
Pirama Arumuga Nainar3ea9e332015-04-08 08:57:32 -0700173// CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap
174// CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr i8, i8* %[[CUR]], i32 8
Jakob Stoklund Olesena4b56d32013-06-05 03:00:18 +0000175// CHECK-DAG: store i8* %[[NXT]], i8** %ap
176// CHECK-DAG: %[[IND:[^ ]+]] = bitcast i8* %[[CUR]] to %struct.medium**
Pirama Arumuga Nainar3ea9e332015-04-08 08:57:32 -0700177// CHECK-DAG: %[[ADR:[^ ]+]] = load %struct.medium*, %struct.medium** %[[IND]]
Jakob Stoklund Olesena4b56d32013-06-05 03:00:18 +0000178// CHECK: br
179 case 'm':
180 s += *va_arg(ap, struct medium).a;
181 break;
182 }
183 return s;
184}