67#define GET_LFIVariantTable_DECL
68#define GET_PairVariantTable_DECL
69#define GET_SIMDPostTable_DECL
70#define GET_MemInfoTable_DECL
71#define GET_LFIVariantTable_IMPL
72#define GET_PairVariantTable_IMPL
73#define GET_SIMDPostTable_IMPL
74#define GET_MemInfoTable_IMPL
77#include "AArch64GenSystemOperands.inc"
96 std::unique_ptr<MCRegisterInfo> &&RI,
97 std::unique_ptr<MCInstrInfo> &&
II)
99 CLOpts(
AArch64_MC::getCLOpts(Ctx.getTargetOptions())) {}
106 return Reg == AArch64SysReg::TPIDR_EL1 ||
Reg == AArch64SysReg::TPIDR_EL2 ||
107 Reg == AArch64SysReg::TPIDR_EL3;
111 return Inst.
getOpcode() == AArch64::MRS &&
116 return Inst.
getOpcode() == AArch64::MSR &&
152 case AArch64::PRFMroW:
153 case AArch64::PRFMroX:
154 case AArch64::PRFMui:
155 case AArch64::PRFUMi:
177 case AArch64::BLRAAZ:
179 case AArch64::BLRABZ:
187 return Opcode == AArch64::RETAA || Opcode == AArch64::RETAB;
191 return Opcode == AArch64::ERET || Opcode == AArch64::ERETAA ||
192 Opcode == AArch64::ERETAB;
197 case AArch64::AUTIASP:
198 case AArch64::AUTIBSP:
199 case AArch64::AUTIAZ:
200 case AArch64::AUTIBZ:
201 case AArch64::XPACLRI:
233 assert(New.getOperand(Idx).isReg());
234 New.getOperand(Idx).setReg(NewReg);
248 if (!
E ||
E->AddrMode != ExpectedMode)
249 return AArch64::INSTRUCTION_LIST_END;
257 return AArch64::INSTRUCTION_LIST_END;
280 if (
const auto *
E = AArch64::lookupPairVariantByOpcode(
Op)) {
284 if (
const auto *
E = AArch64::lookupSIMDPostByOpcode(
Op)) {
288 return AArch64::INSTRUCTION_LIST_END;
291bool AArch64MCLFIRewriter::mayModifySP(
const MCInst &Inst)
const {
295MCRegister AArch64MCLFIRewriter::mayModifyReserved(
const MCInst &Inst)
const {
309 if (DeferredLRGuard && LastSTI && !Symbol->isTemporary()) {
310 emitAddMask(AArch64::LR, AArch64::LR, Out, *LastSTI);
311 DeferredLRGuard =
false;
315 ActiveGuardReg = std::nullopt;
320 if (DeferredLRGuard && LastSTI) {
321 emitAddMask(AArch64::LR, AArch64::LR, Out, *LastSTI);
322 DeferredLRGuard =
false;
330 if (ActiveGuardReg) {
332 if (
Desc.mayAffectControlFlow(Inst, *RegInfo) ||
336 ActiveGuardReg = std::nullopt;
339 Out.emitInstruction(Inst, STI);
347 if (CLOpts.lfi_guard_elim && Dest ==
LFIAddrReg && ActiveGuardReg == Src)
351 emitInst(MCInstBuilder(AArch64::ADDXrx)
360 ActiveGuardReg = Src;
366 emitInst(MCInstBuilder(Opcode).addReg(Target), Out, STI);
369void AArch64MCLFIRewriter::emitPendingTLSDescCall(
MCStreamer &Out,
371 if (!PendingTLSDescCall)
373 const MCExpr *Expr = PendingTLSDescCall;
374 PendingTLSDescCall =
nullptr;
375 emitInst(MCInstBuilder(AArch64::TLSDESCCALL).addExpr(Expr), Out, STI);
382 emitInst(MCInstBuilder(AArch64::ORRXrs)
384 .addReg(AArch64::XZR)
395 unsigned Opcode =
Imm >= 0 ? AArch64::ADDXri : AArch64::SUBXri;
396 emitInst(MCInstBuilder(Opcode)
399 .addImm(std::abs(
Imm))
409 emitInst(MCInstBuilder(AArch64::ADDXrs)
426 emitInst(MCInstBuilder(Opcode).addReg(Dest).addReg(Src1).addReg(Src2).addImm(
431void AArch64MCLFIRewriter::emitMemRoW(
unsigned Opcode,
const MCOperand &DataOp,
435 emitInst(MCInstBuilder(Opcode)
448void AArch64MCLFIRewriter::rewriteIndirectBranch(
const MCInst &Inst,
452 "expected register operand");
458 emitPendingTLSDescCall(Out, STI);
469void AArch64MCLFIRewriter::rewriteReturn(
const MCInst &Inst,
MCStreamer &Out,
472 "expected register operand");
475 rewriteIndirectBranch(Inst, Out, STI);
477 emitInst(Inst, Out, STI);
484void AArch64MCLFIRewriter::rewriteLRModification(
const MCInst &Inst,
489 rewriteLoadStore(Inst, Out, STI);
491 emitInst(Inst, Out, STI);
496 DeferredLRGuard =
true;
504void AArch64MCLFIRewriter::rewriteAuthenticatedReturn(
506 emitInst(MCInstBuilder(Inst.
getOpcode() == AArch64::RETAA ? AArch64::AUTIASP
510 emitAddMask(AArch64::LR, AArch64::LR, Out, STI);
511 emitBranch(AArch64::RET, AArch64::LR, Out, STI);
519void AArch64MCLFIRewriter::rewriteAuthenticatedBranchOrCall(
529 AuthOpcode = AArch64::AUTIA;
533 AuthOpcode = AArch64::AUTIB;
536 case AArch64::BLRAAZ:
537 AuthOpcode = AArch64::AUTIZA;
540 case AArch64::BLRABZ:
541 AuthOpcode = AArch64::AUTIZB;
547 MCInstBuilder Auth(AuthOpcode);
548 Auth.addReg(TargetReg);
549 Auth.addReg(TargetReg);
550 if (AuthOpcode == AArch64::AUTIA || AuthOpcode == AArch64::AUTIB)
552 emitInst(Auth, Out, STI);
556 emitBranch(BranchOpcode,
LFIAddrReg, Out, STI);
571 emitInst(MCInstBuilder(AArch64::LDURXi)
578 emitBranch(AArch64::BLR, AArch64::LR, Out, STI);
587void AArch64MCLFIRewriter::rewriteTPRead(
const MCInst &Inst,
MCStreamer &Out,
591 emitInst(MCInstBuilder(AArch64::LDRXui)
601void AArch64MCLFIRewriter::rewriteTPWrite(
const MCInst &Inst,
MCStreamer &Out,
605 emitInst(MCInstBuilder(AArch64::STRXui)
612bool AArch64MCLFIRewriter::rewriteLoadStoreRoW(
const MCInst &Inst,
621 AArch64::INSTRUCTION_LIST_END) {
623 if (BaseReg == AArch64::SP)
627 emitMemRoW(MemOp, Inst.
getOperand(0), BaseReg, Out, STI);
636 AArch64::INSTRUCTION_LIST_END) {
638 if (BaseReg == AArch64::SP)
641 emitAddImm(BaseReg, BaseReg,
Imm, Out, STI);
642 emitMemRoW(MemOp, Inst.
getOperand(1), BaseReg, Out, STI);
649 AArch64::INSTRUCTION_LIST_END) {
651 if (BaseReg == AArch64::SP)
654 emitMemRoW(MemOp, Inst.
getOperand(1), BaseReg, Out, STI);
655 emitAddImm(BaseReg, BaseReg,
Imm, Out, STI);
708void AArch64MCLFIRewriter::rewriteLoadStoreBase(
const MCInst &Inst,
712 const AArch64::MemInfoEntry *
Info = AArch64::lookupMemInfoByOpcode(Opcode);
715 warning(Inst,
"unknown addressing mode for memory instruction in LFI");
716 return emitInst(Inst, Out, STI);
720 return error(Inst,
"PC-relative literal loads are not supported in LFI");
726 bool BaseIsSP =
BaseReg == AArch64::SP;
729 return emitInst(Inst, Out, STI);
731 if (OffReg == AArch64::XZR || OffReg == AArch64::WZR)
732 return emitInst(Inst, Out, STI);
739 if (!
Info->IsPrePost) {
742 emitInst(NewInst, Out, STI);
747 bool IsNoOffset =
false;
750 if (BaseOpcode == AArch64::INSTRUCTION_LIST_END)
751 return error(Inst,
"unhandled pre/post-index instruction in LFI rewriter");
754 MCInstBuilder NewInst(BaseOpcode);
755 NewInst.setLoc(Inst.
getLoc());
758 for (
int I = 1;
I <
Info->BaseIdx; ++
I)
762 NewInst.addReg(BaseIsSP ? AArch64::SP :
LFIAddrReg);
765 if (IsPre &&
Info->HasOffset)
767 else if (!IsNoOffset)
770 emitInst(NewInst, Out, STI);
772 if (!
Info->HasOffset)
784 if (
const auto *
E = AArch64::lookupPairVariantByOpcode(Opcode))
787 emitAddImm(BaseReg, BaseReg,
Offset, Out, STI);
790 MCRegister OffReg =
OffsetOp.getReg();
791 if (OffReg == AArch64::XZR) {
792 if (
const auto *
E = AArch64::lookupSIMDPostByOpcode(Opcode))
793 emitAddImm(BaseReg, BaseReg,
E->NaturalOffset, Out, STI);
794 }
else if (OffReg != AArch64::WZR) {
800 emitAddReg(BaseReg, BaseReg, OffReg, 0, Out, STI);
806void AArch64MCLFIRewriter::rewriteLoadStore(
const MCInst &Inst,
MCStreamer &Out,
811 bool SkipLoads = STI.
hasFeature(AArch64::FeatureNoLFILoads);
812 bool SkipStores = STI.
hasFeature(AArch64::FeatureNoLFIStores);
814 if ((!IsLoad || SkipLoads) && (!IsStore || SkipStores))
815 return emitInst(Inst, Out, STI);
817 if (rewriteLoadStoreRoW(Inst, Out, STI))
820 rewriteLoadStoreBase(Inst, Out, STI);
827void AArch64MCLFIRewriter::rewriteSPModification(
const MCInst &Inst,
835 return rewriteLRModification(Inst, Out, STI);
836 return rewriteLoadStore(Inst, Out, STI);
840 bool SkipLoads = STI.
hasFeature(AArch64::FeatureNoLFILoads);
841 bool SkipStores = STI.
hasFeature(AArch64::FeatureNoLFIStores);
842 if (SkipLoads && SkipStores)
843 return emitInst(Inst, Out, STI);
852 emitInst(ModInst, Out, STI);
860void AArch64MCLFIRewriter::rewriteVASysOp(
const MCInst &Inst,
MCStreamer &Out,
866 emitInst(MCInstBuilder(AArch64::SYSxt)
877void AArch64MCLFIRewriter::doRewriteInst(
const MCInst &Inst,
MCStreamer &Out,
879 if (Inst.
getOpcode() == AArch64::TLSDESCCALL) {
885 if (MCRegister
Reg = mayModifyReserved(Inst)) {
886 error(Inst, Twine(
"illegal modification of reserved LFI register ") +
893 return rewriteSyscall(Inst, Out, STI);
896 return rewriteTPRead(Inst, Out, STI);
899 return rewriteTPWrite(Inst, Out, STI);
902 error(Inst,
"illegal access to privileged thread pointer register");
907 return rewriteVASysOp(Inst, Out, STI);
910 error(Inst,
"exception returns are not supported by LFI");
918 DeferredLRGuard =
false;
919 return rewriteAuthenticatedReturn(Inst, Out, STI);
926 emitAddMask(AArch64::LR, AArch64::LR, Out, STI);
927 DeferredLRGuard =
false;
932 return rewriteAuthenticatedBranchOrCall(Inst, AArch64::BR, Out, STI);
934 return rewriteAuthenticatedBranchOrCall(Inst, AArch64::BLR, Out, STI);
939 return rewriteReturn(Inst, Out, STI);
942 return rewriteIndirectBranch(Inst, Out, STI);
946 if (mayModifySP(Inst))
947 return rewriteSPModification(Inst, Out, STI);
952 return rewriteLRModification(Inst, Out, STI);
957 return rewriteLoadStore(Inst, Out, STI);
959 emitInst(Inst, Out, STI);
966 AArch64::INSTRUCTION_LIST_END)
969 AArch64::INSTRUCTION_LIST_END)
971 bool IsPre, IsNoOffset;
973 AArch64::INSTRUCTION_LIST_END)
982 ActiveGuardReg = std::nullopt;
994 doRewriteInst(Inst, Out, STI);
static unsigned convertPrePostToBase(unsigned Op, bool &IsPre, bool &IsNoOffset)
static bool isFakeMemAccess(const MCInst &Inst)
static constexpr unsigned LFITPOffset
static constexpr MCRegister LFIScratchReg
static bool pacWritesLR(const MCInst &Inst)
static bool isPrivilegedTPAccess(const MCInst &Inst)
static bool isAuthenticatedBranch(unsigned Opcode)
static constexpr MCRegister LFICtxReg
static bool isPrivilegedTP(int64_t Reg)
static bool isAuthenticatedReturn(unsigned Opcode)
static bool getRoWShift(unsigned Op, unsigned &Shift)
static bool isVASysOp(const MCInst &Inst)
static bool isTPRead(const MCInst &Inst)
static bool mayPrefetch(const MCInst &Inst)
static bool isSyscall(const MCInst &Inst)
static MCInst replaceRegAt(const MCInst &Inst, unsigned Idx, MCRegister NewReg)
static unsigned convertVariantToRoW(unsigned Op, unsigned ExpectedMode)
static constexpr MCRegister LFIAddrReg
static unsigned convertRoXToRoW(unsigned Op, unsigned &Shift)
static bool isExceptionReturn(unsigned Opcode)
static constexpr MCRegister LFIBaseReg
static constexpr int LFISyscallOffset
static bool isTPWrite(const MCInst &Inst)
static bool isAuthenticatedCall(unsigned Opcode)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
std::pair< Instruction::BinaryOps, Value * > OffsetOp
Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
uint64_t IntrinsicInst * II
AArch64MCLFIRewriter(MCContext &Ctx, std::unique_ptr< MCRegisterInfo > &&RI, std::unique_ptr< MCInstrInfo > &&II)
void onLabel(const MCSymbol *Symbol, MCStreamer &Out) override
bool rewriteInst(const MCInst &Inst, MCStreamer &Out, const MCSubtargetInfo &STI) override
void finish(MCStreamer &Out) override
Context object for machine code objects.
Instances of this class represent a single low-level machine instruction.
unsigned getNumOperands() const
unsigned getOpcode() const
const MCOperand & getOperand(unsigned i) const
Describe properties that are true of each instruction in the target description file.
LLVM_ABI bool mayModifyRegister(const MCInst &Inst, MCRegister Reg) const
LLVM_ABI bool mayLoad(const MCInst &Inst) const
LLVM_ABI bool isIndirectBranch(const MCInst &Inst) const
LLVM_ABI void warning(const MCInst &Inst, const Twine &Msg)
LLVM_ABI bool isCall(const MCInst &Inst) const
LLVM_ABI bool isReturn(const MCInst &Inst) const
std::unique_ptr< MCRegisterInfo > RegInfo
LLVM_ABI bool mayStore(const MCInst &Inst) const
LLVM_ABI bool explicitlyModifiesRegister(const MCInst &Inst, MCRegister Reg) const
MCLFIRewriter(MCContext &Ctx, std::unique_ptr< MCRegisterInfo > &&RI, std::unique_ptr< MCInstrInfo > &&II)
LLVM_ABI bool isBranch(const MCInst &Inst) const
Instances of this class represent operands of the MCInst class.
MCRegister getReg() const
Returns the register number.
const MCExpr * getExpr() const
Wrapper class representing physical registers. Should be passed by value.
Streaming machine code generation interface.
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Target - Wrapper for Target specific information.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static unsigned getArithExtendImm(AArch64_AM::ShiftExtendType ET, unsigned Imm)
getArithExtendImm - Encode the extend type and shift amount for an arithmetic instruction: imm: 3-bit...
static unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
This is an optimization pass for GlobalISel generic memory operations.
bool isLFIPrePostMemAccess(unsigned Opcode)
Returns true if Opcode is a pre- or post-indexed memory access that the LFI rewriter expands with a b...
DWARFExpression::Operation Op
static MCRegister getWRegFromXReg(MCRegister Reg)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Implement std::hash so that hash_code can be used in STL containers.