Refactor a lot of patchpoint/stackmap related code to simplify and make it

target independent.

Most of the x86 specific stackmap/patchpoint handling was necessitated by the
use of the native address-mode format for frame index operands. PEI has now
been modified to treat stackmap/patchpoint similarly to DEBUG_INFO, allowing
us to use a simple, platform independent register/offset pair for frame
indexes on stackmap/patchpoints.

Notes:
  - Folding is now platform independent and automatically supported.
  - Emiting patchpoints with direct memory references now just involves calling
    the TargetLoweringBase::emitPatchPoint utility method from the target's
    XXXTargetLowering::EmitInstrWithCustomInserter method. (See
    X86TargetLowering for an example).
  - No more ugly platform-specific operand parsers.

This patch shouldn't change the generated output for X86. 

llvm-svn: 195944
This commit is contained in:
Lang Hames 2013-11-29 03:07:54 +00:00
parent 46a6ed9e64
commit 39609996d9
11 changed files with 222 additions and 241 deletions

View File

@ -92,19 +92,12 @@ public:
: LocType(LocType), Size(Size), Reg(Reg), Offset(Offset) {}
};
// Typedef a function pointer for functions that parse sequences of operands
// and return a Location, plus a new "next" operand iterator.
typedef std::pair<Location, MachineInstr::const_mop_iterator>
(*OperandParser)(MachineInstr::const_mop_iterator,
MachineInstr::const_mop_iterator, const TargetMachine&);
// OpTypes are used to encode information about the following logical
// operand (which may consist of several MachineOperands) for the
// OpParser.
typedef enum { DirectMemRefOp, IndirectMemRefOp, ConstantOp } OpType;
StackMaps(AsmPrinter &AP, OperandParser OpParser)
: AP(AP), OpParser(OpParser) {}
StackMaps(AsmPrinter &AP) : AP(AP) {}
/// \brief Generate a stackmap record for a stackmap instruction.
///
@ -155,10 +148,15 @@ private:
};
AsmPrinter &AP;
OperandParser OpParser;
CallsiteInfoList CSInfos;
ConstantPool ConstPool;
/// Parse
std::pair<Location, MachineInstr::const_mop_iterator>
parseOperand(MachineInstr::const_mop_iterator MOI,
MachineInstr::const_mop_iterator MOE);
/// This should be called by the MC lowering code _immediately_ before
/// lowering the MI to an MCInst. It records where the operands for the
/// instruction are stored, and outputs a label to record the offset of

View File

@ -1685,6 +1685,10 @@ protected:
/// Return true if the value types that can be represented by the specified
/// register class are all legal.
bool isLegalRC(const TargetRegisterClass *RC) const;
/// Replace/modify any TargetFrameIndex operands with a targte-dependent
/// sequence of memory operands that is recognized by PrologEpilogInserter.
MachineBasicBlock *emitPatchPoint(MachineInstr *MI, MachineBasicBlock *MBB) const;
};
/// This class defines information used to lower LLVM code to legal SelectionDAG

View File

@ -731,15 +731,18 @@ void PEI::replaceFrameIndices(MachineBasicBlock *BB, MachineFunction &Fn,
// Frame indicies in debug values are encoded in a target independent
// way with simply the frame index and offset rather than any
// target-specific addressing mode.
if (MI->isDebugValue()) {
assert(i == 0 && "Frame indicies can only appear as the first "
"operand of a DBG_VALUE machine instruction");
if (MI->isDebugValue() ||
MI->getOpcode() == TargetOpcode::STACKMAP ||
MI->getOpcode() == TargetOpcode::PATCHPOINT) {
assert((!MI->isDebugValue() || i == 0) &&
"Frame indicies can only appear as the first operand of a "
"DBG_VALUE machine instruction");
unsigned Reg;
MachineOperand &Offset = MI->getOperand(1);
MachineOperand &Offset = MI->getOperand(i + 1);
Offset.setImm(Offset.getImm() +
TFI->getFrameIndexReference(
Fn, MI->getOperand(0).getIndex(), Reg));
MI->getOperand(0).ChangeToRegister(Reg, false /*isDef*/);
Fn, MI->getOperand(i).getIndex(), Reg));
MI->getOperand(i).ChangeToRegister(Reg, false /*isDef*/);
continue;
}

View File

@ -13,6 +13,7 @@
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCObjectFileInfo.h"
@ -65,6 +66,60 @@ unsigned PatchPointOpers::getNextScratchIdx(unsigned StartIdx) const {
return ScratchIdx;
}
std::pair<StackMaps::Location, MachineInstr::const_mop_iterator>
StackMaps::parseOperand(MachineInstr::const_mop_iterator MOI,
MachineInstr::const_mop_iterator MOE) {
const MachineOperand &MOP = *MOI;
assert(!MOP.isRegMask() && (!MOP.isReg() || !MOP.isImplicit()) &&
"Register mask and implicit operands should not be processed.");
if (MOP.isImm()) {
// Verify anyregcc
// [<def>], <id>, <numBytes>, <target>, <numArgs>, <cc>, ...
switch (MOP.getImm()) {
default: llvm_unreachable("Unrecognized operand type.");
case StackMaps::DirectMemRefOp: {
unsigned Size = AP.TM.getDataLayout()->getPointerSizeInBits();
assert((Size % 8) == 0 && "Need pointer size in bytes.");
Size /= 8;
unsigned Reg = (++MOI)->getReg();
int64_t Imm = (++MOI)->getImm();
return std::make_pair(
Location(StackMaps::Location::Direct, Size, Reg, Imm), ++MOI);
}
case StackMaps::IndirectMemRefOp: {
int64_t Size = (++MOI)->getImm();
assert(Size > 0 && "Need a valid size for indirect memory locations.");
unsigned Reg = (++MOI)->getReg();
int64_t Imm = (++MOI)->getImm();
return std::make_pair(
Location(StackMaps::Location::Indirect, Size, Reg, Imm), ++MOI);
}
case StackMaps::ConstantOp: {
++MOI;
assert(MOI->isImm() && "Expected constant operand.");
int64_t Imm = MOI->getImm();
return std::make_pair(
Location(Location::Constant, sizeof(int64_t), 0, Imm), ++MOI);
}
}
}
// Otherwise this is a reg operand. The physical register number will
// ultimately be encoded as a DWARF regno. The stack map also records the size
// of a spill slot that can hold the register content. (The runtime can
// track the actual size of the data type if it needs to.)
assert(MOP.isReg() && "Expected register operand here.");
assert(TargetRegisterInfo::isPhysicalRegister(MOP.getReg()) &&
"Virtreg operands should have been rewritten before now.");
const TargetRegisterClass *RC =
AP.TM.getRegisterInfo()->getMinimalPhysRegClass(MOP.getReg());
assert(!MOP.getSubReg() && "Physical subreg still around.");
return std::make_pair(
Location(Location::Register, RC->getSize(), MOP.getReg(), 0), ++MOI);
}
void StackMaps::recordStackMapOpers(const MachineInstr &MI, uint32_t ID,
MachineInstr::const_mop_iterator MOI,
MachineInstr::const_mop_iterator MOE,
@ -78,7 +133,7 @@ void StackMaps::recordStackMapOpers(const MachineInstr &MI, uint32_t ID,
if (recordResult) {
std::pair<Location, MachineInstr::const_mop_iterator> ParseResult =
OpParser(MI.operands_begin(), llvm::next(MI.operands_begin()), AP.TM);
parseOperand(MI.operands_begin(), llvm::next(MI.operands_begin()));
Location &Loc = ParseResult.first;
assert(Loc.LocType == Location::Register &&
@ -87,10 +142,8 @@ void StackMaps::recordStackMapOpers(const MachineInstr &MI, uint32_t ID,
}
while (MOI != MOE) {
std::pair<Location, MachineInstr::const_mop_iterator> ParseResult =
OpParser(MOI, MOE, AP.TM);
Location &Loc = ParseResult.first;
Location Loc;
tie(Loc, MOI) = parseOperand(MOI, MOE);
// Move large constants into the constant pool.
if (Loc.LocType == Location::Constant && (Loc.Offset & ~0xFFFFFFFFULL)) {
@ -99,7 +152,6 @@ void StackMaps::recordStackMapOpers(const MachineInstr &MI, uint32_t ID,
}
CallsiteLocs.push_back(Loc);
MOI = ParseResult.second;
}
const MCExpr *CSOffsetExpr = MCBinaryExpr::CreateSub(

View File

@ -13,10 +13,12 @@
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/CodeGen/ScoreboardHazardRecognizer.h"
#include "llvm/CodeGen/StackMaps.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCInstrItineraries.h"
@ -372,6 +374,65 @@ canFoldMemoryOperand(const MachineInstr *MI,
return MI->isCopy() && Ops.size() == 1 && canFoldCopy(MI, Ops[0]);
}
static MachineInstr* foldPatchpoint(MachineFunction &MF,
MachineInstr *MI,
const SmallVectorImpl<unsigned> &Ops,
int FrameIndex,
const TargetInstrInfo &TII) {
unsigned StartIdx = 0;
switch (MI->getOpcode()) {
case TargetOpcode::STACKMAP:
StartIdx = 2; // Skip ID, nShadowBytes.
break;
case TargetOpcode::PATCHPOINT: {
// For PatchPoint, the call args are not foldable.
PatchPointOpers opers(MI);
StartIdx = opers.getVarIdx();
break;
}
default:
llvm_unreachable("unexpected stackmap opcode");
}
// Return false if any operands requested for folding are not foldable (not
// part of the stackmap's live values).
for (SmallVectorImpl<unsigned>::const_iterator I = Ops.begin(), E = Ops.end();
I != E; ++I) {
if (*I < StartIdx)
return 0;
}
MachineInstr *NewMI =
MF.CreateMachineInstr(TII.get(MI->getOpcode()), MI->getDebugLoc(), true);
MachineInstrBuilder MIB(MF, NewMI);
// No need to fold return, the meta data, and function arguments
for (unsigned i = 0; i < StartIdx; ++i)
MIB.addOperand(MI->getOperand(i));
for (unsigned i = StartIdx; i < MI->getNumOperands(); ++i) {
MachineOperand &MO = MI->getOperand(i);
if (std::find(Ops.begin(), Ops.end(), i) != Ops.end()) {
unsigned SpillSize;
unsigned SpillOffset;
// Compute the spill slot size and offset.
const TargetRegisterClass *RC =
MF.getRegInfo().getRegClass(MO.getReg());
bool Valid = TII.getStackSlotRange(RC, MO.getSubReg(), SpillSize,
SpillOffset, &MF.getTarget());
if (!Valid)
report_fatal_error("cannot spill patchpoint subregister operand");
MIB.addImm(StackMaps::IndirectMemRefOp);
MIB.addImm(SpillSize);
MIB.addFrameIndex(FrameIndex);
MIB.addImm(0);
}
else
MIB.addOperand(MO);
}
return NewMI;
}
/// foldMemoryOperand - Attempt to fold a load or store of the specified stack
/// slot into the specified machine instruction for the specified operand(s).
/// If this is possible, a new instruction is returned with the specified
@ -393,8 +454,18 @@ TargetInstrInfo::foldMemoryOperand(MachineBasicBlock::iterator MI,
assert(MBB && "foldMemoryOperand needs an inserted instruction");
MachineFunction &MF = *MBB->getParent();
// Ask the target to do the actual folding.
if (MachineInstr *NewMI = foldMemoryOperandImpl(MF, MI, Ops, FI)) {
MachineInstr *NewMI = 0;
if (MI->getOpcode() == TargetOpcode::STACKMAP ||
MI->getOpcode() == TargetOpcode::PATCHPOINT) {
// Fold stackmap/patchpoint.
NewMI = foldPatchpoint(MF, MI, Ops, FI, *this);
} else {
// Ask the target to do the actual folding.
NewMI =foldMemoryOperandImpl(MF, MI, Ops, FI);
}
if (NewMI) {
NewMI->setMemRefs(MI->memoperands_begin(), MI->memoperands_end());
// Add a memory operand, foldMemoryOperandImpl doesn't do that.
assert((!(Flags & MachineMemOperand::MOStore) ||
@ -450,7 +521,20 @@ TargetInstrInfo::foldMemoryOperand(MachineBasicBlock::iterator MI,
MachineFunction &MF = *MBB.getParent();
// Ask the target to do the actual folding.
MachineInstr *NewMI = foldMemoryOperandImpl(MF, MI, Ops, LoadMI);
MachineInstr *NewMI = 0;
int FrameIndex = 0;
if ((MI->getOpcode() == TargetOpcode::STACKMAP ||
MI->getOpcode() == TargetOpcode::PATCHPOINT) &&
isLoadFromStackSlot(LoadMI, FrameIndex)) {
// Fold stackmap/patchpoint.
NewMI = foldPatchpoint(MF, MI, Ops, FrameIndex, *this);
} else {
// Ask the target to do the actual folding.
NewMI =foldMemoryOperandImpl(MF, MI, Ops, LoadMI);
}
foldMemoryOperandImpl(MF, MI, Ops, LoadMI);
if (!NewMI) return 0;
NewMI = MBB.insert(MI, NewMI);

View File

@ -18,7 +18,9 @@
#include "llvm/CodeGen/Analysis.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/StackMaps.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/GlobalVariable.h"
@ -894,6 +896,60 @@ bool TargetLoweringBase::isLegalRC(const TargetRegisterClass *RC) const {
return false;
}
/// Replace/modify any TargetFrameIndex operands with a targte-dependent
/// sequence of memory operands that is recognized by PrologEpilogInserter.
MachineBasicBlock*
TargetLoweringBase::emitPatchPoint(MachineInstr *MI,
MachineBasicBlock *MBB) const {
const TargetMachine &TM = getTargetMachine();
const TargetInstrInfo *TII = TM.getInstrInfo();
MachineFunction &MF = *MI->getParent()->getParent();
// MI changes inside this loop as we grow operands.
for(unsigned OperIdx = 0; OperIdx != MI->getNumOperands(); ++OperIdx) {
MachineOperand &MO = MI->getOperand(OperIdx);
if (!MO.isFI())
continue;
// foldMemoryOperand builds a new MI after replacing a single FI operand
// with the canonical set of five x86 addressing-mode operands.
int FI = MO.getIndex();
MachineInstrBuilder MIB = BuildMI(MF, MI->getDebugLoc(), MI->getDesc());
// Copy operands before the frame-index.
for (unsigned i = 0; i < OperIdx; ++i)
MIB.addOperand(MI->getOperand(i));
// Add frame index operands: direct-mem-ref tag, #FI, offset.
MIB.addImm(StackMaps::DirectMemRefOp);
MIB.addOperand(MI->getOperand(OperIdx));
MIB.addImm(0);
// Copy the operands after the frame index.
for (unsigned i = OperIdx + 1; i != MI->getNumOperands(); ++i)
MIB.addOperand(MI->getOperand(i));
// Inherit previous memory operands.
MIB->setMemRefs(MI->memoperands_begin(), MI->memoperands_end());
assert(MIB->mayLoad() && "Folded a stackmap use to a non-load!");
// Add a new memory operand for this FI.
const MachineFrameInfo &MFI = *MF.getFrameInfo();
assert(MFI.getObjectOffset(FI) != -1);
MachineMemOperand *MMO =
MF.getMachineMemOperand(MachinePointerInfo::getFixedStack(FI),
MachineMemOperand::MOLoad,
TM.getDataLayout()->getPointerSize(),
MFI.getObjectAlignment(FI));
MIB->addMemOperand(MF, MMO);
// Replace the instruction and update the operand index.
MBB->insert(MachineBasicBlock::iterator(MI), MIB);
OperIdx += (MIB->getNumOperands() - MI->getNumOperands()) - 1;
MI->eraseFromParent();
MI = MIB;
}
return MBB;
}
/// findRepresentativeClass - Return the largest legal super-reg register class
/// of the register class for the specified type and its associated "cost".
std::pair<const TargetRegisterClass*, uint8_t>

View File

@ -27,19 +27,9 @@ class LLVM_LIBRARY_VISIBILITY X86AsmPrinter : public AsmPrinter {
const X86Subtarget *Subtarget;
StackMaps SM;
// Parses operands of PATCHPOINT and STACKMAP to produce stack map Location
// structures. Returns a result location and an iterator to the operand
// immediately following the operands consumed.
//
// This method is implemented in X86MCInstLower.cpp.
static std::pair<StackMaps::Location, MachineInstr::const_mop_iterator>
stackmapOperandParser(MachineInstr::const_mop_iterator MOI,
MachineInstr::const_mop_iterator MOE,
const TargetMachine &TM);
public:
explicit X86AsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
: AsmPrinter(TM, Streamer), SM(*this, stackmapOperandParser) {
: AsmPrinter(TM, Streamer), SM(*this) {
Subtarget = &TM.getSubtarget<X86Subtarget>();
}

View File

@ -15819,51 +15819,6 @@ X86TargetLowering::emitEHSjLjLongJmp(MachineInstr *MI,
return MBB;
}
/// Convert any TargetFrameIndex operands into the x86-specific pattern of five
/// memory operands that is recognized by PrologEpilogInserter.
MachineBasicBlock *
X86TargetLowering::emitPatchPoint(MachineInstr *MI,
MachineBasicBlock *MBB) const {
const TargetMachine &TM = getTargetMachine();
const X86InstrInfo *TII = static_cast<const X86InstrInfo*>(TM.getInstrInfo());
// MI changes inside this loop as we grow operands.
for(unsigned OperIdx = 0; OperIdx != MI->getNumOperands(); ++OperIdx) {
MachineOperand &MO = MI->getOperand(OperIdx);
if (!MO.isFI())
continue;
// foldMemoryOperand builds a new MI after replacing a single FI operand
// with the canonical set of five x86 addressing-mode operands.
int FI = MO.getIndex();
MachineFunction &MF = *MBB->getParent();
SmallVector<unsigned, 1> FIOps(1, OperIdx);
MachineInstr *NewMI = TII->foldMemoryOperandImpl(MF, MI, FIOps, FI);
assert(NewMI && "Cannot fold frame index operand into stackmap.");
// Inherit previous memory operands.
NewMI->setMemRefs(MI->memoperands_begin(), MI->memoperands_end());
assert(NewMI->mayLoad() && "Folded a stackmap use to a non-load!");
// Add a new memory operand for this FI.
const MachineFrameInfo &MFI = *MF.getFrameInfo();
assert(MFI.getObjectOffset(FI) != -1);
MachineMemOperand *MMO =
MF.getMachineMemOperand(MachinePointerInfo::getFixedStack(FI),
MachineMemOperand::MOLoad,
TM.getDataLayout()->getPointerSize(),
MFI.getObjectAlignment(FI));
NewMI->addMemOperand(MF, MMO);
// Replace the instruction and update the operand index.
MBB->insert(MachineBasicBlock::iterator(MI), NewMI);
OperIdx += (NewMI->getNumOperands() - MI->getNumOperands()) - 1;
MI->eraseFromParent();
MI = NewMI;
}
return MBB;
}
MachineBasicBlock *
X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
MachineBasicBlock *BB) const {

View File

@ -973,9 +973,6 @@ namespace llvm {
MachineBasicBlock *emitEHSjLjLongJmp(MachineInstr *MI,
MachineBasicBlock *MBB) const;
MachineBasicBlock *emitPatchPoint(MachineInstr *MI,
MachineBasicBlock *MBB) const;
/// Emit nodes that will be selected as "test Op0,Op0", or something
/// equivalent, for use with the given x86 condition code.
SDValue EmitTest(SDValue Op0, unsigned X86CC, SelectionDAG &DAG) const;

View File

@ -4198,84 +4198,10 @@ breakPartialRegDependency(MachineBasicBlock::iterator MI, unsigned OpNum,
MI->addRegisterKilled(Reg, TRI, true);
}
static MachineInstr* foldPatchpoint(MachineFunction &MF,
MachineInstr *MI,
const SmallVectorImpl<unsigned> &Ops,
int FrameIndex,
const TargetInstrInfo &TII) {
unsigned StartIdx = 0;
switch (MI->getOpcode()) {
case TargetOpcode::STACKMAP:
StartIdx = 2; // Skip ID, nShadowBytes.
break;
case TargetOpcode::PATCHPOINT: {
// For PatchPoint, the call args are not foldable.
PatchPointOpers opers(MI);
StartIdx = opers.getVarIdx();
break;
}
default:
llvm_unreachable("unexpected stackmap opcode");
}
// Return false if any operands requested for folding are not foldable (not
// part of the stackmap's live values).
for (SmallVectorImpl<unsigned>::const_iterator I = Ops.begin(), E = Ops.end();
I != E; ++I) {
if (*I < StartIdx)
return 0;
}
MachineInstr *NewMI =
MF.CreateMachineInstr(TII.get(MI->getOpcode()), MI->getDebugLoc(), true);
MachineInstrBuilder MIB(MF, NewMI);
// No need to fold return, the meta data, and function arguments
for (unsigned i = 0; i < StartIdx; ++i)
MIB.addOperand(MI->getOperand(i));
for (unsigned i = StartIdx; i < MI->getNumOperands(); ++i) {
MachineOperand &MO = MI->getOperand(i);
if (std::find(Ops.begin(), Ops.end(), i) != Ops.end()) {
unsigned SpillSize;
unsigned SpillOffset;
if (MO.isReg()) {
// Compute the spill slot size and offset.
const TargetRegisterClass *RC =
MF.getRegInfo().getRegClass(MO.getReg());
bool Valid = TII.getStackSlotRange(RC, MO.getSubReg(), SpillSize,
SpillOffset, &MF.getTarget());
if (!Valid)
report_fatal_error("cannot spill patchpoint subregister operand");
MIB.addOperand(MachineOperand::CreateImm(StackMaps::IndirectMemRefOp));
MIB.addOperand(MachineOperand::CreateImm(SpillSize));
}
else {
// ExpandISelPseudos is converting a simple frame index into a 5-operand
// frame index.
assert(MO.isFI() && MO.getIndex() == FrameIndex &&
"patchpoint can only fold a vreg operand or frame index");
SpillOffset = 0;
MIB.addOperand(MachineOperand::CreateImm(StackMaps::DirectMemRefOp));
}
MIB.addOperand(MachineOperand::CreateFI(FrameIndex));
addOffset(MIB, SpillOffset);
}
else
MIB.addOperand(MO);
}
return NewMI;
}
MachineInstr*
X86InstrInfo::foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI,
const SmallVectorImpl<unsigned> &Ops,
int FrameIndex) const {
// Special case stack map and patch point intrinsics.
if (MI->getOpcode() == TargetOpcode::STACKMAP
|| MI->getOpcode() == TargetOpcode::PATCHPOINT) {
return foldPatchpoint(MF, MI, Ops, FrameIndex, *this);
}
// Check switch flag
if (NoFusing) return NULL;

View File

@ -674,90 +674,6 @@ static void LowerTlsAddr(MCStreamer &OutStreamer,
.addExpr(tlsRef));
}
static std::pair<StackMaps::Location, MachineInstr::const_mop_iterator>
parseMemoryOperand(StackMaps::Location::LocationType LocTy, unsigned Size,
MachineInstr::const_mop_iterator MOI,
MachineInstr::const_mop_iterator MOE) {
typedef StackMaps::Location Location;
assert(std::distance(MOI, MOE) >= 5 && "Too few operands to encode mem op.");
const MachineOperand &Base = *MOI;
const MachineOperand &Scale = *(++MOI);
const MachineOperand &Index = *(++MOI);
const MachineOperand &Disp = *(++MOI);
const MachineOperand &ZeroReg = *(++MOI);
// Sanity check for supported operand format.
assert(Base.isReg() &&
Scale.isImm() && Scale.getImm() == 1 &&
Index.isReg() && Index.getReg() == 0 &&
Disp.isImm() && ZeroReg.isReg() && (ZeroReg.getReg() == 0) &&
"Unsupported x86 memory operand sequence.");
(void)Scale;
(void)Index;
(void)ZeroReg;
return std::make_pair(
Location(LocTy, Size, Base.getReg(), Disp.getImm()), ++MOI);
}
std::pair<StackMaps::Location, MachineInstr::const_mop_iterator>
X86AsmPrinter::stackmapOperandParser(MachineInstr::const_mop_iterator MOI,
MachineInstr::const_mop_iterator MOE,
const TargetMachine &TM) {
typedef StackMaps::Location Location;
const MachineOperand &MOP = *MOI;
assert(!MOP.isRegMask() && (!MOP.isReg() || !MOP.isImplicit()) &&
"Register mask and implicit operands should not be processed.");
if (MOP.isImm()) {
// Verify anyregcc
// [<def>], <id>, <numBytes>, <target>, <numArgs>, <cc>, ...
switch (MOP.getImm()) {
default: llvm_unreachable("Unrecognized operand type.");
case StackMaps::DirectMemRefOp: {
unsigned Size = TM.getDataLayout()->getPointerSizeInBits();
assert((Size % 8) == 0 && "Need pointer size in bytes.");
Size /= 8;
return parseMemoryOperand(StackMaps::Location::Direct, Size,
llvm::next(MOI), MOE);
}
case StackMaps::IndirectMemRefOp: {
++MOI;
int64_t Size = MOI->getImm();
assert(Size > 0 && "Need a valid size for indirect memory locations.");
return parseMemoryOperand(StackMaps::Location::Indirect, Size,
llvm::next(MOI), MOE);
}
case StackMaps::ConstantOp: {
++MOI;
assert(MOI->isImm() && "Expected constant operand.");
int64_t Imm = MOI->getImm();
return std::make_pair(
Location(Location::Constant, sizeof(int64_t), 0, Imm), ++MOI);
}
}
}
// Otherwise this is a reg operand. The physical register number will
// ultimately be encoded as a DWARF regno. The stack map also records the size
// of a spill slot that can hold the register content. (The runtime can
// track the actual size of the data type if it needs to.)
assert(MOP.isReg() && "Expected register operand here.");
assert(TargetRegisterInfo::isPhysicalRegister(MOP.getReg()) &&
"Virtreg operands should have been rewritten before now.");
const TargetRegisterClass *RC =
TM.getRegisterInfo()->getMinimalPhysRegClass(MOP.getReg());
assert(!MOP.getSubReg() && "Physical subreg still around.");
return std::make_pair(
Location(Location::Register, RC->getSize(), MOP.getReg(), 0), ++MOI);
}
// Lower a stackmap of the form:
// <id>, <shadowBytes>, ...
static void LowerSTACKMAP(MCStreamer &OutStreamer,