Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
53a6590
Update the docs
atrosinenko Oct 21, 2025
d5c907b
Support three-operand call bundle as an option
atrosinenko Oct 10, 2025
9f7b13f
Support D-keys in auth call pseudos
atrosinenko Oct 21, 2025
dd6dc25
Switch ptrauth_strip to bundles
atrosinenko Oct 22, 2025
280fe0f
--> deactivation-symbol Switch auth/sign/resign to bundles
atrosinenko Oct 24, 2025
00b6349
More fixes for deactivation symbols after rebase
atrosinenko Dec 3, 2025
fe2adda
Update the tests in preparation for dropping blend() calls
atrosinenko Oct 28, 2025
4288098
Do not emit blend() in frontend-generated code
atrosinenko Oct 27, 2025
ea798a7
Do not emit temporary blend intrinsic when processing builtins
atrosinenko Oct 29, 2025
af616a9
libunwind: do not store the result of blend() to temporaries
atrosinenko Nov 7, 2025
8847b2d
Normalize operands of ptrauth bundle
atrosinenko Oct 30, 2025
3aef7e3
Fix ConstantPtrAuth::isKnownCompatibleWith
atrosinenko Oct 31, 2025
7b8adca
Removing compatibility hacks from ISel
atrosinenko Oct 31, 2025
30aa963
Update InstCombine tests
atrosinenko Oct 31, 2025
0b8df8c
Implement auto-upgrade
atrosinenko Oct 31, 2025
47b92c7
Upgrade key operand of ptrauth bundle to i64
atrosinenko Nov 6, 2025
1a26e4e
Upgrade various tests
atrosinenko Nov 6, 2025
621dc28
CGPointerAuthInfo: use null discriminator components by default
atrosinenko Nov 6, 2025
d314ed4
Update Verifier and fix the test
atrosinenko Nov 6, 2025
7a1cc15
Add negative test cases for auto-upgrading of ptrauth
atrosinenko Nov 7, 2025
0d0073d
Check that unused llvm.ptrauth.blend is silently eliminated
atrosinenko Nov 7, 2025
b744611
Misc cleanup
atrosinenko Nov 10, 2025
238e726
WIP: [LLVM] Adjust ptrauth operand bundles
atrosinenko Nov 11, 2025
5160d99
LLVM: more cleanups
atrosinenko Nov 12, 2025
804a5b5
WIP: Clang: misc cleanup
atrosinenko Nov 12, 2025
2020667
IMPORTANT FIX: add earlyclobber constraint to AUTxMxN
atrosinenko Nov 13, 2025
f84201d
Add/update InstCombine test cases
atrosinenko Nov 13, 2025
31f049f
Fix target-specific bundle validation and add tests
atrosinenko Dec 3, 2025
1715021
Clarify the FIXME in EmitLoadOfMemberFunctionPointer
atrosinenko Dec 4, 2025
43b31fe
Update validatePtrAuthBundles
atrosinenko Dec 11, 2025
7f9ac25
WIP: Make ConstantPtrAuth target-neutral
atrosinenko Dec 10, 2025
882d499
WIP: More changes to bitcode I/O
atrosinenko Dec 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 53 additions & 20 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5622,43 +5622,79 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
case Builtin::BI__builtin_ptrauth_sign_constant:
return RValue::get(ConstantEmitter(*this).emitAbstract(E, E->getType()));

case Builtin::BI__builtin_ptrauth_blend_discriminator: {
CGM.Error(E->getExprLoc(), "Standalone blend builtin is not supported");
llvm::Type *Ty = ConvertType(E->getType());
return RValue::get(llvm::UndefValue::get(Ty));
}

case Builtin::BI__builtin_ptrauth_auth:
case Builtin::BI__builtin_ptrauth_auth_and_resign:
case Builtin::BI__builtin_ptrauth_blend_discriminator:
case Builtin::BI__builtin_ptrauth_sign_generic_data:
case Builtin::BI__builtin_ptrauth_sign_unauthenticated:
case Builtin::BI__builtin_ptrauth_strip: {
// Emit the arguments.
SmallVector<llvm::Value *, 5> Args;
for (auto argExpr : E->arguments())
Args.push_back(EmitScalarExpr(argExpr));
SmallVector<llvm::Value *, 2> Args;
SmallVector<llvm::OperandBundleDef, 2> OBs;

auto ConvertToInt64 = [&](llvm::Value *V) {
if (V->getType()->isPointerTy())
return Builder.CreatePtrToInt(V, IntPtrTy);
return Builder.CreateZExt(V, IntPtrTy);
};

auto AddPtrAuthBundle = [&](const Expr *KeyExpr, const Expr *DiscrExpr) {
llvm::Value *Key = ConvertToInt64(EmitScalarExpr(KeyExpr));
llvm::Value *IntDiscr = Builder.getInt64(0);
llvm::Value *AddrDiscr = Builder.getInt64(0);

const CallExpr *MaybeBlend = dyn_cast<CallExpr>(DiscrExpr);
if (MaybeBlend && MaybeBlend->getBuiltinCallee() ==
Builtin::BI__builtin_ptrauth_blend_discriminator) {
// Assign modifiers according to blend arguments.
IntDiscr = ConvertToInt64(EmitScalarExpr(MaybeBlend->getArg(1)));
AddrDiscr = ConvertToInt64(EmitScalarExpr(MaybeBlend->getArg(0)));
} else {
// Check if discriminator is a small integer constant and fallback to
// passing an arbitrary raw value otherwise.
llvm::Value *Discr = ConvertToInt64(EmitScalarExpr(DiscrExpr));
llvm::ConstantInt *DiscrConst = dyn_cast<llvm::ConstantInt>(Discr);
if (DiscrConst && isUInt<16>(DiscrConst->getZExtValue()))
IntDiscr = Discr;
else
AddrDiscr = Discr;
}
llvm::Value *Inputs[] = {Key, IntDiscr, AddrDiscr};
OBs.emplace_back("ptrauth", Inputs);
};

// Cast the value to intptr_t, saving its original type.
Args.push_back(EmitScalarExpr(E->getArg(0)));
llvm::Type *OrigValueType = Args[0]->getType();
if (OrigValueType->isPointerTy())
Args[0] = Builder.CreatePtrToInt(Args[0], IntPtrTy);
Args[0] = ConvertToInt64(Args[0]);

switch (BuiltinID) {
default:
llvm_unreachable("bad ptrauth intrinsic");
case Builtin::BI__builtin_ptrauth_auth_and_resign:
if (Args[4]->getType()->isPointerTy())
Args[4] = Builder.CreatePtrToInt(Args[4], IntPtrTy);
[[fallthrough]];
AddPtrAuthBundle(E->getArg(1), E->getArg(2));
AddPtrAuthBundle(E->getArg(3), E->getArg(4));
break;

case Builtin::BI__builtin_ptrauth_auth:
case Builtin::BI__builtin_ptrauth_sign_unauthenticated:
if (Args[2]->getType()->isPointerTy())
Args[2] = Builder.CreatePtrToInt(Args[2], IntPtrTy);
AddPtrAuthBundle(E->getArg(1), E->getArg(2));
break;

case Builtin::BI__builtin_ptrauth_sign_generic_data:
if (Args[1]->getType()->isPointerTy())
Args[1] = Builder.CreatePtrToInt(Args[1], IntPtrTy);
Args.push_back(ConvertToInt64(EmitScalarExpr(E->getArg(1))));
break;

case Builtin::BI__builtin_ptrauth_blend_discriminator:
case Builtin::BI__builtin_ptrauth_strip:
case Builtin::BI__builtin_ptrauth_strip: {
llvm::Value *Key = ConvertToInt64(EmitScalarExpr(E->getArg(1)));
OBs.emplace_back("ptrauth", ArrayRef({Key}));
break;
}
}

// Call the intrinsic.
auto IntrinsicID = [&]() -> unsigned {
Expand All @@ -5667,8 +5703,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
return Intrinsic::ptrauth_auth;
case Builtin::BI__builtin_ptrauth_auth_and_resign:
return Intrinsic::ptrauth_resign;
case Builtin::BI__builtin_ptrauth_blend_discriminator:
return Intrinsic::ptrauth_blend;
case Builtin::BI__builtin_ptrauth_sign_generic_data:
return Intrinsic::ptrauth_sign_generic;
case Builtin::BI__builtin_ptrauth_sign_unauthenticated:
Expand All @@ -5679,10 +5713,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
llvm_unreachable("bad ptrauth intrinsic");
}();
auto Intrinsic = CGM.getIntrinsic(IntrinsicID);
llvm::Value *Result = EmitRuntimeCall(Intrinsic, Args);
llvm::Value *Result = EmitRuntimeCall(Intrinsic, Args, OBs);

if (BuiltinID != Builtin::BI__builtin_ptrauth_sign_generic_data &&
BuiltinID != Builtin::BI__builtin_ptrauth_blend_discriminator &&
OrigValueType->isPointerTy()) {
Result = Builder.CreateIntToPtr(Result, OrigValueType);
}
Expand Down
13 changes: 12 additions & 1 deletion clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5039,10 +5039,21 @@ CodeGenFunction::getBundlesForFunclet(llvm::Value *Callee) {
llvm::CallInst *CodeGenFunction::EmitRuntimeCall(llvm::FunctionCallee callee,
ArrayRef<llvm::Value *> args,
const llvm::Twine &name) {
return EmitRuntimeCall(callee, args, {}, name);
}

llvm::CallInst *CodeGenFunction::EmitRuntimeCall(
llvm::FunctionCallee callee, ArrayRef<llvm::Value *> args,
ArrayRef<llvm::OperandBundleDef> extraBundles, const Twine &name) {
SmallVector<llvm::OperandBundleDef, 3> allBundles;
llvm::append_range(allBundles, getBundlesForFunclet(callee.getCallee()));
llvm::append_range(allBundles, extraBundles);
llvm::CallInst *call = Builder.CreateCall(
callee, args, getBundlesForFunclet(callee.getCallee()), name);
callee, args, allBundles, name);
call->setCallingConv(getRuntimeCC());

// FIXME Attach "convergencectrl" bundle right away instead of re-creating

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please refer me to the tests which trigger this convergence-related condition?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried adding an assertion that the result of cast<llvm::CallInst>(addConvergenceControlToken(call)) equals to call (which should fail on the condition mentioned in this FIXME), here is the list of tests:

  Clang :: CodeGenHLSL/GlobalDestructors.hlsl
  Clang :: CodeGenHLSL/builtins/GroupMemoryBarrierWithGroupSync.hlsl
  Clang :: CodeGenHLSL/builtins/WaveActiveAllTrue.hlsl
  Clang :: CodeGenHLSL/builtins/WaveActiveAnyTrue.hlsl
  Clang :: CodeGenHLSL/builtins/WaveActiveCountBits.hlsl
  Clang :: CodeGenHLSL/builtins/WaveActiveMax.hlsl
  Clang :: CodeGenHLSL/builtins/WaveActiveMin.hlsl
  Clang :: CodeGenHLSL/builtins/WaveActiveSum.hlsl
  Clang :: CodeGenHLSL/builtins/WaveReadLaneAt.hlsl
  Clang :: CodeGenHLSL/builtins/wave_get_lane_count.hlsl
  Clang :: CodeGenHLSL/builtins/wave_get_lane_index_do_while.hlsl
  Clang :: CodeGenHLSL/builtins/wave_get_lane_index_simple.hlsl
  Clang :: CodeGenHLSL/builtins/wave_get_lane_index_subcall.hlsl
  Clang :: CodeGenHLSL/builtins/wave_is_first_lane.hlsl
  Clang :: CodeGenHLSL/convergence/global_array.hlsl
  Clang :: CodeGenHLSL/resources/RWBuffer-constructor-opt.hlsl
  Clang :: CodeGenHLSL/resources/RWBuffer-imageformat.hlsl
  Clang :: CodeGenHLSL/resources/StructuredBuffers-constructors.hlsl
  Clang :: CodeGenHLSL/resources/StructuredBuffers-elementtype.hlsl
  Clang :: CodeGenHLSL/resources/StructuredBuffers-subscripts.hlsl
  Clang :: CodeGenHLSL/resources/TypedBuffers-elementtype.hlsl
  Clang :: CodeGenHLSL/resources/TypedBuffers-subscript.hlsl
  Clang :: CodeGenHLSL/resources/default_cbuffer.hlsl
  Clang :: CodeGenHLSL/resources/res-array-global-multi-dim.hlsl
  Clang :: CodeGenHLSL/resources/res-array-global-unbounded.hlsl
  Clang :: CodeGenHLSL/resources/res-array-global.hlsl
  Clang :: CodeGenHLSL/vk-features/vk.spec-constant.hlsl
  Clang :: CodeGenHLSL/vk-input-builtin.hlsl
  Clang :: CodeGenHLSL/vk_binding_attr.hlsl

// the call instruction.
if (CGM.shouldEmitConvergenceTokens() && call->isConvergent())
return cast<llvm::CallInst>(addConvergenceControlToken(call));
return call;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGClass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2775,7 +2775,7 @@ llvm::Value *CodeGenFunction::GetVTablePtr(Address This,
} else {
VTable = cast<llvm::Instruction>(EmitPointerAuthAuth(
CGPointerAuthInfo(0, PointerAuthenticationMode::Strip, false, false,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not directly related to this PR, but might be a subject for change: it looks like that PointerAuthenticationMode::SignAndStrip is not used at all. I wonder if there are some use cases for that or if it could be safely removed (because for me it now looks like that we just have some dead code which is not used anywhere and is not covered by any tests; but I might be wrong)

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(link added to the description)

nullptr),
0, nullptr),
VTable));
}
}
Expand Down
4 changes: 1 addition & 3 deletions clang/lib/CodeGen/CGExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2227,9 +2227,7 @@ ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {
return ConstantLValue(nullptr);

C = applyOffset(C);
C = CGM.getConstantSignedPointer(
C, AuthInfo.getKey(), nullptr,
cast_or_null<llvm::ConstantInt>(AuthInfo.getDiscriminator()));
C = CGM.getConstantSignedPointer(C, AuthInfo);
return ConstantLValue(C, /*applied offset*/ true, /*signed*/ true);
}

Expand Down
Loading