Jakob Stoklund Olesen | a4b56d3 | 2013-06-05 03:00:18 +0000 | [diff] [blame] | 1 | // RUN: %clang_cc1 -triple sparcv9-unknown-unknown -emit-llvm %s -o - | FileCheck %s |
| 2 | #include <stdarg.h> |
Jakob Stoklund Olesen | 107196c | 2013-05-27 21:48:25 +0000 | [diff] [blame] | 3 | |
Stephen Lin | 93ab6bf | 2013-08-15 06:47:53 +0000 | [diff] [blame] | 4 | // CHECK-LABEL: define void @f_void() |
Jakob Stoklund Olesen | 107196c | 2013-05-27 21:48:25 +0000 | [diff] [blame] | 5 | void f_void(void) {} |
| 6 | |
| 7 | // Arguments and return values smaller than the word size are extended. |
| 8 | |
Stephen Lin | 93ab6bf | 2013-08-15 06:47:53 +0000 | [diff] [blame] | 9 | // CHECK-LABEL: define signext i32 @f_int_1(i32 signext %x) |
Jakob Stoklund Olesen | 107196c | 2013-05-27 21:48:25 +0000 | [diff] [blame] | 10 | int f_int_1(int x) { return x; } |
| 11 | |
Stephen Lin | 93ab6bf | 2013-08-15 06:47:53 +0000 | [diff] [blame] | 12 | // CHECK-LABEL: define zeroext i32 @f_int_2(i32 zeroext %x) |
Jakob Stoklund Olesen | 107196c | 2013-05-27 21:48:25 +0000 | [diff] [blame] | 13 | unsigned f_int_2(unsigned x) { return x; } |
| 14 | |
Stephen Lin | 93ab6bf | 2013-08-15 06:47:53 +0000 | [diff] [blame] | 15 | // CHECK-LABEL: define i64 @f_int_3(i64 %x) |
Jakob Stoklund Olesen | 107196c | 2013-05-27 21:48:25 +0000 | [diff] [blame] | 16 | long long f_int_3(long long x) { return x; } |
| 17 | |
Stephen Lin | 93ab6bf | 2013-08-15 06:47:53 +0000 | [diff] [blame] | 18 | // CHECK-LABEL: define signext i8 @f_int_4(i8 signext %x) |
Jakob Stoklund Olesen | 107196c | 2013-05-27 21:48:25 +0000 | [diff] [blame] | 19 | char f_int_4(char x) { return x; } |
| 20 | |
Stephen Hines | 651f13c | 2014-04-23 16:59:28 -0700 | [diff] [blame] | 21 | // CHECK-LABEL: define fp128 @f_ld(fp128 %x) |
| 22 | long double f_ld(long double x) { return x; } |
| 23 | |
Jakob Stoklund Olesen | 107196c | 2013-05-27 21:48:25 +0000 | [diff] [blame] | 24 | // Small structs are passed in registers. |
| 25 | struct small { |
| 26 | int *a, *b; |
| 27 | }; |
| 28 | |
Stephen Lin | 93ab6bf | 2013-08-15 06:47:53 +0000 | [diff] [blame] | 29 | // CHECK-LABEL: define %struct.small @f_small(i32* %x.coerce0, i32* %x.coerce1) |
Jakob Stoklund Olesen | 107196c | 2013-05-27 21:48:25 +0000 | [diff] [blame] | 30 | struct 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. |
| 37 | struct medium { |
| 38 | int *a, *b; |
| 39 | int *c, *d; |
| 40 | }; |
| 41 | |
Stephen Lin | 93ab6bf | 2013-08-15 06:47:53 +0000 | [diff] [blame] | 42 | // CHECK-LABEL: define %struct.medium @f_medium(%struct.medium* %x) |
Jakob Stoklund Olesen | 107196c | 2013-05-27 21:48:25 +0000 | [diff] [blame] | 43 | struct 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. |
| 50 | struct large { |
| 51 | int *a, *b; |
| 52 | int *c, *d; |
| 53 | int x; |
| 54 | }; |
| 55 | |
Stephen Lin | 93ab6bf | 2013-08-15 06:47:53 +0000 | [diff] [blame] | 56 | // CHECK-LABEL: define void @f_large(%struct.large* noalias sret %agg.result, %struct.large* %x) |
Jakob Stoklund Olesen | 107196c | 2013-05-27 21:48:25 +0000 | [diff] [blame] | 57 | struct large f_large(struct large x) { |
| 58 | x.a += *x.b; |
| 59 | x.b = 0; |
| 60 | return x; |
| 61 | } |
| 62 | |
Jakob Stoklund Olesen | fc782fb | 2013-05-28 04:57:37 +0000 | [diff] [blame] | 63 | // A 64-bit struct fits in a register. |
| 64 | struct reg { |
| 65 | int a, b; |
| 66 | }; |
| 67 | |
Stephen Lin | 93ab6bf | 2013-08-15 06:47:53 +0000 | [diff] [blame] | 68 | // CHECK-LABEL: define i64 @f_reg(i64 %x.coerce) |
Jakob Stoklund Olesen | fc782fb | 2013-05-28 04:57:37 +0000 | [diff] [blame] | 69 | struct 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. |
| 75 | struct mixed { |
| 76 | int a; |
| 77 | float b; |
| 78 | }; |
| 79 | |
Stephen Lin | 93ab6bf | 2013-08-15 06:47:53 +0000 | [diff] [blame] | 80 | // CHECK-LABEL: define inreg %struct.mixed @f_mixed(i32 inreg %x.coerce0, float inreg %x.coerce1) |
Jakob Stoklund Olesen | fc782fb | 2013-05-28 04:57:37 +0000 | [diff] [blame] | 81 | struct mixed f_mixed(struct mixed x) { |
| 82 | x.a += 1; |
| 83 | return x; |
| 84 | } |
| 85 | |
| 86 | // Struct with padding. |
| 87 | struct mixed2 { |
| 88 | int a; |
| 89 | double b; |
| 90 | }; |
| 91 | |
Jakob Stoklund Olesen | 7e9f52f | 2013-06-05 03:00:13 +0000 | [diff] [blame] | 92 | // 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 Olesen | fc782fb | 2013-05-28 04:57:37 +0000 | [diff] [blame] | 95 | struct mixed2 f_mixed2(struct mixed2 x) { |
| 96 | x.a += 1; |
| 97 | return x; |
| 98 | } |
Jakob Stoklund Olesen | 7e9f52f | 2013-06-05 03:00:13 +0000 | [diff] [blame] | 99 | |
| 100 | // Struct with single element and padding in passed in the high bits of a |
| 101 | // register. |
| 102 | struct tiny { |
| 103 | char a; |
| 104 | }; |
| 105 | |
Stephen Lin | 93ab6bf | 2013-08-15 06:47:53 +0000 | [diff] [blame] | 106 | // CHECK-LABEL: define i64 @f_tiny(i64 %x.coerce) |
Jakob Stoklund Olesen | 7e9f52f | 2013-06-05 03:00:13 +0000 | [diff] [blame] | 107 | // CHECK: %[[HB:[^ ]+]] = lshr i64 %x.coerce, 56 |
| 108 | // CHECK: = trunc i64 %[[HB]] to i8 |
| 109 | struct tiny f_tiny(struct tiny x) { |
| 110 | x.a += 1; |
| 111 | return x; |
| 112 | } |
| 113 | |
Stephen Lin | 93ab6bf | 2013-08-15 06:47:53 +0000 | [diff] [blame] | 114 | // CHECK-LABEL: define void @call_tiny() |
Jakob Stoklund Olesen | 7e9f52f | 2013-06-05 03:00:13 +0000 | [diff] [blame] | 115 | // CHECK: %[[XV:[^ ]+]] = zext i8 %{{[^ ]+}} to i64 |
| 116 | // CHECK: %[[HB:[^ ]+]] = shl i64 %[[XV]], 56 |
| 117 | // CHECK: = call i64 @f_tiny(i64 %[[HB]]) |
| 118 | void call_tiny() { |
| 119 | struct tiny x = { 1 }; |
| 120 | f_tiny(x); |
| 121 | } |
Jakob Stoklund Olesen | a4b56d3 | 2013-06-05 03:00:18 +0000 | [diff] [blame] | 122 | |
Stephen Lin | 93ab6bf | 2013-08-15 06:47:53 +0000 | [diff] [blame] | 123 | // CHECK-LABEL: define signext i32 @f_variable(i8* %f, ...) |
Jakob Stoklund Olesen | a4b56d3 | 2013-06-05 03:00:18 +0000 | [diff] [blame] | 124 | // CHECK: %ap = alloca i8* |
| 125 | // CHECK: call void @llvm.va_start |
| 126 | // |
| 127 | int 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 Nainar | 3ea9e33 | 2015-04-08 08:57:32 -0700 | [diff] [blame] | 134 | // CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap |
| 135 | // CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr i8, i8* %[[CUR]], i32 8 |
Jakob Stoklund Olesen | a4b56d3 | 2013-06-05 03:00:18 +0000 | [diff] [blame] | 136 | // CHECK-DAG: store i8* %[[NXT]], i8** %ap |
Pirama Arumuga Nainar | 3ea9e33 | 2015-04-08 08:57:32 -0700 | [diff] [blame] | 137 | // CHECK-DAG: %[[EXT:[^ ]+]] = getelementptr i8, i8* %[[CUR]], i32 4 |
Jakob Stoklund Olesen | a4b56d3 | 2013-06-05 03:00:18 +0000 | [diff] [blame] | 138 | // CHECK-DAG: %[[ADR:[^ ]+]] = bitcast i8* %[[EXT]] to i32* |
Pirama Arumuga Nainar | 3ea9e33 | 2015-04-08 08:57:32 -0700 | [diff] [blame] | 139 | // CHECK-DAG: load i32, i32* %[[ADR]] |
Jakob Stoklund Olesen | a4b56d3 | 2013-06-05 03:00:18 +0000 | [diff] [blame] | 140 | // CHECK: br |
| 141 | case 'i': |
| 142 | s += va_arg(ap, int); |
| 143 | break; |
| 144 | |
Pirama Arumuga Nainar | 3ea9e33 | 2015-04-08 08:57:32 -0700 | [diff] [blame] | 145 | // CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap |
| 146 | // CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr i8, i8* %[[CUR]], i32 8 |
Jakob Stoklund Olesen | a4b56d3 | 2013-06-05 03:00:18 +0000 | [diff] [blame] | 147 | // CHECK-DAG: store i8* %[[NXT]], i8** %ap |
| 148 | // CHECK-DAG: %[[ADR:[^ ]+]] = bitcast i8* %[[CUR]] to i64* |
Pirama Arumuga Nainar | 3ea9e33 | 2015-04-08 08:57:32 -0700 | [diff] [blame] | 149 | // CHECK-DAG: load i64, i64* %[[ADR]] |
Jakob Stoklund Olesen | a4b56d3 | 2013-06-05 03:00:18 +0000 | [diff] [blame] | 150 | // CHECK: br |
| 151 | case 'l': |
| 152 | s += va_arg(ap, long); |
| 153 | break; |
| 154 | |
Pirama Arumuga Nainar | 3ea9e33 | 2015-04-08 08:57:32 -0700 | [diff] [blame] | 155 | // CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap |
| 156 | // CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr i8, i8* %[[CUR]], i32 8 |
Jakob Stoklund Olesen | a4b56d3 | 2013-06-05 03:00:18 +0000 | [diff] [blame] | 157 | // 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 Nainar | 3ea9e33 | 2015-04-08 08:57:32 -0700 | [diff] [blame] | 164 | // CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap |
| 165 | // CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr i8, i8* %[[CUR]], i32 16 |
Jakob Stoklund Olesen | a4b56d3 | 2013-06-05 03:00:18 +0000 | [diff] [blame] | 166 | // 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 Nainar | 3ea9e33 | 2015-04-08 08:57:32 -0700 | [diff] [blame] | 173 | // CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap |
| 174 | // CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr i8, i8* %[[CUR]], i32 8 |
Jakob Stoklund Olesen | a4b56d3 | 2013-06-05 03:00:18 +0000 | [diff] [blame] | 175 | // CHECK-DAG: store i8* %[[NXT]], i8** %ap |
| 176 | // CHECK-DAG: %[[IND:[^ ]+]] = bitcast i8* %[[CUR]] to %struct.medium** |
Pirama Arumuga Nainar | 3ea9e33 | 2015-04-08 08:57:32 -0700 | [diff] [blame] | 177 | // CHECK-DAG: %[[ADR:[^ ]+]] = load %struct.medium*, %struct.medium** %[[IND]] |
Jakob Stoklund Olesen | a4b56d3 | 2013-06-05 03:00:18 +0000 | [diff] [blame] | 178 | // CHECK: br |
| 179 | case 'm': |
| 180 | s += *va_arg(ap, struct medium).a; |
| 181 | break; |
| 182 | } |
| 183 | return s; |
| 184 | } |