1 // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \ 2 // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,NODISC %s 3 4 // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \ 5 // RUN: -fptrauth-vtable-pointer-type-discrimination \ 6 // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,TYPE %s 7 8 // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \ 9 // RUN: -fptrauth-vtable-pointer-address-discrimination \ 10 // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,ADDR %s 11 12 // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \ 13 // RUN: -fptrauth-vtable-pointer-type-discrimination \ 14 // RUN: -fptrauth-vtable-pointer-address-discrimination \ 15 // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,BOTH %s 16 17 // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ 18 // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,NODISC %s 19 20 // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ 21 // RUN: -fptrauth-vtable-pointer-type-discrimination \ 22 // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,TYPE %s 23 24 // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ 25 // RUN: -fptrauth-vtable-pointer-address-discrimination \ 26 // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,ADDR %s 27 28 // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ 29 // RUN: -fptrauth-vtable-pointer-type-discrimination \ 30 // RUN: -fptrauth-vtable-pointer-address-discrimination \ 31 // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,BOTH %s 32 33 #include <ptrauth.h> 34 35 namespace test1 { 36 37 #define authenticated(a...) ptrauth_cxx_vtable_pointer(a) 38 39 struct NoExplicitAuth { 40 virtual ~NoExplicitAuth(); 41 virtual void f(); 42 virtual void g(); 43 }; 44 45 struct authenticated(no_authentication, no_address_discrimination, no_extra_discrimination) ExplicitlyDisableAuth { 46 virtual ~ExplicitlyDisableAuth(); 47 virtual void f(); 48 virtual void g(); 49 }; 50 51 struct authenticated(default_key, address_discrimination, default_extra_discrimination) ExplicitAddressDiscrimination { 52 virtual ~ExplicitAddressDiscrimination(); 53 virtual void f(); 54 virtual void g(); 55 }; 56 57 struct authenticated(default_key, no_address_discrimination, default_extra_discrimination) ExplicitNoAddressDiscrimination { 58 virtual ~ExplicitNoAddressDiscrimination(); 59 virtual void f(); 60 virtual void g(); 61 }; 62 63 struct authenticated(default_key, default_address_discrimination, no_extra_discrimination) ExplicitNoExtraDiscrimination { 64 virtual ~ExplicitNoExtraDiscrimination(); 65 virtual void f(); 66 virtual void g(); 67 }; 68 69 struct authenticated(default_key, default_address_discrimination, type_discrimination) ExplicitTypeDiscrimination { 70 virtual ~ExplicitTypeDiscrimination(); 71 virtual void f(); 72 virtual void g(); 73 }; 74 75 struct authenticated(default_key, default_address_discrimination, custom_discrimination, 42424) ExplicitCustomDiscrimination { 76 virtual ~ExplicitCustomDiscrimination(); 77 virtual void f(); 78 virtual void g(); 79 }; 80 81 template <typename T> 82 struct SubClass : T { 83 virtual void g(); 84 virtual T *h(); 85 }; 86 87 template <typename T> 88 SubClass<T> *make_subclass(T *); 89 90 struct authenticated(default_key, address_discrimination, type_discrimination) BasicStruct { 91 virtual ~BasicStruct(); 92 }; 93 94 template <typename T> 95 struct PrimaryBasicStruct : BasicStruct, T {}; 96 template <typename T> 97 struct PrimaryBasicStruct<T> *make_multiple_primary(T *); 98 99 template <typename T> 100 struct VirtualSubClass : virtual T { 101 virtual void g(); 102 virtual T *h(); 103 }; 104 template <typename T> 105 struct VirtualPrimaryStruct : virtual T, VirtualSubClass<T> {}; 106 template <typename T> 107 struct VirtualPrimaryStruct<T> *make_virtual_primary(T *); 108 109 extern "C" { 110 111 // CHECK: @TVDisc_NoExplicitAuth = global i32 [[DISC_DEFAULT:49565]], align 4 112 int TVDisc_NoExplicitAuth = ptrauth_string_discriminator("_ZTVN5test114NoExplicitAuthE"); 113 114 // CHECK: @TVDisc_ExplicitlyDisableAuth = global i32 [[DISC_DISABLED:24369]], align 4 115 int TVDisc_ExplicitlyDisableAuth = ptrauth_string_discriminator("_ZTVN5test121ExplicitlyDisableAuthE"); 116 117 // CHECK: @TVDisc_ExplicitAddressDiscrimination = global i32 [[DISC_ADDR:56943]], align 4 118 int TVDisc_ExplicitAddressDiscrimination = ptrauth_string_discriminator("_ZTVN5test129ExplicitAddressDiscriminationE"); 119 120 // CHECK: @TVDisc_ExplicitNoAddressDiscrimination = global i32 [[DISC_NO_ADDR:6022]], align 4 121 int TVDisc_ExplicitNoAddressDiscrimination = ptrauth_string_discriminator("_ZTVN5test131ExplicitNoAddressDiscriminationE"); 122 123 // CHECK: @TVDisc_ExplicitNoExtraDiscrimination = global i32 [[DISC_NO_EXTRA:9072]], align 4 124 int TVDisc_ExplicitNoExtraDiscrimination = ptrauth_string_discriminator("_ZTVN5test129ExplicitNoExtraDiscriminationE"); 125 126 // CHECK: @TVDisc_ExplicitTypeDiscrimination = global i32 [[DISC_TYPE:6177]], align 4 127 int TVDisc_ExplicitTypeDiscrimination = ptrauth_string_discriminator("_ZTVN5test126ExplicitTypeDiscriminationE"); 128 129 130 // CHECK-LABEL: define{{.*}} void @test_default(ptr noundef {{%.*}}) {{#.*}} { 131 // CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8 132 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 133 // 134 // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 135 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0) 136 // 137 // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 138 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_DEFAULT]]) 139 // 140 // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 141 // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 142 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]]) 143 // 144 // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 145 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_DEFAULT]]) 146 // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 147 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) 148 void test_default(NoExplicitAuth *a) { 149 a->f(); 150 } 151 152 // CHECK-LABEL: define{{.*}} void @test_disabled(ptr noundef {{%.*}}) {{#.*}} { 153 // CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8 154 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 155 // CHECK-NOT: call i64 @llvm.ptrauth.auth 156 void test_disabled(ExplicitlyDisableAuth *a) { 157 a->f(); 158 } 159 160 // CHECK-LABEL: define{{.*}} void @test_addr_disc(ptr noundef {{%.*}}) {{#.*}} { 161 // CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8 162 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 163 // 164 // NODISC: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 165 // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 166 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]]) 167 // 168 // TYPE: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 169 // TYPE: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_ADDR]]) 170 // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 171 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) 172 // 173 // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 174 // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 175 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]]) 176 // 177 // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 178 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_ADDR]]) 179 // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 180 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) 181 void test_addr_disc(ExplicitAddressDiscrimination *a) { 182 a->f(); 183 } 184 185 // CHECK-LABEL: define{{.*}} void @test_no_addr_disc(ptr noundef {{%.*}}) {{#.*}} { 186 // CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8 187 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 188 // 189 // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 190 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0) 191 // 192 // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 193 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_NO_ADDR]]) 194 // 195 // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 196 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0) 197 // 198 // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 199 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_NO_ADDR]]) 200 void test_no_addr_disc(ExplicitNoAddressDiscrimination *a) { 201 a->f(); 202 } 203 204 // CHECK-LABEL: define{{.*}} void @test_no_extra_disc(ptr noundef {{%.*}}) {{#.*}} { 205 // CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8 206 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 207 // 208 // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 209 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0) 210 // 211 // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 212 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0) 213 // 214 // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 215 // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 216 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]]) 217 // 218 // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 219 // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 220 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]]) 221 void test_no_extra_disc(ExplicitNoExtraDiscrimination *a) { 222 a->f(); 223 } 224 225 // CHECK-LABEL: define{{.*}} void @test_type_disc(ptr noundef {{%.*}}) {{#.*}} { 226 // CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8 227 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 228 // 229 // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 230 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_TYPE]]) 231 // 232 // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 233 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_TYPE]]) 234 // 235 // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 236 // ADDR: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_TYPE]]) 237 // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 238 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) 239 // 240 // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 241 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_TYPE]]) 242 // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 243 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) 244 void test_type_disc(ExplicitTypeDiscrimination *a) { 245 a->f(); 246 } 247 248 // CHECK-LABEL: define{{.*}} void @test_custom_disc(ptr noundef {{%.*}}) {{#.*}} { 249 // CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8 250 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 251 // 252 // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 253 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424) 254 // 255 // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 256 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424) 257 // 258 // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 259 // ADDR: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424) 260 // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 261 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) 262 // 263 // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 264 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424) 265 // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 266 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) 267 void test_custom_disc(ExplicitCustomDiscrimination *a) { 268 a->f(); 269 } 270 271 // 272 // Test some simple single inheritance cases. 273 // Codegen should be the same as the simple cases above once we have a vtable. 274 // 275 276 // CHECK-LABEL: define{{.*}} void @test_subclass_default(ptr noundef {{%.*}}) {{#.*}} { 277 // CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass 278 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 279 // 280 // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 281 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0) 282 // 283 // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 284 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_DEFAULT]]) 285 // 286 // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 287 // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 288 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]]) 289 // 290 // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 291 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_DEFAULT]]) 292 // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 293 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) 294 void test_subclass_default(NoExplicitAuth *a) { 295 make_subclass(a)->f(); 296 } 297 298 // CHECK-LABEL: define{{.*}} void @test_subclass_disabled(ptr noundef {{%.*}}) {{#.*}} { 299 // CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass 300 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 301 // CHECK-NOT: call i64 @llvm.ptrauth.auth 302 void test_subclass_disabled(ExplicitlyDisableAuth *a) { 303 make_subclass(a)->f(); 304 } 305 306 // CHECK-LABEL: define{{.*}} void @test_subclass_addr_disc(ptr noundef {{%.*}}) {{#.*}} { 307 // CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass 308 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 309 // 310 // NODISC: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 311 // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 312 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]]) 313 // 314 // TYPE: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 315 // TYPE: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_ADDR]]) 316 // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 317 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) 318 // 319 // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 320 // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 321 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]]) 322 // 323 // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 324 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_ADDR]]) 325 // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 326 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) 327 void test_subclass_addr_disc(ExplicitAddressDiscrimination *a) { 328 make_subclass(a)->f(); 329 } 330 331 // CHECK-LABEL: define{{.*}} void @test_subclass_no_addr_disc(ptr noundef {{%.*}}) {{#.*}} { 332 // CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass 333 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 334 // 335 // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 336 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0) 337 // 338 // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 339 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_NO_ADDR]]) 340 // 341 // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 342 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0) 343 // 344 // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 345 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_NO_ADDR]]) 346 void test_subclass_no_addr_disc(ExplicitNoAddressDiscrimination *a) { 347 make_subclass(a)->f(); 348 } 349 350 // CHECK-LABEL: define{{.*}} void @test_subclass_no_extra_disc(ptr noundef {{%.*}}) {{#.*}} { 351 // CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass 352 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 353 // 354 // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 355 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0) 356 // 357 // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 358 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0) 359 // 360 // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 361 // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 362 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]]) 363 // 364 // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 365 // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 366 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]]) 367 void test_subclass_no_extra_disc(ExplicitNoExtraDiscrimination *a) { 368 make_subclass(a)->f(); 369 } 370 371 // CHECK-LABEL: define{{.*}} void @test_subclass_type_disc(ptr noundef {{%.*}}) {{#.*}} { 372 // CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass 373 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 374 // 375 // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 376 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_TYPE]]) 377 // 378 // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 379 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_TYPE]]) 380 // 381 // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 382 // ADDR: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_TYPE]]) 383 // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 384 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) 385 // 386 // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 387 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_TYPE]]) 388 // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 389 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) 390 void test_subclass_type_disc(ExplicitTypeDiscrimination *a) { 391 make_subclass(a)->f(); 392 } 393 394 // CHECK-LABEL: define{{.*}} void @test_subclass_custom_disc(ptr noundef {{%.*}}) {{#.*}} { 395 // CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass 396 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 397 // 398 // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 399 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424) 400 // 401 // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 402 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424) 403 // 404 // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 405 // ADDR: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424) 406 // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 407 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) 408 // 409 // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 410 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424) 411 // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 412 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) 413 void test_subclass_custom_disc(ExplicitCustomDiscrimination *a) { 414 make_subclass(a)->f(); 415 } 416 417 418 // 419 // Test some simple multiple inheritance cases. 420 // Codegen should be the same as the simple cases above once we have a vtable. 421 // 422 423 // CHECK-LABEL: define{{.*}} void @test_multiple_default(ptr noundef {{%.*}}) {{#.*}} { 424 // CHECK: [[CALL:%.*]] = call noundef ptr @_ZN5test121make_multiple_primary 425 // CHECK: [[VTADDR:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 8 426 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 427 // 428 // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 429 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0) 430 // 431 // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 432 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_DEFAULT]]) 433 // 434 // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 435 // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 436 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]]) 437 // 438 // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 439 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_DEFAULT]]) 440 // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 441 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) 442 void test_multiple_default(NoExplicitAuth *a) { 443 make_multiple_primary(a)->f(); 444 } 445 446 // CHECK-LABEL: define{{.*}} void @test_multiple_disabled(ptr noundef {{%.*}}) {{#.*}} { 447 // CHECK: [[CALL:%.*]] = call noundef ptr @_ZN5test121make_multiple_primary 448 // CHECK: [[VTADDR:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 8 449 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 450 // CHECK-NOT: call i64 @llvm.ptrauth.auth 451 void test_multiple_disabled(ExplicitlyDisableAuth *a) { 452 make_multiple_primary(a)->f(); 453 } 454 455 // CHECK-LABEL: define{{.*}} void @test_multiple_custom_disc(ptr noundef {{%.*}}) {{#.*}} { 456 // CHECK: [[CALL:%.*]] = call noundef ptr @_ZN5test121make_multiple_primary 457 // CHECK: [[VTADDR:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 8 458 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 459 // 460 // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 461 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424) 462 // 463 // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 464 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424) 465 // 466 // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 467 // ADDR: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424) 468 // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 469 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) 470 // 471 // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 472 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424) 473 // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 474 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) 475 void test_multiple_custom_disc(ExplicitCustomDiscrimination *a) { 476 make_multiple_primary(a)->f(); 477 } 478 479 // 480 // Test some virtual inheritance cases. 481 // Codegen should be the same as the simple cases above once we have a vtable, 482 // but twice for vtt/vtable. The names in the vtt version have "VTT" prefixes. 483 // 484 485 // CHECK-LABEL: define{{.*}} void @test_virtual_default(ptr noundef {{%.*}}) {{#.*}} { 486 // CHECK: [[VTTADDR:%.*]] = call noundef ptr @_ZN5test120make_virtual_primary 487 // CHECK: [[VTTABLE:%.*]] = load ptr, ptr [[VTTADDR]], align 8 488 // 489 // NODISC: [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64 490 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 0) 491 // 492 // TYPE: [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64 493 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 [[DISC_DEFAULT]]) 494 // 495 // ADDR: [[VTTADDRI64:%.*]] = ptrtoint ptr [[VTTADDR]] to i64 496 // ADDR: [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64 497 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 [[VTTADDRI64]]) 498 // 499 // BOTH: [[VTTADDRI64:%.*]] = ptrtoint ptr [[VTTADDR]] to i64 500 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTTADDRI64]], i64 [[DISC_DEFAULT]]) 501 // BOTH: [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64 502 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 [[BLEND]]) 503 504 // CHECK: [[AUTHEDPTR:%.*]] = inttoptr i64 [[AUTHED]] to ptr 505 // CHECK: [[VBOFFPTR:%.*]] = getelementptr i8, ptr [[AUTHEDPTR]], i64 -48 506 // CHECK: [[VBOFFSET:%.*]] = load i64, ptr [[VBOFFPTR]] 507 // CHECK: [[VTADDR:%.*]] = getelementptr inbounds i8, ptr [[VTTADDR]], i64 [[VBOFFSET]] 508 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 509 // 510 // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 511 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0) 512 // 513 // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 514 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_DEFAULT]]) 515 // 516 // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 517 // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 518 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]]) 519 // 520 // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 521 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_DEFAULT]]) 522 // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 523 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) 524 void test_virtual_default(NoExplicitAuth *a) { 525 make_virtual_primary(a)->f(); 526 } 527 528 // CHECK-LABEL: define{{.*}} void @test_virtual_disabled(ptr noundef {{%.*}}) {{#.*}} { 529 // CHECK-NOT: call i64 @llvm.ptrauth.auth 530 void test_virtual_disabled(ExplicitlyDisableAuth *a) { 531 make_virtual_primary(a)->f(); 532 } 533 534 // CHECK-LABEL: define{{.*}} void @test_virtual_custom_disc(ptr noundef {{%.*}}) {{#.*}} { 535 // CHECK: [[VTTADDR:%.*]] = call noundef ptr @_ZN5test120make_virtual_primary 536 // CHECK: [[VTTABLE:%.*]] = load ptr, ptr [[VTTADDR]], align 8 537 // 538 // NODISC: [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64 539 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 42424) 540 // 541 // TYPE: [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64 542 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 42424) 543 // 544 // ADDR: [[VTTADDRI64:%.*]] = ptrtoint ptr [[VTTADDR]] to i64 545 // ADDR: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTTADDRI64]], i64 42424) 546 // ADDR: [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64 547 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 [[BLEND]]) 548 // 549 // BOTH: [[VTTADDRI64:%.*]] = ptrtoint ptr [[VTTADDR]] to i64 550 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTTADDRI64]], i64 42424) 551 // BOTH: [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64 552 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 [[BLEND]]) 553 554 // CHECK: [[AUTHEDPTR:%.*]] = inttoptr i64 [[AUTHED]] to ptr 555 // CHECK: [[VBOFFPTR:%.*]] = getelementptr i8, ptr [[AUTHEDPTR]], i64 -48 556 // CHECK: [[VBOFFSET:%.*]] = load i64, ptr [[VBOFFPTR]] 557 // CHECK: [[VTADDR:%.*]] = getelementptr inbounds i8, ptr [[VTTADDR]], i64 [[VBOFFSET]] 558 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 559 // 560 // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 561 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424) 562 // 563 // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 564 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424) 565 // 566 // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 567 // ADDR: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424) 568 // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 569 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) 570 // 571 // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 572 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424) 573 // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 574 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) 575 void test_virtual_custom_disc(ExplicitCustomDiscrimination *a) { 576 make_virtual_primary(a)->f(); 577 } 578 579 } // extern "C" 580 } // namespace test1 581