Home | History | Annotate | Download | only in CodeGen
      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