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 { i32* } 5 // CHECK: %[[STRUCT_LARGE:.*]] = type { i32*, [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 %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[RETVAL]], i32 0, i32 0 62 // CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[CALL]] to i32* 63 // CHECK: store i32* %[[COERCE_VAL_IP]], i32** %[[COERCE_DIVE]], align 8 64 // CHECK: %[[COERCE_DIVE2:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[RETVAL]], i32 0, i32 0 65 // CHECK: %[[V3:.*]] = load i32*, i32** %[[COERCE_DIVE2]], align 8 66 // CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i32* %[[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 %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[A]], i32 0, i32 0 74 // CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[A_COERCE]] to i32* 75 // CHECK: store i32* %[[COERCE_VAL_IP]], i32** %[[COERCE_DIVE]], align 8 76 // CHECK: %[[CALL:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* {{[^,]*}} %[[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 %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* {{[^,]*}} %[[RETVAL]]) 86 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[RETVAL]], i32 0, i32 0 87 // CHECK: %[[V0:.*]] = load i32*, i32** %[[COERCE_DIVE]], align 8 88 // CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i32* %[[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 %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* {{[^,]*}} %[[T]]) 101 // CHECK: %[[CALL1:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallC1ERKS_(%[[STRUCT_SMALL]]* {{[^,]*}} %[[AGG_TMP]], %[[STRUCT_SMALL]]* nonnull align 8 dereferenceable(8) %[[T]]) 102 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP]], i32 0, i32 0 103 // CHECK: %[[V0:.*]] = load i32*, i32** %[[COERCE_DIVE]], align 8 104 // CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i32* %[[V0]] to i64 105 // CHECK: call void @_Z14testParamSmall5Small(i64 %[[COERCE_VAL_PI]]) 106 // CHECK: %[[CALL2:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* {{[^,]*}} %[[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 %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP]], i32 0, i32 0 119 // CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[CALL]] to i32* 120 // CHECK: store i32* %[[COERCE_VAL_IP]], i32** %[[COERCE_DIVE]], align 8 121 // CHECK: %[[COERCE_DIVE1:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP]], i32 0, i32 0 122 // CHECK: %[[V0:.*]] = load i32*, i32** %[[COERCE_DIVE1]], align 8 123 // CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i32* %[[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 %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP_ENSURED]], i32 0, i32 0 136 // CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[CALL]] to i32* 137 // CHECK: store i32* %[[COERCE_VAL_IP]], i32** %[[COERCE_DIVE]], align 8 138 // CHECK: %[[CALL1:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* {{[^,]*}} %[[AGG_TMP_ENSURED]]) 139 // CHECK: ret void 140 // CHECK: } 141 142 void testIgnoredSmall() { 143 testReturnSmall(); 144 } 145 146 // CHECK: define{{.*}} void @_Z14testParamLarge5Large(%[[STRUCT_LARGE:.*]]* %[[A:.*]]) 147 // CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* {{[^,]*}} %[[A]]) 148 // CHECK: ret void 149 // CHECK: } 150 151 void testParamLarge(Large a) noexcept { 152 } 153 154 // CHECK: define{{.*}} void @_Z15testReturnLargev(%[[STRUCT_LARGE:.*]]* noalias sret(%[[STRUCT_LARGE]]) align 8 %[[AGG_RESULT:.*]]) 155 // CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* {{[^,]*}} %[[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 %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* {{[^,]*}} %[[T]]) 168 // CHECK: %[[CALL1:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeC1ERKS_(%[[STRUCT_LARGE]]* {{[^,]*}} %[[AGG_TMP]], %[[STRUCT_LARGE]]* nonnull align 8 dereferenceable(520) %[[T]]) 169 // CHECK: call void @_Z14testParamLarge5Large(%[[STRUCT_LARGE]]* %[[AGG_TMP]]) 170 // CHECK: %[[CALL2:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* {{[^,]*}} %[[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(%[[STRUCT_LARGE]]* sret(%[[STRUCT_LARGE]]) align 8 %[[AGG_TMP]]) 182 // CHECK: call void @_Z14testParamLarge5Large(%[[STRUCT_LARGE]]* %[[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(%[[STRUCT_LARGE]]* sret(%[[STRUCT_LARGE]]) align 8 %[[AGG_TMP_ENSURED]]) 193 // CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* {{[^,]*}} %[[AGG_TMP_ENSURED]]) 194 // CHECK: ret void 195 // CHECK: } 196 197 void testIgnoredLarge() { 198 testReturnLarge(); 199 } 200 201 // CHECK: define{{.*}} i64 @_Z20testReturnHasTrivialv() 202 // CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_TRIVIAL:.*]], align 4 203 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_TRIVIAL]], %[[STRUCT_TRIVIAL]]* %[[RETVAL]], i32 0, i32 0 204 // CHECK: %[[V0:.*]] = load i32, i32* %[[COERCE_DIVE]], align 4 205 // CHECK: %[[COERCE_VAL_II:.*]] = zext i32 %[[V0]] to i64 206 // CHECK: ret i64 %[[COERCE_VAL_II]] 207 // CHECK: } 208 209 Trivial testReturnHasTrivial() { 210 Trivial t; 211 return t; 212 } 213 214 // CHECK: define{{.*}} void @_Z23testReturnHasNonTrivialv(%[[STRUCT_NONTRIVIAL:.*]]* noalias sret(%[[STRUCT_NONTRIVIAL]]) align 4 %[[AGG_RESULT:.*]]) 215 // CHECK: %[[CALL:.*]] = call %[[STRUCT_NONTRIVIAL]]* @_ZN10NonTrivialC1Ev(%[[STRUCT_NONTRIVIAL]]* {{[^,]*}} %[[AGG_RESULT]]) 216 // CHECK: ret void 217 // CHECK: } 218 219 NonTrivial testReturnHasNonTrivial() { 220 NonTrivial t; 221 return t; 222 } 223 224 // CHECK: define{{.*}} void @_Z18testExceptionSmallv() 225 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_SMALL]], align 8 226 // CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_SMALL]], align 8 227 // CHECK: call %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* {{[^,]*}} %[[AGG_TMP]]) 228 // CHECK: invoke %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* {{[^,]*}} %[[AGG_TMP1]]) 229 230 // CHECK: call void @_Z20calleeExceptionSmall5SmallS_(i64 %{{.*}}, i64 %{{.*}}) 231 // CHECK-NEXT: ret void 232 233 // CHECK: landingpad { i8*, i32 } 234 // CHECK: call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* {{[^,]*}} %[[AGG_TMP]]) 235 // CHECK: br 236 237 // CHECK: resume { i8*, i32 } 238 239 void calleeExceptionSmall(Small, Small); 240 241 void testExceptionSmall() { 242 calleeExceptionSmall(Small(), Small()); 243 } 244 245 // CHECK: define{{.*}} void @_Z18testExceptionLargev() 246 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE]], align 8 247 // CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_LARGE]], align 8 248 // CHECK: call %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* {{[^,]*}} %[[AGG_TMP]]) 249 // CHECK: invoke %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* {{[^,]*}} %[[AGG_TMP1]]) 250 251 // CHECK: call void @_Z20calleeExceptionLarge5LargeS_(%[[STRUCT_LARGE]]* %[[AGG_TMP]], %[[STRUCT_LARGE]]* %[[AGG_TMP1]]) 252 // CHECK-NEXT: ret void 253 254 // CHECK: landingpad { i8*, i32 } 255 // CHECK: call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* {{[^,]*}} %[[AGG_TMP]]) 256 // CHECK: br 257 258 // CHECK: resume { i8*, i32 } 259 260 void calleeExceptionLarge(Large, Large); 261 262 void testExceptionLarge() { 263 calleeExceptionLarge(Large(), Large()); 264 } 265 266 // PR42961 267 268 // CHECK: define{{.*}} @"_ZN3$_08__invokeEv"() 269 // CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_SMALL]], align 8 270 // CHECK: %[[COERCE:.*]] = alloca %[[STRUCT_SMALL]], align 8 271 // CHECK: %[[CALL:.*]] = call{{.*}} @"_ZNK3$_0clEv" 272 // CHECK: %[[COERCEDIVE:.*]] = getelementptr{{.*}} %[[COERCE]] 273 // CHECK: %[[COERCEVALIP:.*]] = inttoptr{{.*}} %[[CALL]] 274 // CHECK: %[[RETVALP:.*]] = bitcast %[[STRUCT_SMALL]]* %[[RETVAL]] 275 // CHECK: %[[COERCEP:.*]] = bitcast %[[STRUCT_SMALL]]* %[[COERCE]] 276 // CHECK: call {{.*}}memcpy{{.*}} %[[RETVALP]]{{.*}} %[[COERCEP]] 277 // CHECK: %[[COERCEDIVE1:.*]] = getelementptr{{.*}} %[[RETVAL]] 278 // CHECK: %[[TMP:.*]] = load{{.*}} %[[COERCEDIVE1]] 279 // CHECK: %[[COERCEVALPI:.*]] = ptrtoint{{.*}} %[[TMP]] 280 // CHECK: ret{{.*}} %[[COERCEVALPI]] 281 282 Small (*fp)() = []() -> Small { return Small(); }; 283