39#define DEBUG_TYPE "stackmaps"
43 cl::desc(
"Specify the stackmap encoding version (default = 3)"));
45const char *StackMaps::WSMP =
"Stack Maps: ";
49 MI.getOperand(
Idx).getImm() == StackMaps::ConstantOp);
50 const auto &MO =
MI.getOperand(
Idx + 1);
58 "invalid stackmap definition");
62 :
MI(
MI), HasDef(
MI->getOperand(0).
isReg() &&
MI->getOperand(0).isDef() &&
63 !
MI->getOperand(0).isImplicit()) {
65 unsigned CheckStartIdx = 0, e =
MI->getNumOperands();
66 while (CheckStartIdx < e && MI->getOperand(CheckStartIdx).
isReg() &&
67 MI->getOperand(CheckStartIdx).isDef() &&
68 !
MI->getOperand(CheckStartIdx).isImplicit())
71 assert(getMetaIdx() == CheckStartIdx &&
72 "Unexpected additional definition in Patchpoint intrinsic.");
82 while (ScratchIdx < e &&
89 assert(ScratchIdx != e &&
"No scratch register available");
118 while (NumDeoptArgs--) {
130 assert(NumGCPtrsIdx < MI->getNumOperands());
131 return (
int)NumGCPtrsIdx;
139 for (
unsigned N = 0;
N < GCMapSize; ++
N) {
142 GCMap.push_back(std::make_pair(
B,
D));
149 unsigned FoldableAreaStart =
getVarIdx();
151 if (MO.getOperandNo() >= FoldableAreaStart)
153 if (MO.isReg() && MO.getReg() == Reg)
160 if (
MI->getOpcode() != TargetOpcode::STATEPOINT)
171 assert(CurIdx < MI->getNumOperands() &&
"Bad meta arg index");
172 const auto &MO =
MI->getOperand(CurIdx);
174 switch (MO.getImm()) {
177 case StackMaps::DirectMemRefOp:
180 case StackMaps::IndirectMemRefOp:
183 case StackMaps::ConstantOp:
189 assert(CurIdx < MI->getNumOperands() &&
"points past operand list");
197 RegNum =
TRI->getDwarfRegNum(SR,
false);
202 assert(RegNum >= 0 && isUInt<16>(RegNum) &&
"Invalid Dwarf register number.");
203 return (
unsigned)RegNum;
209 LiveOutVec &LiveOuts) {
215 case StackMaps::DirectMemRefOp: {
218 unsigned Size =
DL.getPointerSizeInBits();
219 assert((
Size % 8) == 0 &&
"Need pointer size in bytes.");
227 case StackMaps::IndirectMemRefOp: {
229 assert(
Size > 0 &&
"Need a valid size for indirect memory locations.");
236 case StackMaps::ConstantOp: {
238 assert(MOI->
isImm() &&
"Expected constant operand.");
240 if (isInt<32>(Imm)) {
251 "empty and tombstone keys should fit in 32 bits!");
252 auto Result = ConstPool.
insert(std::make_pair(Imm, Imm));
272 "Virtreg operands should have been rewritten before now.");
278 MCRegister LLVMRegNum = *
TRI->getLLVMRegNum(DwarfRegNum,
false);
279 unsigned SubRegIdx =
TRI->getSubRegIndex(LLVMRegNum, MOI->
getReg());
281 Offset =
TRI->getSubRegIdxOffset(SubRegIdx);
297 OS << WSMP <<
"callsites:\n";
298 for (
const auto &CSI : CSInfos) {
302 OS << WSMP <<
"callsite " << CSI.ID <<
"\n";
303 OS << WSMP <<
" has " << CSLocs.size() <<
" locations\n";
306 for (
const auto &Loc : CSLocs) {
307 OS << WSMP <<
"\t\tLoc " <<
Idx <<
": ";
310 OS <<
"<Unprocessed operand>";
326 OS <<
" + " << Loc.Offset;
334 OS <<
"+" << Loc.Offset;
337 OS <<
"Constant " << Loc.Offset;
340 OS <<
"Constant Index " << Loc.Offset;
343 OS <<
"\t[encoding: .byte " << Loc.Type <<
", .byte 0"
344 <<
", .short " << Loc.Size <<
", .short " << Loc.Reg <<
", .short 0"
345 <<
", .int " << Loc.Offset <<
"]\n";
349 OS << WSMP <<
"\thas " << LiveOuts.size() <<
" live-out registers\n";
352 for (
const auto &LO : LiveOuts) {
353 OS << WSMP <<
"\t\tLO " <<
Idx <<
": ";
358 OS <<
"\t[encoding: .short " <<
LO.DwarfRegNum <<
", .byte 0, .byte "
369 unsigned Size =
TRI->getSpillSize(*
TRI->getMinimalPhysRegClass(Reg));
370 return LiveOutReg(Reg, DwarfRegNum,
Size);
376StackMaps::parseRegisterLiveOutMask(
const uint32_t *Mask)
const {
377 assert(Mask &&
"No register mask specified");
382 for (
unsigned Reg = 0, NumRegs =
TRI->getNumRegs(); Reg != NumRegs; ++Reg)
383 if ((Mask[Reg / 32] >> (Reg % 32)) & 1)
390 llvm::sort(LiveOuts, [](
const LiveOutReg &LHS,
const LiveOutReg &RHS) {
392 return LHS.DwarfRegNum <
RHS.DwarfRegNum;
395 for (
auto I = LiveOuts.begin(), E = LiveOuts.end();
I != E; ++
I) {
396 for (
auto *
II = std::next(
I);
II != E; ++
II) {
397 if (
I->DwarfRegNum !=
II->DwarfRegNum) {
402 I->Size = std::max(
I->Size,
II->Size);
403 if (
I->Reg &&
TRI->isSuperRegister(
I->Reg,
II->Reg))
419 LocationVec &Locations,
420 LiveOutVec &LiveOuts) {
423 MOI = parseOperand(MOI, MOE, Locations, LiveOuts);
424 MOI = parseOperand(MOI, MOE, Locations, LiveOuts);
425 MOI = parseOperand(MOI, MOE, Locations, LiveOuts);
428 unsigned NumDeoptArgs =
Locations.back().Offset;
430 assert(NumDeoptArgs == SO.getNumDeoptArgs());
432 while (NumDeoptArgs--)
433 MOI = parseOperand(MOI, MOE, Locations, LiveOuts);
439 unsigned NumGCPointers = MOI->
getImm();
444 unsigned GCPtrIdx = (
unsigned)SO.getFirstGCPtrIdx();
445 assert((
int)GCPtrIdx != -1);
446 assert(MOI -
MI.operands_begin() == GCPtrIdx + 0LL);
447 while (NumGCPointers--) {
453 unsigned NumGCPairs = SO.getGCPointerMap(GCPairs);
457 auto MOB =
MI.operands_begin();
458 for (
auto &
P : GCPairs) {
459 assert(
P.first < GCPtrIndices.
size() &&
"base pointer index not found");
461 "derived pointer index not found");
462 unsigned BaseIdx = GCPtrIndices[
P.first];
463 unsigned DerivedIdx = GCPtrIndices[
P.second];
464 LLVM_DEBUG(
dbgs() <<
"Base : " << BaseIdx <<
" Derived : " << DerivedIdx
466 (void)parseOperand(MOB + BaseIdx, MOE, Locations, LiveOuts);
467 (void)parseOperand(MOB + DerivedIdx, MOE, Locations, LiveOuts);
470 MOI = MOB + GCPtrIdx;
477 unsigned NumAllocas = MOI->
getImm();
479 while (NumAllocas--) {
480 MOI = parseOperand(MOI, MOE, Locations, LiveOuts);
485void StackMaps::recordStackMapOpers(
const MCSymbol &MILabel,
497 parseOperand(
MI.operands_begin(), std::next(
MI.operands_begin()), Locations,
502 if (
MI.getOpcode() == TargetOpcode::STATEPOINT)
503 parseStatepointOpers(
MI, MOI, MOE, Locations, LiveOuts);
506 MOI = parseOperand(MOI, MOE, Locations, LiveOuts);
514 CSInfos.emplace_back(CSOffsetExpr,
ID, std::move(Locations),
515 std::move(LiveOuts));
520 bool HasDynamicFrameSize =
526 CurrentIt->second.RecordCount++;
530 assert(
MI.getOpcode() == TargetOpcode::STACKMAP &&
"expected stackmap");
534 recordStackMapOpers(L,
MI,
ID, std::next(
MI.operands_begin(),
540 assert(
MI.getOpcode() == TargetOpcode::PATCHPOINT &&
"expected patchpoint");
543 const int64_t
ID = opers.
getID();
545 recordStackMapOpers(L,
MI,
ID, MOI,
MI.operands_end(),
550 auto &Locations = CSInfos.back().Locations;
553 for (
unsigned i = 0, e = (opers.
hasDef() ? NArgs + 1 : NArgs); i != e; ++i)
555 "anyreg arg must be in reg.");
561 assert(
MI.getOpcode() == TargetOpcode::STATEPOINT &&
"expected statepoint");
564 const unsigned StartIdx = opers.
getVarIdx();
565 recordStackMapOpers(L,
MI, opers.
getID(),
MI.operands_begin() + StartIdx,
566 MI.operands_end(),
false);
582 OS.emitIntValue(0, 1);
587 OS.emitInt32(FnInfos.
size());
590 OS.emitInt32(ConstPool.
size());
592 LLVM_DEBUG(
dbgs() << WSMP <<
"#callsites = " << CSInfos.size() <<
'\n');
593 OS.emitInt32(CSInfos.size());
603void StackMaps::emitFunctionFrameRecords(
MCStreamer &
OS) {
606 for (
auto const &FR : FnInfos) {
608 <<
" frame size: " << FR.second.StackSize
609 <<
" callsite count: " << FR.second.RecordCount <<
'\n');
610 OS.emitSymbolValue(FR.first, 8);
611 OS.emitIntValue(FR.second.StackSize, 8);
612 OS.emitIntValue(FR.second.RecordCount, 8);
619void StackMaps::emitConstantPoolEntries(
MCStreamer &
OS) {
622 for (
const auto &ConstEntry : ConstPool) {
624 OS.emitIntValue(ConstEntry.second, 8);
660 for (
const auto &CSI : CSInfos) {
668 if (CSLocs.size() > UINT16_MAX || LiveOuts.size() > UINT16_MAX) {
670 OS.emitValue(CSI.CSOffsetExpr, 4);
679 OS.emitIntValue(CSI.ID, 8);
680 OS.emitValue(CSI.CSOffsetExpr, 4);
684 OS.emitInt16(CSLocs.size());
686 for (
const auto &Loc : CSLocs) {
687 OS.emitIntValue(Loc.Type, 1);
688 OS.emitIntValue(0, 1);
689 OS.emitInt16(Loc.Size);
690 OS.emitInt16(Loc.Reg);
692 OS.emitInt32(Loc.Offset);
696 OS.emitValueToAlignment(
Align(8));
700 OS.emitInt16(LiveOuts.size());
702 for (
const auto &LO : LiveOuts) {
703 OS.emitInt16(
LO.DwarfRegNum);
704 OS.emitIntValue(0, 1);
705 OS.emitIntValue(
LO.Size, 1);
708 OS.emitValueToAlignment(
Align(8));
716 assert((!CSInfos.empty() || ConstPool.empty()) &&
717 "Expected empty constant pool too!");
718 assert((!CSInfos.empty() || FnInfos.empty()) &&
719 "Expected empty function record too!");
729 OS.switchSection(StackMapSection);
736 emitStackmapHeader(
OS);
737 emitFunctionFrameRecords(
OS);
738 emitConstantPoolEntries(
OS);
739 emitCallsiteEntries(
OS);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file defines DenseMapInfo traits for DenseMap.
Register const TargetRegisterInfo * TRI
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
static bool isReg(const MCInst &MI, unsigned OpNo)
uint64_t IntrinsicInst * II
static uint64_t getConstMetaVal(const MachineInstr &MI, unsigned Idx)
static cl::opt< int > StackMapVersion("stackmap-version", cl::init(3), cl::Hidden, cl::desc("Specify the stackmap encoding version (default = 3)"))
static unsigned getDwarfRegNum(MCRegister Reg, const TargetRegisterInfo *TRI)
Go up the super-register chain until we hit a valid dwarf register number.
This class is intended to be used as a driving class for all asm writers.
MachineFunction * MF
The current machine function.
MCSymbol * CurrentFnSym
The symbol for the current function.
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
MCSymbol * CurrentFnSymForSize
The symbol used to represent the start of the current function for the purpose of calculating its siz...
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Context object for machine code objects.
const MCObjectFileInfo * getObjectFileInfo() const
LLVM_ABI MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Base class for the full range of assembler expressions which are needed for parsing.
MCSection * getStackMapSection() const
Wrapper class representing physical registers. Should be passed by value.
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Streaming machine code generation interface.
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 ...
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Representation of each machine instruction.
unsigned getNumOperands() const
Retuns the total number of operands.
mop_range uses()
Returns all operands which may be register uses.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
const uint32_t * getRegLiveOut() const
getRegLiveOut - Returns a bit mask of live-out registers.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
bool isRegLiveOut() const
isRegLiveOut - Tests if this is a MO_RegisterLiveOut operand.
bool isEarlyClobber() const
Register getReg() const
getReg - Returns the register number.
std::pair< iterator, bool > try_emplace(const KeyT &Key, Ts &&...Args)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
MI-level patchpoint operands.
uint32_t getNumCallArgs() const
Return the number of call arguments.
LLVM_ABI PatchPointOpers(const MachineInstr *MI)
LLVM_ABI unsigned getNextScratchIdx(unsigned StartIdx=0) const
Get the next scratch register operand index.
uint64_t getID() const
Return the ID for the given patchpoint.
unsigned getStackMapStartIdx() const
Get the index at which stack map locations will be recorded.
unsigned getVarIdx() const
Get the operand index of the variable list of non-argument operands.
Wrapper class representing virtual and physical registers.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
MI-level stackmap operands.
LLVM_ABI StackMapOpers(const MachineInstr *MI)
unsigned getVarIdx() const
Get the operand index of the variable list of non-argument operands.
static LLVM_ABI unsigned getNextMetaArgIdx(const MachineInstr *MI, unsigned CurIdx)
Get index of next meta operand.
LLVM_ABI StackMaps(AsmPrinter &AP)
LLVM_ABI void serializeToStackMapSection()
If there is any stack map data, create a stack map section and serialize the map info into it.
SmallVector< LiveOutReg, 8 > LiveOutVec
SmallVector< Location, 8 > LocationVec
LLVM_ABI void recordStatepoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a statepoint instruction.
LLVM_ABI void recordPatchPoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a patchpoint instruction.
LLVM_ABI void recordStackMap(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a stackmap instruction.
MI-level Statepoint operands.
LLVM_ABI unsigned getGCPointerMap(SmallVectorImpl< std::pair< unsigned, unsigned > > &GCMap)
Get vector of base/derived pairs from statepoint.
LLVM_ABI unsigned getNumAllocaIdx()
Get index of number of gc allocas.
LLVM_ABI unsigned getNumGcMapEntriesIdx()
Get index of number of gc map entries.
LLVM_ABI int getFirstGCPtrIdx()
Get index of first GC pointer operand of -1 if there are none.
unsigned getNumDeoptArgsIdx() const
Get index of Number Deopt Arguments operand.
uint64_t getID() const
Return the ID for the given statepoint.
LLVM_ABI bool isFoldableReg(Register Reg) const
Return true if Reg is used only in operands which can be folded to stack usage.
unsigned getVarIdx() const
Get starting index of non call related arguments (calling convention, statepoint flags,...
LLVM_ABI unsigned getNumGCPtrIdx()
Get index of number of GC pointers.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
This class implements an extremely fast bulk output stream that can only output to a stream.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Reg
All possible values of the reg field in the ModR/M byte.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
This struct is a compact representation of a valid (non-zero power of two) alignment.
An information struct used to provide DenseMap with the various necessary components for a given valu...