// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \ // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,NODISC %s // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \ // RUN: -fptrauth-vtable-pointer-type-discrimination \ // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,TYPE %s // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \ // RUN: -fptrauth-vtable-pointer-address-discrimination \ // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,ADDR %s // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \ // RUN: -fptrauth-vtable-pointer-type-discrimination \ // RUN: -fptrauth-vtable-pointer-address-discrimination \ // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,BOTH %s // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,NODISC %s // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ // RUN: -fptrauth-vtable-pointer-type-discrimination \ // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,TYPE %s // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ // RUN: -fptrauth-vtable-pointer-address-discrimination \ // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,ADDR %s // RUN: %clang_cc1 %s -x c++ -std=c++11 -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ // RUN: -fptrauth-vtable-pointer-type-discrimination \ // RUN: -fptrauth-vtable-pointer-address-discrimination \ // RUN: -emit-llvm -o - | FileCheck --check-prefixes=CHECK,BOTH %s #include namespace test1 { #define authenticated(a...) ptrauth_cxx_vtable_pointer(a) struct NoExplicitAuth { virtual ~NoExplicitAuth(); virtual void f(); virtual void g(); }; struct authenticated(no_authentication, no_address_discrimination, no_extra_discrimination) ExplicitlyDisableAuth { virtual ~ExplicitlyDisableAuth(); virtual void f(); virtual void g(); }; struct authenticated(default_key, address_discrimination, default_extra_discrimination) ExplicitAddressDiscrimination { virtual ~ExplicitAddressDiscrimination(); virtual void f(); virtual void g(); }; struct authenticated(default_key, no_address_discrimination, default_extra_discrimination) ExplicitNoAddressDiscrimination { virtual ~ExplicitNoAddressDiscrimination(); virtual void f(); virtual void g(); }; struct authenticated(default_key, default_address_discrimination, no_extra_discrimination) ExplicitNoExtraDiscrimination { virtual ~ExplicitNoExtraDiscrimination(); virtual void f(); virtual void g(); }; struct authenticated(default_key, default_address_discrimination, type_discrimination) ExplicitTypeDiscrimination { virtual ~ExplicitTypeDiscrimination(); virtual void f(); virtual void g(); }; struct authenticated(default_key, default_address_discrimination, custom_discrimination, 42424) ExplicitCustomDiscrimination { virtual ~ExplicitCustomDiscrimination(); virtual void f(); virtual void g(); }; template struct SubClass : T { virtual void g(); virtual T *h(); }; template SubClass *make_subclass(T *); struct authenticated(default_key, address_discrimination, type_discrimination) BasicStruct { virtual ~BasicStruct(); }; template struct PrimaryBasicStruct : BasicStruct, T {}; template struct PrimaryBasicStruct *make_multiple_primary(T *); template struct VirtualSubClass : virtual T { virtual void g(); virtual T *h(); }; template struct VirtualPrimaryStruct : virtual T, VirtualSubClass {}; template struct VirtualPrimaryStruct *make_virtual_primary(T *); extern "C" { // CHECK: @TVDisc_NoExplicitAuth = global i32 [[DISC_DEFAULT:49565]], align 4 int TVDisc_NoExplicitAuth = ptrauth_string_discriminator("_ZTVN5test114NoExplicitAuthE"); // CHECK: @TVDisc_ExplicitlyDisableAuth = global i32 [[DISC_DISABLED:24369]], align 4 int TVDisc_ExplicitlyDisableAuth = ptrauth_string_discriminator("_ZTVN5test121ExplicitlyDisableAuthE"); // CHECK: @TVDisc_ExplicitAddressDiscrimination = global i32 [[DISC_ADDR:56943]], align 4 int TVDisc_ExplicitAddressDiscrimination = ptrauth_string_discriminator("_ZTVN5test129ExplicitAddressDiscriminationE"); // CHECK: @TVDisc_ExplicitNoAddressDiscrimination = global i32 [[DISC_NO_ADDR:6022]], align 4 int TVDisc_ExplicitNoAddressDiscrimination = ptrauth_string_discriminator("_ZTVN5test131ExplicitNoAddressDiscriminationE"); // CHECK: @TVDisc_ExplicitNoExtraDiscrimination = global i32 [[DISC_NO_EXTRA:9072]], align 4 int TVDisc_ExplicitNoExtraDiscrimination = ptrauth_string_discriminator("_ZTVN5test129ExplicitNoExtraDiscriminationE"); // CHECK: @TVDisc_ExplicitTypeDiscrimination = global i32 [[DISC_TYPE:6177]], align 4 int TVDisc_ExplicitTypeDiscrimination = ptrauth_string_discriminator("_ZTVN5test126ExplicitTypeDiscriminationE"); // CHECK-LABEL: define{{.*}} void @test_default(ptr noundef {{%.*}}) {{#.*}} { // CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 // // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0) // // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_DEFAULT]]) // // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]]) // // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_DEFAULT]]) // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) void test_default(NoExplicitAuth *a) { a->f(); } // CHECK-LABEL: define{{.*}} void @test_disabled(ptr noundef {{%.*}}) {{#.*}} { // CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 // CHECK-NOT: call i64 @llvm.ptrauth.auth void test_disabled(ExplicitlyDisableAuth *a) { a->f(); } // CHECK-LABEL: define{{.*}} void @test_addr_disc(ptr noundef {{%.*}}) {{#.*}} { // CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 // // NODISC: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]]) // // TYPE: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // TYPE: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_ADDR]]) // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) // // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]]) // // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_ADDR]]) // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) void test_addr_disc(ExplicitAddressDiscrimination *a) { a->f(); } // CHECK-LABEL: define{{.*}} void @test_no_addr_disc(ptr noundef {{%.*}}) {{#.*}} { // CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 // // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0) // // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_NO_ADDR]]) // // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0) // // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_NO_ADDR]]) void test_no_addr_disc(ExplicitNoAddressDiscrimination *a) { a->f(); } // CHECK-LABEL: define{{.*}} void @test_no_extra_disc(ptr noundef {{%.*}}) {{#.*}} { // CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 // // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0) // // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0) // // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]]) // // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]]) void test_no_extra_disc(ExplicitNoExtraDiscrimination *a) { a->f(); } // CHECK-LABEL: define{{.*}} void @test_type_disc(ptr noundef {{%.*}}) {{#.*}} { // CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 // // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_TYPE]]) // // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_TYPE]]) // // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // ADDR: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_TYPE]]) // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) // // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_TYPE]]) // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) void test_type_disc(ExplicitTypeDiscrimination *a) { a->f(); } // CHECK-LABEL: define{{.*}} void @test_custom_disc(ptr noundef {{%.*}}) {{#.*}} { // CHECK: [[VTADDR:%.*]] = load ptr, ptr {{%.*}}, align 8 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 // // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424) // // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424) // // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // ADDR: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424) // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) // // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424) // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) void test_custom_disc(ExplicitCustomDiscrimination *a) { a->f(); } // // Test some simple single inheritance cases. // Codegen should be the same as the simple cases above once we have a vtable. // // CHECK-LABEL: define{{.*}} void @test_subclass_default(ptr noundef {{%.*}}) {{#.*}} { // CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 // // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0) // // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_DEFAULT]]) // // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]]) // // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_DEFAULT]]) // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) void test_subclass_default(NoExplicitAuth *a) { make_subclass(a)->f(); } // CHECK-LABEL: define{{.*}} void @test_subclass_disabled(ptr noundef {{%.*}}) {{#.*}} { // CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 // CHECK-NOT: call i64 @llvm.ptrauth.auth void test_subclass_disabled(ExplicitlyDisableAuth *a) { make_subclass(a)->f(); } // CHECK-LABEL: define{{.*}} void @test_subclass_addr_disc(ptr noundef {{%.*}}) {{#.*}} { // CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 // // NODISC: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]]) // // TYPE: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // TYPE: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_ADDR]]) // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) // // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]]) // // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_ADDR]]) // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) void test_subclass_addr_disc(ExplicitAddressDiscrimination *a) { make_subclass(a)->f(); } // CHECK-LABEL: define{{.*}} void @test_subclass_no_addr_disc(ptr noundef {{%.*}}) {{#.*}} { // CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 // // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0) // // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_NO_ADDR]]) // // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0) // // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_NO_ADDR]]) void test_subclass_no_addr_disc(ExplicitNoAddressDiscrimination *a) { make_subclass(a)->f(); } // CHECK-LABEL: define{{.*}} void @test_subclass_no_extra_disc(ptr noundef {{%.*}}) {{#.*}} { // CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 // // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0) // // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0) // // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]]) // // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]]) void test_subclass_no_extra_disc(ExplicitNoExtraDiscrimination *a) { make_subclass(a)->f(); } // CHECK-LABEL: define{{.*}} void @test_subclass_type_disc(ptr noundef {{%.*}}) {{#.*}} { // CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 // // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_TYPE]]) // // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_TYPE]]) // // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // ADDR: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_TYPE]]) // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) // // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_TYPE]]) // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) void test_subclass_type_disc(ExplicitTypeDiscrimination *a) { make_subclass(a)->f(); } // CHECK-LABEL: define{{.*}} void @test_subclass_custom_disc(ptr noundef {{%.*}}) {{#.*}} { // CHECK: [[VTADDR:%.*]] = call noundef ptr @_ZN5test113make_subclass // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 // // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424) // // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424) // // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // ADDR: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424) // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) // // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424) // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) void test_subclass_custom_disc(ExplicitCustomDiscrimination *a) { make_subclass(a)->f(); } // // Test some simple multiple inheritance cases. // Codegen should be the same as the simple cases above once we have a vtable. // // CHECK-LABEL: define{{.*}} void @test_multiple_default(ptr noundef {{%.*}}) {{#.*}} { // CHECK: [[CALL:%.*]] = call noundef ptr @_ZN5test121make_multiple_primary // CHECK: [[VTADDR:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 8 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 // // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0) // // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_DEFAULT]]) // // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]]) // // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_DEFAULT]]) // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) void test_multiple_default(NoExplicitAuth *a) { make_multiple_primary(a)->f(); } // CHECK-LABEL: define{{.*}} void @test_multiple_disabled(ptr noundef {{%.*}}) {{#.*}} { // CHECK: [[CALL:%.*]] = call noundef ptr @_ZN5test121make_multiple_primary // CHECK: [[VTADDR:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 8 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 // CHECK-NOT: call i64 @llvm.ptrauth.auth void test_multiple_disabled(ExplicitlyDisableAuth *a) { make_multiple_primary(a)->f(); } // CHECK-LABEL: define{{.*}} void @test_multiple_custom_disc(ptr noundef {{%.*}}) {{#.*}} { // CHECK: [[CALL:%.*]] = call noundef ptr @_ZN5test121make_multiple_primary // CHECK: [[VTADDR:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 8 // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 // // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424) // // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424) // // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // ADDR: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424) // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) // // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424) // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) void test_multiple_custom_disc(ExplicitCustomDiscrimination *a) { make_multiple_primary(a)->f(); } // // Test some virtual inheritance cases. // Codegen should be the same as the simple cases above once we have a vtable, // but twice for vtt/vtable. The names in the vtt version have "VTT" prefixes. // // CHECK-LABEL: define{{.*}} void @test_virtual_default(ptr noundef {{%.*}}) {{#.*}} { // CHECK: [[VTTADDR:%.*]] = call noundef ptr @_ZN5test120make_virtual_primary // CHECK: [[VTTABLE:%.*]] = load ptr, ptr [[VTTADDR]], align 8 // // NODISC: [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 0) // // TYPE: [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 [[DISC_DEFAULT]]) // // ADDR: [[VTTADDRI64:%.*]] = ptrtoint ptr [[VTTADDR]] to i64 // ADDR: [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 [[VTTADDRI64]]) // // BOTH: [[VTTADDRI64:%.*]] = ptrtoint ptr [[VTTADDR]] to i64 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTTADDRI64]], i64 [[DISC_DEFAULT]]) // BOTH: [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 [[BLEND]]) // CHECK: [[AUTHEDPTR:%.*]] = inttoptr i64 [[AUTHED]] to ptr // CHECK: [[VBOFFPTR:%.*]] = getelementptr i8, ptr [[AUTHEDPTR]], i64 -48 // CHECK: [[VBOFFSET:%.*]] = load i64, ptr [[VBOFFPTR]] // CHECK: [[VTADDR:%.*]] = getelementptr inbounds i8, ptr [[VTTADDR]], i64 [[VBOFFSET]] // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 // // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 0) // // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[DISC_DEFAULT]]) // // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[VTADDRI64]]) // // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 [[DISC_DEFAULT]]) // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) void test_virtual_default(NoExplicitAuth *a) { make_virtual_primary(a)->f(); } // CHECK-LABEL: define{{.*}} void @test_virtual_disabled(ptr noundef {{%.*}}) {{#.*}} { // CHECK-NOT: call i64 @llvm.ptrauth.auth void test_virtual_disabled(ExplicitlyDisableAuth *a) { make_virtual_primary(a)->f(); } // CHECK-LABEL: define{{.*}} void @test_virtual_custom_disc(ptr noundef {{%.*}}) {{#.*}} { // CHECK: [[VTTADDR:%.*]] = call noundef ptr @_ZN5test120make_virtual_primary // CHECK: [[VTTABLE:%.*]] = load ptr, ptr [[VTTADDR]], align 8 // // NODISC: [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 42424) // // TYPE: [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 42424) // // ADDR: [[VTTADDRI64:%.*]] = ptrtoint ptr [[VTTADDR]] to i64 // ADDR: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTTADDRI64]], i64 42424) // ADDR: [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 [[BLEND]]) // // BOTH: [[VTTADDRI64:%.*]] = ptrtoint ptr [[VTTADDR]] to i64 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTTADDRI64]], i64 42424) // BOTH: [[VTTABLEI64:%.*]] = ptrtoint ptr [[VTTABLE]] to i64 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTTABLEI64]], i32 2, i64 [[BLEND]]) // CHECK: [[AUTHEDPTR:%.*]] = inttoptr i64 [[AUTHED]] to ptr // CHECK: [[VBOFFPTR:%.*]] = getelementptr i8, ptr [[AUTHEDPTR]], i64 -48 // CHECK: [[VBOFFSET:%.*]] = load i64, ptr [[VBOFFPTR]] // CHECK: [[VTADDR:%.*]] = getelementptr inbounds i8, ptr [[VTTADDR]], i64 [[VBOFFSET]] // CHECK: [[VTABLE:%.*]] = load ptr, ptr [[VTADDR]], align 8 // // NODISC: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // NODISC: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424) // // TYPE: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // TYPE: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 42424) // // ADDR: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // ADDR: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424) // ADDR: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // ADDR: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) // // BOTH: [[VTADDRI64:%.*]] = ptrtoint ptr [[VTADDR]] to i64 // BOTH: [[BLEND:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[VTADDRI64]], i64 42424) // BOTH: [[VTABLEI64:%.*]] = ptrtoint ptr [[VTABLE]] to i64 // BOTH: [[AUTHED:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[VTABLEI64]], i32 2, i64 [[BLEND]]) void test_virtual_custom_disc(ExplicitCustomDiscrimination *a) { make_virtual_primary(a)->f(); } } // extern "C" } // namespace test1