llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Oliver Hunt (ojhunt) <details> <summary>Changes</summary> These are a pair of builtins to support particularly weird edge case operations while correctly handling the non-trivial implicit pointer authentication schemas applied to polymorphic members. --- Patch is 39.14 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/135469.diff 9 Files Affected: - (modified) clang/docs/LanguageExtensions.rst (+33) - (modified) clang/include/clang/Basic/Builtins.td (+12) - (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+15) - (modified) clang/lib/CodeGen/CGBuiltin.cpp (+30) - (modified) clang/lib/Sema/SemaChecking.cpp (+90) - (added) clang/test/CodeGenCXX/builtin-get-vtable-pointer.cpp (+304) - (added) clang/test/CodeGenCXX/builtin_virtual_member_address.cpp (+41) - (added) clang/test/SemaCXX/builtin-get-vtable-pointer.cpp (+123) - (added) clang/test/SemaCXX/builtin_virtual_member_address.cpp (+57) ``````````diff diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 3b8a9cac6587a..643dea3c6cbf7 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -3031,6 +3031,39 @@ following way: Query for this feature with ``__has_builtin(__builtin_offsetof)``. +``__builtin_get_vtable_pointer`` +-------------------------------- + +``__builtin_get_vtable_pointer`` loads and authenticates the primary vtable +pointer from an instance of a polymorphic C++ class. + +**Syntax**: + +.. code-block:: c++ + + __builtin_get_vtable_pointer(PolymorphicClass*) + +**Example of Use**: + +.. code-block:: c++ + + struct PolymorphicClass { + virtual ~PolymorphicClass(); + }; + + PolymorphicClass anInstance; + const void* vtablePointer = __builtin_get_vtable_pointer(&anInstance); + +**Description**: + +The ``__builtin_get_vtable_pointer`` builtin loads the primary vtable +pointer from a polymorphic C++ type. If the target platform authenticates +vtable pointers, this builtin will perform the authentication and produce +the underlying raw pointer. The object being queried must be polymorphic, +and so must also be a complete type. + +Query for this feature with ``__has_builtin(__builtin_get_vtable_pointer)``. + ``__builtin_call_with_static_chain`` ------------------------------------ diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 868e5b92acdc9..a55f411343c2d 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -970,6 +970,18 @@ def IsWithinLifetime : LangBuiltin<"CXX_LANG"> { let Prototype = "bool(void*)"; } +def GetVtablePointer : LangBuiltin<"CXX_LANG"> { + let Spellings = ["__builtin_get_vtable_pointer"]; + let Attributes = [CustomTypeChecking, NoThrow, Const]; + let Prototype = "void*(void*)"; +} + +def VirtualMemberAddress : Builtin { + let Spellings = ["__builtin_virtual_member_address"]; + let Attributes = [CustomTypeChecking, NoThrow, Const]; + let Prototype = "void*(void*,void*)"; +} + // GCC exception builtins def EHReturn : Builtin { let Spellings = ["__builtin_eh_return"]; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 180ca39bc07e9..8c534850696d9 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1013,6 +1013,13 @@ def err_ptrauth_indirect_goto_addrlabel_arithmetic : Error< "%select{subtraction|addition}0 of address-of-label expressions is not " "supported with ptrauth indirect gotos">; +def err_virtual_member_lhs_cxxrec : Error< + "first argument to __builtin_virtual_member_address must have C++ class type">; +def err_virtual_member_addrof : Error< + "second argument to __builtin_virtual_member_address must be the address of a virtual C++ member function: for example '&Foo::func'">; +def err_virtual_member_inherit : Error< + "first argument to __builtin_virtual_member_address must have a type deriving from class where second argument was defined">; + /// main() // static main() is not an error in C, just in C++. def warn_static_main : Warning<"'main' should not be declared static">, @@ -12547,6 +12554,14 @@ def err_bit_cast_non_trivially_copyable : Error< def err_bit_cast_type_size_mismatch : Error< "size of '__builtin_bit_cast' source type %0 does not match destination type %1 (%2 vs %3 bytes)">; + +def err_get_vtable_pointer_incorrect_type : Error< + "__builtin_get_vtable_pointer requires an argument of%select{| polymorphic}0 class pointer type" + ", but %1 %select{was provided|has no virtual methods}0" +>; +def err_get_vtable_pointer_requires_complete_type : Error< + "__builtin_get_vtable_pointer requires an argument with a complete type, but %0 is incomplete">; + // SYCL-specific diagnostics def warn_sycl_kernel_num_of_template_params : Warning< "'sycl_kernel' attribute only applies to a function template with at least" diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index fe55dfffc1cbe..316f5debf89d7 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -17,6 +17,7 @@ #include "CGDebugInfo.h" #include "CGObjCRuntime.h" #include "CGOpenCLRuntime.h" +#include "CGPointerAuthInfo.h" #include "CGRecordLayout.h" #include "CGValue.h" #include "CodeGenFunction.h" @@ -5349,6 +5350,35 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, return RValue::get(Result); } + case Builtin::BI__builtin_virtual_member_address: { + Address This = EmitLValue(E->getArg(0)).getAddress(); + APValue ConstMemFun; + E->getArg(1)->isCXX11ConstantExpr(getContext(), &ConstMemFun, nullptr); + const CXXMethodDecl *CXXMethod = + cast<CXXMethodDecl>(ConstMemFun.getMemberPointerDecl()); + const CGFunctionInfo &FInfo = + CGM.getTypes().arrangeCXXMethodDeclaration(CXXMethod); + llvm::FunctionType *Ty = CGM.getTypes().GetFunctionType(FInfo); + CGCallee VCallee = CGM.getCXXABI().getVirtualFunctionPointer( + *this, CXXMethod, This, Ty, E->getBeginLoc()); + llvm::Value *Callee = VCallee.getFunctionPointer(); + if (const CGPointerAuthInfo &Schema = VCallee.getPointerAuthInfo()) + Callee = EmitPointerAuthAuth(Schema, Callee); + return RValue::get(Callee); + } + + case Builtin::BI__builtin_get_vtable_pointer: { + auto target = E->getArg(0); + auto type = target->getType(); + auto decl = type->getPointeeCXXRecordDecl(); + assert(decl); + auto thisAddress = EmitPointerWithAlignment(target); + assert(thisAddress.isValid()); + auto vtablePointer = + GetVTablePtr(thisAddress, Int8PtrTy, decl, VTableAuthMode::MustTrap); + return RValue::get(vtablePointer); + } + case Builtin::BI__exception_code: case Builtin::BI_exception_code: return RValue::get(EmitSEHExceptionCode()); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index bffd0dd461d3d..77b8b304f7f0a 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -1764,6 +1764,57 @@ static ExprResult PointerAuthAuthAndResign(Sema &S, CallExpr *Call) { return Call; } +static ExprResult VirtualMemberAddress(Sema &S, CallExpr *Call) { + if (S.checkArgCount(Call, 2)) + return ExprError(); + + for (int i = 0; i < 2; ++i) { + auto ArgRValue = S.DefaultFunctionArrayLvalueConversion(Call->getArg(1)); + if (ArgRValue.isInvalid()) + return ExprError(); + + auto Arg = ArgRValue.get(); + Call->setArg(1, Arg); + } + + if (Call->getArg(0)->isTypeDependent() || Call->getArg(1)->isValueDependent()) + return Call; + + auto ThisArg = Call->getArg(0); + auto ThisTy = ThisArg->getType(); + if (!ThisTy->getAsCXXRecordDecl()) { + S.Diag(ThisArg->getExprLoc(), diag::err_virtual_member_lhs_cxxrec); + return ExprError(); + } + + auto MemFunArg = Call->getArg(1); + APValue Result; + if (!MemFunArg->isCXX11ConstantExpr(S.getASTContext(), &Result, nullptr)) { + S.Diag(MemFunArg->getExprLoc(), diag::err_virtual_member_addrof); + return ExprError(); + } + + if (!Result.isMemberPointer() || + !isa<CXXMethodDecl>(Result.getMemberPointerDecl())) { + S.Diag(MemFunArg->getExprLoc(), diag::err_virtual_member_addrof); + return ExprError(); + } + + auto CXXMethod = cast<CXXMethodDecl>(Result.getMemberPointerDecl()); + if (!CXXMethod->isVirtual()) { + S.Diag(MemFunArg->getExprLoc(), diag::err_virtual_member_addrof); + return ExprError(); + } + + if (ThisTy->getAsCXXRecordDecl() != CXXMethod->getParent() && + !S.IsDerivedFrom(Call->getBeginLoc(), ThisTy, + CXXMethod->getFunctionObjectParameterType())) { + S.Diag(ThisArg->getExprLoc(), diag::err_virtual_member_inherit); + return ExprError(); + } + return Call; +} + static ExprResult PointerAuthStringDiscriminator(Sema &S, CallExpr *Call) { if (checkPointerAuthEnabled(S, Call)) return ExprError(); @@ -1782,6 +1833,39 @@ static ExprResult PointerAuthStringDiscriminator(Sema &S, CallExpr *Call) { return Call; } +static ExprResult GetVTablePointer(Sema &S, CallExpr *call) { + if (S.checkArgCount(call, 1)) + return ExprError(); + auto rvalue = S.DefaultFunctionArrayLvalueConversion(call->getArg(0)); + if (rvalue.isInvalid()) + return ExprError(); + call->setArg(0, rvalue.get()); + auto expression = call->getArg(0); + QualType expressionType = expression->getType(); + const CXXRecordDecl *objectType = expressionType->getPointeeCXXRecordDecl(); + if (!expressionType->isPointerType() || !objectType) { + S.Diag(expression->getBeginLoc(), + diag::err_get_vtable_pointer_incorrect_type) + << 0 << expressionType; + return ExprError(); + } + if (S.RequireCompleteType( + expression->getBeginLoc(), expressionType->getPointeeType(), + diag::err_get_vtable_pointer_requires_complete_type)) { + return ExprError(); + } + + if (!objectType->isPolymorphic()) { + S.Diag(expression->getBeginLoc(), + diag::err_get_vtable_pointer_incorrect_type) + << 1 << objectType; + return ExprError(); + } + QualType returnType = S.Context.getPointerType(S.Context.VoidTy.withConst()); + call->setType(returnType); + return call; +} + static ExprResult BuiltinLaunder(Sema &S, CallExpr *TheCall) { if (S.checkArgCount(TheCall, 1)) return ExprError(); @@ -2625,6 +2709,12 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, return PointerAuthAuthAndResign(*this, TheCall); case Builtin::BI__builtin_ptrauth_string_discriminator: return PointerAuthStringDiscriminator(*this, TheCall); + + case Builtin::BI__builtin_get_vtable_pointer: + return GetVTablePointer(*this, TheCall); + case Builtin::BI__builtin_virtual_member_address: + return VirtualMemberAddress(*this, TheCall); + // OpenCL v2.0, s6.13.16 - Pipe functions case Builtin::BIread_pipe: case Builtin::BIwrite_pipe: diff --git a/clang/test/CodeGenCXX/builtin-get-vtable-pointer.cpp b/clang/test/CodeGenCXX/builtin-get-vtable-pointer.cpp new file mode 100644 index 0000000000000..5577e01a09f6f --- /dev/null +++ b/clang/test/CodeGenCXX/builtin-get-vtable-pointer.cpp @@ -0,0 +1,304 @@ +// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -O1 -disable-llvm-passes -no-enable-noundef-analysis -o - | FileCheck --check-prefix=CHECK-NOAUTH %s +// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple arm64-apple-ios -fptrauth-calls -fptrauth-vtable-pointer-type-discrimination -emit-llvm -O1 -disable-llvm-passes -no-enable-noundef-analysis -o - | FileCheck --check-prefix=CHECK-TYPEAUTH %s +// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple arm64-apple-ios -fptrauth-calls -fptrauth-vtable-pointer-address-discrimination -emit-llvm -O1 -disable-llvm-passes -no-enable-noundef-analysis -o - | FileCheck --check-prefix=CHECK-ADDRESSAUTH %s +// RUN: %clang_cc1 %s -x c++ -std=c++11 -triple arm64-apple-ios -fptrauth-calls -fptrauth-vtable-pointer-type-discrimination -fptrauth-vtable-pointer-address-discrimination -emit-llvm -O1 -disable-llvm-passes -no-enable-noundef-analysis -o - | FileCheck --check-prefix=CHECK-BOTHAUTH %s +// FIXME: Assume load should not require -fstrict-vtable-pointers + +namespace test1 { +struct A { + A(); + virtual void bar(); +}; + +struct B : A { + B(); + virtual void foo(); +}; + +struct Z : A {}; +struct C : Z, B { + C(); + virtual void wibble(); +}; + +struct D : virtual A { +}; + +struct E : D, B { +}; + +const void *a(A *o) { + // CHECK-NOAUTH: define ptr @_ZN5test11aEPNS_1AE(ptr %o) #0 { + // CHECK-TYPEAUTH: define ptr @_ZN5test11aEPNS_1AE(ptr %o) #0 { + return __builtin_get_vtable_pointer(o); + // CHECK-NOAUTH: %vtable = load ptr, ptr %0, align 8 + // CHECK-TYPEAUTH: %0 = load ptr, ptr %o.addr, align 8 + // CHECK-TYPEAUTH: %vtable = load ptr, ptr %0, align 8 + // CHECK-TYPEAUTH: %1 = ptrtoint ptr %vtable to i64 + // CHECK-TYPEAUTH: %2 = call i64 @llvm.ptrauth.auth(i64 %1, i32 2, i64 48388) + // CHECK-TYPEAUTH: %3 = inttoptr i64 %2 to ptr + // CHECK-TYPEAUTH: %4 = load volatile i8, ptr %3, align 8 + // CHECK-ADDRESSAUTH: %2 = ptrtoint ptr %vtable to i64 + // CHECK-ADDRESSAUTH: %3 = call i64 @llvm.ptrauth.auth(i64 %2, i32 2, i64 %1) + // CHECK-ADDRESSAUTH: %4 = inttoptr i64 %3 to ptr + // CHECK-ADDRESSAUTH: %5 = load volatile i8, ptr %4, align 8 + // CHECK-BOTHAUTH: [[T1:%.*]] = ptrtoint ptr %0 to i64 + // CHECK-BOTHAUTH: [[T2:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T1]], i64 48388) + // CHECK-BOTHAUTH: [[T3:%.*]] = ptrtoint ptr %vtable to i64 + // CHECK-BOTHAUTH: [[T4:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[T3]], i32 2, i64 [[T2]]) + // CHECK-BOTHAUTH: [[T5:%.*]] = inttoptr i64 [[T4]] to ptr + // CHECK-BOTHAUTH: [[T6:%.*]] = load volatile i8, ptr [[T5]], align 8 +} + +const void *b(B *o) { + // CHECK-TYPEAUTH: define ptr @_ZN5test11bEPNS_1BE(ptr %o) #0 { + // CHECK-NOAUTH: define ptr @_ZN5test11bEPNS_1BE(ptr %o) #0 { + return __builtin_get_vtable_pointer(o); + // CHECK-NOAUTH: %vtable = load ptr, ptr %0, align 8 + // CHECK-TYPEAUTH: %vtable = load ptr, ptr %0, align 8 + // CHECK-TYPEAUTH: %1 = ptrtoint ptr %vtable to i64 + // CHECK-TYPEAUTH: %2 = call i64 @llvm.ptrauth.auth(i64 %1, i32 2, i64 48388) + // CHECK-TYPEAUTH: %3 = inttoptr i64 %2 to ptr + // CHECK-TYPEAUTH: %4 = load volatile i8, ptr %3, align 8 + // CHECK-ADDRESSAUTH: %2 = ptrtoint ptr %vtable to i64 + // CHECK-ADDRESSAUTH: %3 = call i64 @llvm.ptrauth.auth(i64 %2, i32 2, i64 %1) + // CHECK-ADDRESSAUTH: %4 = inttoptr i64 %3 to ptr + // CHECK-ADDRESSAUTH: %5 = load volatile i8, ptr %4, align 8 + // CHECK-BOTHAUTH: [[T2:%.*]] = call i64 @llvm.ptrauth.blend(i64 %1, i64 48388) + // CHECK-BOTHAUTH: [[T3:%.*]] = ptrtoint ptr %vtable to i64 + // CHECK-BOTHAUTH: [[T4:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[T3]], i32 2, i64 [[T2]]) + // CHECK-BOTHAUTH: [[T5:%.*]] = inttoptr i64 [[T4]] to ptr + // CHECK-BOTHAUTH: [[T6:%.*]] = load volatile i8, ptr [[T5]], align 8 +} + +const void *b_as_A(B *o) { + // CHECK-NOAUTH: define ptr @_ZN5test16b_as_AEPNS_1BE(ptr %o) #0 { + return __builtin_get_vtable_pointer((A *)o); + // CHECK-NOAUTH: %vtable = load ptr, ptr %0, align 8 + // CHECK-TYPEAUTH: %vtable = load ptr, ptr %0, align 8 + // CHECK-TYPEAUTH: %1 = ptrtoint ptr %vtable to i64 + // CHECK-TYPEAUTH: %2 = call i64 @llvm.ptrauth.auth(i64 %1, i32 2, i64 48388) + // CHECK-TYPEAUTH: %3 = inttoptr i64 %2 to ptr + // CHECK-TYPEAUTH: %4 = load volatile i8, ptr %3, align 8 + // CHECK-ADDRESSAUTH: %2 = ptrtoint ptr %vtable to i64 + // CHECK-ADDRESSAUTH: %3 = call i64 @llvm.ptrauth.auth(i64 %2, i32 2, i64 %1) + // CHECK-ADDRESSAUTH: %4 = inttoptr i64 %3 to ptr + // CHECK-ADDRESSAUTH: %5 = load volatile i8, ptr %4, align 8 + // CHECK-BOTHAUTH: [[T2:%.*]] = call i64 @llvm.ptrauth.blend(i64 %1, i64 48388) + // CHECK-BOTHAUTH: [[T3:%.*]] = ptrtoint ptr %vtable to i64 + // CHECK-BOTHAUTH: [[T4:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[T3]], i32 2, i64 [[T2]]) + // CHECK-BOTHAUTH: [[T5:%.*]] = inttoptr i64 [[T4]] to ptr + // CHECK-BOTHAUTH: [[T6:%.*]] = load volatile i8, ptr [[T5]], align 8 +} + +const void *c(C *o) { + // CHECK-NOAUTH: define ptr @_ZN5test11cEPNS_1CE(ptr %o) #0 { + return __builtin_get_vtable_pointer(o); + // CHECK-NOAUTH: %vtable = load ptr, ptr %0, align 8 + // CHECK-TYPEAUTH: %vtable = load ptr, ptr %0, align 8 + // CHECK-TYPEAUTH: %1 = ptrtoint ptr %vtable to i64 + // CHECK-TYPEAUTH: %2 = call i64 @llvm.ptrauth.auth(i64 %1, i32 2, i64 48388) + // CHECK-TYPEAUTH: %3 = inttoptr i64 %2 to ptr + // CHECK-TYPEAUTH: %4 = load volatile i8, ptr %3, align 8 + // CHECK-ADDRESSAUTH: %2 = ptrtoint ptr %vtable to i64 + // CHECK-ADDRESSAUTH: %3 = call i64 @llvm.ptrauth.auth(i64 %2, i32 2, i64 %1) + // CHECK-ADDRESSAUTH: %4 = inttoptr i64 %3 to ptr + // CHECK-ADDRESSAUTH: %5 = load volatile i8, ptr %4, align 8 + // CHECK-BOTHAUTH: [[T2:%.*]] = call i64 @llvm.ptrauth.blend(i64 %1, i64 48388) + // CHECK-BOTHAUTH: [[T3:%.*]] = ptrtoint ptr %vtable to i64 + // CHECK-BOTHAUTH: [[T4:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[T3]], i32 2, i64 [[T2]]) + // CHECK-BOTHAUTH: [[T5:%.*]] = inttoptr i64 [[T4]] to ptr + // CHECK-BOTHAUTH: [[T6:%.*]] = load volatile i8, ptr [[T5]], align 8 +} + +const void *c_as_Z(C *o) { + // CHECK-NOAUTH: define ptr @_ZN5test16c_as_ZEPNS_1CE(ptr %o) #0 { + return __builtin_get_vtable_pointer((Z *)o); + // CHECK-NOAUTH: %0 = load ptr, ptr %o.addr, align 8 + // CHECK-NOAUTH: %vtable = load ptr, ptr %0, align 8 + // CHECK-TYPEAUTH: %vtable = load ptr, ptr %0, align 8 + // CHECK-TYPEAUTH: %1 = ptrtoint ptr %vtable to i64 + // CHECK-TYPEAUTH: %2 = call i64 @llvm.ptrauth.auth(i64 %1, i32 2, i64 48388) + // CHECK-TYPEAUTH: %3 = inttoptr i64 %2 to ptr + // CHECK-TYPEAUTH: %4 = load volatile i8, ptr %3, align 8 + // CHECK-ADDRESSAUTH: %2 = ptrtoint ptr %vtable to i64 + // CHECK-ADDRESSAUTH: %3 = call i64 @llvm.ptrauth.auth(i64 %2, i32 2, i64 %1) + // CHECK-ADDRESSAUTH: %4 = inttoptr i64 %3 to ptr + // CHECK-ADDRESSAUTH: %5 = load volatile i8, ptr %4, align 8 + // CHECK-BOTHAUTH: [[T2:%.*]] = call i64 @llvm.ptrauth.blend(i64 %1, i64 48388) + // CHECK-BOTHAUTH: [[T3:%.*]] = ptrtoint ptr %vtable to i64 + // CHECK-BOTHAUTH: [[T4:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[T3]], i32 2, i64 [[T2]]) + // CHECK-BOTHAUTH: [[T5:%.*]] = inttoptr i64 [[T4]] to ptr + // CHECK-BOTHAUTH: [[T6:%.*]] = load volatile i8, ptr [[T5]], align 8 +} + +const void *c_as_B(C *o) { + // CHECK-NOAUTH: define ptr @_ZN5test16c_as_BEPNS_1CE(ptr %o) #0 { + return __builtin_get_vtable_pointer((B *)o); + // CHECK-NOAUTH: %add.ptr = getelementptr inbounds i8, ptr %0, i64 8 + // CHECK-NOAUTH: br label %cast.end + // CHECK-NOAUTH: %cast.result = phi ptr [ %add.ptr, %cast.notnull ], [ null, %entry ] + // CHECK-NOAUTH: %vtable = load ptr, ptr %cast.result, align 8 + // CHECK-TYPEAUTH: %cast.result = phi ptr [ %add.ptr, %cast.notnull ], [ null, %entry ] + // CHECK-TYPEAUTH: %vtable = load ptr, ptr %cast.result, align 8 + // CHECK-TYPEAUTH: %2 = ptrtoint ptr %vtable to i64 + // CHECK-TYPEAUTH: %3 = call i64 @llvm.ptrauth.auth(i64 %2, i32 2, i64 48388) + // CHECK-TYPEAUTH: %4 = inttoptr i64 %3 to ptr + // CHECK-TYPEAUTH: %5 = load volatile i8, ptr %4, align 8 + // CHECK-ADDRESSAUTH: %2 = ptrtoint ptr %cast.result to i64 + // CHECK-ADDRESSAUTH: %3 = ptrtoint ptr %vtable to i64 + // CHECK-ADDRESSAUTH: %4 = call i64 @llvm.ptrauth.auth(i64 %3, i32 2, i64 %2) + // CHECK-ADDRESSAUTH: %5 = inttoptr i64 %4 to ptr + // CHECK-ADDRESSAUTH: %6 = load volatile i8, ptr %5, align 8 + // CHECK-BOTHAUTH: [[T2:%.*]] = call i64 @llvm.ptrauth.blend(i64 %2, i64 48388) + // CHECK-BOTHAUTH: [[T3:%.*]] = ptrtoint ptr %vtable to i64 + // CHECK-BOTHAUTH: [[T4:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[T3]], i32 2, i64 [[T2]]) + // CHECK-BOTHAUTH: [[T5:%.*]] = inttoptr i64 [[T4]] to ptr + // CHECK-BOTHAUTH: [[T6:%.*]] = load volatile i8, ptr [[T5]], align 8 +} + +const void *d(D *o) { + // CHECK-NOAUTH: define ptr @_ZN5test11dEPNS_1DE(ptr %o) #0 { + return __builtin_get_vtable_pointer(o); + // CHECK-NOAUTH: %vtable = load ptr, ptr %0, align 8 + // CHECK-TYPEAUTH: %vtable = load ptr, ptr %0, align 8 + // CHECK-TYPEAUTH: %1 = ptrtoint ptr %vtable to i64 + // CHECK-TYPEAUTH: %2 = call i64 @llvm.ptrauth.auth(i64 %1, i32 2, i64 48388) + // CHECK-TYPEAUTH: %3 = inttoptr i64 %2 to ptr + // CHECK-TYPEAUTH: %4 = load volatile i8, ptr %3, align 8 + // CHECK-ADDRESSAUTH: %1 = ptrtoint ptr %0 to i64 + // CHECK-ADDRESSAUTH: %2 = ptrtoint ptr %vtable to i64 + // CHECK-ADDRESSAUTH: %3 = call i64 @llvm.ptrauth.auth(i64 %2, i32 2, i64 %1) + // CHECK-ADDRESSAUTH: %4 = inttoptr i64 %3 to ptr + // CHECK-ADDRESSAUTH: %5 = load volatile i8, ptr %4, align 8 + // CHECK-BOTHAUTH: [[T1:%.*]] = ptrtoint ptr %0 to i64 + // CHECK-BOTHAUTH: [[T2:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T1]], i64 48388) + // CHECK-BOTHAUTH: [[T3:%.*]] = ptrtoint ptr %vtable to i64 + // CHECK-BOTHAUTH: [[T4:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[T3]], i32 2, i64 [[T2]]) + // CHECK-BOTHAUTH: [[T5:%.*]] = inttoptr i64 [[T4]] to ptr + // CHECK-BOTHAUTH: [[T6:%.*]] = load volatile i8, ptr [[T5]], align 8 +} + +const void *d_as_A(D *o) { + // CHECK-NOAUTH: define ptr @_ZN5test16d_as_AEPNS_1DE(ptr %o... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/135469 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits