30 #define DEBUG_TYPE "stackmaps"
34 cl::desc(
"Specify the stackmap encoding version (default = 1)"));
36 const char *StackMaps::WSMP =
"Stack Maps: ";
39 : MI(MI), HasDef(MI->getOperand(0).
isReg() && MI->getOperand(0).isDef() &&
40 !MI->getOperand(0).isImplicit()),
41 IsAnyReg(MI->getOperand(getMetaIdx(CCPos)).getImm() ==
45 while (CheckStartIdx < e && MI->getOperand(CheckStartIdx).
isReg() &&
51 "Unexpected additional definition in Patchpoint intrinsic.");
60 unsigned ScratchIdx = StartIdx, e =
MI->getNumOperands();
61 while (ScratchIdx < e &&
62 !(
MI->getOperand(ScratchIdx).isReg() &&
63 MI->getOperand(ScratchIdx).isDef() &&
64 MI->getOperand(ScratchIdx).isImplicit() &&
65 MI->getOperand(ScratchIdx).isEarlyClobber()))
68 assert(ScratchIdx != e &&
"No scratch register available");
83 assert(RegNum >= 0 &&
"Invalid Dwarf register number.");
84 return (
unsigned)RegNum;
90 LiveOutVec &LiveOuts)
const {
98 assert((Size % 8) == 0 &&
"Need pointer size in bytes.");
101 int64_t Imm = (++MOI)->getImm();
107 int64_t Size = (++MOI)->getImm();
108 assert(Size > 0 &&
"Need a valid size for indirect memory locations.");
109 unsigned Reg = (++MOI)->
getReg();
110 int64_t Imm = (++MOI)->getImm();
117 assert(MOI->
isImm() &&
"Expected constant operand.");
118 int64_t Imm = MOI->
getImm();
136 "Virtreg operands should have been rewritten before now.");
138 assert(!MOI->
getSubReg() &&
"Physical subreg still around.");
142 unsigned LLVMRegNum = TRI->
getLLVMRegNum(DwarfRegNum,
false);
160 OS << WSMP <<
"callsites:\n";
161 for (
const auto &CSI : CSInfos) {
162 const LocationVec &CSLocs = CSI.Locations;
163 const LiveOutVec &LiveOuts = CSI.LiveOuts;
165 OS << WSMP <<
"callsite " << CSI.ID <<
"\n";
166 OS << WSMP <<
" has " << CSLocs.size() <<
" locations\n";
169 for (
const auto &Loc : CSLocs) {
170 OS << WSMP <<
"\t\tLoc " << Idx <<
": ";
173 OS <<
"<Unprocessed operand>";
189 OS <<
" + " << Loc.Offset;
197 OS <<
"+" << Loc.Offset;
200 OS <<
"Constant " << Loc.Offset;
203 OS <<
"Constant Index " << Loc.Offset;
206 OS <<
"\t[encoding: .byte " << Loc.Type <<
", .byte " << Loc.Size
207 <<
", .short " << Loc.Reg <<
", .int " << Loc.Offset <<
"]\n";
211 OS << WSMP <<
"\thas " << LiveOuts.size() <<
" live-out registers\n";
214 for (
const auto &
LO : LiveOuts) {
215 OS << WSMP <<
"\t\tLO " << Idx <<
": ";
220 OS <<
"\t[encoding: .short " <<
LO.DwarfRegNum <<
", .byte 0, .byte "
232 return LiveOutReg(Reg, DwarfRegNum, Size);
238 StackMaps::parseRegisterLiveOutMask(
const uint32_t *Mask)
const {
239 assert(Mask &&
"No register mask specified");
244 for (
unsigned Reg = 0, NumRegs = TRI->
getNumRegs(); Reg != NumRegs; ++
Reg)
245 if ((Mask[Reg / 32] >> Reg % 32) & 1)
246 LiveOuts.
push_back(createLiveOutReg(Reg, TRI));
252 std::sort(LiveOuts.begin(), LiveOuts.end(),
253 [](
const LiveOutReg &LHS,
const LiveOutReg &RHS) {
255 return LHS.DwarfRegNum < RHS.DwarfRegNum;
258 for (
auto I = LiveOuts.begin(), E = LiveOuts.end();
I != E; ++
I) {
259 for (
auto II = std::next(
I); II != E; ++II) {
260 if (
I->DwarfRegNum != II->DwarfRegNum) {
265 I->Size = std::max(
I->Size, II->Size);
273 std::remove_if(LiveOuts.begin(), LiveOuts.end(),
274 [](
const LiveOutReg &
LO) {
return LO.Reg == 0; }),
289 LocationVec Locations;
293 assert(
PatchPointOpers(&MI).hasDef() &&
"Stackmap has no return value.");
300 MOI = parseOperand(MOI, MOE, Locations, LiveOuts);
304 for (
auto &Loc : Locations) {
316 (uint64_t)Loc.Offset !=
318 "empty and tombstone keys should fit in 32 bits!");
319 auto Result = ConstPool.
insert(std::make_pair(Loc.Offset, Loc.Offset));
320 Loc.Offset = Result.first - ConstPool.
begin();
330 CSInfos.emplace_back(CSOffsetExpr, ID, std::move(Locations),
331 std::move(LiveOuts));
336 bool HasDynamicFrameSize =
356 auto MOI = std::next(MI.
operands_begin(), opers.getStackMapStartIdx());
358 opers.isAnyReg() && opers.hasDef());
362 auto &Locations = CSInfos.back().Locations;
363 if (opers.isAnyReg()) {
365 for (
unsigned i = 0, e = (opers.hasDef() ? NArgs + 1 : NArgs); i != e; ++i)
367 "anyreg arg must be in reg.");
377 const unsigned StartIdx = opers.getVarIdx();
378 recordStackMapOpers(MI, opers.getID(), MI.
operands_begin() + StartIdx,
392 void StackMaps::emitStackmapHeader(
MCStreamer &OS) {
399 DEBUG(
dbgs() << WSMP <<
"#functions = " << FnStackSize.
size() <<
'\n');
402 DEBUG(
dbgs() << WSMP <<
"#constants = " << ConstPool.
size() <<
'\n');
405 DEBUG(
dbgs() << WSMP <<
"#callsites = " << CSInfos.size() <<
'\n');
415 void StackMaps::emitFunctionFrameRecords(
MCStreamer &OS) {
418 for (
auto const &FR : FnStackSize) {
419 DEBUG(
dbgs() << WSMP <<
"function addr: " << FR.first
420 <<
" frame size: " << FR.second);
429 void StackMaps::emitConstantPoolEntries(
MCStreamer &OS) {
432 for (
const auto &ConstEntry : ConstPool) {
433 DEBUG(
dbgs() << WSMP << ConstEntry.second <<
'\n');
467 void StackMaps::emitCallsiteEntries(
MCStreamer &OS) {
470 for (
const auto &CSI : CSInfos) {
471 const LocationVec &CSLocs = CSI.Locations;
472 const LiveOutVec &LiveOuts = CSI.LiveOuts;
478 if (CSLocs.size() > UINT16_MAX || LiveOuts.size() > UINT16_MAX) {
496 for (
const auto &Loc : CSLocs) {
507 for (
const auto &
LO : LiveOuts) {
521 assert((!CSInfos.empty() || (CSInfos.empty() && ConstPool.empty())) &&
522 "Expected empty constant pool too!");
523 assert((!CSInfos.empty() || (CSInfos.empty() && FnStackSize.empty())) &&
524 "Expected empty function record too!");
540 DEBUG(
dbgs() <<
"********** Stack Map Output **********\n");
541 emitStackmapHeader(OS);
542 emitFunctionFrameRecords(OS);
543 emitConstantPoolEntries(OS);
544 emitCallsiteEntries(OS);
static bool isReg(const MCInst &MI, unsigned OpNo)
bool isInt< 32 >(int64_t x)
Instances of this class represent a uniqued identifier for a section in the current translation unit...
void push_back(const T &Elt)
mop_iterator operands_end()
MCSection * getStackMapSection() const
int getDwarfRegNum(unsigned RegNum, bool isEH) const
Map a target register to an equivalent dwarf register number.
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
void EmitSymbolValue(const MCSymbol *Sym, unsigned Size, bool IsSectionRelative=false)
Special case of EmitValue that avoids the client having to pass in a MCExpr for MCSymbols.
bool isValid() const
isValid - returns true if this iterator is not yet at the end.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
virtual void AddBlankLine()
AddBlankLine - Emit a blank line to a .s file to pretty it up.
A Stackmap instruction captures the location of live variables at its position in the instruction str...
const MachineFunction * MF
The current machine function.
unsigned getVarIdx() const
Get the operand index of the variable list of non-argument operands.
unsigned getSubRegIndex(unsigned RegNo, unsigned SubRegNo) const
For a given register pair, return the sub-register index if the second register is a sub-register of ...
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects...
unsigned getSize() const
getSize - Return the size of the register in bytes, which is also the size of a stack slot allocated ...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MCSuperRegIterator enumerates all super-registers of Reg.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Base class for the full range of assembler expressions which are needed for parsing.
Reg
All possible values of the reg field in the ModR/M byte.
static cl::opt< int > StackMapVersion("stackmap-version", cl::init(1), cl::desc("Specify the stackmap encoding version (default = 1)"))
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted...
unsigned getNumOperands() const
Access to explicit operands of the instruction.
Context object for machine code objects.
unsigned getNumRegs() const
Return the number of registers this target has (useful for sizing arrays holding per register informa...
PatchPointOpers(const MachineInstr *MI)
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
virtual void EmitIntValue(uint64_t Value, unsigned Size)
Special case of EmitValue that avoids the client having to pass in a MCExpr for constant integers...
void recordStatepoint(const MachineInstr &MI)
Generate a stackmap record for a statepoint instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
initializer< Ty > init(const Ty &Val)
Streaming machine code generation interface.
Patchable call instruction - this instruction represents a call to a constant address, followed by a series of NOPs.
MCSymbol * createTempSymbol(bool CanBeUnnamed=true)
Create and return a new assembler temporary symbol with a unique but unspecified name.
MCSymbol * CurrentFnSym
The symbol for the current function.
virtual bool needsStackRealignment(const MachineFunction &MF) const
needsStackRealignment - true if storage within the function requires the stack pointer to be aligned ...
The instances of the Type class are immutable: once they are created, they are never changed...
virtual void SwitchSection(MCSection *Section, const MCExpr *Subsection=nullptr)
Set the current section where code is being emitted to Section.
const MachineOperand & getOperand(unsigned i) const
TargetMachine & TM
Target machine description.
This class is intended to be used as a driving class for all asm writers.
virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value=0, unsigned ValueSize=1, unsigned MaxBytesToEmit=0)
Emit some number of copies of Value until the byte alignment ByteAlignment is reached.
MI-level patchpoint operands.
unsigned getSubReg() const
int getLLVMRegNum(unsigned RegNum, bool isEH) const
Map a dwarf register back to a target register.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
void recordPatchPoint(const MachineInstr &MI)
Generate a stackmap record for a patchpoint instruction.
void serializeToStackMapSection()
If there is any stack map data, create a stack map section and serialize the map info into it...
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
virtual void EmitLabel(MCSymbol *Symbol)
Emit a label for Symbol into the current section.
const DataLayout * getDataLayout() const
Deprecated in 3.7, will be removed in 3.8.
MachineOperand class - Representation of each machine instruction operand.
bool isRegLiveOut() const
isRegLiveOut - Tests if this is a MO_RegisterLiveOut operand.
unsigned getNextScratchIdx(unsigned StartIdx=0) const
Get the next scratch register operand index.
MachineFrameInfo * getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void recordStackMap(const MachineInstr &MI)
Generate a stackmap record for a stackmap instruction.
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
const TargetRegisterClass * getMinimalPhysRegClass(unsigned Reg, MVT VT=MVT::Other) const
getMinimalPhysRegClass - Returns the Register Class of a physical register of the given type...
bool isSuperRegister(unsigned RegA, unsigned RegB) const
Returns true if RegB is a super-register of RegA.
Representation of each machine instruction.
static bool isPhysicalRegister(unsigned Reg)
isPhysicalRegister - Return true if the specified register number is in the physical register namespa...
const uint32_t * getRegLiveOut() const
getRegLiveOut - Returns a bit mask of live-out registers.
MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
StackMaps(AsmPrinter &AP)
Call instruction with associated vm state for deoptimization and list of live pointers for relocation...
unsigned getPointerSizeInBits(unsigned AS=0) const
Layout pointer size, in bits FIXME: The defaults need to be removed once all of the backends/clients ...
MI-level Statepoint operands.
unsigned getSubRegIdxOffset(unsigned Idx) const
Get the offset of the bit range covered by a sub-register index.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
void EmitValue(const MCExpr *Value, unsigned Size, const SMLoc &Loc=SMLoc())
unsigned getReg() const
getReg - Returns the register number.
mop_iterator operands_begin()
const MCObjectFileInfo * getObjectFileInfo() const
This class implements an extremely fast bulk output stream that can only output to a stream...
MCSymbol * CurrentFnSymForSize
The symbol used to represent the start of the current function for the purpose of calculating its siz...
const char * getName(unsigned RegNo) const
Return the human-readable symbolic target-specific name for the specified physical register...
static unsigned getDwarfRegNum(unsigned Reg, const TargetRegisterInfo *TRI)
Go up the super-register chain until we hit a valid dwarf register number.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
unsigned getMetaIdx(unsigned Pos=0) const