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