1 // RUN: %clang_cc1 -triple mips-unknown-linux -o - -emit-llvm %s | FileCheck %s -check-prefixes=ALL,O32 -enable-var-scope 2 // RUN: %clang_cc1 -triple mipsel-unknown-linux -o - -emit-llvm %s | FileCheck %s -check-prefixes=ALL,O32 -enable-var-scope 3 // RUN: %clang_cc1 -triple mips64-unknown-linux -o - -emit-llvm -target-abi n32 %s | FileCheck %s -check-prefixes=ALL,N32,NEW -enable-var-scope 4 // RUN: %clang_cc1 -triple mips64-unknown-linux -o - -emit-llvm -target-abi n32 %s | FileCheck %s -check-prefixes=ALL,N32,NEW -enable-var-scope 5 // RUN: %clang_cc1 -triple mips64-unknown-linux -o - -emit-llvm %s | FileCheck %s -check-prefixes=ALL,N64,NEW -enable-var-scope 6 // RUN: %clang_cc1 -triple mips64el-unknown-linux -o - -emit-llvm %s | FileCheck %s -check-prefixes=ALL,N64,NEW -enable-var-scope 7 8 #include <stdarg.h> 9 10 typedef int v4i32 __attribute__ ((__vector_size__ (16))); 11 12 int test_i32(char *fmt, ...) { 13 va_list va; 14 15 va_start(va, fmt); 16 int v = va_arg(va, int); 17 va_end(va); 18 19 return v; 20 } 21 22 // O32-LABEL: define{{.*}} i32 @test_i32(i8*{{.*}} %fmt, ...) 23 // N32-LABEL: define{{.*}} signext i32 @test_i32(i8*{{.*}} %fmt, ...) 24 // N64-LABEL: define{{.*}} signext i32 @test_i32(i8*{{.*}} %fmt, ...) 25 // 26 // O32: %va = alloca i8*, align [[$PTRALIGN:4]] 27 // N32: %va = alloca i8*, align [[$PTRALIGN:4]] 28 // N64: %va = alloca i8*, align [[$PTRALIGN:8]] 29 // ALL: [[V:%.*]] = alloca i32, align 4 30 // NEW: [[PROMOTION_TEMP:%.*]] = alloca i32, align 4 31 // 32 // ALL: [[VA:%.+]] = bitcast i8** %va to i8* 33 // ALL: call void @llvm.va_start(i8* [[VA]]) 34 // ALL: [[AP_CUR:%.+]] = load i8*, i8** %va, align [[$PTRALIGN]] 35 // O32: [[AP_NEXT:%.+]] = getelementptr inbounds i8, i8* [[AP_CUR]], [[$INTPTR_T:i32]] [[$CHUNKSIZE:4]] 36 // NEW: [[AP_NEXT:%.+]] = getelementptr inbounds i8, i8* [[AP_CUR]], [[$INTPTR_T:i32|i64]] [[$CHUNKSIZE:8]] 37 // 38 // ALL: store i8* [[AP_NEXT]], i8** %va, align [[$PTRALIGN]] 39 // 40 // O32: [[AP_CAST:%.+]] = bitcast i8* [[AP_CUR]] to [[CHUNK_T:i32]]* 41 // O32: [[ARG:%.+]] = load i32, i32* [[AP_CAST]], align [[CHUNKALIGN:4]] 42 // 43 // N32: [[AP_CAST:%.+]] = bitcast i8* [[AP_CUR]] to [[CHUNK_T:i64]]* 44 // N32: [[TMP:%.+]] = load i64, i64* [[AP_CAST]], align [[CHUNKALIGN:8]] 45 // N64: [[AP_CAST:%.+]] = bitcast i8* [[AP_CUR]] to [[CHUNK_T:i64]]* 46 // N64: [[TMP:%.+]] = load i64, i64* [[AP_CAST]], align [[CHUNKALIGN:8]] 47 // NEW: [[TMP2:%.+]] = trunc i64 [[TMP]] to i32 48 // NEW: store i32 [[TMP2]], i32* [[PROMOTION_TEMP]], align 4 49 // NEW: [[ARG:%.+]] = load i32, i32* [[PROMOTION_TEMP]], align 4 50 // ALL: store i32 [[ARG]], i32* [[V]], align 4 51 // 52 // ALL: [[VA1:%.+]] = bitcast i8** %va to i8* 53 // ALL: call void @llvm.va_end(i8* [[VA1]]) 54 // ALL: } 55 56 long long test_i64(char *fmt, ...) { 57 va_list va; 58 59 va_start(va, fmt); 60 long long v = va_arg(va, long long); 61 va_end(va); 62 63 return v; 64 } 65 66 // ALL-LABEL: define{{.*}} i64 @test_i64(i8*{{.*}} %fmt, ...) 67 // 68 // ALL: %va = alloca i8*, align [[$PTRALIGN]] 69 // ALL: [[VA:%.+]] = bitcast i8** %va to i8* 70 // ALL: call void @llvm.va_start(i8* [[VA]]) 71 // ALL: [[AP_CUR:%.+]] = load i8*, i8** %va, align [[$PTRALIGN]] 72 // 73 // i64 is 8-byte aligned, while this is within O32's stack alignment there's no 74 // guarantee that the offset is still 8-byte aligned after earlier reads. 75 // O32: [[TMP1:%.+]] = ptrtoint i8* [[AP_CUR]] to i32 76 // O32: [[TMP2:%.+]] = add i32 [[TMP1]], 7 77 // O32: [[TMP3:%.+]] = and i32 [[TMP2]], -8 78 // O32: [[AP_CUR:%.+]] = inttoptr i32 [[TMP3]] to i8* 79 // 80 // ALL: [[AP_NEXT:%.+]] = getelementptr inbounds i8, i8* [[AP_CUR]], [[$INTPTR_T]] 8 81 // ALL: store i8* [[AP_NEXT]], i8** %va, align [[$PTRALIGN]] 82 // 83 // ALL: [[AP_CAST:%.*]] = bitcast i8* [[AP_CUR]] to i64* 84 // ALL: [[ARG:%.+]] = load i64, i64* [[AP_CAST]], align 8 85 // 86 // ALL: [[VA1:%.+]] = bitcast i8** %va to i8* 87 // ALL: call void @llvm.va_end(i8* [[VA1]]) 88 // ALL: } 89 90 char *test_ptr(char *fmt, ...) { 91 va_list va; 92 93 va_start(va, fmt); 94 char *v = va_arg(va, char *); 95 va_end(va); 96 97 return v; 98 } 99 100 // ALL-LABEL: define{{.*}} i8* @test_ptr(i8*{{.*}} %fmt, ...) 101 // 102 // ALL: %va = alloca i8*, align [[$PTRALIGN]] 103 // ALL: [[V:%.*]] = alloca i8*, align [[$PTRALIGN]] 104 // N32: [[AP_CAST:%.+]] = alloca i8*, align 4 105 // ALL: [[VA:%.+]] = bitcast i8** %va to i8* 106 // ALL: call void @llvm.va_start(i8* [[VA]]) 107 // ALL: [[AP_CUR:%.+]] = load i8*, i8** %va, align [[$PTRALIGN]] 108 // ALL: [[AP_NEXT:%.+]] = getelementptr inbounds i8, i8* [[AP_CUR]], [[$INTPTR_T]] [[$CHUNKSIZE]] 109 // ALL: store i8* [[AP_NEXT]], i8** %va, align [[$PTRALIGN]] 110 // 111 // When the chunk size matches the pointer size, this is easy. 112 // O32: [[AP_CAST:%.+]] = bitcast i8* [[AP_CUR]] to i8** 113 // N64: [[AP_CAST:%.+]] = bitcast i8* [[AP_CUR]] to i8** 114 // Otherwise we need a promotion temporary. 115 // N32: [[TMP1:%.+]] = bitcast i8* [[AP_CUR]] to i64* 116 // N32: [[TMP2:%.+]] = load i64, i64* [[TMP1]], align 8 117 // N32: [[TMP3:%.+]] = trunc i64 [[TMP2]] to i32 118 // N32: [[PTR:%.+]] = inttoptr i32 [[TMP3]] to i8* 119 // N32: store i8* [[PTR]], i8** [[AP_CAST]], align 4 120 // 121 // ALL: [[ARG:%.+]] = load i8*, i8** [[AP_CAST]], align [[$PTRALIGN]] 122 // ALL: store i8* [[ARG]], i8** [[V]], align [[$PTRALIGN]] 123 // 124 // ALL: [[VA1:%.+]] = bitcast i8** %va to i8* 125 // ALL: call void @llvm.va_end(i8* [[VA1]]) 126 // ALL: } 127 128 int test_v4i32(char *fmt, ...) { 129 va_list va; 130 131 va_start(va, fmt); 132 v4i32 v = va_arg(va, v4i32); 133 va_end(va); 134 135 return v[0]; 136 } 137 138 // O32-LABEL: define{{.*}} i32 @test_v4i32(i8*{{.*}} %fmt, ...) 139 // N32-LABEL: define{{.*}} signext i32 @test_v4i32(i8*{{.*}} %fmt, ...) 140 // N64-LABEL: define{{.*}} signext i32 @test_v4i32(i8*{{.*}} %fmt, ...) 141 // 142 // ALL: %va = alloca i8*, align [[$PTRALIGN]] 143 // ALL: [[V:%.+]] = alloca <4 x i32>, align 16 144 // ALL: [[VA1:%.+]] = bitcast i8** %va to i8* 145 // ALL: call void @llvm.va_start(i8* [[VA1]]) 146 // ALL: [[AP_CUR:%.+]] = load i8*, i8** %va, align [[$PTRALIGN]] 147 // 148 // Vectors are 16-byte aligned, however the O32 ABI has a maximum alignment of 149 // 8-bytes since the base of the stack is 8-byte aligned. 150 // O32: [[TMP1:%.+]] = ptrtoint i8* [[AP_CUR]] to i32 151 // O32: [[TMP2:%.+]] = add i32 [[TMP1]], 7 152 // O32: [[TMP3:%.+]] = and i32 [[TMP2]], -8 153 // O32: [[AP_CUR:%.+]] = inttoptr i32 [[TMP3]] to i8* 154 // 155 // NEW: [[TMP1:%.+]] = ptrtoint i8* [[AP_CUR]] to [[$INTPTR_T]] 156 // NEW: [[TMP2:%.+]] = add [[$INTPTR_T]] [[TMP1]], 15 157 // NEW: [[TMP3:%.+]] = and [[$INTPTR_T]] [[TMP2]], -16 158 // NEW: [[AP_CUR:%.+]] = inttoptr [[$INTPTR_T]] [[TMP3]] to i8* 159 // 160 // ALL: [[AP_NEXT:%.+]] = getelementptr inbounds i8, i8* [[AP_CUR]], [[$INTPTR_T]] 16 161 // ALL: store i8* [[AP_NEXT]], i8** %va, align [[$PTRALIGN]] 162 // 163 // ALL: [[AP_CAST:%.+]] = bitcast i8* [[AP_CUR]] to <4 x i32>* 164 // O32: [[ARG:%.+]] = load <4 x i32>, <4 x i32>* [[AP_CAST]], align 8 165 // N64: [[ARG:%.+]] = load <4 x i32>, <4 x i32>* [[AP_CAST]], align 16 166 // N32: [[ARG:%.+]] = load <4 x i32>, <4 x i32>* [[AP_CAST]], align 16 167 // ALL: store <4 x i32> [[ARG]], <4 x i32>* [[V]], align 16 168 // 169 // ALL: [[VA1:%.+]] = bitcast i8** %va to i8* 170 // ALL: call void @llvm.va_end(i8* [[VA1]]) 171 // ALL: [[VECEXT:%.+]] = extractelement <4 x i32> {{.*}}, i32 0 172 // ALL: ret i32 [[VECEXT]] 173 // ALL: } 174