diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 152d9f65f86db..21abc346cf17a 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -456,6 +456,7 @@ ENUM_LANGOPT(SignReturnAddressScope, SignReturnAddressScopeKind, 2, SignReturnAd ENUM_LANGOPT(SignReturnAddressKey, SignReturnAddressKeyKind, 1, SignReturnAddressKeyKind::AKey, "Key used for return address signing") LANGOPT(BranchTargetEnforcement, 1, 0, "Branch-target enforcement enabled") +LANGOPT(BranchProtectionPAuthLR, 1, 0, "Use PC as a diversifier using PAuthLR NOP instructions.") LANGOPT(SpeculativeLoadHardening, 1, 0, "Speculative load hardening enabled") diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index aa0f5023104a1..ac3c324c6c29c 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -1372,6 +1372,7 @@ class TargetInfo : public TransferrableTargetInfo, LangOptions::SignReturnAddressKeyKind SignKey = LangOptions::SignReturnAddressKeyKind::AKey; bool BranchTargetEnforcement = false; + bool BranchProtectionPAuthLR = false; }; /// Determine if the Architecture in this TargetInfo supports branch diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 1b02087425b75..965d402af2d7b 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -6999,6 +6999,8 @@ def msign_return_address_key_EQ : Joined<["-"], "msign-return-address-key=">, Values<"a_key,b_key">; def mbranch_target_enforce : Flag<["-"], "mbranch-target-enforce">, MarshallingInfoFlag>; +def mbranch_protection_pauth_lr : Flag<["-"], "mbranch-protection-pauth-lr">, + MarshallingInfoFlag>; def fno_dllexport_inlines : Flag<["-"], "fno-dllexport-inlines">, MarshallingInfoNegativeFlag>; def cfguard_no_checks : Flag<["-"], "cfguard-no-checks">, diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index def16c032c869..3ee39133fcee7 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -225,6 +225,7 @@ bool AArch64TargetInfo::validateBranchProtection(StringRef Spec, StringRef, BPI.SignKey = LangOptions::SignReturnAddressKeyKind::BKey; BPI.BranchTargetEnforcement = PBP.BranchTargetEnforcement; + BPI.BranchProtectionPAuthLR = PBP.BranchProtectionPAuthLR; return true; } diff --git a/clang/lib/Basic/Targets/ARM.cpp b/clang/lib/Basic/Targets/ARM.cpp index ce7e4d4639cea..6e1842fc64e50 100644 --- a/clang/lib/Basic/Targets/ARM.cpp +++ b/clang/lib/Basic/Targets/ARM.cpp @@ -419,6 +419,7 @@ bool ARMTargetInfo::validateBranchProtection(StringRef Spec, StringRef Arch, BPI.SignKey = LangOptions::SignReturnAddressKeyKind::AKey; BPI.BranchTargetEnforcement = PBP.BranchTargetEnforcement; + BPI.BranchProtectionPAuthLR = PBP.BranchProtectionPAuthLR; return true; } diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index b2e173d0d6949..d78f2594a2376 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -1106,6 +1106,9 @@ void CodeGenModule::Release() { if (LangOpts.BranchTargetEnforcement) getModule().addModuleFlag(llvm::Module::Min, "branch-target-enforcement", 1); + if (LangOpts.BranchProtectionPAuthLR) + getModule().addModuleFlag(llvm::Module::Min, "branch-protection-pauth-lr", + 1); if (LangOpts.hasSignReturnAddress()) getModule().addModuleFlag(llvm::Module::Min, "sign-return-address", 1); if (LangOpts.isSignReturnAddressScopeAll()) diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp index be5145daa00b7..7102d190fe008 100644 --- a/clang/lib/CodeGen/Targets/AArch64.cpp +++ b/clang/lib/CodeGen/Targets/AArch64.cpp @@ -136,6 +136,8 @@ class AArch64TargetCodeGenInfo : public TargetCodeGenInfo { Fn->addFnAttr("branch-target-enforcement", BPI.BranchTargetEnforcement ? "true" : "false"); + Fn->addFnAttr("branch-protection-pauth-lr", + BPI.BranchProtectionPAuthLR ? "true" : "false"); } bool isScalarizableAsmOperand(CodeGen::CodeGenFunction &CGF, diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index de9fd5eaa1e02..4783affd3220b 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -1497,7 +1497,7 @@ static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args, << Triple.getArchName(); StringRef Scope, Key; - bool IndirectBranches; + bool IndirectBranches, BranchProtectionPAuthLR; if (A->getOption().matches(options::OPT_msign_return_address_EQ)) { Scope = A->getValue(); @@ -1506,6 +1506,7 @@ static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args, << A->getSpelling() << Scope; Key = "a_key"; IndirectBranches = false; + BranchProtectionPAuthLR = false; } else { StringRef DiagMsg; llvm::ARM::ParsedBranchProtection PBP; @@ -1517,6 +1518,7 @@ static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args, << "b-key" << A->getAsString(Args); Scope = PBP.Scope; Key = PBP.Key; + BranchProtectionPAuthLR = PBP.BranchProtectionPAuthLR; IndirectBranches = PBP.BranchTargetEnforcement; } @@ -1525,6 +1527,9 @@ static void CollectARMPACBTIOptions(const ToolChain &TC, const ArgList &Args, if (!Scope.equals("none")) CmdArgs.push_back( Args.MakeArgString(Twine("-msign-return-address-key=") + Key)); + if (BranchProtectionPAuthLR) + CmdArgs.push_back( + Args.MakeArgString(Twine("-mbranch-protection-pauth-lr"))); if (IndirectBranches) CmdArgs.push_back("-mbranch-target-enforce"); } diff --git a/clang/test/CodeGen/aarch64-branch-protection-attr.c b/clang/test/CodeGen/aarch64-branch-protection-attr.c index 3c2714e2feda2..8ab3e17ade426 100644 --- a/clang/test/CodeGen/aarch64-branch-protection-attr.c +++ b/clang/test/CodeGen/aarch64-branch-protection-attr.c @@ -46,6 +46,24 @@ __attribute__ ((target("branch-protection=pac-ret+leaf+bti"))) void btileaf() {} // CHECK: define{{.*}} void @btileaf() #[[#BTIPACLEAF:]] + +__attribute__ ((target("branch-protection=pac-ret+pc"))) +void pauthlr() {} +// CHECK: define{{.*}} void @pauthlr() #[[#PAUTHLR:]] + +__attribute__ ((target("branch-protection=pac-ret+pc+b-key"))) +void pauthlr_bkey() {} +// CHECK: define{{.*}} void @pauthlr_bkey() #[[#PAUTHLR_BKEY:]] + +__attribute__ ((target("branch-protection=pac-ret+pc+leaf"))) +void pauthlr_leaf() {} +// CHECK: define{{.*}} void @pauthlr_leaf() #[[#PAUTHLR_LEAF:]] + +__attribute__ ((target("branch-protection=pac-ret+pc+bti"))) +void pauthlr_bti() {} +// CHECK: define{{.*}} void @pauthlr_bti() #[[#PAUTHLR_BTI:]] + + // CHECK-DAG: attributes #[[#NONE]] = { {{.*}} "branch-target-enforcement"="false" {{.*}} "sign-return-address"="none" // CHECK-DAG: attributes #[[#STD]] = { {{.*}} "branch-target-enforcement"="true" {{.*}} "sign-return-address"="non-leaf" "sign-return-address-key"="a_key" @@ -61,3 +79,13 @@ void btileaf() {} // CHECK-DAG: attributes #[[#PACBKEYLEAF]] = { {{.*}} "branch-target-enforcement"="false" {{.*}}"sign-return-address"="all" "sign-return-address-key"="b_key" // CHECK-DAG: attributes #[[#BTIPACLEAF]] = { {{.*}}"branch-target-enforcement"="true" {{.*}} "sign-return-address"="all" "sign-return-address-key"="a_key" + + +// CHECK-DAG: attributes #[[#PAUTHLR]] = { {{.*}}"branch-protection-pauth-lr"="true" {{.*}}"branch-target-enforcement"="false" {{.*}}"sign-return-address"="non-leaf" "sign-return-address-key"="a_key" + +// CHECK-DAG: attributes #[[#PAUTHLR_BKEY]] = { {{.*}}"branch-protection-pauth-lr"="true" {{.*}}"branch-target-enforcement"="false" {{.*}}"sign-return-address"="non-leaf" "sign-return-address-key"="b_key" + +// CHECK-DAG: attributes #[[#PAUTHLR_LEAF]] = { {{.*}}"branch-protection-pauth-lr"="true" {{.*}}"branch-target-enforcement"="false" {{.*}}"sign-return-address"="all" "sign-return-address-key"="a_key" + +// CHECK-DAG: attributes #[[#PAUTHLR_BTI]] = { {{.*}}"branch-protection-pauth-lr"="true" {{.*}}"branch-target-enforcement"="true" {{.*}}"sign-return-address"="non-leaf" "sign-return-address-key"="a_key" + diff --git a/clang/test/Driver/aarch64-pauth-lr.c b/clang/test/Driver/aarch64-pauth-lr.c new file mode 100644 index 0000000000000..2e1b530fc9895 --- /dev/null +++ b/clang/test/Driver/aarch64-pauth-lr.c @@ -0,0 +1,23 @@ +// Check the -cc1 flags for the various forms of -mbranch-protection=pac-ret+pc. + +// RUN: %clang -target aarch64-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+pc 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR +// RUN: %clang -target aarch64-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+pc+b-key 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR-B-KEY +// RUN: %clang -target aarch64-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+pc+leaf 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR-LEAF +// RUN: %clang -target aarch64-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+pc+bti 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR-BTI +// RUN: %clang -target aarch64-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+pc+leaf+b-key+bti 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR-LEAF-B-KEY-BTI +// RUN: %clang -target aarch64-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+pc -march=armv9.5-a 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR +// RUN: %clang -target aarch64-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+pc+b-key -march=armv9.5-a 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR-B-KEY +// RUN: %clang -target aarch64-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+pc+leaf -march=armv9.5-a 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR-LEAF +// RUN: %clang -target aarch64-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+pc+bti -march=armv9.5-a 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR-BTI +// RUN: %clang -target aarch64-arm-none-eabi -c %s -### -mbranch-protection=pac-ret+pc+leaf+b-key+bti -march=armv9.5-a 2>&1 | FileCheck %s --check-prefixes=PAUTH-LR-LEAF-B-KEY-BTI + +// PAUTH-LR: "-msign-return-address=non-leaf" "-msign-return-address-key=a_key" "-mbranch-protection-pauth-lr" +// PAUTH-LR-B-KEY: "-msign-return-address=non-leaf" "-msign-return-address-key=b_key" "-mbranch-protection-pauth-lr" +// PAUTH-LR-LEAF: "-msign-return-address=all" "-msign-return-address-key=a_key" "-mbranch-protection-pauth-lr" +// PAUTH-LR-BTI: "-msign-return-address=non-leaf" "-msign-return-address-key=a_key" "-mbranch-protection-pauth-lr" +// PAUTH-LR-LEAF-B-KEY-BTI: "-msign-return-address=all" "-msign-return-address-key=b_key" "-mbranch-protection-pauth-lr" "-mbranch-target-enforce" + +// NOT-PAUTH-LR: "-mbranch-target-enforce" +// NOT-PAUTH-LR-B-KEY: "-mbranch-target-enforce" +// NOT-PAUTH-LR-LEAF: "-mbranch-target-enforce" +// NOT-PAUTH-LR-BTI: "-mbranch-target-enforce" diff --git a/clang/test/Driver/aarch64-v95a.c b/clang/test/Driver/aarch64-v95a.c index 366cade86a9fb..6fac62e8b389a 100644 --- a/clang/test/Driver/aarch64-v95a.c +++ b/clang/test/Driver/aarch64-v95a.c @@ -1,3 +1,5 @@ +// ===== Base v9.5a architecture ===== + // RUN: %clang -target aarch64 -march=armv9.5a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV95A %s // RUN: %clang -target aarch64 -march=armv9.5-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV95A %s // RUN: %clang -target aarch64 -mlittle-endian -march=armv9.5a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV95A %s @@ -5,6 +7,7 @@ // RUN: %clang -target aarch64_be -mlittle-endian -march=armv9.5a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV95A %s // RUN: %clang -target aarch64_be -mlittle-endian -march=armv9.5-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV95A %s // GENERICV95A: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+neon" "-target-feature" "+v9.5a" + // RUN: %clang -target aarch64_be -march=armv9.5a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV95A-BE %s // RUN: %clang -target aarch64_be -march=armv9.5-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV95A-BE %s // RUN: %clang -target aarch64 -mbig-endian -march=armv9.5a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV95A-BE %s @@ -18,3 +21,7 @@ // RUN: %clang -target aarch64 -march=armv9.5a+cpa -### -c %s 2>&1 | FileCheck -check-prefix=V95A-CPA %s // RUN: %clang -target aarch64 -march=armv9.5-a+cpa -### -c %s 2>&1 | FileCheck -check-prefix=V95A-CPA %s // V95A-CPA: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+neon" "-target-feature" "+v9.5a" "-target-feature" "+cpa" + +// RUN: %clang -target aarch64 -march=armv9.5a+pauth-lr -### -c %s 2>&1 | FileCheck -check-prefix=V95A-PAUTHLR %s +// RUN: %clang -target aarch64 -march=armv9.5-a+pauth-lr -### -c %s 2>&1 | FileCheck -check-prefix=V95A-PAUTHLR %s +// V95A-PAUTHLR: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+neon" "-target-feature" "+v9.5a" "-target-feature" "+pauth-lr" diff --git a/clang/test/Preprocessor/aarch64-target-features.c b/clang/test/Preprocessor/aarch64-target-features.c index db89aa7b608ad..b3da54162da04 100644 --- a/clang/test/Preprocessor/aarch64-target-features.c +++ b/clang/test/Preprocessor/aarch64-target-features.c @@ -600,6 +600,7 @@ // RUN: %clang -target aarch64-none-elf -march=armv9.1-a -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-V81-OR-LATER,CHECK-V83-OR-LATER,CHECK-V85-OR-LATER %s // RUN: %clang -target aarch64-none-elf -march=armv9.2-a -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-V81-OR-LATER,CHECK-V83-OR-LATER,CHECK-V85-OR-LATER %s // RUN: %clang -target aarch64-none-elf -march=armv9.3-a -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-V81-OR-LATER,CHECK-V83-OR-LATER,CHECK-V85-OR-LATER %s +// RUN: %clang -target aarch64-none-elf -march=armv9.4-a -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-V81-OR-LATER,CHECK-V83-OR-LATER,CHECK-V85-OR-LATER %s // RUN: %clang -target aarch64-none-elf -march=armv9.5-a -x c -E -dM %s -o - | FileCheck --check-prefixes=CHECK-V81-OR-LATER,CHECK-V83-OR-LATER,CHECK-V85-OR-LATER %s // CHECK-V81-OR-LATER: __ARM_FEATURE_ATOMICS 1 // CHECK-V85-OR-LATER: __ARM_FEATURE_BTI 1 diff --git a/llvm/include/llvm/TargetParser/AArch64TargetParser.h b/llvm/include/llvm/TargetParser/AArch64TargetParser.h index f0b35790133fb..6c7410a8b8f79 100644 --- a/llvm/include/llvm/TargetParser/AArch64TargetParser.h +++ b/llvm/include/llvm/TargetParser/AArch64TargetParser.h @@ -174,6 +174,7 @@ enum ArchExtKind : unsigned { AEK_SMEF8F32 = 70, // FEAT_SME_F8F32 AEK_SMEFA64 = 71, // FEAT_SME_FA64 AEK_CPA = 72, // FEAT_CPA + AEK_PAUTHLR = 73, // FEAT_PAuth_LR AEK_NUM_EXTENSIONS }; using ExtensionBitset = Bitset; @@ -297,6 +298,7 @@ inline constexpr ExtensionInfo Extensions[] = { {"sme-f8f32", AArch64::AEK_SMEF8F32, "+sme-f8f32", "-sme-f8f32", FEAT_INIT, "+sme2,+fp8", 0}, {"sme-fa64", AArch64::AEK_SMEFA64, "+sme-fa64", "-sme-fa64", FEAT_INIT, "", 0}, {"cpa", AArch64::AEK_CPA, "+cpa", "-cpa", FEAT_INIT, "", 0}, + {"pauth-lr", AArch64::AEK_PAUTHLR, "+pauth-lr", "-pauth-lr", FEAT_INIT, "", 0}, // Special cases {"none", AArch64::AEK_NONE, {}, {}, FEAT_INIT, "", ExtensionInfo::MaxFMVPriority}, }; diff --git a/llvm/include/llvm/TargetParser/ARMTargetParserCommon.h b/llvm/include/llvm/TargetParser/ARMTargetParserCommon.h index e3d9ffc1d4db5..1e4187c6fb111 100644 --- a/llvm/include/llvm/TargetParser/ARMTargetParserCommon.h +++ b/llvm/include/llvm/TargetParser/ARMTargetParserCommon.h @@ -41,6 +41,7 @@ struct ParsedBranchProtection { StringRef Scope; StringRef Key; bool BranchTargetEnforcement; + bool BranchProtectionPAuthLR; }; bool parseBranchProtection(StringRef Spec, ParsedBranchProtection &PBP, diff --git a/llvm/lib/Target/AArch64/AArch64.td b/llvm/lib/Target/AArch64/AArch64.td index db92a94e40e4b..97e92a57a7ff4 100644 --- a/llvm/lib/Target/AArch64/AArch64.td +++ b/llvm/lib/Target/AArch64/AArch64.td @@ -622,8 +622,13 @@ def FeatureLdpAlignedOnly : SubtargetFeature<"ldp-aligned-only", "HasLdpAlignedO def FeatureStpAlignedOnly : SubtargetFeature<"stp-aligned-only", "HasStpAlignedOnly", "true", "In order to emit stp, first check if the store will be aligned to 2 * element_size">; +// AArch64 2023 Architecture Extensions (v9.5-A) + def FeatureCPA : SubtargetFeature<"cpa", "HasCPA", "true", - "Enable ARMv9.5-A Checked Pointer Arithmetic (FEAT_CPA)">; + "Enable Armv9.5-A Checked Pointer Arithmetic (FEAT_CPA)">; + +def FeaturePAuthLR : SubtargetFeature<"pauth-lr", "HasPAuthLR", + "true", "Enable Armv9.5-A PAC enhancements (FEAT_PAuth_LR)">; //===----------------------------------------------------------------------===// // Architectures. @@ -810,7 +815,7 @@ def SMEUnsupported : AArch64Unsupported { SME2Unsupported.F); } -let F = [HasPAuth] in +let F = [HasPAuth, HasPAuthLR] in def PAUnsupported : AArch64Unsupported; include "AArch64SchedA53.td" diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td index 690ac0dcda621..cb63d8726744d 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td +++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td @@ -2368,6 +2368,80 @@ class ClearAuth data, string asm> let Inst{4-0} = Rd; } +// v9.5-A FEAT_PAuth_LR + +class SignAuthFixedRegs opcode2, bits<6> opcode, string asm> + : I<(outs), (ins), asm, "", "", []>, + Sched<[WriteI, ReadI]> { + let Inst{31} = 0b1; // sf + let Inst{30} = 0b1; + let Inst{29} = 0b0; // S + let Inst{28-21} = 0b11010110; + let Inst{20-16} = opcode2; + let Inst{15-10} = opcode; + let Inst{9-5} = 0b11111; // Rn + let Inst{4-0} = 0b11110; // Rd +} + +def PAuthPCRelLabel16Operand : PCRelLabel<16> { + let Name = "PAuthPCRelLabel16"; + let PredicateMethod = "isPAuthPCRelLabel16Operand"; +} +def am_pauth_pcrel : Operand { + let EncoderMethod = "getPAuthPCRelOpValue"; + let DecoderMethod = "DecodePCRelLabel16"; + let PrintMethod = "printAlignedLabel"; + let ParserMatchClass = PAuthPCRelLabel16Operand; + let OperandType = "OPERAND_PCREL"; +} + +class SignAuthPCRel opc, string asm> + : I<(outs), (ins am_pauth_pcrel:$label), asm, "\t$label", "", []>, + Sched<[]> { + bits<16> label; + let Inst{31} = 0b1; // sf + let Inst{30-23} = 0b11100111; + let Inst{22-21} = opc; + let Inst{20-5} = label; // imm + let Inst{4-0} = 0b11111; // Rd +} + +class SignAuthOneReg opcode2, bits<6> opcode, string asm> + : I<(outs), (ins GPR64:$Rn), asm, "\t$Rn", "", []>, + Sched<[]> { + bits<5> Rn; + let Inst{31} = 0b1; // sf + let Inst{30} = 0b1; + let Inst{29} = 0b0; // S + let Inst{28-21} = 0b11010110; + let Inst{20-16} = opcode2; + let Inst{15-10} = opcode; + let Inst{9-5} = Rn; + let Inst{4-0} = 0b11110; // Rd +} + +class SignAuthReturnPCRel opc, bits<5> op2, string asm> + : I<(outs), (ins am_pauth_pcrel:$label), asm, "\t$label", "", []>, + Sched<[WriteAtomic]> { + bits<16> label; + let Inst{31-24} = 0b01010101; + let Inst{23-21} = opc; + let Inst{20-5} = label; // imm16 + let Inst{4-0} = op2; +} + +class SignAuthReturnReg op3, string asm> + : I<(outs), (ins GPR64common:$Rm), asm, "\t$Rm", "", []>, + Sched<[WriteAtomic]> { + bits<5> Rm; + let Inst{31-25} = 0b1101011; + let Inst{24-21} = 0b0010; // opc + let Inst{20-16} = 0b11111; // op2 + let Inst{15-10} = op3; + let Inst{9-5} = 0b11111; // Rn + let Inst{4-0} = Rm; // op4 (Rm) +} + // Base class for the Armv8.4-A 8 and 16-bit flag manipulation instructions class BaseFlagManipulation : I<(outs), iops, asm, ops, "", []>, diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp index 175f6ef49c3ba..6d85e1fb5fbf1 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -8802,12 +8802,23 @@ AArch64InstrInfo::getOutliningTypeImpl(MachineBasicBlock::iterator &MIT, // Don't outline anything used for return address signing. The outlined // function will get signed later if needed switch (MI.getOpcode()) { + case AArch64::PACM: case AArch64::PACIASP: case AArch64::PACIBSP: + case AArch64::PACIASPPC: + case AArch64::PACIBSPPC: case AArch64::AUTIASP: case AArch64::AUTIBSP: + case AArch64::AUTIASPPCi: + case AArch64::AUTIASPPCr: + case AArch64::AUTIBSPPCi: + case AArch64::AUTIBSPPCr: case AArch64::RETAA: case AArch64::RETAB: + case AArch64::RETAASPPCi: + case AArch64::RETAASPPCr: + case AArch64::RETABSPPCi: + case AArch64::RETABSPPCr: case AArch64::EMITBKEY: case AArch64::PAUTH_PROLOGUE: case AArch64::PAUTH_EPILOGUE: diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index 4ccac40f99a0a..977729bb082b7 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -61,6 +61,9 @@ def HasLOR : Predicate<"Subtarget->hasLOR()">, def HasPAuth : Predicate<"Subtarget->hasPAuth()">, AssemblerPredicateWithAll<(all_of FeaturePAuth), "pauth">; +def HasPAuthLR : Predicate<"Subtarget->hasPAuthLR()">, + AssemblerPredicateWithAll<(all_of FeaturePAuthLR), "pauth-lr">; + def HasJS : Predicate<"Subtarget->hasJS()">, AssemblerPredicateWithAll<(all_of FeatureJS), "jsconv">; @@ -1646,6 +1649,42 @@ let Predicates = [HasPAuth] in { } +// v9.5-A pointer authentication extensions + +// Always accept "pacm" as an alias for "hint #39", but don't emit it when +// disassembling if we don't have the pauth-lr feature. +let CRm = 0b0100 in { + def PACM : SystemNoOperands<0b111, "hint\t#39">; +} +def : InstAlias<"pacm", (PACM), 0>; + +let Predicates = [HasPAuthLR] in { + let Defs = [LR], Uses = [LR, SP] in { + // opcode2, opcode, asm + def PACIASPPC : SignAuthFixedRegs<0b00001, 0b101000, "paciasppc">; + def PACIBSPPC : SignAuthFixedRegs<0b00001, 0b101001, "pacibsppc">; + def PACNBIASPPC : SignAuthFixedRegs<0b00001, 0b100000, "pacnbiasppc">; + def PACNBIBSPPC : SignAuthFixedRegs<0b00001, 0b100001, "pacnbibsppc">; + // opc, asm + def AUTIASPPCi : SignAuthPCRel<0b00, "autiasppc">; + def AUTIBSPPCi : SignAuthPCRel<0b01, "autibsppc">; + // opcode2, opcode, asm + def AUTIASPPCr : SignAuthOneReg<0b00001, 0b100100, "autiasppc">; + def AUTIBSPPCr : SignAuthOneReg<0b00001, 0b100101, "autibsppc">; + } + + let Uses = [LR, SP], isReturn = 1, isTerminator = 1, isBarrier = 1 in { + // opc, op2, asm + def RETAASPPCi : SignAuthReturnPCRel<0b000, 0b11111, "retaasppc">; + def RETABSPPCi : SignAuthReturnPCRel<0b001, 0b11111, "retabsppc">; + // op3, asm + def RETAASPPCr : SignAuthReturnReg<0b000010, "retaasppc">; + def RETABSPPCr : SignAuthReturnReg<0b000011, "retabsppc">; + } + def : InstAlias<"pacm", (PACM), 1>; +} + + // v8.3a floating point conversion for javascript let Predicates = [HasJS, HasFPARMv8], Defs = [NZCV] in def FJCVTZS : BaseFPToIntegerUnscaled<0b01, 0b11, 0b110, FPR64, GPR32, diff --git a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp index 9da59ef2a8062..1a8c71888a852 100644 --- a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp @@ -93,16 +93,24 @@ AArch64FunctionInfo::AArch64FunctionInfo(const Function &F, // TODO: skip functions that have no instrumented allocas for optimization IsMTETagged = F.hasFnAttribute(Attribute::SanitizeMemTag); - if (!F.hasFnAttribute("branch-target-enforcement")) { - if (const auto *BTE = mdconst::extract_or_null( - F.getParent()->getModuleFlag("branch-target-enforcement"))) - BranchTargetEnforcement = BTE->getZExtValue(); - } else { - const StringRef BTIEnable = - F.getFnAttribute("branch-target-enforcement").getValueAsString(); - assert(BTIEnable == "true" || BTIEnable == "false"); - BranchTargetEnforcement = BTIEnable == "true"; - } + // BTI/PAuthLR may be set either on the function or the module. Set Bool from + // either the function attribute or module attribute, depending on what is + // set. + // Note: the module attributed is numeric (0 or 1) but the function attribute + // is stringy ("true" or "false"). + auto TryFnThenModule = [&](StringRef AttrName, bool &Bool) { + if (F.hasFnAttribute(AttrName)) { + const StringRef V = F.getFnAttribute(AttrName).getValueAsString(); + assert(V.equals_insensitive("true") || V.equals_insensitive("false")); + Bool = V.equals_insensitive("true"); + } else if (const auto *ModVal = mdconst::extract_or_null( + F.getParent()->getModuleFlag(AttrName))) { + Bool = ModVal->getZExtValue(); + } + }; + + TryFnThenModule("branch-target-enforcement", BranchTargetEnforcement); + TryFnThenModule("branch-protection-pauth-lr", BranchProtectionPAuthLR); // The default stack probe size is 4096 if the function has no // stack-probe-size attribute. This is a safe default because it is the diff --git a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h index 219f83cfd32e0..cd4a18bfbc23a 100644 --- a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h +++ b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h @@ -22,6 +22,7 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/IR/Function.h" #include "llvm/MC/MCLinkerOptimizationHint.h" +#include "llvm/MC/MCSymbol.h" #include #include @@ -164,10 +165,21 @@ class AArch64FunctionInfo final : public MachineFunctionInfo { /// SignWithBKey modifies the default PAC-RET mode to signing with the B key. bool SignWithBKey = false; + /// SigningInstrOffset captures the offset of the PAC-RET signing instruction + /// within the prologue, so it can be re-used for authentication in the + /// epilogue when using PC as a second salt (FEAT_PAuth_LR) + MCSymbol *SignInstrLabel = nullptr; + /// BranchTargetEnforcement enables placing BTI instructions at potential /// indirect branch destinations. bool BranchTargetEnforcement = false; + /// Indicates that SP signing should be diversified with PC as-per PAuthLR. + /// This is set by -mbranch-protection and will emit NOP instructions unless + /// the subtarget feature +pauthlr is also used (in which case non-NOP + /// instructions are emitted). + bool BranchProtectionPAuthLR = false; + /// Whether this function has an extended frame record [Ctx, FP, LR]. If so, /// bit 60 of the in-memory FP will be 1 to enable other tools to detect the /// extended record. @@ -436,10 +448,16 @@ class AArch64FunctionInfo final : public MachineFunctionInfo { bool needsShadowCallStackPrologueEpilogue(MachineFunction &MF) const; bool shouldSignWithBKey() const { return SignWithBKey; } + + MCSymbol *getSigningInstrLabel() const { return SignInstrLabel; } + void setSigningInstrLabel(MCSymbol *Label) { SignInstrLabel = Label; } + bool isMTETagged() const { return IsMTETagged; } bool branchTargetEnforcement() const { return BranchTargetEnforcement; } + bool branchProtectionPAuthLR() const { return BranchProtectionPAuthLR; } + void setHasSwiftAsyncContext(bool HasContext) { HasSwiftAsyncContext = HasContext; } diff --git a/llvm/lib/Target/AArch64/AArch64PointerAuth.cpp b/llvm/lib/Target/AArch64/AArch64PointerAuth.cpp index 7576d2a899d1a..334149a6bf5cf 100644 --- a/llvm/lib/Target/AArch64/AArch64PointerAuth.cpp +++ b/llvm/lib/Target/AArch64/AArch64PointerAuth.cpp @@ -60,11 +60,35 @@ FunctionPass *llvm::createAArch64PointerAuthPass() { char AArch64PointerAuth::ID = 0; +// Where PAuthLR support is not known at compile time, it is supported using +// PACM. PACM is in the hint space so has no effect when PAuthLR is not +// supported by the hardware, but will alter the behaviour of PACI*SP, AUTI*SP +// and RETAA/RETAB if the hardware supports PAuthLR. +static void BuildPACM(const AArch64Subtarget &Subtarget, MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, DebugLoc DL, + MachineInstr::MIFlag Flags, MCSymbol *PACSym = nullptr) { + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); + auto &MFnI = *MBB.getParent()->getInfo(); + + // ADR X16, + if (PACSym) { + assert(Flags == MachineInstr::FrameDestroy); + BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADR)) + .addReg(AArch64::X16) + .addSym(PACSym); + } + + // Only emit PACM if -mbranch-protection has +pc and the target does not + // have feature +pauth-lr. + if (MFnI.branchProtectionPAuthLR() && !Subtarget.hasPAuthLR()) + BuildMI(MBB, MBBI, DL, TII->get(AArch64::PACM)).setMIFlag(Flags); +} + void AArch64PointerAuth::signLR(MachineFunction &MF, MachineBasicBlock::iterator MBBI) const { - const AArch64FunctionInfo *MFnI = MF.getInfo(); - bool UseBKey = MFnI->shouldSignWithBKey(); - bool EmitCFI = MFnI->needsDwarfUnwindInfo(MF); + auto &MFnI = *MF.getInfo(); + bool UseBKey = MFnI.shouldSignWithBKey(); + bool EmitCFI = MFnI.needsDwarfUnwindInfo(MF); bool NeedsWinCFI = MF.hasWinCFI(); MachineBasicBlock &MBB = *MBBI->getParent(); @@ -77,11 +101,29 @@ void AArch64PointerAuth::signLR(MachineFunction &MF, .setMIFlag(MachineInstr::FrameSetup); } + // PAuthLR authentication instructions need to know the value of PC at the + // point of signing (PACI*). + if (MFnI.branchProtectionPAuthLR()) { + MCSymbol *PACSym = MF.getMMI().getContext().createTempSymbol(); + MFnI.setSigningInstrLabel(PACSym); + } + // No SEH opcode for this one; it doesn't materialize into an // instruction on Windows. - BuildMI(MBB, MBBI, DL, - TII->get(UseBKey ? AArch64::PACIBSP : AArch64::PACIASP)) - .setMIFlag(MachineInstr::FrameSetup); + if (MFnI.branchProtectionPAuthLR() && Subtarget->hasPAuthLR()) { + BuildMI(MBB, MBBI, DL, + TII->get(MFnI.shouldSignWithBKey() ? AArch64::PACIBSPPC + : AArch64::PACIASPPC)) + .setMIFlag(MachineInstr::FrameSetup) + ->setPreInstrSymbol(MF, MFnI.getSigningInstrLabel()); + } else { + BuildPACM(*Subtarget, MBB, MBBI, DL, MachineInstr::FrameSetup); + BuildMI(MBB, MBBI, DL, + TII->get(MFnI.shouldSignWithBKey() ? AArch64::PACIBSP + : AArch64::PACIASP)) + .setMIFlag(MachineInstr::FrameSetup) + ->setPreInstrSymbol(MF, MFnI.getSigningInstrLabel()); + } if (EmitCFI) { unsigned CFIIndex = @@ -118,15 +160,37 @@ void AArch64PointerAuth::authenticateLR( // DW_CFA_AARCH64_negate_ra_state can't be emitted. bool TerminatorIsCombinable = TI != MBB.end() && TI->getOpcode() == AArch64::RET; + MCSymbol *PACSym = MFnI->getSigningInstrLabel(); + if (Subtarget->hasPAuth() && TerminatorIsCombinable && !NeedsWinCFI && !MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack)) { - unsigned CombinedRetOpcode = UseBKey ? AArch64::RETAB : AArch64::RETAA; - BuildMI(MBB, TI, DL, TII->get(CombinedRetOpcode)).copyImplicitOps(*TI); + if (MFnI->branchProtectionPAuthLR() && Subtarget->hasPAuthLR()) { + assert(PACSym && "No PAC instruction to refer to"); + BuildMI(MBB, TI, DL, + TII->get(UseBKey ? AArch64::RETABSPPCi : AArch64::RETAASPPCi)) + .addSym(PACSym) + .copyImplicitOps(*MBBI) + .setMIFlag(MachineInstr::FrameDestroy); + } else { + BuildPACM(*Subtarget, MBB, TI, DL, MachineInstr::FrameDestroy, PACSym); + BuildMI(MBB, TI, DL, TII->get(UseBKey ? AArch64::RETAB : AArch64::RETAA)) + .copyImplicitOps(*MBBI) + .setMIFlag(MachineInstr::FrameDestroy); + } MBB.erase(TI); } else { - unsigned AutOpcode = UseBKey ? AArch64::AUTIBSP : AArch64::AUTIASP; - BuildMI(MBB, MBBI, DL, TII->get(AutOpcode)) - .setMIFlag(MachineInstr::FrameDestroy); + if (MFnI->branchProtectionPAuthLR() && Subtarget->hasPAuthLR()) { + assert(PACSym && "No PAC instruction to refer to"); + BuildMI(MBB, MBBI, DL, + TII->get(UseBKey ? AArch64::AUTIBSPPCi : AArch64::AUTIASPPCi)) + .addSym(PACSym) + .setMIFlag(MachineInstr::FrameDestroy); + } else { + BuildPACM(*Subtarget, MBB, MBBI, DL, MachineInstr::FrameDestroy, PACSym); + BuildMI(MBB, MBBI, DL, + TII->get(UseBKey ? AArch64::AUTIBSP : AArch64::AUTIASP)) + .setMIFlag(MachineInstr::FrameDestroy); + } if (EmitAsyncCFI) { unsigned CFIIndex = diff --git a/llvm/lib/Target/AArch64/AArch64SchedA64FX.td b/llvm/lib/Target/AArch64/AArch64SchedA64FX.td index 813b4a3affcfd..7edce4b61605d 100644 --- a/llvm/lib/Target/AArch64/AArch64SchedA64FX.td +++ b/llvm/lib/Target/AArch64/AArch64SchedA64FX.td @@ -22,7 +22,7 @@ def A64FXModel : SchedMachineModel { list UnsupportedFeatures = !listconcat(SMEUnsupported.F, SVEUnsupported.F, [HasMTE, HasMatMulInt8, HasBF16, - HasPAuth, HasCPA]); + HasPAuth, HasPAuthLR, HasCPA]); let FullInstRWOverlapCheck = 0; } diff --git a/llvm/lib/Target/AArch64/AArch64SchedNeoverseN2.td b/llvm/lib/Target/AArch64/AArch64SchedNeoverseN2.td index 53cf725f0e235..a6fab5e6245f8 100644 --- a/llvm/lib/Target/AArch64/AArch64SchedNeoverseN2.td +++ b/llvm/lib/Target/AArch64/AArch64SchedNeoverseN2.td @@ -19,7 +19,7 @@ def NeoverseN2Model : SchedMachineModel { let CompleteModel = 1; list UnsupportedFeatures = !listconcat(SMEUnsupported.F, - [HasSVE2p1, HasCPA]); + [HasSVE2p1, HasPAuthLR, HasCPA]); } //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp index 74afa4183e67e..38a92cb096029 100644 --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -1696,6 +1696,21 @@ class AArch64Operand : public MCParsedAsmOperand { return DiagnosticPredicateTy::Match; } + bool isPAuthPCRelLabel16Operand() const { + // PAuth PCRel16 operands are similar to regular branch targets, but only + // negative values are allowed for concrete immediates as signing instr + // should be in a lower address. + if (!isImm()) + return false; + const MCConstantExpr *MCE = dyn_cast(getImm()); + if (!MCE) + return true; + int64_t Val = MCE->getValue(); + if (Val & 0b11) + return false; + return (Val <= 0) && (Val > -(1 << 18)); + } + void addExpr(MCInst &Inst, const MCExpr *Expr) const { // Add as immediates when possible. Null MCExpr = 0. if (!Expr) @@ -1997,6 +2012,19 @@ class AArch64Operand : public MCParsedAsmOperand { Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2)); } + void addPAuthPCRelLabel16Operands(MCInst &Inst, unsigned N) const { + // PC-relative operands don't encode the low bits, so shift them off + // here. If it's a label, however, just put it on directly as there's + // not enough information now to do anything. + assert(N == 1 && "Invalid number of operands!"); + const MCConstantExpr *MCE = dyn_cast(getImm()); + if (!MCE) { + addExpr(Inst, getImm()); + return; + } + Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2)); + } + void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const { // Branch operands don't encode the low bits, so shift them off // here. If it's a label, however, just put it on directly as there's diff --git a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp index cf2d3879292d1..c8cebaa5995e0 100644 --- a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp +++ b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp @@ -165,6 +165,9 @@ static DecodeStatus DecodeFixedPointScaleImm32(MCInst &Inst, unsigned Imm, static DecodeStatus DecodeFixedPointScaleImm64(MCInst &Inst, unsigned Imm, uint64_t Address, const MCDisassembler *Decoder); +static DecodeStatus DecodePCRelLabel16(MCInst &Inst, unsigned Imm, + uint64_t Address, + const MCDisassembler *Decoder); static DecodeStatus DecodePCRelLabel19(MCInst &Inst, unsigned Imm, uint64_t Address, const MCDisassembler *Decoder); @@ -887,6 +890,21 @@ static DecodeStatus DecodeFixedPointScaleImm64(MCInst &Inst, unsigned Imm, return Success; } +static DecodeStatus DecodePCRelLabel16(MCInst &Inst, unsigned Imm, + uint64_t Addr, + const MCDisassembler *Decoder) { + // Immediate is encoded as the top 16-bits of an unsigned 18-bit negative + // PC-relative offset. + int64_t ImmVal = Imm; + if (ImmVal < 0 || ImmVal > (1 << 16)) + return Fail; + ImmVal = -ImmVal; + if (!Decoder->tryAddingSymbolicOperand(Inst, (ImmVal << 2), Addr, + /*IsBranch=*/false, 0, 0, 4)) + Inst.addOperand(MCOperand::createImm(ImmVal)); + return Success; +} + static DecodeStatus DecodePCRelLabel19(MCInst &Inst, unsigned Imm, uint64_t Addr, const MCDisassembler *Decoder) { diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp index a6900b8963bb3..30ef3680ae79c 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp @@ -67,6 +67,7 @@ class AArch64AsmBackend : public MCAsmBackend { {"fixup_aarch64_ldr_pcrel_imm19", 5, 19, PCRelFlagVal}, {"fixup_aarch64_movw", 5, 16, 0}, {"fixup_aarch64_pcrel_branch14", 5, 14, PCRelFlagVal}, + {"fixup_aarch64_pcrel_branch16", 5, 16, PCRelFlagVal}, {"fixup_aarch64_pcrel_branch19", 5, 19, PCRelFlagVal}, {"fixup_aarch64_pcrel_branch26", 0, 26, PCRelFlagVal}, {"fixup_aarch64_pcrel_call26", 0, 26, PCRelFlagVal}}; @@ -121,6 +122,7 @@ static unsigned getFixupKindNumBytes(unsigned Kind) { case AArch64::fixup_aarch64_movw: case AArch64::fixup_aarch64_pcrel_branch14: + case AArch64::fixup_aarch64_pcrel_branch16: case AArch64::fixup_aarch64_add_imm12: case AArch64::fixup_aarch64_ldst_imm12_scale1: case AArch64::fixup_aarch64_ldst_imm12_scale2: @@ -314,6 +316,17 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, const MCValue &Target, if (Value & 0x3) Ctx.reportError(Fixup.getLoc(), "fixup not sufficiently aligned"); return (Value >> 2) & 0x3fff; + case AArch64::fixup_aarch64_pcrel_branch16: + // Unsigned PC-relative offset, so invert the negative immediate. + SignedValue = -SignedValue; + Value = static_cast(SignedValue); + // Check valid 18-bit unsigned range. + if (SignedValue < 0 || SignedValue > ((1 << 18) - 1)) + Ctx.reportError(Fixup.getLoc(), "fixup value out of range"); + // Low two bits are not encoded (4-byte alignment assumed). + if (Value & 0b11) + Ctx.reportError(Fixup.getLoc(), "fixup not sufficiently aligned"); + return (Value >> 2) & 0xffff; case AArch64::fixup_aarch64_pcrel_branch26: case AArch64::fixup_aarch64_pcrel_call26: if (TheTriple.isOSBinFormatCOFF() && !IsResolved && SignedValue != 0) { @@ -380,6 +393,7 @@ unsigned AArch64AsmBackend::getFixupKindContainereSizeInBytes(unsigned Kind) con case AArch64::fixup_aarch64_movw: case AArch64::fixup_aarch64_pcrel_branch14: + case AArch64::fixup_aarch64_pcrel_branch16: case AArch64::fixup_aarch64_add_imm12: case AArch64::fixup_aarch64_ldst_imm12_scale1: case AArch64::fixup_aarch64_ldst_imm12_scale2: diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp index 9de40661298cc..496ab18e9b195 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp @@ -186,6 +186,10 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx, return R_CLS(LD_PREL_LO19); case AArch64::fixup_aarch64_pcrel_branch14: return R_CLS(TSTBR14); + case AArch64::fixup_aarch64_pcrel_branch16: + Ctx.reportError(Fixup.getLoc(), + "relocation of PAC/AUT instructions is not supported"); + return ELF::R_AARCH64_NONE; case AArch64::fixup_aarch64_pcrel_branch19: return R_CLS(CONDBR19); default: diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64FixupKinds.h b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64FixupKinds.h index 767dd88055201..fdee2d5ad2bf3 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64FixupKinds.h +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64FixupKinds.h @@ -43,6 +43,11 @@ enum Fixups { // The high 14 bits of a 21-bit pc-relative immediate. fixup_aarch64_pcrel_branch14, + // The high 16 bits of a 18-bit unsigned PC-relative immediate. Used by + // pointer authentication, only within a function, so no relocation can be + // generated. + fixup_aarch64_pcrel_branch16, + // The high 19 bits of a 21-bit pc-relative immediate. Same encoding as // fixup_aarch64_pcrel_adrhi, except this is use by b.cc and generates // relocations directly when necessary. diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp index dbc4323a860f5..c3e12b6d8024e 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp @@ -88,6 +88,12 @@ class AArch64MCCodeEmitter : public MCCodeEmitter { SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + /// getPAuthPCRelOpValue - Return the encoded value for a pointer + /// authentication pc-relative operand. + uint32_t getPAuthPCRelOpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + /// getLoadLiteralOpValue - Return the encoded value for a load-literal /// pc-relative address. uint32_t getLoadLiteralOpValue(const MCInst &MI, unsigned OpIdx, @@ -327,6 +333,29 @@ uint32_t AArch64MCCodeEmitter::getCondBranchTargetOpValue( return 0; } +/// getPAuthPCRelOpValue - Return the encoded value for a pointer +/// authentication pc-relative operand. +uint32_t +AArch64MCCodeEmitter::getPAuthPCRelOpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpIdx); + + // If the destination is an immediate, invert sign as it's a negative value + // that should be encoded as unsigned + if (MO.isImm()) + return -(MO.getImm()); + assert(MO.isExpr() && "Unexpected target type!"); + + MCFixupKind Kind = MCFixupKind(AArch64::fixup_aarch64_pcrel_branch16); + Fixups.push_back(MCFixup::create(0, MO.getExpr(), Kind, MI.getLoc())); + + ++MCNumFixups; + + // All of the information is in the fixup. + return 0; +} + /// getLoadLiteralOpValue - Return the encoded value for a load-literal /// pc-relative address. uint32_t diff --git a/llvm/lib/TargetParser/ARMTargetParserCommon.cpp b/llvm/lib/TargetParser/ARMTargetParserCommon.cpp index 10b80cad43472..6d3a59d532fd3 100644 --- a/llvm/lib/TargetParser/ARMTargetParserCommon.cpp +++ b/llvm/lib/TargetParser/ARMTargetParserCommon.cpp @@ -134,13 +134,13 @@ ARM::EndianKind ARM::parseArchEndian(StringRef Arch) { } // Parse a branch protection specification, which has the form -// standard | none | [bti,pac-ret[+b-key,+leaf]*] +// standard | none | [bti,pac-ret[+b-key,+leaf,+pc]*] // Returns true on success, with individual elements of the specification // returned in `PBP`. Returns false in error, with `Err` containing // an erroneous part of the spec. bool ARM::parseBranchProtection(StringRef Spec, ParsedBranchProtection &PBP, StringRef &Err) { - PBP = {"none", "a_key", false}; + PBP = {"none", "a_key", false, false}; if (Spec == "none") return true; // defaults are ok @@ -166,6 +166,8 @@ bool ARM::parseBranchProtection(StringRef Spec, ParsedBranchProtection &PBP, PBP.Scope = "all"; else if (PACOpt == "b-key") PBP.Key = "b_key"; + else if (PACOpt == "pc") + PBP.BranchProtectionPAuthLR = true; else break; } diff --git a/llvm/test/CodeGen/AArch64/sign-return-address-pauth-lr.ll b/llvm/test/CodeGen/AArch64/sign-return-address-pauth-lr.ll new file mode 100644 index 0000000000000..a78fa853d99dc --- /dev/null +++ b/llvm/test/CodeGen/AArch64/sign-return-address-pauth-lr.ll @@ -0,0 +1,542 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 + +; PauthLR is controlled via a combination of -mbranch-protection and +pauth-lr. +; -mbranch-protection=+pc enables branch protection. If the feature +pauth-lr +; is available (v9.5a onwards) then non-NOP instructions are used; otherwise +; NOP instructions are used. + +; There are 6 cases to cover: + +; feature \ -mbranch-protection= | none | pac-ret | pac-ret+pc +; ------------------------------------------------------------------------ +; without +pauth-lr | no codegen | old pac | NOP pauth-lr +; with +pauth-lr | no codegen | old pac | non-NOP pauth-lr + +; sign-return-address.ll tests combinations of -mbranch-protection=none/pac-ret +; and whether +pauth-lr is present or not. + +; sign-return-address-pauth-lr.ll is identical, with the addition of this module +; attribute, which enables -mbranch-protection=pac-ret+pc, and therefore tests +; the remaining parameter combinations in the table: +!llvm.module.flags = !{!1} +!1 = !{i32 1, !"branch-protection-pauth-lr", i32 1} + +; RUN: llc -mtriple=aarch64 < %s | FileCheck --check-prefixes=CHECK,COMPAT %s +; RUN: llc -mtriple=aarch64 -mattr=v8.3a < %s | FileCheck --check-prefixes=CHECK,V83A %s +; RUN: llc -mtriple=aarch64 -mattr=v9a -mattr=pauth-lr < %s | FileCheck --check-prefixes=PAUTHLR %s + +define i32 @leaf(i32 %x) { +; CHECK-LABEL: leaf: +; CHECK: // %bb.0: +; CHECK-NEXT: ret +; +; PAUTHLR-LABEL: leaf: +; PAUTHLR: // %bb.0: +; PAUTHLR-NEXT: ret + ret i32 %x +} + +define i32 @leaf_sign_none(i32 %x) "sign-return-address"="none" { +; CHECK-LABEL: leaf_sign_none: +; CHECK: // %bb.0: +; CHECK-NEXT: ret +; +; PAUTHLR-LABEL: leaf_sign_none: +; PAUTHLR: // %bb.0: +; PAUTHLR-NEXT: ret + ret i32 %x +} + +define i32 @leaf_sign_non_leaf(i32 %x) "sign-return-address"="non-leaf" { +; CHECK-LABEL: leaf_sign_non_leaf: +; CHECK: // %bb.0: +; CHECK-NEXT: ret +; +; PAUTHLR-LABEL: leaf_sign_non_leaf: +; PAUTHLR: // %bb.0: +; PAUTHLR-NEXT: ret + ret i32 %x +} + +define i32 @leaf_sign_all(i32 %x) "sign-return-address"="all" { +; COMPAT-LABEL: leaf_sign_all: +; COMPAT: // %bb.0: +; COMPAT-NEXT: hint #39 +; COMPAT-NEXT: .Ltmp0: +; COMPAT-NEXT: hint #25 +; COMPAT-NEXT: .cfi_negate_ra_state +; COMPAT-NEXT: adr x16, .Ltmp0 +; COMPAT-NEXT: hint #39 +; COMPAT-NEXT: hint #29 +; COMPAT-NEXT: ret +; +; V83A-LABEL: leaf_sign_all: +; V83A: // %bb.0: +; V83A-NEXT: hint #39 +; V83A-NEXT: .Ltmp0: +; V83A-NEXT: paciasp +; V83A-NEXT: .cfi_negate_ra_state +; V83A-NEXT: adr x16, .Ltmp0 +; V83A-NEXT: hint #39 +; V83A-NEXT: retaa +; +; PAUTHLR-LABEL: leaf_sign_all: +; PAUTHLR: // %bb.0: +; PAUTHLR-NEXT: .Ltmp0: +; PAUTHLR-NEXT: paciasppc +; PAUTHLR-NEXT: .cfi_negate_ra_state +; PAUTHLR-NEXT: retaasppc .Ltmp0 + ret i32 %x +} + +define i64 @leaf_clobbers_lr(i64 %x) "sign-return-address"="non-leaf" { +; COMPAT-LABEL: leaf_clobbers_lr: +; COMPAT: // %bb.0: +; COMPAT-NEXT: hint #39 +; COMPAT-NEXT: .Ltmp1: +; COMPAT-NEXT: hint #25 +; COMPAT-NEXT: .cfi_negate_ra_state +; COMPAT-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; COMPAT-NEXT: .cfi_def_cfa_offset 16 +; COMPAT-NEXT: .cfi_offset w30, -16 +; COMPAT-NEXT: //APP +; COMPAT-NEXT: mov x30, x0 +; COMPAT-NEXT: //NO_APP +; COMPAT-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; COMPAT-NEXT: adr x16, .Ltmp1 +; COMPAT-NEXT: hint #39 +; COMPAT-NEXT: hint #29 +; COMPAT-NEXT: ret +; +; V83A-LABEL: leaf_clobbers_lr: +; V83A: // %bb.0: +; V83A-NEXT: hint #39 +; V83A-NEXT: .Ltmp1: +; V83A-NEXT: paciasp +; V83A-NEXT: .cfi_negate_ra_state +; V83A-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; V83A-NEXT: .cfi_def_cfa_offset 16 +; V83A-NEXT: .cfi_offset w30, -16 +; V83A-NEXT: //APP +; V83A-NEXT: mov x30, x0 +; V83A-NEXT: //NO_APP +; V83A-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; V83A-NEXT: adr x16, .Ltmp1 +; V83A-NEXT: hint #39 +; V83A-NEXT: retaa +; +; PAUTHLR-LABEL: leaf_clobbers_lr: +; PAUTHLR: // %bb.0: +; PAUTHLR-NEXT: .Ltmp1: +; PAUTHLR-NEXT: paciasppc +; PAUTHLR-NEXT: .cfi_negate_ra_state +; PAUTHLR-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; PAUTHLR-NEXT: .cfi_def_cfa_offset 16 +; PAUTHLR-NEXT: .cfi_offset w30, -16 +; PAUTHLR-NEXT: //APP +; PAUTHLR-NEXT: mov x30, x0 +; PAUTHLR-NEXT: //NO_APP +; PAUTHLR-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; PAUTHLR-NEXT: retaasppc .Ltmp1 + call void asm sideeffect "mov x30, $0", "r,~{lr}"(i64 %x) #1 + ret i64 %x +} + +declare i32 @foo(i32) + +define i32 @non_leaf_sign_all(i32 %x) "sign-return-address"="all" { +; COMPAT-LABEL: non_leaf_sign_all: +; COMPAT: // %bb.0: +; COMPAT-NEXT: hint #39 +; COMPAT-NEXT: .Ltmp2: +; COMPAT-NEXT: hint #25 +; COMPAT-NEXT: .cfi_negate_ra_state +; COMPAT-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; COMPAT-NEXT: .cfi_def_cfa_offset 16 +; COMPAT-NEXT: .cfi_offset w30, -16 +; COMPAT-NEXT: bl foo +; COMPAT-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; COMPAT-NEXT: adr x16, .Ltmp2 +; COMPAT-NEXT: hint #39 +; COMPAT-NEXT: hint #29 +; COMPAT-NEXT: ret +; +; V83A-LABEL: non_leaf_sign_all: +; V83A: // %bb.0: +; V83A-NEXT: hint #39 +; V83A-NEXT: .Ltmp2: +; V83A-NEXT: paciasp +; V83A-NEXT: .cfi_negate_ra_state +; V83A-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; V83A-NEXT: .cfi_def_cfa_offset 16 +; V83A-NEXT: .cfi_offset w30, -16 +; V83A-NEXT: bl foo +; V83A-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; V83A-NEXT: adr x16, .Ltmp2 +; V83A-NEXT: hint #39 +; V83A-NEXT: retaa +; +; PAUTHLR-LABEL: non_leaf_sign_all: +; PAUTHLR: // %bb.0: +; PAUTHLR-NEXT: .Ltmp2: +; PAUTHLR-NEXT: paciasppc +; PAUTHLR-NEXT: .cfi_negate_ra_state +; PAUTHLR-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; PAUTHLR-NEXT: .cfi_def_cfa_offset 16 +; PAUTHLR-NEXT: .cfi_offset w30, -16 +; PAUTHLR-NEXT: bl foo +; PAUTHLR-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; PAUTHLR-NEXT: retaasppc .Ltmp2 + %call = call i32 @foo(i32 %x) + ret i32 %call +} + +define i32 @non_leaf_sign_non_leaf(i32 %x) "sign-return-address"="non-leaf" { +; COMPAT-LABEL: non_leaf_sign_non_leaf: +; COMPAT: // %bb.0: +; COMPAT-NEXT: hint #39 +; COMPAT-NEXT: .Ltmp3: +; COMPAT-NEXT: hint #25 +; COMPAT-NEXT: .cfi_negate_ra_state +; COMPAT-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; COMPAT-NEXT: .cfi_def_cfa_offset 16 +; COMPAT-NEXT: .cfi_offset w30, -16 +; COMPAT-NEXT: bl foo +; COMPAT-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; COMPAT-NEXT: adr x16, .Ltmp3 +; COMPAT-NEXT: hint #39 +; COMPAT-NEXT: hint #29 +; COMPAT-NEXT: ret +; +; V83A-LABEL: non_leaf_sign_non_leaf: +; V83A: // %bb.0: +; V83A-NEXT: hint #39 +; V83A-NEXT: .Ltmp3: +; V83A-NEXT: paciasp +; V83A-NEXT: .cfi_negate_ra_state +; V83A-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; V83A-NEXT: .cfi_def_cfa_offset 16 +; V83A-NEXT: .cfi_offset w30, -16 +; V83A-NEXT: bl foo +; V83A-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; V83A-NEXT: adr x16, .Ltmp3 +; V83A-NEXT: hint #39 +; V83A-NEXT: retaa +; +; PAUTHLR-LABEL: non_leaf_sign_non_leaf: +; PAUTHLR: // %bb.0: +; PAUTHLR-NEXT: .Ltmp3: +; PAUTHLR-NEXT: paciasppc +; PAUTHLR-NEXT: .cfi_negate_ra_state +; PAUTHLR-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; PAUTHLR-NEXT: .cfi_def_cfa_offset 16 +; PAUTHLR-NEXT: .cfi_offset w30, -16 +; PAUTHLR-NEXT: bl foo +; PAUTHLR-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; PAUTHLR-NEXT: retaasppc .Ltmp3 + %call = call i32 @foo(i32 %x) + ret i32 %call +} + +; Should not use the RETAA instruction. +define i32 @non_leaf_scs(i32 %x) "sign-return-address"="non-leaf" shadowcallstack "target-features"="+v8.3a,+reserve-x18" { +; CHECK-LABEL: non_leaf_scs: +; CHECK: // %bb.0: +; CHECK-NEXT: str x30, [x18], #8 +; CHECK-NEXT: .cfi_escape 0x16, 0x12, 0x02, 0x82, 0x78 // +; CHECK-NEXT: hint #39 +; CHECK-NEXT: .Ltmp4: +; CHECK-NEXT: paciasp +; CHECK-NEXT: .cfi_negate_ra_state +; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: .cfi_offset w30, -16 +; CHECK-NEXT: bl foo +; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; CHECK-NEXT: adr x16, .Ltmp4 +; CHECK-NEXT: hint #39 +; CHECK-NEXT: autiasp +; CHECK-NEXT: ldr x30, [x18, #-8]! +; CHECK-NEXT: ret +; +; PAUTHLR-LABEL: non_leaf_scs: +; PAUTHLR: // %bb.0: +; PAUTHLR-NEXT: str x30, [x18], #8 +; PAUTHLR-NEXT: .cfi_escape 0x16, 0x12, 0x02, 0x82, 0x78 // +; PAUTHLR-NEXT: .Ltmp4: +; PAUTHLR-NEXT: paciasppc +; PAUTHLR-NEXT: .cfi_negate_ra_state +; PAUTHLR-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; PAUTHLR-NEXT: .cfi_def_cfa_offset 16 +; PAUTHLR-NEXT: .cfi_offset w30, -16 +; PAUTHLR-NEXT: bl foo +; PAUTHLR-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; PAUTHLR-NEXT: autiasppc .Ltmp4 +; PAUTHLR-NEXT: ldr x30, [x18, #-8]! +; PAUTHLR-NEXT: ret + %call = call i32 @foo(i32 %x) + ret i32 %call +} + +define i32 @leaf_sign_all_v83(i32 %x) "sign-return-address"="all" "target-features"="+v8.3a" { +; CHECK-LABEL: leaf_sign_all_v83: +; CHECK: // %bb.0: +; CHECK-NEXT: hint #39 +; CHECK-NEXT: .Ltmp5: +; CHECK-NEXT: paciasp +; CHECK-NEXT: .cfi_negate_ra_state +; CHECK-NEXT: adr x16, .Ltmp5 +; CHECK-NEXT: hint #39 +; CHECK-NEXT: retaa +; +; PAUTHLR-LABEL: leaf_sign_all_v83: +; PAUTHLR: // %bb.0: +; PAUTHLR-NEXT: .Ltmp5: +; PAUTHLR-NEXT: paciasppc +; PAUTHLR-NEXT: .cfi_negate_ra_state +; PAUTHLR-NEXT: retaasppc .Ltmp5 + ret i32 %x +} + +declare fastcc i64 @bar(i64) + +define fastcc void @spill_lr_and_tail_call(i64 %x) "sign-return-address"="all" { +; COMPAT-LABEL: spill_lr_and_tail_call: +; COMPAT: // %bb.0: +; COMPAT-NEXT: hint #39 +; COMPAT-NEXT: .Ltmp6: +; COMPAT-NEXT: hint #25 +; COMPAT-NEXT: .cfi_negate_ra_state +; COMPAT-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; COMPAT-NEXT: .cfi_def_cfa_offset 16 +; COMPAT-NEXT: .cfi_offset w30, -16 +; COMPAT-NEXT: //APP +; COMPAT-NEXT: mov x30, x0 +; COMPAT-NEXT: //NO_APP +; COMPAT-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; COMPAT-NEXT: adr x16, .Ltmp6 +; COMPAT-NEXT: hint #39 +; COMPAT-NEXT: hint #29 +; COMPAT-NEXT: b bar +; +; V83A-LABEL: spill_lr_and_tail_call: +; V83A: // %bb.0: +; V83A-NEXT: hint #39 +; V83A-NEXT: .Ltmp6: +; V83A-NEXT: paciasp +; V83A-NEXT: .cfi_negate_ra_state +; V83A-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; V83A-NEXT: .cfi_def_cfa_offset 16 +; V83A-NEXT: .cfi_offset w30, -16 +; V83A-NEXT: //APP +; V83A-NEXT: mov x30, x0 +; V83A-NEXT: //NO_APP +; V83A-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; V83A-NEXT: adr x16, .Ltmp6 +; V83A-NEXT: hint #39 +; V83A-NEXT: autiasp +; V83A-NEXT: b bar +; +; PAUTHLR-LABEL: spill_lr_and_tail_call: +; PAUTHLR: // %bb.0: +; PAUTHLR-NEXT: .Ltmp6: +; PAUTHLR-NEXT: paciasppc +; PAUTHLR-NEXT: .cfi_negate_ra_state +; PAUTHLR-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill +; PAUTHLR-NEXT: .cfi_def_cfa_offset 16 +; PAUTHLR-NEXT: .cfi_offset w30, -16 +; PAUTHLR-NEXT: //APP +; PAUTHLR-NEXT: mov x30, x0 +; PAUTHLR-NEXT: //NO_APP +; PAUTHLR-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload +; PAUTHLR-NEXT: autiasppc .Ltmp6 +; PAUTHLR-NEXT: b bar + call void asm sideeffect "mov x30, $0", "r,~{lr}"(i64 %x) #1 + tail call fastcc i64 @bar(i64 %x) + ret void +} + +define i32 @leaf_sign_all_a_key(i32 %x) "sign-return-address"="all" "sign-return-address-key"="a_key" { +; COMPAT-LABEL: leaf_sign_all_a_key: +; COMPAT: // %bb.0: +; COMPAT-NEXT: hint #39 +; COMPAT-NEXT: .Ltmp7: +; COMPAT-NEXT: hint #25 +; COMPAT-NEXT: .cfi_negate_ra_state +; COMPAT-NEXT: adr x16, .Ltmp7 +; COMPAT-NEXT: hint #39 +; COMPAT-NEXT: hint #29 +; COMPAT-NEXT: ret +; +; V83A-LABEL: leaf_sign_all_a_key: +; V83A: // %bb.0: +; V83A-NEXT: hint #39 +; V83A-NEXT: .Ltmp7: +; V83A-NEXT: paciasp +; V83A-NEXT: .cfi_negate_ra_state +; V83A-NEXT: adr x16, .Ltmp7 +; V83A-NEXT: hint #39 +; V83A-NEXT: retaa +; +; PAUTHLR-LABEL: leaf_sign_all_a_key: +; PAUTHLR: // %bb.0: +; PAUTHLR-NEXT: .Ltmp7: +; PAUTHLR-NEXT: paciasppc +; PAUTHLR-NEXT: .cfi_negate_ra_state +; PAUTHLR-NEXT: retaasppc .Ltmp7 + ret i32 %x +} + +define i32 @leaf_sign_all_b_key(i32 %x) "sign-return-address"="all" "sign-return-address-key"="b_key" { +; COMPAT-LABEL: leaf_sign_all_b_key: +; COMPAT: // %bb.0: +; COMPAT-NEXT: .cfi_b_key_frame +; COMPAT-NEXT: hint #39 +; COMPAT-NEXT: .Ltmp8: +; COMPAT-NEXT: hint #27 +; COMPAT-NEXT: .cfi_negate_ra_state +; COMPAT-NEXT: adr x16, .Ltmp8 +; COMPAT-NEXT: hint #39 +; COMPAT-NEXT: hint #31 +; COMPAT-NEXT: ret +; +; V83A-LABEL: leaf_sign_all_b_key: +; V83A: // %bb.0: +; V83A-NEXT: .cfi_b_key_frame +; V83A-NEXT: hint #39 +; V83A-NEXT: .Ltmp8: +; V83A-NEXT: pacibsp +; V83A-NEXT: .cfi_negate_ra_state +; V83A-NEXT: adr x16, .Ltmp8 +; V83A-NEXT: hint #39 +; V83A-NEXT: retab +; +; PAUTHLR-LABEL: leaf_sign_all_b_key: +; PAUTHLR: // %bb.0: +; PAUTHLR-NEXT: .cfi_b_key_frame +; PAUTHLR-NEXT: .Ltmp8: +; PAUTHLR-NEXT: pacibsppc +; PAUTHLR-NEXT: .cfi_negate_ra_state +; PAUTHLR-NEXT: retabsppc .Ltmp8 + ret i32 %x +} + +define i32 @leaf_sign_all_v83_b_key(i32 %x) "sign-return-address"="all" "target-features"="+v8.3a" "sign-return-address-key"="b_key" { +; CHECK-LABEL: leaf_sign_all_v83_b_key: +; CHECK: // %bb.0: +; CHECK-NEXT: .cfi_b_key_frame +; CHECK-NEXT: hint #39 +; CHECK-NEXT: .Ltmp9: +; CHECK-NEXT: pacibsp +; CHECK-NEXT: .cfi_negate_ra_state +; CHECK-NEXT: adr x16, .Ltmp9 +; CHECK-NEXT: hint #39 +; CHECK-NEXT: retab +; +; PAUTHLR-LABEL: leaf_sign_all_v83_b_key: +; PAUTHLR: // %bb.0: +; PAUTHLR-NEXT: .cfi_b_key_frame +; PAUTHLR-NEXT: .Ltmp9: +; PAUTHLR-NEXT: pacibsppc +; PAUTHLR-NEXT: .cfi_negate_ra_state +; PAUTHLR-NEXT: retabsppc .Ltmp9 + ret i32 %x +} + +; Note that BTI instruction is not needed before PACIASP. +define i32 @leaf_sign_all_a_key_bti(i32 %x) "sign-return-address"="all" "sign-return-address-key"="a_key" "branch-target-enforcement"="true"{ +; COMPAT-LABEL: leaf_sign_all_a_key_bti: +; COMPAT: // %bb.0: +; COMPAT-NEXT: hint #34 +; COMPAT-NEXT: hint #39 +; COMPAT-NEXT: .Ltmp10: +; COMPAT-NEXT: hint #25 +; COMPAT-NEXT: .cfi_negate_ra_state +; COMPAT-NEXT: adr x16, .Ltmp10 +; COMPAT-NEXT: hint #39 +; COMPAT-NEXT: hint #29 +; COMPAT-NEXT: ret +; +; V83A-LABEL: leaf_sign_all_a_key_bti: +; V83A: // %bb.0: +; V83A-NEXT: hint #34 +; V83A-NEXT: hint #39 +; V83A-NEXT: .Ltmp10: +; V83A-NEXT: paciasp +; V83A-NEXT: .cfi_negate_ra_state +; V83A-NEXT: adr x16, .Ltmp10 +; V83A-NEXT: hint #39 +; V83A-NEXT: retaa +; +; PAUTHLR-LABEL: leaf_sign_all_a_key_bti: +; PAUTHLR: // %bb.0: +; PAUTHLR-NEXT: bti c +; PAUTHLR-NEXT: .Ltmp10: +; PAUTHLR-NEXT: paciasppc +; PAUTHLR-NEXT: .cfi_negate_ra_state +; PAUTHLR-NEXT: retaasppc .Ltmp10 + ret i32 %x +} + +; Note that BTI instruction is not needed before PACIBSP. +define i32 @leaf_sign_all_b_key_bti(i32 %x) "sign-return-address"="all" "sign-return-address-key"="b_key" "branch-target-enforcement"="true"{ +; COMPAT-LABEL: leaf_sign_all_b_key_bti: +; COMPAT: // %bb.0: +; COMPAT-NEXT: hint #34 +; COMPAT-NEXT: .cfi_b_key_frame +; COMPAT-NEXT: hint #39 +; COMPAT-NEXT: .Ltmp11: +; COMPAT-NEXT: hint #27 +; COMPAT-NEXT: .cfi_negate_ra_state +; COMPAT-NEXT: adr x16, .Ltmp11 +; COMPAT-NEXT: hint #39 +; COMPAT-NEXT: hint #31 +; COMPAT-NEXT: ret +; +; V83A-LABEL: leaf_sign_all_b_key_bti: +; V83A: // %bb.0: +; V83A-NEXT: hint #34 +; V83A-NEXT: .cfi_b_key_frame +; V83A-NEXT: hint #39 +; V83A-NEXT: .Ltmp11: +; V83A-NEXT: pacibsp +; V83A-NEXT: .cfi_negate_ra_state +; V83A-NEXT: adr x16, .Ltmp11 +; V83A-NEXT: hint #39 +; V83A-NEXT: retab +; +; PAUTHLR-LABEL: leaf_sign_all_b_key_bti: +; PAUTHLR: // %bb.0: +; PAUTHLR-NEXT: bti c +; PAUTHLR-NEXT: .cfi_b_key_frame +; PAUTHLR-NEXT: .Ltmp11: +; PAUTHLR-NEXT: pacibsppc +; PAUTHLR-NEXT: .cfi_negate_ra_state +; PAUTHLR-NEXT: retabsppc .Ltmp11 + ret i32 %x +} + +; Note that BTI instruction is not needed before PACIBSP. +define i32 @leaf_sign_all_v83_b_key_bti(i32 %x) "sign-return-address"="all" "target-features"="+v8.3a" "sign-return-address-key"="b_key" "branch-target-enforcement"="true" { +; CHECK-LABEL: leaf_sign_all_v83_b_key_bti: +; CHECK: // %bb.0: +; CHECK-NEXT: hint #34 +; CHECK-NEXT: .cfi_b_key_frame +; CHECK-NEXT: hint #39 +; CHECK-NEXT: .Ltmp12: +; CHECK-NEXT: pacibsp +; CHECK-NEXT: .cfi_negate_ra_state +; CHECK-NEXT: adr x16, .Ltmp12 +; CHECK-NEXT: hint #39 +; CHECK-NEXT: retab +; +; PAUTHLR-LABEL: leaf_sign_all_v83_b_key_bti: +; PAUTHLR: // %bb.0: +; PAUTHLR-NEXT: bti c +; PAUTHLR-NEXT: .cfi_b_key_frame +; PAUTHLR-NEXT: .Ltmp12: +; PAUTHLR-NEXT: pacibsppc +; PAUTHLR-NEXT: .cfi_negate_ra_state +; PAUTHLR-NEXT: retabsppc .Ltmp12 + ret i32 %x +} diff --git a/llvm/test/CodeGen/AArch64/sign-return-address.ll b/llvm/test/CodeGen/AArch64/sign-return-address.ll index 5680915c7f414..1481d4beb50d6 100644 --- a/llvm/test/CodeGen/AArch64/sign-return-address.ll +++ b/llvm/test/CodeGen/AArch64/sign-return-address.ll @@ -2,6 +2,9 @@ ; RUN: llc -mtriple=aarch64 < %s | FileCheck --check-prefixes=CHECK,COMPAT %s ; RUN: llc -mtriple=aarch64 -mattr=v8.3a < %s | FileCheck --check-prefixes=CHECK,V83A %s +; v9.5-A is not expected to change codegen without -mbranch-protection=+pc, so reuse V83A. +; RUN: llc -mtriple=aarch64 -mattr=v9.5a < %s | FileCheck --check-prefixes=CHECK,V83A %s + define i32 @leaf(i32 %x) { ; CHECK-LABEL: leaf: ; CHECK: // %bb.0: diff --git a/llvm/test/MC/AArch64/armv9.5a-pauthlr-diagnostics.s b/llvm/test/MC/AArch64/armv9.5a-pauthlr-diagnostics.s new file mode 100644 index 0000000000000..d06183be9da3e --- /dev/null +++ b/llvm/test/MC/AArch64/armv9.5a-pauthlr-diagnostics.s @@ -0,0 +1,57 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+pauth-lr 2>&1 < %s | FileCheck %s + + autiasppc #2 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: expected label or encodable integer pc offset +// CHECK-NEXT: autiasppc #2 +// CHECK-NOT: [[@LINE-3]]:{{[0-9]+}}: + + autiasppc #1<<17 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: expected label or encodable integer pc offset +// CHECK-NEXT: autiasppc #1<<17 +// CHECK-NOT: [[@LINE-3]]:{{[0-9]+}}: + + autiasppc #-2 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: expected label or encodable integer pc offset +// CHECK-NEXT: autiasppc #-2 +// CHECK-NOT: [[@LINE-3]]:{{[0-9]+}}: + + autiasppc w0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: expected label or encodable integer pc offset +// CHECK-NEXT: autiasppc w0 +// CHECK-NOT: [[@LINE-3]]:{{[0-9]+}}: + + autiasppc sp +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: expected label or encodable integer pc offset +// CHECK-NEXT: autiasppc sp +// CHECK-NOT: [[@LINE-3]]:{{[0-9]+}}: + + retabsppc #2 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: expected label or encodable integer pc offset +// CHECK-NEXT: retabsppc #2 +// CHECK-NOT: [[@LINE-3]]:{{[0-9]+}}: + + retabsppc #(1<<17) +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: expected label or encodable integer pc offset +// CHECK-NEXT: retabsppc #(1<<17) +// CHECK-NOT: [[@LINE-3]]:{{[0-9]+}}: + + retabsppc #-2 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: expected label or encodable integer pc offset +// CHECK-NEXT: retabsppc #-2 +// CHECK-NOT: [[@LINE-3]]:{{[0-9]+}}: + + retaasppc w0 +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: expected label or encodable integer pc offset +// CHECK-NEXT: retaasppc w0 +// CHECK-NOT: [[@LINE-3]]:{{[0-9]+}}: + + retaasppc sp +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: expected label or encodable integer pc offset +// CHECK-NEXT: retaasppc sp +// CHECK-NOT: [[@LINE-3]]:{{[0-9]+}}: + + retaasppc xzr +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: expected label or encodable integer pc offset +// CHECK-NEXT: retaasppc xzr +// CHECK-NOT: [[@LINE-3]]:{{[0-9]+}}: + diff --git a/llvm/test/MC/AArch64/armv9.5a-pauthlr-reloc.s b/llvm/test/MC/AArch64/armv9.5a-pauthlr-reloc.s new file mode 100644 index 0000000000000..c10142a199766 --- /dev/null +++ b/llvm/test/MC/AArch64/armv9.5a-pauthlr-reloc.s @@ -0,0 +1,12 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+pauth-lr -filetype=obj -o /dev/null 2>&1 < %s | FileCheck %s + + autiasppc undef_label +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: relocation of PAC/AUT instructions is not supported +// CHECK-NEXT: autiasppc undef_label +// CHECK-NOT: [[@LINE-3]]:{{[0-9]+}}: + + autibsppc undef_label +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: relocation of PAC/AUT instructions is not supported +// CHECK-NEXT: autibsppc undef_label +// CHECK-NOT: [[@LINE-3]]:{{[0-9]+}}: + diff --git a/llvm/test/MC/AArch64/armv9.5a-pauthlr.s b/llvm/test/MC/AArch64/armv9.5a-pauthlr.s new file mode 100644 index 0000000000000..24e9c44984683 --- /dev/null +++ b/llvm/test/MC/AArch64/armv9.5a-pauthlr.s @@ -0,0 +1,151 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+pauth-lr < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+pauth-lr < %s \ +// RUN: | llvm-objdump -d --mattr=+pauth-lr - | FileCheck %s --check-prefix=CHECK-DISASS +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+pauth-lr < %s \ +// RUN: | llvm-objdump -d --mattr=-pauth-lr - | FileCheck %s --check-prefix=CHECK-UNKNOWN + +// Label at address 4, so we can test that the address shows up in the +// disassembly. + nop +label1: + + paciasppc +// CHECK-INST: paciasppc +// CHECK-DISASS: paciasppc +// CHECK-ENCODING: [0xfe,0xa3,0xc1,0xda] +// CHECK-ERROR: instruction requires: pauth-lr +// CHECK-UNKNOWN: dac1a3fe + + pacibsppc +// CHECK-INST: pacibsppc +// CHECK-DISASS: pacibsppc +// CHECK-ENCODING: [0xfe,0xa7,0xc1,0xda] +// CHECK-ERROR: instruction requires: pauth-lr +// CHECK-UNKNOWN: dac1a7fe + + pacnbiasppc +// CHECK-INST: pacnbiasppc +// CHECK-DISASS: pacnbiasppc +// CHECK-ENCODING: [0xfe,0x83,0xc1,0xda] +// CHECK-ERROR: instruction requires: pauth-lr +// CHECK-UNKNOWN: dac183fe + + pacnbibsppc +// CHECK-INST: pacnbibsppc +// CHECK-DISASS: pacnbibsppc +// CHECK-ENCODING: [0xfe,0x87,0xc1,0xda] +// CHECK-ERROR: instruction requires: pauth-lr +// CHECK-UNKNOWN: dac187fe + + autiasppc label1 +// CHECK-INST: autiasppc label1 +// CHECK-DISASS: autiasppc 0x4 +// CHECK-ENCODING: [0bAAA11111,A,0b100AAAAA,0xf3] +// CHECK-ENCODING: fixup A - offset: 0, value: label1, kind: fixup_aarch64_pcrel_branch16 +// CHECK-ERROR: instruction requires: pauth-lr +// CHECK-UNKNOWN: f380009f + + autibsppc label1 +// CHECK-INST: autibsppc label1 +// CHECK-DISASS: autibsppc 0x4 +// CHECK-ENCODING: [0bAAA11111,A,0b101AAAAA,0xf3] +// CHECK-ENCODING: fixup A - offset: 0, value: label1, kind: fixup_aarch64_pcrel_branch16 +// CHECK-ERROR: instruction requires: pauth-lr +// CHECK-UNKNOWN: f3a000bf + + autibsppc #0 +// CHECK-INST: autibsppc #0 +// CHECK-DISASS: autibsppc 0x1c +// CHECK-ENCODING: [0x1f,0x00,0xa0,0xf3] +// CHECK-ERROR: instruction requires: pauth-lr +// CHECK-UNKNOWN: f3a0001f + + autibsppc #-(1<<18)+4 +// CHECK-INST: autibsppc #-262140 +// CHECK-DISASS: autibsppc 0xfffffffffffc0024 +// CHECK-ENCODING: [0xff,0xff,0xbf,0xf3] +// CHECK-ERROR: instruction requires: pauth-lr +// CHECK-UNKNOWN: f3bfffff + + autiasppc x0 +// CHECK-INST: autiasppc x0 +// CHECK-DISASS: autiasppc x0 +// CHECK-ENCODING: [0x1e,0x90,0xc1,0xda] +// CHECK-ERROR: instruction requires: pauth-lr +// CHECK-UNKNOWN: dac1901e + + autibsppc x1 +// CHECK-INST: autibsppc x1 +// CHECK-DISASS: autibsppc x1 +// CHECK-ENCODING: [0x3e,0x94,0xc1,0xda] +// CHECK-ERROR: instruction requires: pauth-lr +// CHECK-UNKNOWN: dac1943e + + autiasppc xzr +// CHECK-INST: autiasppc xzr +// CHECK-DISASS: autiasppc xzr +// CHECK-ENCODING: [0xfe,0x93,0xc1,0xda] +// CHECK-ERROR: instruction requires: pauth-lr +// CHECK-UNKNOWN: dac193fe + + autibsppc xzr +// CHECK-INST: autibsppc xzr +// CHECK-DISASS: autibsppc xzr +// CHECK-ENCODING: [0xfe,0x97,0xc1,0xda] +// CHECK-ERROR: instruction requires: pauth-lr +// CHECK-UNKNOWN: dac197fe + + + retaasppc label1 +// CHECK-INST: retaasppc label1 +// CHECK-DISASS: retaasppc 0x4 +// CHECK-ENCODING: [0bAAA11111,A,0b000AAAAA,0x55] +// CHECK-ENCODING: // fixup A - offset: 0, value: label1, kind: fixup_aarch64_pcrel_branch16 +// CHECK-ERROR: instruction requires: pauth-lr +// CHECK-UNKNOWN: 5500019f + + retabsppc label1 +// CHECK-INST: retabsppc label1 +// CHECK-DISASS: retabsppc 0x4 +// CHECK-ENCODING: [0bAAA11111,A,0b001AAAAA,0x55] +// CHECK-ENCODING: // fixup A - offset: 0, value: label1, kind: fixup_aarch64_pcrel_branch16 +// CHECK-ERROR: instruction requires: pauth-lr +// CHECK-UNKNOWN: 552001bf + + retaasppc #0 +// CHECK-INST: retaasppc #0 +// CHECK-DISASS: retaasppc 0x3c +// CHECK-ENCODING: [0x1f,0x00,0x00,0x55] +// CHECK-ERROR: instruction requires: pauth-lr +// CHECK-UNKNOWN: 5500001f + + retaasppc #-(1<<18)+4 +// CHECK-INST: retaasppc #-262140 +// CHECK-DISASS: retaasppc 0xfffffffffffc0044 +// CHECK-ENCODING: [0xff,0xff,0x1f,0x55] +// CHECK-ERROR: instruction requires: pauth-lr +// CHECK-UNKNOWN: 551fffff + + retaasppc x2 +// CHECK-INST: retaasppc x2 +// CHECK-DISASS: retaasppc x2 +// CHECK-ENCODING: [0xe2,0x0b,0x5f,0xd6] +// CHECK-ERROR: instruction requires: pauth-lr +// CHECK-UNKNOWN: d65f0be2 + + retabsppc x3 +// CHECK-INST: retabsppc x3 +// CHECK-DISASS: retabsppc x3 +// CHECK-ENCODING: [0xe3,0x0f,0x5f,0xd6] +// CHECK-ERROR: instruction requires: pauth-lr +// CHECK-UNKNOWN: d65f0fe3 + + pacm +// CHECK-INST: pacm +// CHECK-DISASS: pacm +// CHECK-ENCODING: [0xff,0x24,0x03,0xd5] +// CHECK-ERROR-NOT: instruction requires: +// CHECK-UNKNOWN: d50324ff hint #39 diff --git a/llvm/test/MC/Disassembler/AArch64/armv9.5a-pauthlr.txt b/llvm/test/MC/Disassembler/AArch64/armv9.5a-pauthlr.txt new file mode 100644 index 0000000000000..caf1fde2c2b7c --- /dev/null +++ b/llvm/test/MC/Disassembler/AArch64/armv9.5a-pauthlr.txt @@ -0,0 +1,78 @@ +# RUN: llvm-mc -triple aarch64 -disassemble -mattr=+pauth-lr < %s | FileCheck %s +# RUN: not llvm-mc -triple aarch64 -disassemble < %s 2>&1 | FileCheck %s --check-prefix=NO-PAUTHLR + +[0xfe,0xa3,0xc1,0xda] +# CHECK: paciasppc +# NO-PAUTHLR: invalid instruction encoding + +[0xfe,0xa7,0xc1,0xda] +# CHECK: pacibsppc +# NO-PAUTHLR: invalid instruction encoding + +[0xfe,0x83,0xc1,0xda] +# CHECK: pacnbiasppc +# NO-PAUTHLR: invalid instruction encoding + +[0xfe,0x87,0xc1,0xda] +# CHECK: pacnbibsppc +# NO-PAUTHLR: invalid instruction encoding + +[0x9f,0x00,0x80,0xf3] +# CHECK: autiasppc #-16 +# NO-PAUTHLR: invalid instruction encoding + +[0xbf,0x00,0xa0,0xf3] +# CHECK: autibsppc #-20 +# NO-PAUTHLR: invalid instruction encoding + +[0x1f,0x00,0xa0,0xf3] +# CHECK: autibsppc #0 +# NO-PAUTHLR: invalid instruction encoding + +[0xff,0xff,0xbf,0xf3] +# CHECK: autibsppc #-262140 +# NO-PAUTHLR: invalid instruction encoding + +[0x1e,0x90,0xc1,0xda] +# CHECK: autiasppc x0 +# NO-PAUTHLR: invalid instruction encoding + +[0x3e,0x94,0xc1,0xda] +# CHECK: autibsppc x1 +# NO-PAUTHLR: invalid instruction encoding + +[0xfe,0x93,0xc1,0xda] +# CHECK: autiasppc xzr +# NO-PAUTHLR: invalid instruction encoding + +[0xfe,0x97,0xc1,0xda] +# CHECK: autibsppc xzr +# NO-PAUTHLR: invalid instruction encoding + +[0xbf,0x01,0x00,0x55] +# CHECK: retaasppc #-52 +# NO-PAUTHLR: invalid instruction encoding + +[0xdf,0x01,0x20,0x55] +# CHECK: retabsppc #-56 +# NO-PAUTHLR: invalid instruction encoding + +[0x1f,0x00,0x00,0x55] +# CHECK: retaasppc #0 +# NO-PAUTHLR: invalid instruction encoding + +[0xff,0xff,0x1f,0x55] +# CHECK: retaasppc #-262140 +# NO-PAUTHLR: invalid instruction encoding + +[0xe2,0x0b,0x5f,0xd6] +# CHECK: retaasppc x2 +# NO-PAUTHLR: invalid instruction encoding + +[0xe3,0x0f,0x5f,0xd6] +# CHECK: retabsppc x3 +# NO-PAUTHLR: invalid instruction encoding + +[0xff,0x24,0x03,0xd5] +# CHECK: pacm +# NO-PAUTHLR: hint #39 diff --git a/llvm/unittests/TargetParser/TargetParserTest.cpp b/llvm/unittests/TargetParser/TargetParserTest.cpp index 30e60ad92b68e..866176ab09836 100644 --- a/llvm/unittests/TargetParser/TargetParserTest.cpp +++ b/llvm/unittests/TargetParser/TargetParserTest.cpp @@ -1812,7 +1812,8 @@ TEST(TargetParserTest, AArch64ExtensionFeatures) { AArch64::AEK_SSVE_FP8DOT4, AArch64::AEK_LUT, AArch64::AEK_SME_LUTv2, AArch64::AEK_SMEF8F16, AArch64::AEK_SMEF8F32, AArch64::AEK_SMEFA64, - AArch64::AEK_CPA}; + AArch64::AEK_CPA, AArch64::AEK_PAUTHLR, + }; std::vector Features; @@ -1899,6 +1900,7 @@ TEST(TargetParserTest, AArch64ExtensionFeatures) { EXPECT_TRUE(llvm::is_contained(Features, "+sme-f8f32")); EXPECT_TRUE(llvm::is_contained(Features, "+sme-fa64")); EXPECT_TRUE(llvm::is_contained(Features, "+cpa")); + EXPECT_TRUE(llvm::is_contained(Features, "+pauth-lr")); // Assuming we listed every extension above, this should produce the same // result. (note that AEK_NONE doesn't have a name so it won't be in the