64#define GET_LFIVariantTable_DECL
65#define GET_PairVariantTable_DECL
66#define GET_SIMDPostTable_DECL
67#define GET_MemInfoTable_DECL
68#define GET_LFIVariantTable_IMPL
69#define GET_PairVariantTable_IMPL
70#define GET_SIMDPostTable_IMPL
71#define GET_MemInfoTable_IMPL
74#include "AArch64GenSystemOperands.inc"
97 return Reg == AArch64SysReg::TPIDR_EL1 ||
Reg == AArch64SysReg::TPIDR_EL2 ||
98 Reg == AArch64SysReg::TPIDR_EL3;
102 return Inst.
getOpcode() == AArch64::MRS &&
107 return Inst.
getOpcode() == AArch64::MSR &&
143 case AArch64::PRFMroW:
144 case AArch64::PRFMroX:
145 case AArch64::PRFMui:
146 case AArch64::PRFUMi:
178 assert(New.getOperand(Idx).isReg());
179 New.getOperand(Idx).setReg(NewReg);
193 if (!
E ||
E->AddrMode != ExpectedMode)
194 return AArch64::INSTRUCTION_LIST_END;
202 return AArch64::INSTRUCTION_LIST_END;
225 if (
const auto *
E = AArch64::lookupPairVariantByOpcode(
Op)) {
229 if (
const auto *
E = AArch64::lookupSIMDPostByOpcode(
Op)) {
233 return AArch64::INSTRUCTION_LIST_END;
236bool AArch64MCLFIRewriter::mayModifySP(
const MCInst &Inst)
const {
240MCRegister AArch64MCLFIRewriter::mayModifyReserved(
const MCInst &Inst)
const {
264 emitInst(Inst, Out, STI);
273 emitInst(Branch, Out, STI);
276void AArch64MCLFIRewriter::emitPendingTLSDescCall(
MCStreamer &Out,
278 if (!PendingTLSDescCall)
283 PendingTLSDescCall =
nullptr;
284 emitInst(Marker, Out, STI);
297 emitInst(Inst, Out, STI);
303 assert(std::abs(Imm) <= 4095);
320 emitInst(Inst, Out, STI);
335 emitInst(Inst, Out, STI);
354 emitInst(Inst, Out, STI);
357void AArch64MCLFIRewriter::emitMemRoW(
unsigned Opcode,
const MCOperand &DataOp,
368 emitInst(Inst, Out, STI);
375void AArch64MCLFIRewriter::rewriteIndirectBranch(
const MCInst &Inst,
379 "expected register operand");
385 emitPendingTLSDescCall(Out, STI);
396void AArch64MCLFIRewriter::rewriteReturn(
const MCInst &Inst,
MCStreamer &Out,
399 "expected register operand");
402 rewriteIndirectBranch(Inst, Out, STI);
404 emitInst(Inst, Out, STI);
411void AArch64MCLFIRewriter::rewriteLRModification(
const MCInst &Inst,
416 rewriteLoadStore(Inst, Out, STI);
418 emitInst(Inst, Out, STI);
419 emitAddMask(AArch64::LR, AArch64::LR, Out, STI);
435 Load.setOpcode(AArch64::LDURXi);
439 emitInst(Load, Out, STI);
442 emitBranch(AArch64::BLR, AArch64::LR, Out, STI);
451void AArch64MCLFIRewriter::rewriteTPRead(
const MCInst &Inst,
MCStreamer &Out,
456 Load.setOpcode(AArch64::LDRXui);
460 emitInst(Load, Out, STI);
466void AArch64MCLFIRewriter::rewriteTPWrite(
const MCInst &Inst,
MCStreamer &Out,
471 Store.setOpcode(AArch64::STRXui);
475 emitInst(Store, Out, STI);
478bool AArch64MCLFIRewriter::rewriteLoadStoreRoW(
const MCInst &Inst,
487 AArch64::INSTRUCTION_LIST_END) {
489 if (BaseReg == AArch64::SP)
493 emitMemRoW(MemOp, Inst.
getOperand(0), BaseReg, Out, STI);
502 AArch64::INSTRUCTION_LIST_END) {
504 if (BaseReg == AArch64::SP)
507 emitAddImm(BaseReg, BaseReg, Imm, Out, STI);
508 emitMemRoW(MemOp, Inst.
getOperand(1), BaseReg, Out, STI);
515 AArch64::INSTRUCTION_LIST_END) {
517 if (BaseReg == AArch64::SP)
520 emitMemRoW(MemOp, Inst.
getOperand(1), BaseReg, Out, STI);
521 emitAddImm(BaseReg, BaseReg, Imm, Out, STI);
574void AArch64MCLFIRewriter::rewriteLoadStoreBase(
const MCInst &Inst,
578 const AArch64::MemInfoEntry *
Info = AArch64::lookupMemInfoByOpcode(Opcode);
581 warning(Inst,
"unknown addressing mode for memory instruction in LFI");
582 return emitInst(Inst, Out, STI);
586 return error(Inst,
"PC-relative literal loads are not supported in LFI");
592 bool BaseIsSP =
BaseReg == AArch64::SP;
595 return emitInst(Inst, Out, STI);
597 if (OffReg == AArch64::XZR || OffReg == AArch64::WZR)
598 return emitInst(Inst, Out, STI);
605 if (!
Info->IsPrePost) {
608 emitInst(NewInst, Out, STI);
613 bool IsNoOffset =
false;
616 if (BaseOpcode == AArch64::INSTRUCTION_LIST_END)
617 return error(Inst,
"unhandled pre/post-index instruction in LFI rewriter");
625 for (
int I = 1;
I <
Info->BaseIdx; ++
I)
629 MCRegister AccessBase = BaseIsSP ? AArch64::SP :
LFIAddrReg;
633 if (IsPre &&
Info->HasOffset)
635 else if (!IsNoOffset)
638 emitInst(NewInst, Out, STI);
640 if (!
Info->HasOffset)
652 if (
const auto *
E = AArch64::lookupPairVariantByOpcode(Opcode))
655 emitAddImm(BaseReg, BaseReg,
Offset, Out, STI);
658 MCRegister OffReg =
OffsetOp.getReg();
659 if (OffReg == AArch64::XZR) {
660 if (
const auto *
E = AArch64::lookupSIMDPostByOpcode(Opcode))
661 emitAddImm(BaseReg, BaseReg,
E->NaturalOffset, Out, STI);
662 }
else if (OffReg != AArch64::WZR) {
668 emitAddReg(BaseReg, BaseReg, OffReg, 0, Out, STI);
674void AArch64MCLFIRewriter::rewriteLoadStore(
const MCInst &Inst,
MCStreamer &Out,
679 bool SkipLoads = STI.
hasFeature(AArch64::FeatureNoLFILoads);
680 bool SkipStores = STI.
hasFeature(AArch64::FeatureNoLFIStores);
682 if ((!IsLoad || SkipLoads) && (!IsStore || SkipStores))
683 return emitInst(Inst, Out, STI);
685 if (rewriteLoadStoreRoW(Inst, Out, STI))
688 rewriteLoadStoreBase(Inst, Out, STI);
695void AArch64MCLFIRewriter::rewriteSPModification(
const MCInst &Inst,
703 return rewriteLRModification(Inst, Out, STI);
704 return rewriteLoadStore(Inst, Out, STI);
708 bool SkipLoads = STI.
hasFeature(AArch64::FeatureNoLFILoads);
709 bool SkipStores = STI.
hasFeature(AArch64::FeatureNoLFIStores);
710 if (SkipLoads && SkipStores)
711 return emitInst(Inst, Out, STI);
720 emitInst(ModInst, Out, STI);
728void AArch64MCLFIRewriter::rewriteVASysOp(
const MCInst &Inst,
MCStreamer &Out,
741 emitInst(NewInst, Out, STI);
746void AArch64MCLFIRewriter::doRewriteInst(
const MCInst &Inst,
MCStreamer &Out,
748 if (Inst.
getOpcode() == AArch64::TLSDESCCALL) {
754 if (MCRegister
Reg = mayModifyReserved(Inst)) {
755 error(Inst, Twine(
"illegal modification of reserved LFI register ") +
762 return rewriteSyscall(Inst, Out, STI);
765 return rewriteTPRead(Inst, Out, STI);
768 return rewriteTPWrite(Inst, Out, STI);
771 error(Inst,
"illegal access to privileged thread pointer register");
776 return rewriteVASysOp(Inst, Out, STI);
781 return rewriteReturn(Inst, Out, STI);
784 return rewriteIndirectBranch(Inst, Out, STI);
788 if (mayModifySP(Inst))
789 return rewriteSPModification(Inst, Out, STI);
793 return rewriteLRModification(Inst, Out, STI);
798 return rewriteLoadStore(Inst, Out, STI);
800 emitInst(Inst, Out, STI);
807 AArch64::INSTRUCTION_LIST_END)
810 AArch64::INSTRUCTION_LIST_END)
812 bool IsPre, IsNoOffset;
814 AArch64::INSTRUCTION_LIST_END)
827 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 isPrivilegedTPAccess(const MCInst &Inst)
static constexpr MCRegister LFICtxReg
static bool isPrivilegedTP(int64_t Reg)
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 constexpr MCRegister LFIBaseReg
static constexpr int LFISyscallOffset
static bool isTPWrite(const MCInst &Inst)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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.
bool rewriteInst(const MCInst &Inst, MCStreamer &Out, const MCSubtargetInfo &STI) override
Instances of this class represent a single low-level machine instruction.
unsigned getNumOperands() const
unsigned getOpcode() const
void addOperand(const MCOperand Op)
void setOpcode(unsigned Op)
const MCOperand & getOperand(unsigned i) const
LLVM_ABI bool mayModifyRegister(const MCInst &Inst, MCRegister Reg) const
LLVM_ABI bool mayLoad(const MCInst &Inst) const
LLVM_ABI void warning(const MCInst &Inst, const Twine &Msg)
std::unique_ptr< MCRegisterInfo > RegInfo
LLVM_ABI bool mayStore(const MCInst &Inst) const
LLVM_ABI bool explicitlyModifiesRegister(const MCInst &Inst, MCRegister Reg) const
Instances of this class represent operands of the MCInst class.
static MCOperand createExpr(const MCExpr *Val)
static MCOperand createReg(MCRegister Reg)
static MCOperand createImm(int64_t Val)
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.
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
Target - Wrapper for Target specific information.
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)