49 case X86::ADDR16_PREFIX:
50 case X86::ADDR32_PREFIX:
62 return Inst.
getOpcode() == X86::CALL64pcrel32;
126 return Reg == X86::NoRegister ||
127 getX86MCRegisterClass(X86::GR64RegClassID).contains(
Reg);
131 if (getX86MCRegisterClass(X86::GR32RegClassID).
contains(
Reg))
133 return RegInfo->getSubReg(
Reg, X86::sub_32bit);
136void X86::X86MCLFIRewriter::emitWithPrefixes(
const MCInst &Inst,
138 const MCSubtargetInfo &STI) {
139 for (
const MCInst &Prefix : Prefixes)
140 Out.emitInstruction(Prefix, STI);
142 Out.emitInstruction(Inst, STI);
145void X86::X86MCLFIRewriter::discardPrefixes() {
146 for (
const MCInst &Prefix : Prefixes)
147 error(Prefix,
"unsupported instruction prefix");
158void X86::X86MCLFIRewriter::rewriteSyscall(
const MCInst &Inst, MCStreamer &Out,
159 const MCSubtargetInfo &STI) {
160 Out.emitBundleLock(
false, STI);
166 MCInstBuilder(X86::LEA64r)
170 .addReg(X86::NoRegister)
172 .addReg(X86::NoRegister),
176 Out.emitInstruction(MCInstBuilder(X86::JMP64m)
179 .addReg(X86::NoRegister)
181 .addReg(X86::NoRegister),
184 Out.emitLabel(Symbol);
185 Out.emitBundleUnlock(STI);
190void X86::X86MCLFIRewriter::emitSandboxBranchReg(MCRegister
Reg,
192 const MCSubtargetInfo &STI) {
193 MCRegister Reg32 = RegInfo->getSubReg(
Reg, X86::sub_32bit);
195 Out.emitInstruction(MCInstBuilder(X86::AND32ri8)
228void X86::X86MCLFIRewriter::rewriteIndirectBranch(
const MCInst &Inst,
230 const MCSubtargetInfo &STI) {
239 MCInstBuilder Mov(X86::MOV64rm);
243 Mov.setLoc(Inst.
getLoc());
244 doRewriteInst(Mov, Out, STI);
249 return error(Inst,
"indirect branch through reserved register");
252 Out.emitBundleLock(isCall(Inst), STI);
254 emitSandboxBranchReg(Target, Out, STI);
257 MCInstBuilder(isCall(Inst) ? X86::CALL64r : X86::JMP64r).addReg(Target);
260 Out.emitInstruction(Branch, STI);
262 Out.emitBundleUnlock(STI);
267void X86::X86MCLFIRewriter::rewriteDirectCall(
const MCInst &Inst,
269 const MCSubtargetInfo &STI) {
270 Out.emitBundleLock(
true, STI);
271 emitWithPrefixes(Inst, Out, STI);
272 Out.emitBundleUnlock(STI);
296void X86::X86MCLFIRewriter::rewriteReturn(
const MCInst &Inst, MCStreamer &Out,
297 const MCSubtargetInfo &STI) {
299 return error(Inst,
"unsupported return instruction");
308 doRewriteInst(MCInstBuilder(X86::ADD64ri32)
316 Out.emitBundleLock(
false, STI);
322 Out.emitBundleUnlock(STI);
332 .addReg(X86::NoRegister)
334 .addReg(X86::NoRegister),
338bool X86::X86MCLFIRewriter::isFSAccess(
const MCInst &Inst) {
339 return (mayLoad(Inst) || mayStore(Inst)) &&
361void X86::X86MCLFIRewriter::rewriteFSAccess(
const MCInst &Inst, MCStreamer &Out,
362 const MCSubtargetInfo &STI) {
364 assert(MemIdx >= 0 &&
"expected an %fs memory operand");
368 bool HasBase =
BaseReg != X86::NoRegister;
369 bool HasIndex = IndexReg != X86::NoRegister;
375 if (!HasBase && !HasIndex && !HasDisp) {
380 return emitWithPrefixes(
Modified, Out, STI);
384 BaseReg == X86::RSP || BaseReg == X86::RIP)
385 return error(Inst,
"unsupported addressing mode for %fs access");
394 if (
Desc.getNumDefs() > 0 &&
395 getX86MCRegisterClass(X86::GR64RegClassID).
contains(DestReg) &&
402 return error(Inst,
"%fs access reads reserved register %r11");
413 if (HasBase && HasIndex) {
414 Out.emitInstruction(MCInstBuilder(X86::LEA64r)
420 .addReg(X86::NoRegister),
433 if (HasBase && !HasIndex)
452 case X86::MASKMOVDQU:
453 case X86::MASKMOVDQU64:
454 case X86::VMASKMOVDQU:
455 case X86::VMASKMOVDQU64:
456 case X86::MMX_MASKMOVQ:
457 case X86::MMX_MASKMOVQ64:
462 case X86::MOVDIR64B32:
463 case X86::MOVDIR64B64:
464 case X86::MOVDIR64B32_EVEX:
465 case X86::MOVDIR64B64_EVEX:
468 case X86::ENQCMD32_EVEX:
469 case X86::ENQCMD64_EVEX:
472 case X86::ENQCMDS32_EVEX:
473 case X86::ENQCMDS64_EVEX:
497 case X86::LOCK_BTC_RM16rm:
498 case X86::LOCK_BTC_RM32rm:
499 case X86::LOCK_BTC_RM64rm:
500 case X86::LOCK_BTR_RM16rm:
501 case X86::LOCK_BTR_RM32rm:
502 case X86::LOCK_BTR_RM64rm:
503 case X86::LOCK_BTS_RM16rm:
504 case X86::LOCK_BTS_RM32rm:
505 case X86::LOCK_BTS_RM64rm:
532 return Index && getX86MCRegisterClass(X86::GR64RegClassID).contains(Index);
540 const MCRegisterClass &GR32 = getX86MCRegisterClass(X86::GR32RegClassID);
551void X86::X86MCLFIRewriter::sandboxMemOperand(MCInst &Inst,
int MemIdx)
const {
559 if (
Index.getReg() == X86::RIZ) {
560 Index.setReg(X86::NoRegister);
582 Base.setReg(getReg32(
Base.getReg()));
589void X86::X86MCLFIRewriter::sandboxMemAccess(MCInst &Inst)
const {
595 sandboxMemOperand(Inst, MemIdx);
598void X86::X86MCLFIRewriter::rewriteMemAccess(
const MCInst &Inst,
600 const MCSubtargetInfo &STI) {
601 MCInst Sandboxed(Inst);
602 sandboxMemAccess(Sandboxed);
603 emitWithPrefixes(Sandboxed, Out, STI);
607struct StringOpPointers {
619 case X86::REP_STOSB_64:
620 case X86::REP_STOSW_64:
621 case X86::REP_STOSD_64:
622 case X86::REP_STOSQ_64:
627 return StringOpPointers{
true,
false};
632 case X86::REP_MOVSB_64:
633 case X86::REP_MOVSW_64:
634 case X86::REP_MOVSD_64:
635 case X86::REP_MOVSQ_64:
640 return StringOpPointers{
true,
true};
645 return StringOpPointers{
false,
true};
653 Out.emitInstruction(
MCInstBuilder(X86::MOV32rr).addReg(Reg32).addReg(Reg32),
662 .addReg(X86::NoRegister),
675void X86::X86MCLFIRewriter::rewriteStringOperation(
const MCInst &Inst,
677 const MCSubtargetInfo &STI) {
679 assert(Ptrs &&
"expected a string instruction");
683 for (
const MCOperand &
Op : Inst) {
686 if (
Op.getReg() == X86::EDI ||
Op.getReg() == X86::ESI)
687 return error(Inst,
"unsupported address size for string instruction");
688 if (
Op.getReg() == X86::FS)
689 return error(Inst,
"unsupported segment override for string instruction");
692 Out.emitBundleLock(
false, STI);
699 emitWithPrefixes(Inst, Out, STI);
701 Out.emitBundleUnlock(STI);
734 return X86::LEA64_32r;
738 return X86::ADD32ri8;
744 return X86::SUB32ri8;
750 return X86::AND32ri8;
762 return X86::XOR32ri8;
770MCRegister X86::X86MCLFIRewriter::getWrittenStackReg(
const MCInst &Inst)
const {
772 for (
unsigned I = 0,
E =
Desc.getNumDefs();
I <
E; ++
I) {
774 if (
Op.isReg() && RegInfo->regsOverlap(
Op.getReg(), X86::RSP))
777 return X86::NoRegister;
788 .addReg(X86::NoRegister),
798void X86::X86MCLFIRewriter::rewriteStackModification(
799 MCRegister StackReg,
const MCInst &Inst, MCStreamer &Out,
800 const MCSubtargetInfo &STI) {
801 if (StackReg != X86::RSP)
802 return error(Inst,
"unsupported modification of the stack pointer");
812 Out.emitBundleLock(
false, STI);
814 MCInstBuilder(X86::MOV32rr).addReg(X86::ESP).addReg(X86::R11D), STI);
816 Out.emitBundleUnlock(STI);
831 return error(Inst,
"unsupported modification of the stack pointer");
833 MCInstBuilder
Load(X86::MOV64rm);
838 doRewriteInst(
Load, Out, STI);
840 MCInstBuilder RegForm(*RegOpcode);
841 for (
int I = 0;
I < MemIdx; ++
I)
844 RegForm.setLoc(Inst.
getLoc());
845 return doRewriteInst(RegForm, Out, STI);
850 return error(Inst,
"unsupported modification of the stack pointer");
856 for (
unsigned I = 0,
E = std::min<unsigned>(OpInfo.
size(),
862 if (getX86MCRegisterClass(X86::GR64RegClassID).
contains(
Op.getReg()))
863 Op.setReg(RegInfo->getSubReg(
Op.getReg(), X86::sub_32bit));
866 Out.emitBundleLock(
false, STI);
869 Out.emitBundleUnlock(STI);
879void X86::X86MCLFIRewriter::rewriteLeave(
const MCInst &Inst, MCStreamer &Out,
880 const MCSubtargetInfo &STI) {
881 doRewriteInst(MCInstBuilder(X86::MOV64rr)
886 Out.emitInstruction(MCInstBuilder(X86::POP64r).addReg(X86::RBP), STI);
889void X86::X86MCLFIRewriter::doRewriteInst(
const MCInst &Inst, MCStreamer &Out,
890 const MCSubtargetInfo &STI) {
892 return error(Inst,
"LFI only supports 64-bit mode");
898 return error(Inst,
"unsupported instruction prefix");
899 Prefixes.push_back(Inst);
906 return error(Inst,
"unsupported lock prefix");
910 return error(Inst,
"illegal modification of reserved LFI register");
913 return error(Inst,
"illegal modification of reserved segment base");
916 return rewriteSyscall(Inst, Out, STI);
919 return rewriteReturn(Inst, Out, STI);
922 return rewriteDirectCall(Inst, Out, STI);
926 return error(Inst,
"unsupported branch instruction");
928 if (isIndirectBranch(Inst) || isCall(Inst)) {
930 return error(Inst,
"unsupported indirect branch");
931 return rewriteIndirectBranch(Inst, Out, STI);
934 for (
const MCOperand &
Op : Inst)
936 return error(Inst,
"invalid use of reserved segment register %gs");
938 if (MCRegister StackReg = getWrittenStackReg(Inst))
939 return rewriteStackModification(StackReg, Inst, Out, STI);
947 return error(Inst,
"unsupported memory access");
950 return error(Inst,
"unsupported bit test with a register bit offset");
952 if (isFSAccess(Inst))
953 return rewriteFSAccess(Inst, Out, STI);
959 return error(Inst,
"unsupported 32-bit address size");
962 return rewriteStringOperation(Inst, Out, STI);
964 if (Inst.getOpcode() == X86::LEAVE64)
965 return rewriteLeave(Inst, Out, STI);
967 if (Inst.getOpcode() == X86::ENTER &&
968 (!Inst.getOperand(1).isImm() ||
969 static_cast<uint64_t>(Inst.getOperand(1).getImm()) > 1))
970 return error(Inst,
"unsupported nesting level for enter");
972 rewriteMemAccess(Inst, Out, STI);
983 size_t PrefixesBefore = Prefixes.size();
985 doRewriteInst(Inst, Out, STI);
987 if (Prefixes.size() == PrefixesBefore)
static constexpr MCRegister LFIScratchReg
static bool isSyscall(const MCInst &Inst)
static constexpr MCRegister LFIBaseReg
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")
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
static bool isPrefix(unsigned Opcode, const MCInstrInfo &MCII)
Check if the instruction is a prefix.
static bool isWriteSegmentBase(unsigned Opcode)
static void emitStackFixup(MCStreamer &Out, const MCSubtargetInfo &STI)
static std::optional< unsigned > memToRegOpcode(unsigned Opcode)
static bool has32BitAddress(const MCInst &Inst, int MemIdx)
static bool isDirectCall(const MCInst &Inst)
static void emitTPLoad(MCRegister Reg, MCStreamer &Out, const MCSubtargetInfo &STI)
static bool hasNoTrackPrefix(const MCInst &Inst, const MCInstrInfo &InstInfo)
static bool isGR64OrNone(MCRegister Reg)
static bool isPrefix(const MCInst &Inst, const MCInstrInfo &InstInfo)
static bool isSupportedIndirectBranch(const MCInst &Inst)
static int findFSMemOperand(const MCInst &Inst, const MCInstrInfo &InstInfo)
static bool hasGPRIndex(const MCInst &Inst, int MemIdx)
static bool isSupportedPrefix(const MCInst &Inst)
static constexpr MCRegister LFITPReg
static constexpr int TPOffset
static void emitStringPtrFixup(MCRegister Reg, MCRegister Reg32, MCStreamer &Out, const MCSubtargetInfo &STI)
static bool isSyscall(const MCInst &Inst)
static bool hasImplicitMemPointer(unsigned Opcode)
static constexpr MCRegister LFIBaseSeg
static bool readsRegister(const MCInst &Inst, const MCInstrDesc &Desc, MCRegister Reg, const MCRegisterInfo &RI)
static bool isSandboxBaseReg(MCRegister Reg)
static std::optional< unsigned > demote64BitOpcode(unsigned Opcode)
static bool ignoresMemOperand(unsigned Opcode)
static bool isBitTestWithRegOffset(unsigned Opcode)
static std::optional< StringOpPointers > getStringOpPointers(unsigned Opcode)
size_t size() const
Get the array size.
Instances of this class represent a single low-level machine instruction.
unsigned getNumOperands() const
unsigned getFlags() const
unsigned getOpcode() const
const MCOperand & getOperand(unsigned i) const
Describe properties that are true of each instruction in the target description file.
Interface to description of machine instruction set.
std::unique_ptr< MCRegisterInfo > RegInfo
Instances of this class represent operands of the MCInst class.
void setReg(MCRegister Reg)
Set the register number.
MCRegister getReg() const
Returns the register number.
MCRegisterClass - Base class of TargetRegisterClass.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
bool regsOverlap(MCRegister RegA, MCRegister RegB) const
Returns true if the two registers are equal or alias each other.
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
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
A Use represents the edge between a Value definition and its users.
void finish(MCStreamer &Out) override
bool rewriteInst(const MCInst &Inst, MCStreamer &Out, const MCSubtargetInfo &STI) override
void onLabel(const MCSymbol *Symbol, MCStreamer &Out) override
bool isPrefix(uint64_t TSFlags)
int getMemoryOperandIdx(const MCInstrDesc &Desc)
@ RawFrmMemOffs
RawFrmMemOffs - This form is for instructions that store an absolute memory offset as an immediate wi...
constexpr unsigned LFIBundleSize
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).
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >