1 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --filter "^define |^entry:" --version 2 2 // RUN: %clang_cc1 -triple riscv32 -target-feature +f -target-abi ilp32f -emit-llvm %s -o - \ 3 // RUN: | FileCheck -check-prefixes=CHECK-C,CHECK32-C %s 4 // RUN: %clang_cc1 -triple riscv32 -target-feature +f -target-feature +d -target-abi ilp32d -emit-llvm %s -o - \ 5 // RUN: | FileCheck -check-prefixes=CHECK-C,CHECK32-C %s 6 // RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-abi lp64f -emit-llvm %s -o - \ 7 // RUN: | FileCheck -check-prefixes=CHECK-C,CHECK64-C %s 8 // RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-feature +d -target-abi lp64d -emit-llvm %s -o - \ 9 // RUN: | FileCheck -check-prefixes=CHECK-C,CHECK64-C %s 10 // RUN: %clang_cc1 -x c++ -triple riscv32 -target-feature +f -target-abi ilp32f -emit-llvm %s -o - \ 11 // RUN: | FileCheck -check-prefixes=CHECK-CXX,CHECK32-CXX %s 12 // RUN: %clang_cc1 -x c++ -triple riscv32 -target-feature +f -target-feature +d -target-abi ilp32d -emit-llvm %s -o - \ 13 // RUN: | FileCheck -check-prefixes=CHECK-CXX,CHECK32-CXX %s 14 // RUN: %clang_cc1 -x c++ -triple riscv64 -target-feature +f -target-abi lp64f -emit-llvm %s -o - \ 15 // RUN: | FileCheck -check-prefixes=CHECK-CXX,CHECK64-CXX %s 16 // RUN: %clang_cc1 -x c++ -triple riscv64 -target-feature +f -target-feature +d -target-abi lp64d -emit-llvm %s -o - \ 17 // RUN: | FileCheck -check-prefixes=CHECK-CXX,CHECK64-CXX %s 18 19 #include <stdint.h> 20 21 // Fields containing empty structs or unions are ignored when flattening 22 // structs for the hard FP ABIs, even in C++. The rules for arrays of empty 23 // structs or unions are subtle and documented in 24 // <https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc#hardware-floating-point-calling-convention>. 25 26 struct empty { struct { struct { } e; }; }; 27 struct s1 { struct empty e; float f; }; 28 29 // CHECK-C-LABEL: define dso_local float @test_s1 30 // CHECK-C-SAME: (float [[TMP0:%.*]]) #[[ATTR0:[0-9]+]] { 31 // CHECK-C: entry: 32 // 33 // CHECK-CXX-LABEL: define dso_local float @_Z7test_s12s1 34 // CHECK-CXX-SAME: (float [[TMP0:%.*]]) #[[ATTR0:[0-9]+]] { 35 // CHECK-CXX: entry: 36 // 37 struct s1 test_s1(struct s1 a) { 38 return a; 39 } 40 41 struct s2 { struct empty e; int32_t i; float f; }; 42 43 // CHECK-C-LABEL: define dso_local { i32, float } @test_s2 44 // CHECK-C-SAME: (i32 [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] { 45 // CHECK-C: entry: 46 // 47 // CHECK-CXX-LABEL: define dso_local { i32, float } @_Z7test_s22s2 48 // CHECK-CXX-SAME: (i32 [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] { 49 // CHECK-CXX: entry: 50 // 51 struct s2 test_s2(struct s2 a) { 52 return a; 53 } 54 55 struct s3 { struct empty e; float f; float g; }; 56 57 // CHECK-C-LABEL: define dso_local { float, float } @test_s3 58 // CHECK-C-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] { 59 // CHECK-C: entry: 60 // 61 // CHECK-CXX-LABEL: define dso_local { float, float } @_Z7test_s32s3 62 // CHECK-CXX-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] { 63 // CHECK-CXX: entry: 64 // 65 struct s3 test_s3(struct s3 a) { 66 return a; 67 } 68 69 struct s4 { struct empty e; float __complex__ c; }; 70 71 // CHECK-C-LABEL: define dso_local { float, float } @test_s4 72 // CHECK-C-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] { 73 // CHECK-C: entry: 74 // 75 // CHECK-CXX-LABEL: define dso_local { float, float } @_Z7test_s42s4 76 // CHECK-CXX-SAME: (float [[TMP0:%.*]], float [[TMP1:%.*]]) #[[ATTR0]] { 77 // CHECK-CXX: entry: 78 // 79 struct s4 test_s4(struct s4 a) { 80 return a; 81 } 82 83 // An array of empty fields isn't ignored in C++ (this isn't explicit in the 84 // psABI, but matches observed g++ behaviour). 85 86 struct s5 { struct empty e[1]; float f; }; 87 88 // CHECK-C-LABEL: define dso_local float @test_s5 89 // CHECK-C-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] { 90 // CHECK-C: entry: 91 // 92 // CHECK32-CXX-LABEL: define dso_local [2 x i32] @_Z7test_s52s5 93 // CHECK32-CXX-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] { 94 // CHECK32-CXX: entry: 95 // 96 // CHECK64-CXX-LABEL: define dso_local i64 @_Z7test_s52s5 97 // CHECK64-CXX-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] { 98 // CHECK64-CXX: entry: 99 // 100 struct s5 test_s5(struct s5 a) { 101 return a; 102 } 103 104 struct empty_arr { struct { struct { } e[1]; }; }; 105 struct s6 { struct empty_arr e; float f; }; 106 107 // CHECK-C-LABEL: define dso_local float @test_s6 108 // CHECK-C-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] { 109 // CHECK-C: entry: 110 // 111 // CHECK32-CXX-LABEL: define dso_local [2 x i32] @_Z7test_s62s6 112 // CHECK32-CXX-SAME: ([2 x i32] [[A_COERCE:%.*]]) #[[ATTR0]] { 113 // CHECK32-CXX: entry: 114 // 115 // CHECK64-CXX-LABEL: define dso_local i64 @_Z7test_s62s6 116 // CHECK64-CXX-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] { 117 // CHECK64-CXX: entry: 118 // 119 struct s6 test_s6(struct s6 a) { 120 return a; 121 } 122 123 struct s7 { struct empty e[0]; float f; }; 124 125 // CHECK-C-LABEL: define dso_local float @test_s7 126 // CHECK-C-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] { 127 // CHECK-C: entry: 128 // 129 // CHECK-CXX-LABEL: define dso_local float @_Z7test_s72s7 130 // CHECK-CXX-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] { 131 // CHECK-CXX: entry: 132 // 133 struct s7 test_s7(struct s7 a) { 134 return a; 135 } 136 137 struct empty_arr0 { struct { struct { } e[0]; }; }; 138 struct s8 { struct empty_arr0 e; float f; }; 139 140 // CHECK-C-LABEL: define dso_local float @test_s8 141 // CHECK-C-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] { 142 // CHECK-C: entry: 143 // 144 // CHECK-CXX-LABEL: define dso_local float @_Z7test_s82s8 145 // CHECK-CXX-SAME: (float [[TMP0:%.*]]) #[[ATTR0]] { 146 // CHECK-CXX: entry: 147 // 148 struct s8 test_s8(struct s8 a) { 149 return a; 150 } 151 152 struct s9 { 153 struct empty e; 154 }; 155 156 // CHECK-C-LABEL: define dso_local void @test_s9 157 // CHECK-C-SAME: () #[[ATTR0]] { 158 // CHECK-C: entry: 159 // 160 // CHECK32-CXX-LABEL: define dso_local void @_Z7test_s92s9 161 // CHECK32-CXX-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] { 162 // CHECK32-CXX: entry: 163 // 164 // CHECK64-CXX-LABEL: define dso_local void @_Z7test_s92s9 165 // CHECK64-CXX-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] { 166 // CHECK64-CXX: entry: 167 // 168 void test_s9(struct s9 a) {} 169 170 struct s10 { }; 171 // CHECK-C-LABEL: define dso_local void @test_s10 172 // CHECK-C-SAME: () #[[ATTR0]] { 173 // CHECK-C: entry: 174 // 175 // CHECK32-CXX-LABEL: define dso_local i32 @_Z8test_s103s10 176 // CHECK32-CXX-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] { 177 // CHECK32-CXX: entry: 178 // 179 // CHECK64-CXX-LABEL: define dso_local i64 @_Z8test_s103s10 180 // CHECK64-CXX-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] { 181 // CHECK64-CXX: entry: 182 // 183 struct s10 test_s10(struct s10 a) { 184 return a; 185 } 186 187 struct s11 { int : 0; }; 188 // CHECK-C-LABEL: define dso_local void @test_s11 189 // CHECK-C-SAME: () #[[ATTR0]] { 190 // CHECK-C: entry: 191 // 192 // CHECK32-CXX-LABEL: define dso_local i32 @_Z8test_s113s11 193 // CHECK32-CXX-SAME: (i32 [[A_COERCE:%.*]]) #[[ATTR0]] { 194 // CHECK32-CXX: entry: 195 // 196 // CHECK64-CXX-LABEL: define dso_local i64 @_Z8test_s113s11 197 // CHECK64-CXX-SAME: (i64 [[A_COERCE:%.*]]) #[[ATTR0]] { 198 // CHECK64-CXX: entry: 199 // 200 struct s11 test_s11(struct s11 a) { 201 return a; 202 } 203 204 struct s12 {int x[0];}; 205 // CHECK32-C-LABEL: define dso_local i32 @test_s12 206 // CHECK32-C-SAME: (i32 noundef [[I1:%.*]], i32 noundef [[I2:%.*]]) #[[ATTR0]] { 207 // CHECK32-C: entry: 208 // 209 // CHECK64-C-LABEL: define dso_local signext i32 @test_s12 210 // CHECK64-C-SAME: (i32 noundef signext [[I1:%.*]], i32 noundef signext [[I2:%.*]]) #[[ATTR0]] { 211 // CHECK64-C: entry: 212 // 213 // CHECK32-CXX-LABEL: define dso_local noundef i32 @_Z8test_s12i3s12i 214 // CHECK32-CXX-SAME: (i32 noundef [[I1:%.*]], i32 noundef [[I2:%.*]]) #[[ATTR0]] { 215 // CHECK32-CXX: entry: 216 // 217 // CHECK64-CXX-LABEL: define dso_local noundef signext i32 @_Z8test_s12i3s12i 218 // CHECK64-CXX-SAME: (i32 noundef signext [[I1:%.*]], i32 noundef signext [[I2:%.*]]) #[[ATTR0]] { 219 // CHECK64-CXX: entry: 220 // 221 int test_s12(int32_t i1, struct s12 a, int32_t i2) { 222 return i2; 223 } 224 225 //// NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: 226 // CHECK32-C: {{.*}} 227 // CHECK64-C: {{.*}} 228