31 cl::desc(
"Enable the LFI guard elimination optimization"),
70#define GET_LFIVariantTable_DECL
71#define GET_PairVariantTable_DECL
72#define GET_SIMDPostTable_DECL
73#define GET_MemInfoTable_DECL
74#define GET_LFIVariantTable_IMPL
75#define GET_PairVariantTable_IMPL
76#define GET_SIMDPostTable_IMPL
77#define GET_MemInfoTable_IMPL
80#include "AArch64GenSystemOperands.inc"
103 return Reg == AArch64SysReg::TPIDR_EL1 ||
Reg == AArch64SysReg::TPIDR_EL2 ||
104 Reg == AArch64SysReg::TPIDR_EL3;
108 return Inst.
getOpcode() == AArch64::MRS &&
113 return Inst.
getOpcode() == AArch64::MSR &&
149 case AArch64::PRFMroW:
150 case AArch64::PRFMroX:
151 case AArch64::PRFMui:
152 case AArch64::PRFUMi:
174 case AArch64::BLRAAZ:
176 case AArch64::BLRABZ:
184 return Opcode == AArch64::RETAA || Opcode == AArch64::RETAB;
188 return Opcode == AArch64::ERET || Opcode == AArch64::ERETAA ||
189 Opcode == AArch64::ERETAB;
194 case AArch64::AUTIASP:
195 case AArch64::AUTIBSP:
196 case AArch64::AUTIAZ:
197 case AArch64::AUTIBZ:
198 case AArch64::XPACLRI:
230 assert(New.getOperand(Idx).isReg());
231 New.getOperand(Idx).setReg(NewReg);
245 if (!
E ||
E->AddrMode != ExpectedMode)
246 return AArch64::INSTRUCTION_LIST_END;
254 return AArch64::INSTRUCTION_LIST_END;
277 if (
const auto *
E = AArch64::lookupPairVariantByOpcode(
Op)) {
281 if (
const auto *
E = AArch64::lookupSIMDPostByOpcode(
Op)) {
285 return AArch64::INSTRUCTION_LIST_END;
288bool AArch64MCLFIRewriter::mayModifySP(
const MCInst &Inst)
const {
292MCRegister AArch64MCLFIRewriter::mayModifyReserved(
const MCInst &Inst)
const {
306 if (DeferredLRGuard && LastSTI) {
307 emitAddMask(AArch64::LR, AArch64::LR, Out, *LastSTI);
308 DeferredLRGuard =
false;
312 ActiveGuardReg = std::nullopt;
317 if (DeferredLRGuard && LastSTI) {
318 emitAddMask(AArch64::LR, AArch64::LR, Out, *LastSTI);
319 DeferredLRGuard =
false;
327 if (ActiveGuardReg) {
329 if (
Desc.mayAffectControlFlow(Inst, *RegInfo) ||
333 ActiveGuardReg = std::nullopt;
355 emitInst(Inst, Out, STI);
359 ActiveGuardReg = Src;
368 emitInst(Branch, Out, STI);
371void AArch64MCLFIRewriter::emitPendingTLSDescCall(
MCStreamer &Out,
373 if (!PendingTLSDescCall)
378 PendingTLSDescCall =
nullptr;
379 emitInst(Marker, Out, STI);
392 emitInst(Inst, Out, STI);
398 assert(std::abs(Imm) <= 4095);
415 emitInst(Inst, Out, STI);
430 emitInst(Inst, Out, STI);
449 emitInst(Inst, Out, STI);
452void AArch64MCLFIRewriter::emitMemRoW(
unsigned Opcode,
const MCOperand &DataOp,
463 emitInst(Inst, Out, STI);
470void AArch64MCLFIRewriter::rewriteIndirectBranch(
const MCInst &Inst,
474 "expected register operand");
480 emitPendingTLSDescCall(Out, STI);
491void AArch64MCLFIRewriter::rewriteReturn(
const MCInst &Inst,
MCStreamer &Out,
494 "expected register operand");
497 rewriteIndirectBranch(Inst, Out, STI);
499 emitInst(Inst, Out, STI);
506void AArch64MCLFIRewriter::rewriteLRModification(
const MCInst &Inst,
511 rewriteLoadStore(Inst, Out, STI);
513 emitInst(Inst, Out, STI);
518 DeferredLRGuard =
true;
526void AArch64MCLFIRewriter::rewriteAuthenticatedReturn(
531 emitInst(Auth, Out, STI);
533 emitAddMask(AArch64::LR, AArch64::LR, Out, STI);
534 emitBranch(AArch64::RET, AArch64::LR, Out, STI);
542void AArch64MCLFIRewriter::rewriteAuthenticatedBranchOrCall(
559 case AArch64::BLRAAZ:
563 case AArch64::BLRABZ:
574 emitInst(Auth, Out, STI);
578 emitBranch(BranchOpcode,
LFIAddrReg, Out, STI);
594 Load.setOpcode(AArch64::LDURXi);
598 emitInst(
Load, Out, STI);
601 emitBranch(AArch64::BLR, AArch64::LR, Out, STI);
610void AArch64MCLFIRewriter::rewriteTPRead(
const MCInst &Inst,
MCStreamer &Out,
615 Load.setOpcode(AArch64::LDRXui);
619 emitInst(
Load, Out, STI);
625void AArch64MCLFIRewriter::rewriteTPWrite(
const MCInst &Inst,
MCStreamer &Out,
630 Store.setOpcode(AArch64::STRXui);
634 emitInst(
Store, Out, STI);
637bool AArch64MCLFIRewriter::rewriteLoadStoreRoW(
const MCInst &Inst,
646 AArch64::INSTRUCTION_LIST_END) {
648 if (BaseReg == AArch64::SP)
652 emitMemRoW(MemOp, Inst.
getOperand(0), BaseReg, Out, STI);
661 AArch64::INSTRUCTION_LIST_END) {
663 if (BaseReg == AArch64::SP)
666 emitAddImm(BaseReg, BaseReg, Imm, Out, STI);
667 emitMemRoW(MemOp, Inst.
getOperand(1), BaseReg, Out, STI);
674 AArch64::INSTRUCTION_LIST_END) {
676 if (BaseReg == AArch64::SP)
679 emitMemRoW(MemOp, Inst.
getOperand(1), BaseReg, Out, STI);
680 emitAddImm(BaseReg, BaseReg, Imm, Out, STI);
733void AArch64MCLFIRewriter::rewriteLoadStoreBase(
const MCInst &Inst,
737 const AArch64::MemInfoEntry *
Info = AArch64::lookupMemInfoByOpcode(Opcode);
740 warning(Inst,
"unknown addressing mode for memory instruction in LFI");
741 return emitInst(Inst, Out, STI);
745 return error(Inst,
"PC-relative literal loads are not supported in LFI");
751 bool BaseIsSP =
BaseReg == AArch64::SP;
754 return emitInst(Inst, Out, STI);
756 if (OffReg == AArch64::XZR || OffReg == AArch64::WZR)
757 return emitInst(Inst, Out, STI);
764 if (!
Info->IsPrePost) {
767 emitInst(NewInst, Out, STI);
772 bool IsNoOffset =
false;
775 if (BaseOpcode == AArch64::INSTRUCTION_LIST_END)
776 return error(Inst,
"unhandled pre/post-index instruction in LFI rewriter");
784 for (
int I = 1;
I <
Info->BaseIdx; ++
I)
788 MCRegister AccessBase = BaseIsSP ? AArch64::SP :
LFIAddrReg;
792 if (IsPre &&
Info->HasOffset)
794 else if (!IsNoOffset)
797 emitInst(NewInst, Out, STI);
799 if (!
Info->HasOffset)
811 if (
const auto *
E = AArch64::lookupPairVariantByOpcode(Opcode))
814 emitAddImm(BaseReg, BaseReg,
Offset, Out, STI);
817 MCRegister OffReg =
OffsetOp.getReg();
818 if (OffReg == AArch64::XZR) {
819 if (
const auto *
E = AArch64::lookupSIMDPostByOpcode(Opcode))
820 emitAddImm(BaseReg, BaseReg,
E->NaturalOffset, Out, STI);
821 }
else if (OffReg != AArch64::WZR) {
827 emitAddReg(BaseReg, BaseReg, OffReg, 0, Out, STI);
833void AArch64MCLFIRewriter::rewriteLoadStore(
const MCInst &Inst,
MCStreamer &Out,
838 bool SkipLoads = STI.
hasFeature(AArch64::FeatureNoLFILoads);
839 bool SkipStores = STI.
hasFeature(AArch64::FeatureNoLFIStores);
841 if ((!IsLoad || SkipLoads) && (!IsStore || SkipStores))
842 return emitInst(Inst, Out, STI);
844 if (rewriteLoadStoreRoW(Inst, Out, STI))
847 rewriteLoadStoreBase(Inst, Out, STI);
854void AArch64MCLFIRewriter::rewriteSPModification(
const MCInst &Inst,
862 return rewriteLRModification(Inst, Out, STI);
863 return rewriteLoadStore(Inst, Out, STI);
867 bool SkipLoads = STI.
hasFeature(AArch64::FeatureNoLFILoads);
868 bool SkipStores = STI.
hasFeature(AArch64::FeatureNoLFIStores);
869 if (SkipLoads && SkipStores)
870 return emitInst(Inst, Out, STI);
879 emitInst(ModInst, Out, STI);
887void AArch64MCLFIRewriter::rewriteVASysOp(
const MCInst &Inst,
MCStreamer &Out,
900 emitInst(NewInst, Out, STI);
905void AArch64MCLFIRewriter::doRewriteInst(
const MCInst &Inst,
MCStreamer &Out,
907 if (Inst.
getOpcode() == AArch64::TLSDESCCALL) {
913 if (MCRegister
Reg = mayModifyReserved(Inst)) {
914 error(Inst, Twine(
"illegal modification of reserved LFI register ") +
921 return rewriteSyscall(Inst, Out, STI);
924 return rewriteTPRead(Inst, Out, STI);
927 return rewriteTPWrite(Inst, Out, STI);
930 error(Inst,
"illegal access to privileged thread pointer register");
935 return rewriteVASysOp(Inst, Out, STI);
938 error(Inst,
"exception returns are not supported by LFI");
946 DeferredLRGuard =
false;
947 return rewriteAuthenticatedReturn(Inst, Out, STI);
954 emitAddMask(AArch64::LR, AArch64::LR, Out, STI);
955 DeferredLRGuard =
false;
960 return rewriteAuthenticatedBranchOrCall(Inst, AArch64::BR, Out, STI);
962 return rewriteAuthenticatedBranchOrCall(Inst, AArch64::BLR, Out, STI);
967 return rewriteReturn(Inst, Out, STI);
970 return rewriteIndirectBranch(Inst, Out, STI);
974 if (mayModifySP(Inst))
975 return rewriteSPModification(Inst, Out, STI);
980 return rewriteLRModification(Inst, Out, STI);
985 return rewriteLoadStore(Inst, Out, STI);
987 emitInst(Inst, Out, STI);
994 AArch64::INSTRUCTION_LIST_END)
997 AArch64::INSTRUCTION_LIST_END)
999 bool IsPre, IsNoOffset;
1001 AArch64::INSTRUCTION_LIST_END)
1010 ActiveGuardReg = std::nullopt;
1022 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 cl::opt< bool > LFIGuardElim("aarch64-lfi-guard-elim", cl::Hidden, cl::desc("Enable the LFI guard elimination optimization"), cl::init(true))
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 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
void addOperand(const MCOperand Op)
void setOpcode(unsigned Op)
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.
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
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 ==...
initializer< Ty > init(const Ty &Val)
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
This is an optimization pass for GlobalISel generic memory operations.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
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)