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-LABEL: 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-LABEL: define signext i32 @f_int_1(i32 signext %x)
     10 int f_int_1(int x) { return x; }
     11 
     12 // CHECK-LABEL: define zeroext i32 @f_int_2(i32 zeroext %x)
     13 unsigned f_int_2(unsigned x) { return x; }
     14 
     15 // CHECK-LABEL: define i64 @f_int_3(i64 %x)
     16 long long f_int_3(long long x) { return x; }
     17 
     18 // CHECK-LABEL: define signext i8 @f_int_4(i8 signext %x)
     19 char f_int_4(char x) { return x; }
     20 
     21 // CHECK-LABEL: define fp128 @f_ld(fp128 %x)
     22 long double f_ld(long double x) { return x; }
     23 
     24 // Small structs are passed in registers.
     25 struct small {
     26   int *a, *b;
     27 };
     28 
     29 // CHECK-LABEL: define %struct.small @f_small(i32* %x.coerce0, i32* %x.coerce1)
     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 
     42 // CHECK-LABEL: define %struct.medium @f_medium(%struct.medium* %x)
     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 
     56 // CHECK-LABEL: define void @f_large(%struct.large* noalias sret %agg.result, %struct.large* %x)
     57 struct large f_large(struct large x) {
     58   x.a += *x.b;
     59   x.b = 0;
     60   return x;
     61 }
     62 
     63 // A 64-bit struct fits in a register.
     64 struct reg {
     65   int a, b;
     66 };
     67 
     68 // CHECK-LABEL: define i64 @f_reg(i64 %x.coerce)
     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 
     80 // CHECK-LABEL: define inreg %struct.mixed @f_mixed(i32 inreg %x.coerce0, float inreg %x.coerce1)
     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 
     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
     95 struct mixed2 f_mixed2(struct mixed2 x) {
     96   x.a += 1;
     97   return x;
     98 }
     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 
    106 // CHECK-LABEL: define i64 @f_tiny(i64 %x.coerce)
    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 
    114 // CHECK-LABEL: define void @call_tiny()
    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 }
    122 
    123 // CHECK-LABEL: define signext i32 @f_variable(i8* %f, ...)
    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 
    134 // CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap
    135 // CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, i8* %[[CUR]], i64 8
    136 // CHECK-DAG: store i8* %[[NXT]], i8** %ap
    137 // CHECK-DAG: %[[EXT:[^ ]+]] = getelementptr inbounds i8, i8* %[[CUR]], i64 4
    138 // CHECK-DAG: %[[ADR:[^ ]+]] = bitcast i8* %[[EXT]] to i32*
    139 // CHECK-DAG: load i32, i32* %[[ADR]]
    140 // CHECK: br
    141   case 'i':
    142     s += va_arg(ap, int);
    143     break;
    144 
    145 // CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap
    146 // CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, i8* %[[CUR]], i64 8
    147 // CHECK-DAG: store i8* %[[NXT]], i8** %ap
    148 // CHECK-DAG: %[[ADR:[^ ]+]] = bitcast i8* %[[CUR]] to i64*
    149 // CHECK-DAG: load i64, i64* %[[ADR]]
    150 // CHECK: br
    151   case 'l':
    152     s += va_arg(ap, long);
    153     break;
    154 
    155 // CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap
    156 // CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, i8* %[[CUR]], i64 8
    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 
    164 // CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap
    165 // CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, i8* %[[CUR]], i64 16
    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 
    173 // CHECK: %[[CUR:[^ ]+]] = load i8*, i8** %ap
    174 // CHECK-DAG: %[[NXT:[^ ]+]] = getelementptr inbounds i8, i8* %[[CUR]], i64 8
    175 // CHECK-DAG: store i8* %[[NXT]], i8** %ap
    176 // CHECK-DAG: %[[IND:[^ ]+]] = bitcast i8* %[[CUR]] to %struct.medium**
    177 // CHECK-DAG: %[[ADR:[^ ]+]] = load %struct.medium*, %struct.medium** %[[IND]]
    178 // CHECK: br
    179   case 'm':
    180     s += *va_arg(ap, struct medium).a;
    181     break;
    182   }
    183   return s;
    184 }
    185