Index: llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp +++ llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp @@ -64,6 +64,16 @@ using namespace llvm; +enum PtrauthCheckMode { Default, Unchecked, Poison, Trap }; +static cl::opt +PtrauthAuthChecks("aarch64-ptrauth-auth-checks", cl::Hidden, + cl::values( + clEnumValN(Unchecked, "none", "don't test for failure"), + clEnumValN(Poison, "poison", "poison on failure"), + clEnumValN(Trap, "trap", "trap on failure")), + cl::desc("Check pointer authentication auth/resign failures"), + cl::init(Default)); + #define DEBUG_TYPE "asm-printer" namespace { @@ -116,6 +126,12 @@ void emitSled(const MachineInstr &MI, SledKind Kind); + // Emit the sequence for AUT or AUTPAC. + void emitPtrauthAuthResign(const MachineInstr *MI); + // Emit the sequence to compute a discriminator into x17, or reuse AddrDisc. + unsigned emitPtrauthDiscriminator(uint16_t Disc, unsigned AddrDisc, + unsigned &InstsEmitted); + /// tblgen'erated driver function for lowering simple MI->MC /// pseudo instructions. bool emitPseudoExpansionLowering(MCStreamer &OutStreamer, @@ -1167,6 +1183,257 @@ } } +unsigned AArch64AsmPrinter::emitPtrauthDiscriminator(uint16_t Disc, + unsigned AddrDisc, + unsigned &InstsEmitted) { + // If there is no constant discriminator, there's no blend involved: + // just use the address discriminator register as-is (XZR or not). + if (!Disc) + return AddrDisc; + + // If there's only a constant discriminator, MOV it into x17. + if (AddrDisc == AArch64::XZR) { + EmitToStreamer(*OutStreamer, + MCInstBuilder(AArch64::MOVZXi) + .addReg(AArch64::X17) + .addImm(Disc) + .addImm(/*shift=*/0)); + ++InstsEmitted; + return AArch64::X17; + } + + // If there are both, emit a blend into x17. + EmitToStreamer(*OutStreamer, + MCInstBuilder(AArch64::ORRXrs) + .addReg(AArch64::X17) + .addReg(AArch64::XZR) + .addReg(AddrDisc) + .addImm(0)); + ++InstsEmitted; + EmitToStreamer(*OutStreamer, + MCInstBuilder(AArch64::MOVKXi) + .addReg(AArch64::X17) + .addReg(AArch64::X17) + .addImm(Disc) + .addImm(/*shift=*/48)); + ++InstsEmitted; + return AArch64::X17; +} + +void AArch64AsmPrinter::emitPtrauthAuthResign(const MachineInstr *MI) { + unsigned InstsEmitted = 0; + const bool IsAUTPAC = MI->getOpcode() == AArch64::AUTPAC; + + // We can expand AUT/AUTPAC into 3 possible sequences: + // - unchecked: + // autia x16, x0 + // pacib x16, x1 ; if AUTPAC + // + // - checked and clearing: + // mov x17, x0 + // movk x17, #disc, lsl #48 + // autia x16, x17 + // mov x17, x16 + // xpaci x17 + // cmp x16, x17 + // b.eq Lsuccess + // mov x16, x17 + // b Lend + // Lsuccess: + // mov x17, x1 + // movk x17, #disc, lsl #48 + // pacib x16, x17 + // Lend: + // Where we only emit the AUT if we started with an AUT. + // + // - checked and trapping: + // mov x17, x0 + // movk x17, #disc, lsl #48 + // autia x16, x0 + // mov x17, x16 + // xpaci x17 + // cmp x16, x17 + // b.eq Lsuccess + // brk #<0xc470 + aut key> + // Lsuccess: + // mov x17, x1 + // movk x17, #disc, lsl #48 + // pacib x16, x17 ; if AUTPAC + // Where the b.eq skips over the trap if the PAC is valid. + // + // This sequence is expensive, but we need more information to be able to + // do better. + // + // We can't TBZ the poison bit because EnhancedPAC2 XORs the PAC bits + // on failure. + // We can't TST the PAC bits because we don't always know how the address + // space is setup for the target environment (and the bottom PAC bit is + // based on that). + // Either way, we also don't always know whether TBI is enabled or not for + // the specific target environment. + + // By default, auth/resign sequences check for auth failures. + bool ShouldCheck = true; + // In the checked sequence, we only trap if explicitly requested. + bool ShouldTrap = MF->getFunction().hasFnAttribute("ptrauth-auth-traps"); + + // However, command-line flags can override this, for experimentation. + switch (PtrauthAuthChecks) { + case PtrauthCheckMode::Default: break; + case PtrauthCheckMode::Unchecked: + ShouldCheck = ShouldTrap = false; + break; + case PtrauthCheckMode::Poison: + ShouldCheck = true; + ShouldTrap = false; + break; + case PtrauthCheckMode::Trap: + ShouldCheck = ShouldTrap = true; + break; + } + + auto AUTKey = (AArch64PACKey::ID)MI->getOperand(0).getImm(); + uint64_t AUTDisc = MI->getOperand(1).getImm(); + unsigned AUTAddrDisc = MI->getOperand(2).getReg(); + + unsigned XPACOpc = getXPACOpcodeForKey(AUTKey); + + // Compute aut discriminator into x17 + assert(isUInt<16>(AUTDisc)); + unsigned AUTDiscReg = emitPtrauthDiscriminator(AUTDisc, AUTAddrDisc, InstsEmitted); + bool AUTZero = AUTDiscReg == AArch64::XZR; + unsigned AUTOpc = getAUTOpcodeForKey(AUTKey, AUTZero); + + // autiza x16 ; if AUTZero + // autia x16, x17 ; if !AUTZero + MCInst AUTInst; + AUTInst.setOpcode(AUTOpc); + AUTInst.addOperand(MCOperand::createReg(AArch64::X16)); + AUTInst.addOperand(MCOperand::createReg(AArch64::X16)); + if (!AUTZero) + AUTInst.addOperand(MCOperand::createReg(AUTDiscReg)); + EmitToStreamer(*OutStreamer, AUTInst); + ++InstsEmitted; + + // Unchecked or checked-but-non-trapping AUT is just an "AUT": we're done. + if (!IsAUTPAC && (!ShouldCheck || !ShouldTrap)) { + assert(STI->getInstrInfo()->getInstSizeInBytes(*MI) >= InstsEmitted * 4); + return; + } + + MCSymbol *EndSym = nullptr; + + // Checked sequences do an additional strip-and-compare. + if (ShouldCheck) { + MCSymbol *SuccessSym = createTempSymbol("auth_success_"); + + // XPAC has tied src/dst: use x17 as a temporary copy. + // mov x17, x16 + EmitToStreamer(*OutStreamer, + MCInstBuilder(AArch64::ORRXrs) + .addReg(AArch64::X17) + .addReg(AArch64::XZR) + .addReg(AArch64::X16) + .addImm(0)); + ++InstsEmitted; + + // xpaci x17 + EmitToStreamer(*OutStreamer, + MCInstBuilder(XPACOpc) + .addReg(AArch64::X17) + .addReg(AArch64::X17)); + ++InstsEmitted; + + // cmp x16, x17 + EmitToStreamer(*OutStreamer, + MCInstBuilder(AArch64::SUBSXrs) + .addReg(AArch64::XZR) + .addReg(AArch64::X16) + .addReg(AArch64::X17) + .addImm(0)); + ++InstsEmitted; + + // b.eq Lsuccess + EmitToStreamer(*OutStreamer, + MCInstBuilder(AArch64::Bcc) + .addImm(AArch64CC::EQ) + .addExpr(MCSymbolRefExpr::create(SuccessSym, OutContext))); + ++InstsEmitted; + + if (ShouldTrap) { + // Trapping sequences do a 'brk'. + // brk #<0xc470 + aut key> + EmitToStreamer(*OutStreamer, + MCInstBuilder(AArch64::BRK) + .addImm(0xc470 | AUTKey)); + ++InstsEmitted; + } else { + // Non-trapping checked sequences return the stripped result in x16, + // skipping over the PAC if there is one. + + // FIXME: can we simply return the AUT result, already in x16? without.. + // ..traps this is usable as an oracle anyway, based on high bits + // mov x17, x16 + EmitToStreamer(*OutStreamer, + MCInstBuilder(AArch64::ORRXrs) + .addReg(AArch64::X16) + .addReg(AArch64::XZR) + .addReg(AArch64::X17) + .addImm(0)); + ++InstsEmitted; + + if (IsAUTPAC) { + EndSym = createTempSymbol("resign_end_"); + + // b Lend + EmitToStreamer(*OutStreamer, + MCInstBuilder(AArch64::B) + .addExpr(MCSymbolRefExpr::create(EndSym, OutContext))); + ++InstsEmitted; + } + } + + // If the auth check succeeds, we can continue. + // Lsuccess: + OutStreamer->emitLabel(SuccessSym); + } + + // We already emitted unchecked and checked-but-non-trapping AUTs. + // That left us with trapping AUTs, and AUTPACs. + // Trapping AUTs don't need PAC: we're done. + if (!IsAUTPAC) { + assert(STI->getInstrInfo()->getInstSizeInBytes(*MI) >= InstsEmitted * 4); + return; + } + + auto PACKey = (AArch64PACKey::ID)MI->getOperand(3).getImm(); + uint64_t PACDisc = MI->getOperand(4).getImm(); + unsigned PACAddrDisc = MI->getOperand(5).getReg(); + + // Compute pac discriminator into x17 + assert(isUInt<16>(PACDisc)); + unsigned PACDiscReg = + emitPtrauthDiscriminator(PACDisc, PACAddrDisc, InstsEmitted); + bool PACZero = PACDiscReg == AArch64::XZR; + unsigned PACOpc = getPACOpcodeForKey(PACKey, PACZero); + + // pacizb x16 ; if PACZero + // pacib x16, x17 ; if !PACZero + MCInst PACInst; + PACInst.setOpcode(PACOpc); + PACInst.addOperand(MCOperand::createReg(AArch64::X16)); + PACInst.addOperand(MCOperand::createReg(AArch64::X16)); + if (!PACZero) + PACInst.addOperand(MCOperand::createReg(PACDiscReg)); + EmitToStreamer(*OutStreamer, PACInst); + ++InstsEmitted; + + assert(STI->getInstrInfo()->getInstSizeInBytes(*MI) >= InstsEmitted * 4); + // Lend: + if (EndSym) + OutStreamer->emitLabel(EndSym); +} + // Simple pseudo-instructions have their lowering (with expansion to real // instructions) auto-generated. #include "AArch64GenMCPseudoLowering.inc" @@ -1297,6 +1564,11 @@ return; } + case AArch64::AUT: + case AArch64::AUTPAC: + emitPtrauthAuthResign(MI); + return; + // Tail calls use pseudo instructions so they have the proper code-gen // attributes (isCall, isReturn, etc.). We lower them to the real // instruction here. Index: llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp =================================================================== --- llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp +++ llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp @@ -317,6 +317,9 @@ bool tryIndexedLoad(SDNode *N); + void SelectPtrauthAuth(SDNode *N); + void SelectPtrauthResign(SDNode *N); + bool trySelectStackSlotTagP(SDNode *N); void SelectTagP(SDNode *N); @@ -1378,6 +1381,96 @@ ReplaceNode(N, CurDAG->getMachineNode(Opc, dl, VT, Ops)); } +static std::tuple +extractPtrauthBlendDiscriminators(SDValue Disc, SelectionDAG *DAG) { + SDLoc DL(Disc); + SDValue AddrDisc; + SDValue ConstDisc; + + // If this is a blend, remember the constant and address discriminators. + // Otherwise, it's either a constant discriminator, or a non-blended + // address discriminator. + if (Disc->getOpcode() == ISD::INTRINSIC_WO_CHAIN && + Disc->getConstantOperandVal(0) == Intrinsic::ptrauth_blend) { + AddrDisc = Disc->getOperand(1); + ConstDisc = Disc->getOperand(2); + } else { + ConstDisc = Disc; + } + + // If the constant discriminator (either the blend RHS, or the entire + // discriminator value) isn't a 16-bit constant, bail out, and let the + // discriminator be computed separately. + auto *ConstDiscN = dyn_cast(ConstDisc); + if (!ConstDiscN || !isUInt<16>(ConstDiscN->getZExtValue())) + return std::make_tuple(DAG->getTargetConstant(0, DL, MVT::i64), Disc); + + // If there's no address discriminator, use XZR directly. + if (!AddrDisc) + AddrDisc = DAG->getRegister(AArch64::XZR, MVT::i64); + + return std::make_tuple( + DAG->getTargetConstant(ConstDiscN->getZExtValue(), DL, MVT::i64), + AddrDisc); +} + +void AArch64DAGToDAGISel::SelectPtrauthAuth(SDNode *N) { + SDLoc DL(N); + // IntrinsicID is operand #0 + SDValue Val = N->getOperand(1); + SDValue AUTKey = N->getOperand(2); + SDValue AUTDisc = N->getOperand(3); + + unsigned AUTKeyC = cast(AUTKey)->getZExtValue(); + AUTKey = CurDAG->getTargetConstant(AUTKeyC, DL, MVT::i64); + + SDValue AUTAddrDisc, AUTConstDisc; + std::tie(AUTConstDisc, AUTAddrDisc) = + extractPtrauthBlendDiscriminators(AUTDisc, CurDAG); + + SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(), DL, + AArch64::X16, Val, SDValue()); + SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc, X16Copy.getValue(1)}; + + SDNode *AUT = CurDAG->getMachineNode(AArch64::AUT, DL, MVT::i64, Ops); + ReplaceNode(N, AUT); + return; +} + +void AArch64DAGToDAGISel::SelectPtrauthResign(SDNode *N) { + SDLoc DL(N); + // IntrinsicID is operand #0 + SDValue Val = N->getOperand(1); + SDValue AUTKey = N->getOperand(2); + SDValue AUTDisc = N->getOperand(3); + SDValue PACKey = N->getOperand(4); + SDValue PACDisc = N->getOperand(5); + + unsigned AUTKeyC = cast(AUTKey)->getZExtValue(); + unsigned PACKeyC = cast(PACKey)->getZExtValue(); + + AUTKey = CurDAG->getTargetConstant(AUTKeyC, DL, MVT::i64); + PACKey = CurDAG->getTargetConstant(PACKeyC, DL, MVT::i64); + + SDValue AUTAddrDisc, AUTConstDisc; + std::tie(AUTConstDisc, AUTAddrDisc) = + extractPtrauthBlendDiscriminators(AUTDisc, CurDAG); + + SDValue PACAddrDisc, PACConstDisc; + std::tie(PACConstDisc, PACAddrDisc) = + extractPtrauthBlendDiscriminators(PACDisc, CurDAG); + + SDValue X16Copy = CurDAG->getCopyToReg(CurDAG->getEntryNode(), DL, + AArch64::X16, Val, SDValue()); + + SDValue Ops[] = {AUTKey, AUTConstDisc, AUTAddrDisc, PACKey, + PACConstDisc, PACAddrDisc, X16Copy.getValue(1)}; + + SDNode *AUTPAC = CurDAG->getMachineNode(AArch64::AUTPAC, DL, MVT::i64, Ops); + ReplaceNode(N, AUTPAC); + return; +} + bool AArch64DAGToDAGISel::tryIndexedLoad(SDNode *N) { LoadSDNode *LD = cast(N); if (LD->isUnindexed()) @@ -4137,6 +4230,15 @@ if (tryMULLV64LaneV128(IntNo, Node)) return; break; + + case Intrinsic::ptrauth_auth: + SelectPtrauthAuth(Node); + return; + + case Intrinsic::ptrauth_resign: + SelectPtrauthResign(Node); + return; + } break; } Index: llvm/lib/Target/AArch64/AArch64InstrInfo.td =================================================================== --- llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -1391,6 +1391,36 @@ defm LDRAA : AuthLoad<0, "ldraa", simm10Scaled>; defm LDRAB : AuthLoad<1, "ldrab", simm10Scaled>; + // AUT pseudo. + // This directly manipulates x16/x17, which are the only registers the OS + // guarantees are safe to use for sensitive operations. + def AUT : Pseudo<(outs), (ins i32imm:$Key, i64imm:$Disc, GPR64noip:$AddrDisc), + []>, Sched<[WriteI, ReadI]> { + let isCodeGenOnly = 1; + let hasSideEffects = 1; + let mayStore = 0; + let mayLoad = 0; + let Size = 32; + let Defs = [X16,X17,NZCV]; + let Uses = [X16]; + } + + // AUT and re-PAC a value, using different keys/data. + // This directly manipulates x16/x17, which are the only registers the OS + // guarantees are safe to use for sensitive operations. + def AUTPAC + : Pseudo<(outs), + (ins i32imm:$AUTKey, i64imm:$AUTDisc, GPR64noip:$AUTAddrDisc, + i32imm:$PACKey, i64imm:$PACDisc, GPR64noip:$PACAddrDisc), + []>, Sched<[WriteI, ReadI]> { + let isCodeGenOnly = 1; + let hasSideEffects = 1; + let mayStore = 0; + let mayLoad = 0; + let Size = 48; + let Defs = [X16,X17,NZCV]; + let Uses = [X16]; + } } // v8.3a floating point conversion for javascript Index: llvm/lib/Target/AArch64/GISel/AArch64GlobalISelUtils.h =================================================================== --- llvm/lib/Target/AArch64/GISel/AArch64GlobalISelUtils.h +++ llvm/lib/Target/AArch64/GISel/AArch64GlobalISelUtils.h @@ -53,6 +53,12 @@ /// \returns true if \p MI was replaced with a G_BZERO. bool tryEmitBZero(MachineInstr &MI, MachineIRBuilder &MIRBuilder, bool MinSize); +/// Analyze a ptrauth discriminator value to try to find the constant integer +/// and address parts, cracking a ptrauth_blend intrinsic if there is one. +/// \returns integer/address disc. parts, with NoRegister if no address disc. +std::tuple +extractPtrauthBlendDiscriminators(Register Disc, MachineRegisterInfo &MRI); + /// Find the AArch64 condition codes necessary to represent \p P for a scalar /// floating point comparison. /// Index: llvm/lib/Target/AArch64/GISel/AArch64GlobalISelUtils.cpp =================================================================== --- llvm/lib/Target/AArch64/GISel/AArch64GlobalISelUtils.cpp +++ llvm/lib/Target/AArch64/GISel/AArch64GlobalISelUtils.cpp @@ -96,6 +96,35 @@ return true; } +std::tuple +AArch64GISelUtils::extractPtrauthBlendDiscriminators(Register Disc, + MachineRegisterInfo &MRI) { + Register AddrDisc = Disc; + uint16_t ConstDisc = 0; + + if (auto ConstDiscVal = getIConstantVRegVal(Disc, MRI)) { + if (isUInt<16>(ConstDiscVal->getZExtValue())) { + ConstDisc = ConstDiscVal->getZExtValue(); + AddrDisc = AArch64::XZR; + } + return std::make_tuple(ConstDisc, AddrDisc); + } + + auto *DiscMI = MRI.getVRegDef(Disc); + if (!DiscMI || DiscMI->getOpcode() != TargetOpcode::G_INTRINSIC || + DiscMI->getOperand(1).getIntrinsicID() != Intrinsic::ptrauth_blend) + return std::make_tuple(ConstDisc, AddrDisc); + + if (auto ConstDiscVal = + getIConstantVRegVal(DiscMI->getOperand(3).getReg(), MRI)) { + if (isUInt<16>(ConstDiscVal->getZExtValue())) { + ConstDisc = ConstDiscVal->getZExtValue(); + AddrDisc = DiscMI->getOperand(2).getReg(); + } + } + return std::make_tuple(ConstDisc, AddrDisc); +} + void AArch64GISelUtils::changeFCMPPredToAArch64CC( const CmpInst::Predicate P, AArch64CC::CondCode &CondCode, AArch64CC::CondCode &CondCode2) { Index: llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp =================================================================== --- llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp +++ llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp @@ -5867,6 +5867,64 @@ I.eraseFromParent(); return true; } + case Intrinsic::ptrauth_resign: { + Register DstReg = I.getOperand(0).getReg(); + Register ValReg = I.getOperand(2).getReg(); + uint64_t AUTKey = I.getOperand(3).getImm(); + Register AUTDisc = I.getOperand(4).getReg(); + uint64_t PACKey = I.getOperand(5).getImm(); + Register PACDisc = I.getOperand(6).getReg(); + + Register AUTAddrDisc = AUTDisc; + uint16_t AUTConstDiscC = 0; + std::tie(AUTConstDiscC, AUTAddrDisc) = + extractPtrauthBlendDiscriminators(AUTDisc, MRI); + + Register PACAddrDisc = PACDisc; + uint16_t PACConstDiscC = 0; + std::tie(PACConstDiscC, PACAddrDisc) = + extractPtrauthBlendDiscriminators(PACDisc, MRI); + + MIB.buildCopy({AArch64::X16}, {ValReg}); + MIB.buildInstr(TargetOpcode::IMPLICIT_DEF, {AArch64::X17}, {}); + MIB.buildInstr(AArch64::AUTPAC) + .addImm(AUTKey) + .addImm(AUTConstDiscC) + .addUse(AUTAddrDisc) + .addImm(PACKey) + .addImm(PACConstDiscC) + .addUse(PACAddrDisc) + .constrainAllUses(TII, TRI, RBI); + MIB.buildCopy({DstReg}, Register(AArch64::X16)); + + RBI.constrainGenericRegister(DstReg, AArch64::GPR64RegClass, MRI); + I.eraseFromParent(); + return true; + } + case Intrinsic::ptrauth_auth: { + Register DstReg = I.getOperand(0).getReg(); + Register ValReg = I.getOperand(2).getReg(); + uint64_t AUTKey = I.getOperand(3).getImm(); + Register AUTDisc = I.getOperand(4).getReg(); + + Register AUTAddrDisc = AUTDisc; + uint16_t AUTConstDiscC = 0; + std::tie(AUTConstDiscC, AUTAddrDisc) = + extractPtrauthBlendDiscriminators(AUTDisc, MRI); + + MIB.buildCopy({AArch64::X16}, {ValReg}); + MIB.buildInstr(TargetOpcode::IMPLICIT_DEF, {AArch64::X17}, {}); + MIB.buildInstr(AArch64::AUT) + .addImm(AUTKey) + .addImm(AUTConstDiscC) + .addUse(AUTAddrDisc) + .constrainAllUses(TII, TRI, RBI); + MIB.buildCopy({DstReg}, Register(AArch64::X16)); + + RBI.constrainGenericRegister(DstReg, AArch64::GPR64RegClass, MRI); + I.eraseFromParent(); + return true; + } case Intrinsic::ptrauth_blend: { MachineFunction &MF = *I.getParent()->getParent(); auto RHS = getIConstantVRegVal(I.getOperand(3).getReg(), MRI); Index: llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign-with-blend.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign-with-blend.ll @@ -0,0 +1,284 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel=0 -verify-machineinstrs \ +; RUN: -aarch64-ptrauth-auth-checks=none | FileCheck %s --check-prefixes=UNCHECKED,SDAG-UNCHECKED +; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN: -aarch64-ptrauth-auth-checks=none | FileCheck %s --check-prefixes=UNCHECKED,GISEL-UNCHECKED + +; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel=0 -verify-machineinstrs \ +; RUN: | FileCheck %s --check-prefixes=CHECKED,SDAG-CHECKED +; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN: | FileCheck %s --check-prefixes=CHECKED,GISEL-CHECKED + +; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel=0 -verify-machineinstrs \ +; RUN: -aarch64-ptrauth-auth-checks=trap | FileCheck %s --check-prefixes=TRAP,SDAG-TRAP +; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN: -aarch64-ptrauth-auth-checks=trap | FileCheck %s --check-prefixes=TRAP,GISEL-TRAP + +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + +define i64 @test_auth_blend(i64 %arg, i64 %arg1) { +; UNCHECKED-LABEL: test_auth_blend: +; UNCHECKED: ; %bb.0: +; UNCHECKED-NEXT: mov x16, x0 +; UNCHECKED-NEXT: mov x17, x1 +; UNCHECKED-NEXT: movk x17, #65535, lsl #48 +; UNCHECKED-NEXT: autda x16, x17 +; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: ret +; +; CHECKED-LABEL: test_auth_blend: +; CHECKED: ; %bb.0: +; CHECKED-NEXT: mov x16, x0 +; CHECKED-NEXT: mov x17, x1 +; CHECKED-NEXT: movk x17, #65535, lsl #48 +; CHECKED-NEXT: autda x16, x17 +; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: ret +; +; TRAP-LABEL: test_auth_blend: +; TRAP: ; %bb.0: +; TRAP-NEXT: mov x16, x0 +; TRAP-NEXT: mov x17, x1 +; TRAP-NEXT: movk x17, #65535, lsl #48 +; TRAP-NEXT: autda x16, x17 +; TRAP-NEXT: mov x17, x16 +; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: cmp x16, x17 +; TRAP-NEXT: b.eq Lauth_success_0 +; TRAP-NEXT: brk #0xc472 +; TRAP-NEXT: Lauth_success_0: +; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: ret + %tmp0 = call i64 @llvm.ptrauth.blend(i64 %arg1, i64 65535) + %tmp1 = call i64 @llvm.ptrauth.auth(i64 %arg, i32 2, i64 %tmp0) + ret i64 %tmp1 +} + +define i64 @test_resign_blend(i64 %arg, i64 %arg1, i64 %arg2) { +; UNCHECKED-LABEL: test_resign_blend: +; UNCHECKED: ; %bb.0: +; UNCHECKED-NEXT: mov x16, x0 +; UNCHECKED-NEXT: mov x17, x1 +; UNCHECKED-NEXT: movk x17, #12345, lsl #48 +; UNCHECKED-NEXT: autda x16, x17 +; UNCHECKED-NEXT: mov x17, x2 +; UNCHECKED-NEXT: movk x17, #56789, lsl #48 +; UNCHECKED-NEXT: pacdb x16, x17 +; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: ret +; +; CHECKED-LABEL: test_resign_blend: +; CHECKED: ; %bb.0: +; CHECKED-NEXT: mov x16, x0 +; CHECKED-NEXT: mov x17, x1 +; CHECKED-NEXT: movk x17, #12345, lsl #48 +; CHECKED-NEXT: autda x16, x17 +; CHECKED-NEXT: mov x17, x16 +; CHECKED-NEXT: xpacd x17 +; CHECKED-NEXT: cmp x16, x17 +; CHECKED-NEXT: b.eq Lauth_success_0 +; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: b Lresign_end_0 +; CHECKED-NEXT: Lauth_success_0: +; CHECKED-NEXT: mov x17, x2 +; CHECKED-NEXT: movk x17, #56789, lsl #48 +; CHECKED-NEXT: pacdb x16, x17 +; CHECKED-NEXT: Lresign_end_0: +; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: ret +; +; TRAP-LABEL: test_resign_blend: +; TRAP: ; %bb.0: +; TRAP-NEXT: mov x16, x0 +; TRAP-NEXT: mov x17, x1 +; TRAP-NEXT: movk x17, #12345, lsl #48 +; TRAP-NEXT: autda x16, x17 +; TRAP-NEXT: mov x17, x16 +; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: cmp x16, x17 +; TRAP-NEXT: b.eq Lauth_success_1 +; TRAP-NEXT: brk #0xc472 +; TRAP-NEXT: Lauth_success_1: +; TRAP-NEXT: mov x17, x2 +; TRAP-NEXT: movk x17, #56789, lsl #48 +; TRAP-NEXT: pacdb x16, x17 +; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: ret + %tmp0 = call i64 @llvm.ptrauth.blend(i64 %arg1, i64 12345) + %tmp1 = call i64 @llvm.ptrauth.blend(i64 %arg2, i64 56789) + %tmp2 = call i64 @llvm.ptrauth.resign(i64 %arg, i32 2, i64 %tmp0, i32 3, i64 %tmp1) + ret i64 %tmp2 +} + +define i64 @test_resign_blend_and_const(i64 %arg, i64 %arg1) { +; UNCHECKED-LABEL: test_resign_blend_and_const: +; UNCHECKED: ; %bb.0: +; UNCHECKED-NEXT: mov x16, x0 +; UNCHECKED-NEXT: mov x17, x1 +; UNCHECKED-NEXT: movk x17, #12345, lsl #48 +; UNCHECKED-NEXT: autda x16, x17 +; UNCHECKED-NEXT: mov x17, #56789 +; UNCHECKED-NEXT: pacdb x16, x17 +; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: ret +; +; CHECKED-LABEL: test_resign_blend_and_const: +; CHECKED: ; %bb.0: +; CHECKED-NEXT: mov x16, x0 +; CHECKED-NEXT: mov x17, x1 +; CHECKED-NEXT: movk x17, #12345, lsl #48 +; CHECKED-NEXT: autda x16, x17 +; CHECKED-NEXT: mov x17, x16 +; CHECKED-NEXT: xpacd x17 +; CHECKED-NEXT: cmp x16, x17 +; CHECKED-NEXT: b.eq Lauth_success_1 +; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: b Lresign_end_1 +; CHECKED-NEXT: Lauth_success_1: +; CHECKED-NEXT: mov x17, #56789 +; CHECKED-NEXT: pacdb x16, x17 +; CHECKED-NEXT: Lresign_end_1: +; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: ret +; +; TRAP-LABEL: test_resign_blend_and_const: +; TRAP: ; %bb.0: +; TRAP-NEXT: mov x16, x0 +; TRAP-NEXT: mov x17, x1 +; TRAP-NEXT: movk x17, #12345, lsl #48 +; TRAP-NEXT: autda x16, x17 +; TRAP-NEXT: mov x17, x16 +; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: cmp x16, x17 +; TRAP-NEXT: b.eq Lauth_success_2 +; TRAP-NEXT: brk #0xc472 +; TRAP-NEXT: Lauth_success_2: +; TRAP-NEXT: mov x17, #56789 +; TRAP-NEXT: pacdb x16, x17 +; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: ret + %tmp0 = call i64 @llvm.ptrauth.blend(i64 %arg1, i64 12345) + %tmp1 = call i64 @llvm.ptrauth.resign(i64 %arg, i32 2, i64 %tmp0, i32 3, i64 56789) + ret i64 %tmp1 +} + +define i64 @test_resign_blend_and_addr(i64 %arg, i64 %arg1, i64 %arg2) { +; UNCHECKED-LABEL: test_resign_blend_and_addr: +; UNCHECKED: ; %bb.0: +; UNCHECKED-NEXT: mov x16, x0 +; UNCHECKED-NEXT: mov x17, x1 +; UNCHECKED-NEXT: movk x17, #12345, lsl #48 +; UNCHECKED-NEXT: autda x16, x17 +; UNCHECKED-NEXT: pacdb x16, x2 +; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: ret +; +; CHECKED-LABEL: test_resign_blend_and_addr: +; CHECKED: ; %bb.0: +; CHECKED-NEXT: mov x16, x0 +; CHECKED-NEXT: mov x17, x1 +; CHECKED-NEXT: movk x17, #12345, lsl #48 +; CHECKED-NEXT: autda x16, x17 +; CHECKED-NEXT: mov x17, x16 +; CHECKED-NEXT: xpacd x17 +; CHECKED-NEXT: cmp x16, x17 +; CHECKED-NEXT: b.eq Lauth_success_2 +; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: b Lresign_end_2 +; CHECKED-NEXT: Lauth_success_2: +; CHECKED-NEXT: pacdb x16, x2 +; CHECKED-NEXT: Lresign_end_2: +; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: ret +; +; TRAP-LABEL: test_resign_blend_and_addr: +; TRAP: ; %bb.0: +; TRAP-NEXT: mov x16, x0 +; TRAP-NEXT: mov x17, x1 +; TRAP-NEXT: movk x17, #12345, lsl #48 +; TRAP-NEXT: autda x16, x17 +; TRAP-NEXT: mov x17, x16 +; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: cmp x16, x17 +; TRAP-NEXT: b.eq Lauth_success_3 +; TRAP-NEXT: brk #0xc472 +; TRAP-NEXT: Lauth_success_3: +; TRAP-NEXT: pacdb x16, x2 +; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: ret + %tmp0 = call i64 @llvm.ptrauth.blend(i64 %arg1, i64 12345) + %tmp1 = call i64 @llvm.ptrauth.resign(i64 %arg, i32 2, i64 %tmp0, i32 3, i64 %arg2) + ret i64 %tmp1 +} + +define i64 @test_auth_too_large_discriminator(i64 %arg, i64 %arg1) { +; SDAG-UNCHECKED-LABEL: test_auth_too_large_discriminator: +; SDAG-UNCHECKED: ; %bb.0: +; SDAG-UNCHECKED-NEXT: mov w8, #65536 +; SDAG-UNCHECKED-NEXT: bfi x1, x8, #48, #16 +; SDAG-UNCHECKED-NEXT: mov x16, x0 +; SDAG-UNCHECKED-NEXT: autda x16, x1 +; SDAG-UNCHECKED-NEXT: mov x0, x16 +; SDAG-UNCHECKED-NEXT: ret +; +; GISEL-UNCHECKED-LABEL: test_auth_too_large_discriminator: +; GISEL-UNCHECKED: ; %bb.0: +; GISEL-UNCHECKED-NEXT: movk x1, #0, lsl #48 +; GISEL-UNCHECKED-NEXT: mov x16, x0 +; GISEL-UNCHECKED-NEXT: autda x16, x1 +; GISEL-UNCHECKED-NEXT: mov x0, x16 +; GISEL-UNCHECKED-NEXT: ret +; +; SDAG-CHECKED-LABEL: test_auth_too_large_discriminator: +; SDAG-CHECKED: ; %bb.0: +; SDAG-CHECKED-NEXT: mov w8, #65536 +; SDAG-CHECKED-NEXT: bfi x1, x8, #48, #16 +; SDAG-CHECKED-NEXT: mov x16, x0 +; SDAG-CHECKED-NEXT: autda x16, x1 +; SDAG-CHECKED-NEXT: mov x0, x16 +; SDAG-CHECKED-NEXT: ret +; +; GISEL-CHECKED-LABEL: test_auth_too_large_discriminator: +; GISEL-CHECKED: ; %bb.0: +; GISEL-CHECKED-NEXT: movk x1, #0, lsl #48 +; GISEL-CHECKED-NEXT: mov x16, x0 +; GISEL-CHECKED-NEXT: autda x16, x1 +; GISEL-CHECKED-NEXT: mov x0, x16 +; GISEL-CHECKED-NEXT: ret +; +; SDAG-TRAP-LABEL: test_auth_too_large_discriminator: +; SDAG-TRAP: ; %bb.0: +; SDAG-TRAP-NEXT: mov w8, #65536 +; SDAG-TRAP-NEXT: bfi x1, x8, #48, #16 +; SDAG-TRAP-NEXT: mov x16, x0 +; SDAG-TRAP-NEXT: autda x16, x1 +; SDAG-TRAP-NEXT: mov x17, x16 +; SDAG-TRAP-NEXT: xpacd x17 +; SDAG-TRAP-NEXT: cmp x16, x17 +; SDAG-TRAP-NEXT: b.eq Lauth_success_4 +; SDAG-TRAP-NEXT: brk #0xc472 +; SDAG-TRAP-NEXT: Lauth_success_4: +; SDAG-TRAP-NEXT: mov x0, x16 +; SDAG-TRAP-NEXT: ret +; +; GISEL-TRAP-LABEL: test_auth_too_large_discriminator: +; GISEL-TRAP: ; %bb.0: +; GISEL-TRAP-NEXT: movk x1, #0, lsl #48 +; GISEL-TRAP-NEXT: mov x16, x0 +; GISEL-TRAP-NEXT: autda x16, x1 +; GISEL-TRAP-NEXT: mov x17, x16 +; GISEL-TRAP-NEXT: xpacd x17 +; GISEL-TRAP-NEXT: cmp x16, x17 +; GISEL-TRAP-NEXT: b.eq Lauth_success_4 +; GISEL-TRAP-NEXT: brk #0xc472 +; GISEL-TRAP-NEXT: Lauth_success_4: +; GISEL-TRAP-NEXT: mov x0, x16 +; GISEL-TRAP-NEXT: ret + %tmp0 = call i64 @llvm.ptrauth.blend(i64 %arg1, i64 65536) + %tmp1 = call i64 @llvm.ptrauth.auth(i64 %arg, i32 2, i64 %tmp0) + ret i64 %tmp1 +} + +declare i64 @llvm.ptrauth.auth(i64, i32, i64) +declare i64 @llvm.ptrauth.resign(i64, i32, i64, i32, i64) +declare i64 @llvm.ptrauth.blend(i64, i64) Index: llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign.ll @@ -0,0 +1,764 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel=0 -verify-machineinstrs \ +; RUN: -aarch64-ptrauth-auth-checks=none | FileCheck %s --check-prefixes=UNCHECKED +; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN: -aarch64-ptrauth-auth-checks=none | FileCheck %s --check-prefixes=UNCHECKED + +; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel=0 -verify-machineinstrs \ +; RUN: | FileCheck %s --check-prefixes=CHECKED +; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN: | FileCheck %s --check-prefixes=CHECKED + +; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel=0 -verify-machineinstrs \ +; RUN: -aarch64-ptrauth-auth-checks=trap | FileCheck %s --check-prefixes=TRAP +; RUN: llc < %s -mtriple arm64e-apple-darwin -global-isel -global-isel-abort=1 -verify-machineinstrs \ +; RUN: -aarch64-ptrauth-auth-checks=trap | FileCheck %s --check-prefixes=TRAP + +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + +define i64 @test_auth_ia(i64 %arg, i64 %arg1) { +; UNCHECKED-LABEL: test_auth_ia: +; UNCHECKED: ; %bb.0: +; UNCHECKED-NEXT: mov x16, x0 +; UNCHECKED-NEXT: autia x16, x1 +; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: ret +; +; CHECKED-LABEL: test_auth_ia: +; CHECKED: ; %bb.0: +; CHECKED-NEXT: mov x16, x0 +; CHECKED-NEXT: autia x16, x1 +; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: ret +; +; TRAP-LABEL: test_auth_ia: +; TRAP: ; %bb.0: +; TRAP-NEXT: mov x16, x0 +; TRAP-NEXT: autia x16, x1 +; TRAP-NEXT: mov x17, x16 +; TRAP-NEXT: xpaci x17 +; TRAP-NEXT: cmp x16, x17 +; TRAP-NEXT: b.eq Lauth_success_0 +; TRAP-NEXT: brk #0xc470 +; TRAP-NEXT: Lauth_success_0: +; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 0, i64 %arg1) + ret i64 %tmp +} + +define i64 @test_auth_ia_zero(i64 %arg) { +; UNCHECKED-LABEL: test_auth_ia_zero: +; UNCHECKED: ; %bb.0: +; UNCHECKED-NEXT: mov x16, x0 +; UNCHECKED-NEXT: autiza x16 +; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: ret +; +; CHECKED-LABEL: test_auth_ia_zero: +; CHECKED: ; %bb.0: +; CHECKED-NEXT: mov x16, x0 +; CHECKED-NEXT: autiza x16 +; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: ret +; +; TRAP-LABEL: test_auth_ia_zero: +; TRAP: ; %bb.0: +; TRAP-NEXT: mov x16, x0 +; TRAP-NEXT: autiza x16 +; TRAP-NEXT: mov x17, x16 +; TRAP-NEXT: xpaci x17 +; TRAP-NEXT: cmp x16, x17 +; TRAP-NEXT: b.eq Lauth_success_1 +; TRAP-NEXT: brk #0xc470 +; TRAP-NEXT: Lauth_success_1: +; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 0, i64 0) + ret i64 %tmp +} + +define i64 @test_auth_ib(i64 %arg, i64 %arg1) { +; UNCHECKED-LABEL: test_auth_ib: +; UNCHECKED: ; %bb.0: +; UNCHECKED-NEXT: mov x16, x0 +; UNCHECKED-NEXT: autib x16, x1 +; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: ret +; +; CHECKED-LABEL: test_auth_ib: +; CHECKED: ; %bb.0: +; CHECKED-NEXT: mov x16, x0 +; CHECKED-NEXT: autib x16, x1 +; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: ret +; +; TRAP-LABEL: test_auth_ib: +; TRAP: ; %bb.0: +; TRAP-NEXT: mov x16, x0 +; TRAP-NEXT: autib x16, x1 +; TRAP-NEXT: mov x17, x16 +; TRAP-NEXT: xpaci x17 +; TRAP-NEXT: cmp x16, x17 +; TRAP-NEXT: b.eq Lauth_success_2 +; TRAP-NEXT: brk #0xc471 +; TRAP-NEXT: Lauth_success_2: +; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 1, i64 %arg1) + ret i64 %tmp +} + +define i64 @test_auth_ib_zero(i64 %arg) { +; UNCHECKED-LABEL: test_auth_ib_zero: +; UNCHECKED: ; %bb.0: +; UNCHECKED-NEXT: mov x16, x0 +; UNCHECKED-NEXT: autizb x16 +; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: ret +; +; CHECKED-LABEL: test_auth_ib_zero: +; CHECKED: ; %bb.0: +; CHECKED-NEXT: mov x16, x0 +; CHECKED-NEXT: autizb x16 +; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: ret +; +; TRAP-LABEL: test_auth_ib_zero: +; TRAP: ; %bb.0: +; TRAP-NEXT: mov x16, x0 +; TRAP-NEXT: autizb x16 +; TRAP-NEXT: mov x17, x16 +; TRAP-NEXT: xpaci x17 +; TRAP-NEXT: cmp x16, x17 +; TRAP-NEXT: b.eq Lauth_success_3 +; TRAP-NEXT: brk #0xc471 +; TRAP-NEXT: Lauth_success_3: +; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 1, i64 0) + ret i64 %tmp +} + +define i64 @test_auth_da(i64 %arg, i64 %arg1) { +; UNCHECKED-LABEL: test_auth_da: +; UNCHECKED: ; %bb.0: +; UNCHECKED-NEXT: mov x16, x0 +; UNCHECKED-NEXT: autda x16, x1 +; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: ret +; +; CHECKED-LABEL: test_auth_da: +; CHECKED: ; %bb.0: +; CHECKED-NEXT: mov x16, x0 +; CHECKED-NEXT: autda x16, x1 +; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: ret +; +; TRAP-LABEL: test_auth_da: +; TRAP: ; %bb.0: +; TRAP-NEXT: mov x16, x0 +; TRAP-NEXT: autda x16, x1 +; TRAP-NEXT: mov x17, x16 +; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: cmp x16, x17 +; TRAP-NEXT: b.eq Lauth_success_4 +; TRAP-NEXT: brk #0xc472 +; TRAP-NEXT: Lauth_success_4: +; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 2, i64 %arg1) + ret i64 %tmp +} + +define i64 @test_auth_da_zero(i64 %arg) { +; UNCHECKED-LABEL: test_auth_da_zero: +; UNCHECKED: ; %bb.0: +; UNCHECKED-NEXT: mov x16, x0 +; UNCHECKED-NEXT: autdza x16 +; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: ret +; +; CHECKED-LABEL: test_auth_da_zero: +; CHECKED: ; %bb.0: +; CHECKED-NEXT: mov x16, x0 +; CHECKED-NEXT: autdza x16 +; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: ret +; +; TRAP-LABEL: test_auth_da_zero: +; TRAP: ; %bb.0: +; TRAP-NEXT: mov x16, x0 +; TRAP-NEXT: autdza x16 +; TRAP-NEXT: mov x17, x16 +; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: cmp x16, x17 +; TRAP-NEXT: b.eq Lauth_success_5 +; TRAP-NEXT: brk #0xc472 +; TRAP-NEXT: Lauth_success_5: +; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 2, i64 0) + ret i64 %tmp +} + +define i64 @test_auth_db(i64 %arg, i64 %arg1) { +; UNCHECKED-LABEL: test_auth_db: +; UNCHECKED: ; %bb.0: +; UNCHECKED-NEXT: mov x16, x0 +; UNCHECKED-NEXT: autdb x16, x1 +; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: ret +; +; CHECKED-LABEL: test_auth_db: +; CHECKED: ; %bb.0: +; CHECKED-NEXT: mov x16, x0 +; CHECKED-NEXT: autdb x16, x1 +; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: ret +; +; TRAP-LABEL: test_auth_db: +; TRAP: ; %bb.0: +; TRAP-NEXT: mov x16, x0 +; TRAP-NEXT: autdb x16, x1 +; TRAP-NEXT: mov x17, x16 +; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: cmp x16, x17 +; TRAP-NEXT: b.eq Lauth_success_6 +; TRAP-NEXT: brk #0xc473 +; TRAP-NEXT: Lauth_success_6: +; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 3, i64 %arg1) + ret i64 %tmp +} + +define i64 @test_auth_db_zero(i64 %arg) { +; UNCHECKED-LABEL: test_auth_db_zero: +; UNCHECKED: ; %bb.0: +; UNCHECKED-NEXT: mov x16, x0 +; UNCHECKED-NEXT: autdzb x16 +; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: ret +; +; CHECKED-LABEL: test_auth_db_zero: +; CHECKED: ; %bb.0: +; CHECKED-NEXT: mov x16, x0 +; CHECKED-NEXT: autdzb x16 +; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: ret +; +; TRAP-LABEL: test_auth_db_zero: +; TRAP: ; %bb.0: +; TRAP-NEXT: mov x16, x0 +; TRAP-NEXT: autdzb x16 +; TRAP-NEXT: mov x17, x16 +; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: cmp x16, x17 +; TRAP-NEXT: b.eq Lauth_success_7 +; TRAP-NEXT: brk #0xc473 +; TRAP-NEXT: Lauth_success_7: +; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 3, i64 0) + ret i64 %tmp +} + +; Note that this might seem like a no-op but is actually a valid way to enforce +; the validity of a signature. +define i64 @test_resign_ia_ia(i64 %arg, i64 %arg1, i64 %arg2) { +; UNCHECKED-LABEL: test_resign_ia_ia: +; UNCHECKED: ; %bb.0: +; UNCHECKED-NEXT: mov x16, x0 +; UNCHECKED-NEXT: autia x16, x1 +; UNCHECKED-NEXT: pacia x16, x2 +; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: ret +; +; CHECKED-LABEL: test_resign_ia_ia: +; CHECKED: ; %bb.0: +; CHECKED-NEXT: mov x16, x0 +; CHECKED-NEXT: autia x16, x1 +; CHECKED-NEXT: mov x17, x16 +; CHECKED-NEXT: xpaci x17 +; CHECKED-NEXT: cmp x16, x17 +; CHECKED-NEXT: b.eq Lauth_success_0 +; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: b Lresign_end_0 +; CHECKED-NEXT: Lauth_success_0: +; CHECKED-NEXT: pacia x16, x2 +; CHECKED-NEXT: Lresign_end_0: +; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: ret +; +; TRAP-LABEL: test_resign_ia_ia: +; TRAP: ; %bb.0: +; TRAP-NEXT: mov x16, x0 +; TRAP-NEXT: autia x16, x1 +; TRAP-NEXT: mov x17, x16 +; TRAP-NEXT: xpaci x17 +; TRAP-NEXT: cmp x16, x17 +; TRAP-NEXT: b.eq Lauth_success_8 +; TRAP-NEXT: brk #0xc470 +; TRAP-NEXT: Lauth_success_8: +; TRAP-NEXT: pacia x16, x2 +; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 0, i64 %arg1, i32 0, i64 %arg2) + ret i64 %tmp +} + +define i64 @test_resign_ib_ia(i64 %arg, i64 %arg1, i64 %arg2) { +; UNCHECKED-LABEL: test_resign_ib_ia: +; UNCHECKED: ; %bb.0: +; UNCHECKED-NEXT: mov x16, x0 +; UNCHECKED-NEXT: autib x16, x1 +; UNCHECKED-NEXT: pacia x16, x2 +; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: ret +; +; CHECKED-LABEL: test_resign_ib_ia: +; CHECKED: ; %bb.0: +; CHECKED-NEXT: mov x16, x0 +; CHECKED-NEXT: autib x16, x1 +; CHECKED-NEXT: mov x17, x16 +; CHECKED-NEXT: xpaci x17 +; CHECKED-NEXT: cmp x16, x17 +; CHECKED-NEXT: b.eq Lauth_success_1 +; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: b Lresign_end_1 +; CHECKED-NEXT: Lauth_success_1: +; CHECKED-NEXT: pacia x16, x2 +; CHECKED-NEXT: Lresign_end_1: +; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: ret +; +; TRAP-LABEL: test_resign_ib_ia: +; TRAP: ; %bb.0: +; TRAP-NEXT: mov x16, x0 +; TRAP-NEXT: autib x16, x1 +; TRAP-NEXT: mov x17, x16 +; TRAP-NEXT: xpaci x17 +; TRAP-NEXT: cmp x16, x17 +; TRAP-NEXT: b.eq Lauth_success_9 +; TRAP-NEXT: brk #0xc471 +; TRAP-NEXT: Lauth_success_9: +; TRAP-NEXT: pacia x16, x2 +; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 1, i64 %arg1, i32 0, i64 %arg2) + ret i64 %tmp +} + +define i64 @test_resign_da_ia(i64 %arg, i64 %arg1, i64 %arg2) { +; UNCHECKED-LABEL: test_resign_da_ia: +; UNCHECKED: ; %bb.0: +; UNCHECKED-NEXT: mov x16, x0 +; UNCHECKED-NEXT: autda x16, x1 +; UNCHECKED-NEXT: pacia x16, x2 +; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: ret +; +; CHECKED-LABEL: test_resign_da_ia: +; CHECKED: ; %bb.0: +; CHECKED-NEXT: mov x16, x0 +; CHECKED-NEXT: autda x16, x1 +; CHECKED-NEXT: mov x17, x16 +; CHECKED-NEXT: xpacd x17 +; CHECKED-NEXT: cmp x16, x17 +; CHECKED-NEXT: b.eq Lauth_success_2 +; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: b Lresign_end_2 +; CHECKED-NEXT: Lauth_success_2: +; CHECKED-NEXT: pacia x16, x2 +; CHECKED-NEXT: Lresign_end_2: +; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: ret +; +; TRAP-LABEL: test_resign_da_ia: +; TRAP: ; %bb.0: +; TRAP-NEXT: mov x16, x0 +; TRAP-NEXT: autda x16, x1 +; TRAP-NEXT: mov x17, x16 +; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: cmp x16, x17 +; TRAP-NEXT: b.eq Lauth_success_10 +; TRAP-NEXT: brk #0xc472 +; TRAP-NEXT: Lauth_success_10: +; TRAP-NEXT: pacia x16, x2 +; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 2, i64 %arg1, i32 0, i64 %arg2) + ret i64 %tmp +} + +define i64 @test_resign_db_ia(i64 %arg, i64 %arg1, i64 %arg2) { +; UNCHECKED-LABEL: test_resign_db_ia: +; UNCHECKED: ; %bb.0: +; UNCHECKED-NEXT: mov x16, x0 +; UNCHECKED-NEXT: autdb x16, x1 +; UNCHECKED-NEXT: pacia x16, x2 +; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: ret +; +; CHECKED-LABEL: test_resign_db_ia: +; CHECKED: ; %bb.0: +; CHECKED-NEXT: mov x16, x0 +; CHECKED-NEXT: autdb x16, x1 +; CHECKED-NEXT: mov x17, x16 +; CHECKED-NEXT: xpacd x17 +; CHECKED-NEXT: cmp x16, x17 +; CHECKED-NEXT: b.eq Lauth_success_3 +; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: b Lresign_end_3 +; CHECKED-NEXT: Lauth_success_3: +; CHECKED-NEXT: pacia x16, x2 +; CHECKED-NEXT: Lresign_end_3: +; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: ret +; +; TRAP-LABEL: test_resign_db_ia: +; TRAP: ; %bb.0: +; TRAP-NEXT: mov x16, x0 +; TRAP-NEXT: autdb x16, x1 +; TRAP-NEXT: mov x17, x16 +; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: cmp x16, x17 +; TRAP-NEXT: b.eq Lauth_success_11 +; TRAP-NEXT: brk #0xc473 +; TRAP-NEXT: Lauth_success_11: +; TRAP-NEXT: pacia x16, x2 +; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 3, i64 %arg1, i32 0, i64 %arg2) + ret i64 %tmp +} + +define i64 @test_resign_db_ib(i64 %arg, i64 %arg1, i64 %arg2) { +; UNCHECKED-LABEL: test_resign_db_ib: +; UNCHECKED: ; %bb.0: +; UNCHECKED-NEXT: mov x16, x0 +; UNCHECKED-NEXT: autdb x16, x1 +; UNCHECKED-NEXT: pacib x16, x2 +; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: ret +; +; CHECKED-LABEL: test_resign_db_ib: +; CHECKED: ; %bb.0: +; CHECKED-NEXT: mov x16, x0 +; CHECKED-NEXT: autdb x16, x1 +; CHECKED-NEXT: mov x17, x16 +; CHECKED-NEXT: xpacd x17 +; CHECKED-NEXT: cmp x16, x17 +; CHECKED-NEXT: b.eq Lauth_success_4 +; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: b Lresign_end_4 +; CHECKED-NEXT: Lauth_success_4: +; CHECKED-NEXT: pacib x16, x2 +; CHECKED-NEXT: Lresign_end_4: +; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: ret +; +; TRAP-LABEL: test_resign_db_ib: +; TRAP: ; %bb.0: +; TRAP-NEXT: mov x16, x0 +; TRAP-NEXT: autdb x16, x1 +; TRAP-NEXT: mov x17, x16 +; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: cmp x16, x17 +; TRAP-NEXT: b.eq Lauth_success_12 +; TRAP-NEXT: brk #0xc473 +; TRAP-NEXT: Lauth_success_12: +; TRAP-NEXT: pacib x16, x2 +; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 3, i64 %arg1, i32 1, i64 %arg2) + ret i64 %tmp +} + +define i64 @test_resign_db_da(i64 %arg, i64 %arg1, i64 %arg2) { +; UNCHECKED-LABEL: test_resign_db_da: +; UNCHECKED: ; %bb.0: +; UNCHECKED-NEXT: mov x16, x0 +; UNCHECKED-NEXT: autdb x16, x1 +; UNCHECKED-NEXT: pacda x16, x2 +; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: ret +; +; CHECKED-LABEL: test_resign_db_da: +; CHECKED: ; %bb.0: +; CHECKED-NEXT: mov x16, x0 +; CHECKED-NEXT: autdb x16, x1 +; CHECKED-NEXT: mov x17, x16 +; CHECKED-NEXT: xpacd x17 +; CHECKED-NEXT: cmp x16, x17 +; CHECKED-NEXT: b.eq Lauth_success_5 +; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: b Lresign_end_5 +; CHECKED-NEXT: Lauth_success_5: +; CHECKED-NEXT: pacda x16, x2 +; CHECKED-NEXT: Lresign_end_5: +; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: ret +; +; TRAP-LABEL: test_resign_db_da: +; TRAP: ; %bb.0: +; TRAP-NEXT: mov x16, x0 +; TRAP-NEXT: autdb x16, x1 +; TRAP-NEXT: mov x17, x16 +; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: cmp x16, x17 +; TRAP-NEXT: b.eq Lauth_success_13 +; TRAP-NEXT: brk #0xc473 +; TRAP-NEXT: Lauth_success_13: +; TRAP-NEXT: pacda x16, x2 +; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 3, i64 %arg1, i32 2, i64 %arg2) + ret i64 %tmp +} + +define i64 @test_resign_db_db(i64 %arg, i64 %arg1, i64 %arg2) { +; UNCHECKED-LABEL: test_resign_db_db: +; UNCHECKED: ; %bb.0: +; UNCHECKED-NEXT: mov x16, x0 +; UNCHECKED-NEXT: autdb x16, x1 +; UNCHECKED-NEXT: pacdb x16, x2 +; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: ret +; +; CHECKED-LABEL: test_resign_db_db: +; CHECKED: ; %bb.0: +; CHECKED-NEXT: mov x16, x0 +; CHECKED-NEXT: autdb x16, x1 +; CHECKED-NEXT: mov x17, x16 +; CHECKED-NEXT: xpacd x17 +; CHECKED-NEXT: cmp x16, x17 +; CHECKED-NEXT: b.eq Lauth_success_6 +; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: b Lresign_end_6 +; CHECKED-NEXT: Lauth_success_6: +; CHECKED-NEXT: pacdb x16, x2 +; CHECKED-NEXT: Lresign_end_6: +; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: ret +; +; TRAP-LABEL: test_resign_db_db: +; TRAP: ; %bb.0: +; TRAP-NEXT: mov x16, x0 +; TRAP-NEXT: autdb x16, x1 +; TRAP-NEXT: mov x17, x16 +; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: cmp x16, x17 +; TRAP-NEXT: b.eq Lauth_success_14 +; TRAP-NEXT: brk #0xc473 +; TRAP-NEXT: Lauth_success_14: +; TRAP-NEXT: pacdb x16, x2 +; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 3, i64 %arg1, i32 3, i64 %arg2) + ret i64 %tmp +} + +define i64 @test_resign_iza_db(i64 %arg, i64 %arg1, i64 %arg2) { +; UNCHECKED-LABEL: test_resign_iza_db: +; UNCHECKED: ; %bb.0: +; UNCHECKED-NEXT: mov x16, x0 +; UNCHECKED-NEXT: autiza x16 +; UNCHECKED-NEXT: pacdb x16, x2 +; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: ret +; +; CHECKED-LABEL: test_resign_iza_db: +; CHECKED: ; %bb.0: +; CHECKED-NEXT: mov x16, x0 +; CHECKED-NEXT: autiza x16 +; CHECKED-NEXT: mov x17, x16 +; CHECKED-NEXT: xpaci x17 +; CHECKED-NEXT: cmp x16, x17 +; CHECKED-NEXT: b.eq Lauth_success_7 +; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: b Lresign_end_7 +; CHECKED-NEXT: Lauth_success_7: +; CHECKED-NEXT: pacdb x16, x2 +; CHECKED-NEXT: Lresign_end_7: +; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: ret +; +; TRAP-LABEL: test_resign_iza_db: +; TRAP: ; %bb.0: +; TRAP-NEXT: mov x16, x0 +; TRAP-NEXT: autiza x16 +; TRAP-NEXT: mov x17, x16 +; TRAP-NEXT: xpaci x17 +; TRAP-NEXT: cmp x16, x17 +; TRAP-NEXT: b.eq Lauth_success_15 +; TRAP-NEXT: brk #0xc470 +; TRAP-NEXT: Lauth_success_15: +; TRAP-NEXT: pacdb x16, x2 +; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 0, i64 0, i32 3, i64 %arg2) + ret i64 %tmp +} + +define i64 @test_resign_da_dzb(i64 %arg, i64 %arg1, i64 %arg2) { +; UNCHECKED-LABEL: test_resign_da_dzb: +; UNCHECKED: ; %bb.0: +; UNCHECKED-NEXT: mov x16, x0 +; UNCHECKED-NEXT: autda x16, x1 +; UNCHECKED-NEXT: pacdzb x16 +; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: ret +; +; CHECKED-LABEL: test_resign_da_dzb: +; CHECKED: ; %bb.0: +; CHECKED-NEXT: mov x16, x0 +; CHECKED-NEXT: autda x16, x1 +; CHECKED-NEXT: mov x17, x16 +; CHECKED-NEXT: xpacd x17 +; CHECKED-NEXT: cmp x16, x17 +; CHECKED-NEXT: b.eq Lauth_success_8 +; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: b Lresign_end_8 +; CHECKED-NEXT: Lauth_success_8: +; CHECKED-NEXT: pacdzb x16 +; CHECKED-NEXT: Lresign_end_8: +; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: ret +; +; TRAP-LABEL: test_resign_da_dzb: +; TRAP: ; %bb.0: +; TRAP-NEXT: mov x16, x0 +; TRAP-NEXT: autda x16, x1 +; TRAP-NEXT: mov x17, x16 +; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: cmp x16, x17 +; TRAP-NEXT: b.eq Lauth_success_16 +; TRAP-NEXT: brk #0xc472 +; TRAP-NEXT: Lauth_success_16: +; TRAP-NEXT: pacdzb x16 +; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 2, i64 %arg1, i32 3, i64 0) + ret i64 %tmp +} + +define i64 @test_auth_trap_attribute(i64 %arg, i64 %arg1) "ptrauth-auth-traps" { +; UNCHECKED-LABEL: test_auth_trap_attribute: +; UNCHECKED: ; %bb.0: +; UNCHECKED-NEXT: mov x16, x0 +; UNCHECKED-NEXT: autia x16, x1 +; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: ret +; +; CHECKED-LABEL: test_auth_trap_attribute: +; CHECKED: ; %bb.0: +; CHECKED-NEXT: mov x16, x0 +; CHECKED-NEXT: autia x16, x1 +; CHECKED-NEXT: mov x17, x16 +; CHECKED-NEXT: xpaci x17 +; CHECKED-NEXT: cmp x16, x17 +; CHECKED-NEXT: b.eq Lauth_success_9 +; CHECKED-NEXT: brk #0xc470 +; CHECKED-NEXT: Lauth_success_9: +; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: ret +; +; TRAP-LABEL: test_auth_trap_attribute: +; TRAP: ; %bb.0: +; TRAP-NEXT: mov x16, x0 +; TRAP-NEXT: autia x16, x1 +; TRAP-NEXT: mov x17, x16 +; TRAP-NEXT: xpaci x17 +; TRAP-NEXT: cmp x16, x17 +; TRAP-NEXT: b.eq Lauth_success_17 +; TRAP-NEXT: brk #0xc470 +; TRAP-NEXT: Lauth_success_17: +; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 0, i64 %arg1) + ret i64 %tmp +} + +define i64 @test_auth_ia_constdisc(i64 %arg) { +; UNCHECKED-LABEL: test_auth_ia_constdisc: +; UNCHECKED: ; %bb.0: +; UNCHECKED-NEXT: mov x16, x0 +; UNCHECKED-NEXT: mov x17, #256 +; UNCHECKED-NEXT: autia x16, x17 +; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: ret +; +; CHECKED-LABEL: test_auth_ia_constdisc: +; CHECKED: ; %bb.0: +; CHECKED-NEXT: mov x16, x0 +; CHECKED-NEXT: mov x17, #256 +; CHECKED-NEXT: autia x16, x17 +; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: ret +; +; TRAP-LABEL: test_auth_ia_constdisc: +; TRAP: ; %bb.0: +; TRAP-NEXT: mov x16, x0 +; TRAP-NEXT: mov x17, #256 +; TRAP-NEXT: autia x16, x17 +; TRAP-NEXT: mov x17, x16 +; TRAP-NEXT: xpaci x17 +; TRAP-NEXT: cmp x16, x17 +; TRAP-NEXT: b.eq Lauth_success_18 +; TRAP-NEXT: brk #0xc470 +; TRAP-NEXT: Lauth_success_18: +; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.auth(i64 %arg, i32 0, i64 256) + ret i64 %tmp +} + +define i64 @test_resign_da_constdisc(i64 %arg, i64 %arg1) { +; UNCHECKED-LABEL: test_resign_da_constdisc: +; UNCHECKED: ; %bb.0: +; UNCHECKED-NEXT: mov x16, x0 +; UNCHECKED-NEXT: autda x16, x1 +; UNCHECKED-NEXT: mov x17, #256 +; UNCHECKED-NEXT: pacda x16, x17 +; UNCHECKED-NEXT: mov x0, x16 +; UNCHECKED-NEXT: ret +; +; CHECKED-LABEL: test_resign_da_constdisc: +; CHECKED: ; %bb.0: +; CHECKED-NEXT: mov x16, x0 +; CHECKED-NEXT: autda x16, x1 +; CHECKED-NEXT: mov x17, x16 +; CHECKED-NEXT: xpacd x17 +; CHECKED-NEXT: cmp x16, x17 +; CHECKED-NEXT: b.eq Lauth_success_10 +; CHECKED-NEXT: mov x16, x17 +; CHECKED-NEXT: b Lresign_end_9 +; CHECKED-NEXT: Lauth_success_10: +; CHECKED-NEXT: mov x17, #256 +; CHECKED-NEXT: pacda x16, x17 +; CHECKED-NEXT: Lresign_end_9: +; CHECKED-NEXT: mov x0, x16 +; CHECKED-NEXT: ret +; +; TRAP-LABEL: test_resign_da_constdisc: +; TRAP: ; %bb.0: +; TRAP-NEXT: mov x16, x0 +; TRAP-NEXT: autda x16, x1 +; TRAP-NEXT: mov x17, x16 +; TRAP-NEXT: xpacd x17 +; TRAP-NEXT: cmp x16, x17 +; TRAP-NEXT: b.eq Lauth_success_19 +; TRAP-NEXT: brk #0xc472 +; TRAP-NEXT: Lauth_success_19: +; TRAP-NEXT: mov x17, #256 +; TRAP-NEXT: pacda x16, x17 +; TRAP-NEXT: mov x0, x16 +; TRAP-NEXT: ret + %tmp = call i64 @llvm.ptrauth.resign(i64 %arg, i32 2, i64 %arg1, i32 2, i64 256) + ret i64 %tmp +} + +declare i64 @llvm.ptrauth.auth(i64, i32, i64) +declare i64 @llvm.ptrauth.resign(i64, i32, i64, i32, i64)