Skip to content

Commit

Permalink
[AArch64] Add isAuthenticated predicate to MCInstDesc
Browse files Browse the repository at this point in the history
Add a predicate to MCInstDesc that allows tools to determine whether an
instruction authenticates a pointer. This can be used by diagnostic
tools to hint at pointer authentication failures.

Differential Revision: https://reviews.llvm.org/D70329

rdar://55089604
(cherry picked from commit a9052b4)
  • Loading branch information
vedantk committed Jan 10, 2020
1 parent 4f65b63 commit eb8a955
Show file tree
Hide file tree
Showing 9 changed files with 61 additions and 6 deletions.
10 changes: 10 additions & 0 deletions llvm/include/llvm/MC/MCInstrDesc.h
Expand Up @@ -168,6 +168,7 @@ enum Flag {
Add,
Trap,
VariadicOpsAreDefs,
Authenticated,
};
}

Expand Down Expand Up @@ -408,6 +409,15 @@ class MCInstrDesc {
return Flags & (1ULL << MCID::VariadicOpsAreDefs);
}

/// Return true if this instruction authenticates a pointer (e.g. LDRAx/BRAx
/// from ARMv8.3, which perform loads/branches with authentication).
///
/// An authenticated instruction may fail in an ABI-defined manner when
/// operating on an invalid signed pointer.
bool isAuthenticated() const {
return Flags & (1ULL << MCID::Authenticated);
}

//===--------------------------------------------------------------------===//
// Side Effect Analysis
//===--------------------------------------------------------------------===//
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/Target/Target.td
Expand Up @@ -530,6 +530,7 @@ class Instruction : InstructionEncoding {
bit hasCtrlDep = 0; // Does this instruction r/w ctrl-flow chains?
bit isNotDuplicable = 0; // Is it unsafe to duplicate this instruction?
bit isConvergent = 0; // Is this instruction convergent?
bit isAuthenticated = 0; // Does this instruction authenticate a pointer?
bit isAsCheapAsAMove = 0; // As cheap (or cheaper) than a move instruction.
bit hasExtraSrcRegAllocReq = 0; // Sources have special regalloc requirement?
bit hasExtraDefRegAllocReq = 0; // Defs have special regalloc requirement?
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/AArch64/AArch64InstrFormats.td
Expand Up @@ -1490,6 +1490,7 @@ class RCPCLoad<bits<2> sz, string asm, RegisterClass RC>
class AuthBase<bits<1> M, dag oops, dag iops, string asm, string operands,
list<dag> pattern>
: I<oops, iops, asm, operands, "", pattern>, Sched<[]> {
let isAuthenticated = 1;
let Inst{31-25} = 0b1101011;
let Inst{20-11} = 0b1111100001;
let Inst{10} = M;
Expand Down Expand Up @@ -1529,6 +1530,7 @@ class BaseAuthLoad<bit M, bit W, dag oops, dag iops, string asm,
bits<10> offset;
bits<5> Rn;
bits<5> Rt;
let isAuthenticated = 1;
let Inst{31-24} = 0b11111000;
let Inst{23} = M;
let Inst{22} = offset{9};
Expand Down
18 changes: 12 additions & 6 deletions llvm/lib/Target/AArch64/AArch64InstrInfo.td
Expand Up @@ -841,20 +841,26 @@ def AArch64authtcret: SDNode<"AArch64ISD::AUTH_TC_RETURN",
let Uses = [LR], Defs = [LR] in {
def PACIAZ : SystemNoOperands<0b000, "paciaz">;
def PACIBZ : SystemNoOperands<0b010, "pacibz">;
def AUTIAZ : SystemNoOperands<0b100, "autiaz">;
def AUTIBZ : SystemNoOperands<0b110, "autibz">;
let isAuthenticated = 1 in {
def AUTIAZ : SystemNoOperands<0b100, "autiaz">;
def AUTIBZ : SystemNoOperands<0b110, "autibz">;
}
}
let Uses = [LR, SP], Defs = [LR] in {
def PACIASP : SystemNoOperands<0b001, "paciasp">;
def PACIBSP : SystemNoOperands<0b011, "pacibsp">;
def AUTIASP : SystemNoOperands<0b101, "autiasp">;
def AUTIBSP : SystemNoOperands<0b111, "autibsp">;
let isAuthenticated = 1 in {
def AUTIASP : SystemNoOperands<0b101, "autiasp">;
def AUTIBSP : SystemNoOperands<0b111, "autibsp">;
}
}
let Uses = [X16, X17], Defs = [X17], CRm = 0b0001 in {
def PACIA1716 : SystemNoOperands<0b000, "pacia1716">;
def PACIB1716 : SystemNoOperands<0b010, "pacib1716">;
def AUTIA1716 : SystemNoOperands<0b100, "autia1716">;
def AUTIB1716 : SystemNoOperands<0b110, "autib1716">;
let isAuthenticated = 1 in {
def AUTIA1716 : SystemNoOperands<0b100, "autia1716">;
def AUTIB1716 : SystemNoOperands<0b110, "autib1716">;
}
}

let Uses = [LR], Defs = [LR], CRm = 0b0000 in {
Expand Down
32 changes: 32 additions & 0 deletions llvm/unittests/Target/AArch64/InstSizes.cpp
Expand Up @@ -78,6 +78,38 @@ void runChecks(

} // anonymous namespace

TEST(InstSizes, Authenticated) {
std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
ASSERT_TRUE(TM);
std::unique_ptr<AArch64InstrInfo> II = createInstrInfo(TM.get());

auto isAuthInst = [](AArch64InstrInfo &II, MachineFunction &MF) {
auto I = MF.begin()->begin();
EXPECT_EQ(4u, II.getInstSizeInBytes(*I));
EXPECT_TRUE(I->getDesc().isAuthenticated());
};

runChecks(TM.get(), II.get(), "",
" \n"
" BLRAA $x10, $x9\n",
isAuthInst);

runChecks(TM.get(), II.get(), "",
" \n"
" RETAB implicit $lr, implicit $sp, implicit killed $x0\n",
isAuthInst);

runChecks(TM.get(), II.get(), "",
" \n"
" frame-destroy AUTIASP implicit-def $lr, implicit killed $lr, implicit $sp\n",
isAuthInst);

runChecks(TM.get(), II.get(), "",
" \n"
" frame-destroy AUTIBSP implicit-def $lr, implicit killed $lr, implicit $sp\n",
isAuthInst);
}

TEST(InstSizes, STACKMAP) {
std::unique_ptr<LLVMTargetMachine> TM = createTargetMachine();
ASSERT_TRUE(TM);
Expand Down
1 change: 1 addition & 0 deletions llvm/utils/TableGen/CodeGenInstruction.cpp
Expand Up @@ -396,6 +396,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R)
hasNoSchedulingInfo = R->getValueAsBit("hasNoSchedulingInfo");
FastISelShouldIgnore = R->getValueAsBit("FastISelShouldIgnore");
variadicOpsAreDefs = R->getValueAsBit("variadicOpsAreDefs");
isAuthenticated = R->getValueAsBit("isAuthenticated");

bool Unset;
mayLoad = R->getValueAsBitOrUnset("mayLoad", Unset);
Expand Down
1 change: 1 addition & 0 deletions llvm/utils/TableGen/CodeGenInstruction.h
Expand Up @@ -278,6 +278,7 @@ template <typename T> class ArrayRef;
bool hasChain : 1;
bool hasChain_Inferred : 1;
bool variadicOpsAreDefs : 1;
bool isAuthenticated : 1;

std::string DeprecatedReason;
bool HasComplexDeprecationPredicate;
Expand Down
1 change: 1 addition & 0 deletions llvm/utils/TableGen/InstrDocsEmitter.cpp
Expand Up @@ -138,6 +138,7 @@ void EmitInstrDocs(RecordKeeper &RK, raw_ostream &OS) {
FLAG(isConvergent)
FLAG(hasNoSchedulingInfo)
FLAG(variadicOpsAreDefs)
FLAG(isAuthenticated)
if (!FlagStrings.empty()) {
OS << "Flags: ";
bool IsFirst = true;
Expand Down
1 change: 1 addition & 0 deletions llvm/utils/TableGen/InstrInfoEmitter.cpp
Expand Up @@ -703,6 +703,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
if (Inst.isInsertSubreg) OS << "|(1ULL<<MCID::InsertSubreg)";
if (Inst.isConvergent) OS << "|(1ULL<<MCID::Convergent)";
if (Inst.variadicOpsAreDefs) OS << "|(1ULL<<MCID::VariadicOpsAreDefs)";
if (Inst.isAuthenticated) OS << "|(1ULL<<MCID::Authenticated)";

// Emit all of the target-specific flags...
BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags");
Expand Down

0 comments on commit eb8a955

Please sign in to comment.