1 // RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fcxx-exceptions -fexceptions -emit-llvm -o - %s | FileCheck %s 2 // RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fcxx-exceptions -fexceptions -fclang-abi-compat=4.0 -emit-llvm -o - %s | FileCheck %s 3 4 // CHECK: %[[STRUCT_SMALL:.*]] = type { ptr } 5 // CHECK: %[[STRUCT_LARGE:.*]] = type { ptr, [128 x i32] } 6 // CHECK: %[[STRUCT_TRIVIAL:.*]] = type { i32 } 7 // CHECK: %[[STRUCT_NONTRIVIAL:.*]] = type { i32 } 8 9 struct __attribute__((trivial_abi)) Small { 10 int *p; 11 Small(); 12 ~Small(); 13 Small(const Small &) noexcept; 14 Small &operator=(const Small &); 15 }; 16 17 struct __attribute__((trivial_abi)) Large { 18 int *p; 19 int a[128]; 20 Large(); 21 ~Large(); 22 Large(const Large &) noexcept; 23 Large &operator=(const Large &); 24 }; 25 26 struct Trivial { 27 int a; 28 }; 29 30 struct NonTrivial { 31 NonTrivial(); 32 ~NonTrivial(); 33 int a; 34 }; 35 36 struct HasTrivial { 37 Small s; 38 Trivial m; 39 }; 40 41 struct HasNonTrivial { 42 Small s; 43 NonTrivial m; 44 }; 45 46 struct B0 { 47 virtual Small m0(); 48 }; 49 50 struct B1 { 51 virtual Small m0(); 52 }; 53 54 struct D0 : B0, B1 { 55 Small m0() override; 56 }; 57 58 // CHECK-LABEL: define{{.*}} i64 @_ZThn8_N2D02m0Ev( 59 // CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_SMALL]], align 8 60 // CHECK: %[[CALL:.*]] = tail call i64 @_ZN2D02m0Ev( 61 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds nuw %[[STRUCT_SMALL]], ptr %[[RETVAL]], i32 0, i32 0 62 // CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[CALL]] to ptr 63 // CHECK: store ptr %[[COERCE_VAL_IP]], ptr %[[COERCE_DIVE]], align 8 64 // CHECK: %[[COERCE_DIVE2:.*]] = getelementptr inbounds nuw %[[STRUCT_SMALL]], ptr %[[RETVAL]], i32 0, i32 0 65 // CHECK: %[[V3:.*]] = load ptr, ptr %[[COERCE_DIVE2]], align 8 66 // CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint ptr %[[V3]] to i64 67 // CHECK: ret i64 %[[COERCE_VAL_PI]] 68 69 Small D0::m0() { return {}; } 70 71 // CHECK: define{{.*}} void @_Z14testParamSmall5Small(i64 %[[A_COERCE:.*]]) 72 // CHECK: %[[A:.*]] = alloca %[[STRUCT_SMALL]], align 8 73 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds nuw %[[STRUCT_SMALL]], ptr %[[A]], i32 0, i32 0 74 // CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[A_COERCE]] to ptr 75 // CHECK: store ptr %[[COERCE_VAL_IP]], ptr %[[COERCE_DIVE]], align 8 76 // CHECK: %[[CALL:.*]] = call noundef ptr @_ZN5SmallD1Ev(ptr {{[^,]*}} %[[A]]) 77 // CHECK: ret void 78 // CHECK: } 79 80 void testParamSmall(Small a) noexcept { 81 } 82 83 // CHECK: define{{.*}} i64 @_Z15testReturnSmallv() 84 // CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8 85 // CHECK: %[[CALL:.*]] = call noundef ptr @_ZN5SmallC1Ev(ptr {{[^,]*}} %[[RETVAL]]) 86 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds nuw %[[STRUCT_SMALL]], ptr %[[RETVAL]], i32 0, i32 0 87 // CHECK: %[[V0:.*]] = load ptr, ptr %[[COERCE_DIVE]], align 8 88 // CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint ptr %[[V0]] to i64 89 // CHECK: ret i64 %[[COERCE_VAL_PI]] 90 // CHECK: } 91 92 Small testReturnSmall() { 93 Small t; 94 return t; 95 } 96 97 // CHECK: define{{.*}} void @_Z14testCallSmall0v() 98 // CHECK: %[[T:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8 99 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_SMALL]], align 8 100 // CHECK: %[[CALL:.*]] = call noundef ptr @_ZN5SmallC1Ev(ptr {{[^,]*}} %[[T]]) 101 // CHECK: %[[CALL1:.*]] = call noundef ptr @_ZN5SmallC1ERKS_(ptr {{[^,]*}} %[[AGG_TMP]], ptr noundef nonnull align 8 dereferenceable(8) %[[T]]) 102 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds nuw %[[STRUCT_SMALL]], ptr %[[AGG_TMP]], i32 0, i32 0 103 // CHECK: %[[V0:.*]] = load ptr, ptr %[[COERCE_DIVE]], align 8 104 // CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint ptr %[[V0]] to i64 105 // CHECK: call void @_Z14testParamSmall5Small(i64 %[[COERCE_VAL_PI]]) 106 // CHECK: %[[CALL2:.*]] = call noundef ptr @_ZN5SmallD1Ev(ptr {{[^,]*}} %[[T]]) 107 // CHECK: ret void 108 // CHECK: } 109 110 void testCallSmall0() { 111 Small t; 112 testParamSmall(t); 113 } 114 115 // CHECK: define{{.*}} void @_Z14testCallSmall1v() 116 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8 117 // CHECK: %[[CALL:.*]] = call i64 @_Z15testReturnSmallv() 118 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds nuw %[[STRUCT_SMALL]], ptr %[[AGG_TMP]], i32 0, i32 0 119 // CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[CALL]] to ptr 120 // CHECK: store ptr %[[COERCE_VAL_IP]], ptr %[[COERCE_DIVE]], align 8 121 // CHECK: %[[COERCE_DIVE1:.*]] = getelementptr inbounds nuw %[[STRUCT_SMALL]], ptr %[[AGG_TMP]], i32 0, i32 0 122 // CHECK: %[[V0:.*]] = load ptr, ptr %[[COERCE_DIVE1]], align 8 123 // CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint ptr %[[V0]] to i64 124 // CHECK: call void @_Z14testParamSmall5Small(i64 %[[COERCE_VAL_PI]]) 125 // CHECK: ret void 126 // CHECK: } 127 128 void testCallSmall1() { 129 testParamSmall(testReturnSmall()); 130 } 131 132 // CHECK: define{{.*}} void @_Z16testIgnoredSmallv() 133 // CHECK: %[[AGG_TMP_ENSURED:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8 134 // CHECK: %[[CALL:.*]] = call i64 @_Z15testReturnSmallv() 135 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds nuw %[[STRUCT_SMALL]], ptr %[[AGG_TMP_ENSURED]], i32 0, i32 0 136 // CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[CALL]] to ptr 137 // CHECK: store ptr %[[COERCE_VAL_IP]], ptr %[[COERCE_DIVE]], align 8 138 // CHECK: %[[CALL1:.*]] = call noundef ptr @_ZN5SmallD1Ev(ptr {{[^,]*}} %[[AGG_TMP_ENSURED]]) 139 // CHECK: ret void 140 // CHECK: } 141 142 void testIgnoredSmall() { 143 testReturnSmall(); 144 } 145 146 // CHECK: define{{.*}} void @_Z14testParamLarge5Large(ptr noundef %[[A:.*]]) 147 // CHECK: %[[CALL:.*]] = call noundef ptr @_ZN5LargeD1Ev(ptr {{[^,]*}} %[[A]]) 148 // CHECK: ret void 149 // CHECK: } 150 151 void testParamLarge(Large a) noexcept { 152 } 153 154 // CHECK: define{{.*}} void @_Z15testReturnLargev(ptr dead_on_unwind noalias writable sret(%[[STRUCT_LARGE]]) align 8 %[[AGG_RESULT:.*]]) 155 // CHECK: %[[CALL:.*]] = call noundef ptr @_ZN5LargeC1Ev(ptr {{[^,]*}} %[[AGG_RESULT]]) 156 // CHECK: ret void 157 // CHECK: } 158 159 Large testReturnLarge() { 160 Large t; 161 return t; 162 } 163 164 // CHECK: define{{.*}} void @_Z14testCallLarge0v() 165 // CHECK: %[[T:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8 166 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE]], align 8 167 // CHECK: %[[CALL:.*]] = call noundef ptr @_ZN5LargeC1Ev(ptr {{[^,]*}} %[[T]]) 168 // CHECK: %[[CALL1:.*]] = call noundef ptr @_ZN5LargeC1ERKS_(ptr {{[^,]*}} %[[AGG_TMP]], ptr noundef nonnull align 8 dereferenceable(520) %[[T]]) 169 // CHECK: call void @_Z14testParamLarge5Large(ptr noundef %[[AGG_TMP]]) 170 // CHECK: %[[CALL2:.*]] = call noundef ptr @_ZN5LargeD1Ev(ptr {{[^,]*}} %[[T]]) 171 // CHECK: ret void 172 // CHECK: } 173 174 void testCallLarge0() { 175 Large t; 176 testParamLarge(t); 177 } 178 179 // CHECK: define{{.*}} void @_Z14testCallLarge1v() 180 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8 181 // CHECK: call void @_Z15testReturnLargev(ptr dead_on_unwind writable sret(%[[STRUCT_LARGE]]) align 8 %[[AGG_TMP]]) 182 // CHECK: call void @_Z14testParamLarge5Large(ptr noundef %[[AGG_TMP]]) 183 // CHECK: ret void 184 // CHECK: } 185 186 void testCallLarge1() { 187 testParamLarge(testReturnLarge()); 188 } 189 190 // CHECK: define{{.*}} void @_Z16testIgnoredLargev() 191 // CHECK: %[[AGG_TMP_ENSURED:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8 192 // CHECK: call void @_Z15testReturnLargev(ptr dead_on_unwind writable sret(%[[STRUCT_LARGE]]) align 8 %[[AGG_TMP_ENSURED]]) 193 // CHECK: %[[CALL:.*]] = call noundef ptr @_ZN5LargeD1Ev(ptr {{[^,]*}} %[[AGG_TMP_ENSURED]]) 194 // CHECK: ret void 195 // CHECK: } 196 197 void testIgnoredLarge() { 198 testReturnLarge(); 199 } 200 201 // CHECK: define{{.*}} i32 @_Z20testReturnHasTrivialv() 202 // CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_TRIVIAL:.*]], align 4 203 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds nuw %[[STRUCT_TRIVIAL]], ptr %[[RETVAL]], i32 0, i32 0 204 // CHECK: %[[V0:.*]] = load i32, ptr %[[COERCE_DIVE]], align 4 205 // CHECK: ret i32 %[[V0]] 206 // CHECK: } 207 208 Trivial testReturnHasTrivial() { 209 Trivial t; 210 return t; 211 } 212 213 // CHECK: define{{.*}} void @_Z23testReturnHasNonTrivialv(ptr dead_on_unwind noalias writable sret(%[[STRUCT_NONTRIVIAL:.*]]) align 4 %[[AGG_RESULT:.*]]) 214 // CHECK: %[[CALL:.*]] = call noundef ptr @_ZN10NonTrivialC1Ev(ptr {{[^,]*}} %[[AGG_RESULT]]) 215 // CHECK: ret void 216 // CHECK: } 217 218 NonTrivial testReturnHasNonTrivial() { 219 NonTrivial t; 220 return t; 221 } 222 223 // CHECK: define{{.*}} void @_Z18testExceptionSmallv() 224 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_SMALL]], align 8 225 // CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_SMALL]], align 8 226 // CHECK: call noundef ptr @_ZN5SmallC1Ev(ptr {{[^,]*}} %[[AGG_TMP]]) 227 // CHECK: invoke noundef ptr @_ZN5SmallC1Ev(ptr {{[^,]*}} %[[AGG_TMP1]]) 228 229 // CHECK: call void @_Z20calleeExceptionSmall5SmallS_(i64 %{{.*}}, i64 %{{.*}}) 230 // CHECK-NEXT: ret void 231 232 // CHECK: landingpad { ptr, i32 } 233 // CHECK: call noundef ptr @_ZN5SmallD1Ev(ptr {{[^,]*}} %[[AGG_TMP]]) 234 // CHECK: br 235 236 // CHECK: resume { ptr, i32 } 237 238 void calleeExceptionSmall(Small, Small); 239 240 void testExceptionSmall() { 241 calleeExceptionSmall(Small(), Small()); 242 } 243 244 // CHECK: define{{.*}} void @_Z18testExceptionLargev() 245 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE]], align 8 246 // CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_LARGE]], align 8 247 // CHECK: call noundef ptr @_ZN5LargeC1Ev(ptr {{[^,]*}} %[[AGG_TMP]]) 248 // CHECK: invoke noundef ptr @_ZN5LargeC1Ev(ptr {{[^,]*}} %[[AGG_TMP1]]) 249 250 // CHECK: call void @_Z20calleeExceptionLarge5LargeS_(ptr noundef %[[AGG_TMP]], ptr noundef %[[AGG_TMP1]]) 251 // CHECK-NEXT: ret void 252 253 // CHECK: landingpad { ptr, i32 } 254 // CHECK: call noundef ptr @_ZN5LargeD1Ev(ptr {{[^,]*}} %[[AGG_TMP]]) 255 // CHECK: br 256 257 // CHECK: resume { ptr, i32 } 258 259 void calleeExceptionLarge(Large, Large); 260 261 void testExceptionLarge() { 262 calleeExceptionLarge(Large(), Large()); 263 } 264 265 // CHECK: define void @_ZN7GH930401gEPNS_1SE 266 // CHECK: [[CALL:%.*]] = call i64 @_ZN7GH930401fEv 267 // CHECK-NEXT: [[TRUNC:%.*]] = trunc i64 [[CALL]] to i56 268 // CHECK-NEXT: store i56 [[TRUNC]] 269 // CHECK-NEXT: ret void 270 void* operator new(unsigned long, void*); 271 namespace GH93040 { 272 struct [[clang::trivial_abi]] S { 273 char a; 274 int x; 275 __attribute((aligned(2))) char y; 276 S(); 277 } __attribute((packed)); 278 S f(); 279 void g(S* s) { new(s) S(f()); } 280 struct S2 { [[no_unique_address]] S s; char c;}; 281 static_assert(sizeof(S) == 8 && sizeof(S2) == 8, ""); 282 } 283 284 285 // PR42961 286 287 // CHECK: define{{.*}} @"_ZN3$_08__invokeEv"() 288 // CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_SMALL]], align 8 289 // CHECK: %[[COERCE:.*]] = alloca %[[STRUCT_SMALL]], align 8 290 // CHECK: %[[CALL:.*]] = call{{.*}} @"_ZNK3$_0clEv" 291 // CHECK: %[[COERCEDIVE:.*]] = getelementptr{{.*}} %[[COERCE]] 292 // CHECK: %[[COERCEVALIP:.*]] = inttoptr{{.*}} %[[CALL]] 293 // CHECK: call {{.*}}memcpy{{.*}} %[[RETVAL]]{{.*}} %[[COERCE]] 294 // CHECK: %[[COERCEDIVE1:.*]] = getelementptr{{.*}} %[[RETVAL]] 295 // CHECK: %[[TMP:.*]] = load{{.*}} %[[COERCEDIVE1]] 296 // CHECK: %[[COERCEVALPI:.*]] = ptrtoint{{.*}} %[[TMP]] 297 // CHECK: ret{{.*}} %[[COERCEVALPI]] 298 299 Small (*fp)() = []() -> Small { return Small(); }; 300