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 // CHECK: define void @_Z14testParamSmall5Small(i64 %[[A_COERCE:.*]]) 47 // CHECK: %[[A:.*]] = alloca %[[STRUCT_SMALL]], align 8 48 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[A]], i32 0, i32 0 49 // CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[A_COERCE]] to i32* 50 // CHECK: store i32* %[[COERCE_VAL_IP]], i32** %[[COERCE_DIVE]], align 8 51 // CHECK: %[[CALL:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* %[[A]]) 52 // CHECK: ret void 53 // CHECK: } 54 55 void testParamSmall(Small a) noexcept { 56 } 57 58 // CHECK: define i64 @_Z15testReturnSmallv() 59 // CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8 60 // CHECK: %[[CALL:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* %[[RETVAL]]) 61 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[RETVAL]], i32 0, i32 0 62 // CHECK: %[[V0:.*]] = load i32*, i32** %[[COERCE_DIVE]], align 8 63 // CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i32* %[[V0]] to i64 64 // CHECK: ret i64 %[[COERCE_VAL_PI]] 65 // CHECK: } 66 67 Small testReturnSmall() { 68 Small t; 69 return t; 70 } 71 72 // CHECK: define void @_Z14testCallSmall0v() 73 // CHECK: %[[T:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8 74 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_SMALL]], align 8 75 // CHECK: %[[CALL:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* %[[T]]) 76 // CHECK: %[[CALL1:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallC1ERKS_(%[[STRUCT_SMALL]]* %[[AGG_TMP]], %[[STRUCT_SMALL]]* dereferenceable(8) %[[T]]) 77 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP]], i32 0, i32 0 78 // CHECK: %[[V0:.*]] = load i32*, i32** %[[COERCE_DIVE]], align 8 79 // CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i32* %[[V0]] to i64 80 // CHECK: call void @_Z14testParamSmall5Small(i64 %[[COERCE_VAL_PI]]) 81 // CHECK: %[[CALL2:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* %[[T]]) 82 // CHECK: ret void 83 // CHECK: } 84 85 void testCallSmall0() { 86 Small t; 87 testParamSmall(t); 88 } 89 90 // CHECK: define void @_Z14testCallSmall1v() 91 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8 92 // CHECK: %[[CALL:.*]] = call i64 @_Z15testReturnSmallv() 93 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP]], i32 0, i32 0 94 // CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[CALL]] to i32* 95 // CHECK: store i32* %[[COERCE_VAL_IP]], i32** %[[COERCE_DIVE]], align 8 96 // CHECK: %[[COERCE_DIVE1:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP]], i32 0, i32 0 97 // CHECK: %[[V0:.*]] = load i32*, i32** %[[COERCE_DIVE1]], align 8 98 // CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i32* %[[V0]] to i64 99 // CHECK: call void @_Z14testParamSmall5Small(i64 %[[COERCE_VAL_PI]]) 100 // CHECK: ret void 101 // CHECK: } 102 103 void testCallSmall1() { 104 testParamSmall(testReturnSmall()); 105 } 106 107 // CHECK: define void @_Z16testIgnoredSmallv() 108 // CHECK: %[[AGG_TMP_ENSURED:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8 109 // CHECK: %[[CALL:.*]] = call i64 @_Z15testReturnSmallv() 110 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP_ENSURED]], i32 0, i32 0 111 // CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[CALL]] to i32* 112 // CHECK: store i32* %[[COERCE_VAL_IP]], i32** %[[COERCE_DIVE]], align 8 113 // CHECK: %[[CALL1:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* %[[AGG_TMP_ENSURED]]) 114 // CHECK: ret void 115 // CHECK: } 116 117 void testIgnoredSmall() { 118 testReturnSmall(); 119 } 120 121 // CHECK: define void @_Z14testParamLarge5Large(%[[STRUCT_LARGE:.*]]* %[[A:.*]]) 122 // CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* %[[A]]) 123 // CHECK: ret void 124 // CHECK: } 125 126 void testParamLarge(Large a) noexcept { 127 } 128 129 // CHECK: define void @_Z15testReturnLargev(%[[STRUCT_LARGE:.*]]* noalias sret %[[AGG_RESULT:.*]]) 130 // CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* %[[AGG_RESULT]]) 131 // CHECK: ret void 132 // CHECK: } 133 134 Large testReturnLarge() { 135 Large t; 136 return t; 137 } 138 139 // CHECK: define void @_Z14testCallLarge0v() 140 // CHECK: %[[T:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8 141 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE]], align 8 142 // CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* %[[T]]) 143 // CHECK: %[[CALL1:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeC1ERKS_(%[[STRUCT_LARGE]]* %[[AGG_TMP]], %[[STRUCT_LARGE]]* dereferenceable(520) %[[T]]) 144 // CHECK: call void @_Z14testParamLarge5Large(%[[STRUCT_LARGE]]* %[[AGG_TMP]]) 145 // CHECK: %[[CALL2:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* %[[T]]) 146 // CHECK: ret void 147 // CHECK: } 148 149 void testCallLarge0() { 150 Large t; 151 testParamLarge(t); 152 } 153 154 // CHECK: define void @_Z14testCallLarge1v() 155 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8 156 // CHECK: call void @_Z15testReturnLargev(%[[STRUCT_LARGE]]* sret %[[AGG_TMP]]) 157 // CHECK: call void @_Z14testParamLarge5Large(%[[STRUCT_LARGE]]* %[[AGG_TMP]]) 158 // CHECK: ret void 159 // CHECK: } 160 161 void testCallLarge1() { 162 testParamLarge(testReturnLarge()); 163 } 164 165 // CHECK: define void @_Z16testIgnoredLargev() 166 // CHECK: %[[AGG_TMP_ENSURED:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8 167 // CHECK: call void @_Z15testReturnLargev(%[[STRUCT_LARGE]]* sret %[[AGG_TMP_ENSURED]]) 168 // CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* %[[AGG_TMP_ENSURED]]) 169 // CHECK: ret void 170 // CHECK: } 171 172 void testIgnoredLarge() { 173 testReturnLarge(); 174 } 175 176 // CHECK: define i64 @_Z20testReturnHasTrivialv() 177 // CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_TRIVIAL:.*]], align 4 178 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_TRIVIAL]], %[[STRUCT_TRIVIAL]]* %[[RETVAL]], i32 0, i32 0 179 // CHECK: %[[V0:.*]] = load i32, i32* %[[COERCE_DIVE]], align 4 180 // CHECK: %[[COERCE_VAL_II:.*]] = zext i32 %[[V0]] to i64 181 // CHECK: ret i64 %[[COERCE_VAL_II]] 182 // CHECK: } 183 184 Trivial testReturnHasTrivial() { 185 Trivial t; 186 return t; 187 } 188 189 // CHECK: define void @_Z23testReturnHasNonTrivialv(%[[STRUCT_NONTRIVIAL:.*]]* noalias sret %[[AGG_RESULT:.*]]) 190 // CHECK: %[[CALL:.*]] = call %[[STRUCT_NONTRIVIAL]]* @_ZN10NonTrivialC1Ev(%[[STRUCT_NONTRIVIAL]]* %[[AGG_RESULT]]) 191 // CHECK: ret void 192 // CHECK: } 193 194 NonTrivial testReturnHasNonTrivial() { 195 NonTrivial t; 196 return t; 197 } 198 199 // CHECK: define void @_Z18testExceptionSmallv() 200 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_SMALL]], align 8 201 // CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_SMALL]], align 8 202 // CHECK: call %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* %[[AGG_TMP]]) 203 // CHECK: invoke %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* %[[AGG_TMP1]]) 204 205 // CHECK: call void @_Z20calleeExceptionSmall5SmallS_(i64 %{{.*}}, i64 %{{.*}}) 206 // CHECK-NEXT: ret void 207 208 // CHECK: landingpad { i8*, i32 } 209 // CHECK: call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* %[[AGG_TMP]]) 210 // CHECK: br 211 212 // CHECK: resume { i8*, i32 } 213 214 void calleeExceptionSmall(Small, Small); 215 216 void testExceptionSmall() { 217 calleeExceptionSmall(Small(), Small()); 218 } 219 220 // CHECK: define void @_Z18testExceptionLargev() 221 // CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE]], align 8 222 // CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_LARGE]], align 8 223 // CHECK: call %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* %[[AGG_TMP]]) 224 // CHECK: invoke %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* %[[AGG_TMP1]]) 225 226 // CHECK: call void @_Z20calleeExceptionLarge5LargeS_(%[[STRUCT_LARGE]]* %[[AGG_TMP]], %[[STRUCT_LARGE]]* %[[AGG_TMP1]]) 227 // CHECK-NEXT: ret void 228 229 // CHECK: landingpad { i8*, i32 } 230 // CHECK: call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* %[[AGG_TMP]]) 231 // CHECK: br 232 233 // CHECK: resume { i8*, i32 } 234 235 void calleeExceptionLarge(Large, Large); 236 237 void testExceptionLarge() { 238 calleeExceptionLarge(Large(), Large()); 239 } 240