66#define GET_LFIVariantTable_DECL
67#define GET_PairVariantTable_DECL
68#define GET_SIMDPostTable_DECL
69#define GET_MemInfoTable_DECL
70#define GET_LFIVariantTable_IMPL
71#define GET_PairVariantTable_IMPL
72#define GET_SIMDPostTable_IMPL
73#define GET_MemInfoTable_IMPL
76#include "AArch64GenSystemOperands.inc"
99 return Reg == AArch64SysReg::TPIDR_EL1 ||
Reg == AArch64SysReg::TPIDR_EL2 ||
100 Reg == AArch64SysReg::TPIDR_EL3;
104 return Inst.
getOpcode() == AArch64::MRS &&
109 return Inst.
getOpcode() == AArch64::MSR &&
145 case AArch64::PRFMroW:
146 case AArch64::PRFMroX:
147 case AArch64::PRFMui:
148 case AArch64::PRFUMi:
170 case AArch64::BLRAAZ:
172 case AArch64::BLRABZ:
180 return Opcode == AArch64::RETAA || Opcode == AArch64::RETAB;
184 return Opcode == AArch64::ERET || Opcode == AArch64::ERETAA ||
185 Opcode == AArch64::ERETAB;
190 case AArch64::AUTIASP:
191 case AArch64::AUTIBSP:
192 case AArch64::AUTIAZ:
193 case AArch64::AUTIBZ:
194 case AArch64::XPACLRI:
226 assert(New.getOperand(Idx).isReg());
227 New.getOperand(Idx).setReg(NewReg);
241 if (!
E ||
E->AddrMode != ExpectedMode)
242 return AArch64::INSTRUCTION_LIST_END;
250 return AArch64::INSTRUCTION_LIST_END;
273 if (
const auto *
E = AArch64::lookupPairVariantByOpcode(
Op)) {
277 if (
const auto *
E = AArch64::lookupSIMDPostByOpcode(
Op)) {
281 return AArch64::INSTRUCTION_LIST_END;
284bool AArch64MCLFIRewriter::mayModifySP(
const MCInst &Inst)
const {
288MCRegister AArch64MCLFIRewriter::mayModifyReserved(
const MCInst &Inst)
const {
302 if (DeferredLRGuard && LastSTI && !Symbol->isTemporary()) {
303 emitAddMask(AArch64::LR, AArch64::LR, Out, *LastSTI);
304 DeferredLRGuard =
false;
308 ActiveGuardReg = std::nullopt;
313 if (DeferredLRGuard && LastSTI) {
314 emitAddMask(AArch64::LR, AArch64::LR, Out, *LastSTI);
315 DeferredLRGuard =
false;
323 if (ActiveGuardReg) {
325 if (
Desc.mayAffectControlFlow(Inst, *RegInfo) ||
329 ActiveGuardReg = std::nullopt;
332 Out.emitInstruction(Inst, STI);
340 if (CLOpts.lfi_guard_elim && Dest ==
LFIAddrReg && ActiveGuardReg == Src)
344 emitInst(MCInstBuilder(AArch64::ADDXrx)
353 ActiveGuardReg = Src;
359 emitInst(MCInstBuilder(Opcode).addReg(Target), Out, STI);
362void AArch64MCLFIRewriter::emitPendingTLSDescCall(
MCStreamer &Out,
364 if (!PendingTLSDescCall)
366 const MCExpr *Expr = PendingTLSDescCall;
367 PendingTLSDescCall =
nullptr;
368 emitInst(MCInstBuilder(AArch64::TLSDESCCALL).addExpr(Expr), Out, STI);
375 emitInst(MCInstBuilder(AArch64::ORRXrs)
377 .addReg(AArch64::XZR)
388 unsigned Opcode =
Imm >= 0 ? AArch64::ADDXri : AArch64::SUBXri;
389 emitInst(MCInstBuilder(Opcode)
392 .addImm(std::abs(
Imm))
402 emitInst(MCInstBuilder(AArch64::ADDXrs)
419 emitInst(MCInstBuilder(Opcode).addReg(Dest).addReg(Src1).addReg(Src2).addImm(
424void AArch64MCLFIRewriter::emitMemRoW(
unsigned Opcode,
const MCOperand &DataOp,
428 emitInst(MCInstBuilder(Opcode)
441void AArch64MCLFIRewriter::rewriteIndirectBranch(
const MCInst &Inst,
445 "expected register operand");
451 emitPendingTLSDescCall(Out, STI);
462void AArch64MCLFIRewriter::rewriteReturn(
const MCInst &Inst,
MCStreamer &Out,
465 "expected register operand");
468 rewriteIndirectBranch(Inst, Out, STI);
470 emitInst(Inst, Out, STI);
477void AArch64MCLFIRewriter::rewriteLRModification(
const MCInst &Inst,
482 rewriteLoadStore(Inst, Out, STI);
484 emitInst(Inst, Out, STI);
489 DeferredLRGuard =
true;
497void AArch64MCLFIRewriter::rewriteAuthenticatedReturn(
499 emitInst(MCInstBuilder(Inst.
getOpcode() == AArch64::RETAA ? AArch64::AUTIASP
503 emitAddMask(AArch64::LR, AArch64::LR, Out, STI);
504 emitBranch(AArch64::RET, AArch64::LR, Out, STI);
512void AArch64MCLFIRewriter::rewriteAuthenticatedBranchOrCall(
522 AuthOpcode = AArch64::AUTIA;
526 AuthOpcode = AArch64::AUTIB;
529 case AArch64::BLRAAZ:
530 AuthOpcode = AArch64::AUTIZA;
533 case AArch64::BLRABZ:
534 AuthOpcode = AArch64::AUTIZB;
540 MCInstBuilder Auth(AuthOpcode);
541 Auth.addReg(TargetReg);
542 Auth.addReg(TargetReg);
543 if (AuthOpcode == AArch64::AUTIA || AuthOpcode == AArch64::AUTIB)
545 emitInst(Auth, Out, STI);
549 emitBranch(BranchOpcode,
LFIAddrReg, Out, STI);
564 emitInst(MCInstBuilder(AArch64::LDURXi)
571 emitBranch(AArch64::BLR, AArch64::LR, Out, STI);
580void AArch64MCLFIRewriter::rewriteTPRead(
const MCInst &Inst,
MCStreamer &Out,
584 emitInst(MCInstBuilder(AArch64::LDRXui)
594void AArch64MCLFIRewriter::rewriteTPWrite(
const MCInst &Inst,
MCStreamer &Out,
598 emitInst(MCInstBuilder(AArch64::STRXui)
605bool AArch64MCLFIRewriter::rewriteLoadStoreRoW(
const MCInst &Inst,
614 AArch64::INSTRUCTION_LIST_END) {
616 if (BaseReg == AArch64::SP)
620 emitMemRoW(MemOp, Inst.
getOperand(0), BaseReg, Out, STI);
629 AArch64::INSTRUCTION_LIST_END) {
631 if (BaseReg == AArch64::SP)
634 emitAddImm(BaseReg, BaseReg,
Imm, Out, STI);
635 emitMemRoW(MemOp, Inst.
getOperand(1), BaseReg, Out, STI);
642 AArch64::INSTRUCTION_LIST_END) {
644 if (BaseReg == AArch64::SP)
647 emitMemRoW(MemOp, Inst.
getOperand(1), BaseReg, Out, STI);
648 emitAddImm(BaseReg, BaseReg,
Imm, Out, STI);
701void AArch64MCLFIRewriter::rewriteLoadStoreBase(
const MCInst &Inst,
705 const AArch64::MemInfoEntry *
Info = AArch64::lookupMemInfoByOpcode(Opcode);
708 warning(Inst,
"unknown addressing mode for memory instruction in LFI");
709 return emitInst(Inst, Out, STI);
713 return error(Inst,
"PC-relative literal loads are not supported in LFI");
719 bool BaseIsSP =
BaseReg == AArch64::SP;
722 return emitInst(Inst, Out, STI);
724 if (OffReg == AArch64::XZR || OffReg == AArch64::WZR)
725 return emitInst(Inst, Out, STI);
732 if (!
Info->IsPrePost) {
735 emitInst(NewInst, Out, STI);
740 bool IsNoOffset =
false;
743 if (BaseOpcode == AArch64::INSTRUCTION_LIST_END)
744 return error(Inst,
"unhandled pre/post-index instruction in LFI rewriter");
747 MCInstBuilder NewInst(BaseOpcode);
748 NewInst.setLoc(Inst.
getLoc());
751 for (
int I = 1;
I <
Info->BaseIdx; ++
I)
755 NewInst.addReg(BaseIsSP ? AArch64::SP :
LFIAddrReg);
758 if (IsPre &&
Info->HasOffset)
760 else if (!IsNoOffset)
763 emitInst(NewInst, Out, STI);
765 if (!
Info->HasOffset)
777 if (
const auto *
E = AArch64::lookupPairVariantByOpcode(Opcode))
780 emitAddImm(BaseReg, BaseReg,
Offset, Out, STI);
783 MCRegister OffReg =
OffsetOp.getReg();
784 if (OffReg == AArch64::XZR) {
785 if (
const auto *
E = AArch64::lookupSIMDPostByOpcode(Opcode))
786 emitAddImm(BaseReg, BaseReg,
E->NaturalOffset, Out, STI);
787 }
else if (OffReg != AArch64::WZR) {
793 emitAddReg(BaseReg, BaseReg, OffReg, 0, Out, STI);
799void AArch64MCLFIRewriter::rewriteLoadStore(
const MCInst &Inst,
MCStreamer &Out,
804 bool SkipLoads = STI.
hasFeature(AArch64::FeatureNoLFILoads);
805 bool SkipStores = STI.
hasFeature(AArch64::FeatureNoLFIStores);
807 if ((!IsLoad || SkipLoads) && (!IsStore || SkipStores))
808 return emitInst(Inst, Out, STI);
810 if (rewriteLoadStoreRoW(Inst, Out, STI))
813 rewriteLoadStoreBase(Inst, Out, STI);
820void AArch64MCLFIRewriter::rewriteSPModification(
const MCInst &Inst,
828 return rewriteLRModification(Inst, Out, STI);
829 return rewriteLoadStore(Inst, Out, STI);
833 bool SkipLoads = STI.
hasFeature(AArch64::FeatureNoLFILoads);
834 bool SkipStores = STI.
hasFeature(AArch64::FeatureNoLFIStores);
835 if (SkipLoads && SkipStores)
836 return emitInst(Inst, Out, STI);
845 emitInst(ModInst, Out, STI);
853void AArch64MCLFIRewriter::rewriteVASysOp(
const MCInst &Inst,
MCStreamer &Out,
859 emitInst(MCInstBuilder(AArch64::SYSxt)
870void AArch64MCLFIRewriter::doRewriteInst(
const MCInst &Inst,
MCStreamer &Out,
872 if (Inst.
getOpcode() == AArch64::TLSDESCCALL) {
878 if (MCRegister
Reg = mayModifyReserved(Inst)) {
879 error(Inst, Twine(
"illegal modification of reserved LFI register ") +
886 return rewriteSyscall(Inst, Out, STI);
889 return rewriteTPRead(Inst, Out, STI);
892 return rewriteTPWrite(Inst, Out, STI);
895 error(Inst,
"illegal access to privileged thread pointer register");
900 return rewriteVASysOp(Inst, Out, STI);
903 error(Inst,
"exception returns are not supported by LFI");
911 DeferredLRGuard =
false;
912 return rewriteAuthenticatedReturn(Inst, Out, STI);
919 emitAddMask(AArch64::LR, AArch64::LR, Out, STI);
920 DeferredLRGuard =
false;
925 return rewriteAuthenticatedBranchOrCall(Inst, AArch64::BR, Out, STI);
927 return rewriteAuthenticatedBranchOrCall(Inst, AArch64::BLR, Out, STI);
932 return rewriteReturn(Inst, Out, STI);
935 return rewriteIndirectBranch(Inst, Out, STI);
939 if (mayModifySP(Inst))
940 return rewriteSPModification(Inst, Out, STI);
945 return rewriteLRModification(Inst, Out, STI);
950 return rewriteLoadStore(Inst, Out, STI);
952 emitInst(Inst, Out, STI);
959 AArch64::INSTRUCTION_LIST_END)
962 AArch64::INSTRUCTION_LIST_END)
964 bool IsPre, IsNoOffset;
966 AArch64::INSTRUCTION_LIST_END)
975 ActiveGuardReg = std::nullopt;
987 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.
void onLabel(const MCSymbol *Symbol, MCStreamer &Out) override
bool rewriteInst(const MCInst &Inst, MCStreamer &Out, const MCSubtargetInfo &STI) override
void finish(MCStreamer &Out) override
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
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)