30 #define DEBUG_TYPE "stackmaps"
34 cl::desc(
"Specify the stackmap encoding version (default = 2)"));
36 const char *StackMaps::WSMP =
"Stack Maps: ";
41 "invalid stackmap definition");
45 : MI(MI), HasDef(MI->getOperand(0).
isReg() && MI->getOperand(0).isDef() &&
46 !MI->getOperand(0).isImplicit()) {
49 while (CheckStartIdx < e && MI->getOperand(CheckStartIdx).
isReg() &&
54 assert(getMetaIdx() == CheckStartIdx &&
55 "Unexpected additional definition in Patchpoint intrinsic.");
64 unsigned ScratchIdx = StartIdx, e =
MI->getNumOperands();
65 while (ScratchIdx < e &&
66 !(
MI->getOperand(ScratchIdx).isReg() &&
67 MI->getOperand(ScratchIdx).isDef() &&
68 MI->getOperand(ScratchIdx).isImplicit() &&
69 MI->getOperand(ScratchIdx).isEarlyClobber()))
72 assert(ScratchIdx != e &&
"No scratch register available");
87 assert(RegNum >= 0 &&
"Invalid Dwarf register number.");
88 return (
unsigned)RegNum;
94 LiveOutVec &LiveOuts)
const {
103 unsigned Size =
DL.getPointerSizeInBits();
104 assert((Size % 8) == 0 &&
"Need pointer size in bytes.");
107 int64_t Imm = (++MOI)->getImm();
113 int64_t Size = (++MOI)->getImm();
114 assert(Size > 0 &&
"Need a valid size for indirect memory locations.");
115 unsigned Reg = (++MOI)->
getReg();
116 int64_t Imm = (++MOI)->getImm();
123 assert(MOI->
isImm() &&
"Expected constant operand.");
124 int64_t Imm = MOI->
getImm();
142 "Virtreg operands should have been rewritten before now.");
148 unsigned LLVMRegNum = TRI->
getLLVMRegNum(DwarfRegNum,
false);
166 OS << WSMP <<
"callsites:\n";
167 for (
const auto &CSI : CSInfos) {
168 const LocationVec &CSLocs = CSI.Locations;
169 const LiveOutVec &LiveOuts = CSI.LiveOuts;
171 OS << WSMP <<
"callsite " << CSI.ID <<
"\n";
172 OS << WSMP <<
" has " << CSLocs.size() <<
" locations\n";
175 for (
const auto &Loc : CSLocs) {
176 OS << WSMP <<
"\t\tLoc " << Idx <<
": ";
179 OS <<
"<Unprocessed operand>";
195 OS <<
" + " << Loc.Offset;
203 OS <<
"+" << Loc.Offset;
206 OS <<
"Constant " << Loc.Offset;
209 OS <<
"Constant Index " << Loc.Offset;
212 OS <<
"\t[encoding: .byte " << Loc.Type <<
", .byte " << Loc.Size
213 <<
", .short " << Loc.Reg <<
", .int " << Loc.Offset <<
"]\n";
217 OS << WSMP <<
"\thas " << LiveOuts.size() <<
" live-out registers\n";
220 for (
const auto &
LO : LiveOuts) {
221 OS << WSMP <<
"\t\tLO " << Idx <<
": ";
226 OS <<
"\t[encoding: .short " <<
LO.DwarfRegNum <<
", .byte 0, .byte "
238 return LiveOutReg(Reg, DwarfRegNum, Size);
244 StackMaps::parseRegisterLiveOutMask(
const uint32_t *
Mask)
const {
245 assert(Mask &&
"No register mask specified");
250 for (
unsigned Reg = 0, NumRegs = TRI->
getNumRegs(); Reg != NumRegs; ++
Reg)
251 if ((Mask[Reg / 32] >> Reg % 32) & 1)
252 LiveOuts.
push_back(createLiveOutReg(Reg, TRI));
258 std::sort(LiveOuts.begin(), LiveOuts.end(),
259 [](
const LiveOutReg &LHS,
const LiveOutReg &RHS) {
261 return LHS.DwarfRegNum < RHS.DwarfRegNum;
264 for (
auto I = LiveOuts.begin(),
E = LiveOuts.end();
I !=
E; ++
I) {
265 for (
auto II = std::next(
I); II !=
E; ++II) {
266 if (
I->DwarfRegNum != II->DwarfRegNum) {
271 I->Size = std::max(
I->Size, II->Size);
279 remove_if(LiveOuts, [](
const LiveOutReg &
LO) {
return LO.Reg == 0; }),
294 LocationVec Locations;
305 MOI = parseOperand(MOI, MOE, Locations, LiveOuts);
309 for (
auto &Loc : Locations) {
321 (uint64_t)Loc.Offset !=
323 "empty and tombstone keys should fit in 32 bits!");
324 auto Result = ConstPool.
insert(std::make_pair(Loc.Offset, Loc.Offset));
325 Loc.Offset = Result.first - ConstPool.
begin();
335 CSInfos.emplace_back(CSOffsetExpr, ID, std::move(Locations),
336 std::move(LiveOuts));
341 bool HasDynamicFrameSize =
343 uint64_t FrameSize = HasDynamicFrameSize ? UINT64_MAX : MFI.
getStackSize();
346 if (CurrentIt != FnInfos.
end())
347 CurrentIt->second.RecordCount++;
353 assert(MI.
getOpcode() == TargetOpcode::STACKMAP &&
"expected stackmap");
357 recordStackMapOpers(MI, ID, std::next(MI.
operands_begin(), opers.getVarIdx()),
362 assert(MI.
getOpcode() == TargetOpcode::PATCHPOINT &&
"expected patchpoint");
365 const int64_t ID = opers.getID();
366 auto MOI = std::next(MI.
operands_begin(), opers.getStackMapStartIdx());
368 opers.isAnyReg() && opers.hasDef());
372 auto &Locations = CSInfos.back().Locations;
373 if (opers.isAnyReg()) {
374 unsigned NArgs = opers.getNumCallArgs();
375 for (
unsigned i = 0, e = (opers.hasDef() ? NArgs + 1 : NArgs);
i != e; ++
i)
377 "anyreg arg must be in reg.");
382 assert(MI.
getOpcode() == TargetOpcode::STATEPOINT &&
"expected statepoint");
387 const unsigned StartIdx = opers.getVarIdx();
388 recordStackMapOpers(MI, opers.getID(), MI.
operands_begin() + StartIdx,
402 void StackMaps::emitStackmapHeader(
MCStreamer &OS) {
409 DEBUG(
dbgs() << WSMP <<
"#functions = " << FnInfos.
size() <<
'\n');
412 DEBUG(
dbgs() << WSMP <<
"#constants = " << ConstPool.
size() <<
'\n');
415 DEBUG(
dbgs() << WSMP <<
"#callsites = " << CSInfos.size() <<
'\n');
426 void StackMaps::emitFunctionFrameRecords(
MCStreamer &OS) {
429 for (
auto const &FR : FnInfos) {
430 DEBUG(
dbgs() << WSMP <<
"function addr: " << FR.first
431 <<
" frame size: " << FR.second.StackSize
432 <<
" callsite count: " << FR.second.RecordCount <<
'\n');
442 void StackMaps::emitConstantPoolEntries(
MCStreamer &OS) {
445 for (
const auto &ConstEntry : ConstPool) {
446 DEBUG(
dbgs() << WSMP << ConstEntry.second <<
'\n');
480 void StackMaps::emitCallsiteEntries(
MCStreamer &OS) {
483 for (
const auto &CSI : CSInfos) {
484 const LocationVec &CSLocs = CSI.Locations;
485 const LiveOutVec &LiveOuts = CSI.LiveOuts;
491 if (CSLocs.size() > UINT16_MAX || LiveOuts.size() > UINT16_MAX) {
509 for (
const auto &Loc : CSLocs) {
520 for (
const auto &
LO : LiveOuts) {
534 assert((!CSInfos.empty() || ConstPool.empty()) &&
535 "Expected empty constant pool too!");
536 assert((!CSInfos.empty() || FnInfos.empty()) &&
537 "Expected empty function record too!");
553 DEBUG(
dbgs() <<
"********** Stack Map Output **********\n");
554 emitStackmapHeader(OS);
555 emitFunctionFrameRecords(OS);
556 emitConstantPoolEntries(OS);
557 emitCallsiteEntries(OS);
static bool isReg(const MCInst &MI, unsigned OpNo)
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.
auto remove_if(R &&Range, UnaryPredicate P) -> decltype(std::begin(Range))
Provide wrappers to std::remove_if which take ranges instead of having to pass begin/end explicitly...
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
Return the size of the register in bytes, which is also the size of a stack slot allocated to hold a ...
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.
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.
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)
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
iterator find(const KeyT &Key)
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 EmitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
void recordStatepoint(const MachineInstr &MI)
Generate a stackmap record for a statepoint instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
initializer< Ty > init(const Ty &Val)
Streaming machine code generation interface.
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.
The instances of the Type class are immutable: once they are created, they are never changed...
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
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
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...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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)
StackMapOpers(const MachineInstr *MI)
constexpr bool isInt< 32 >(int64_t x)
virtual void EmitLabel(MCSymbol *Symbol)
Emit a label for Symbol into the current section.
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.
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
Returns the Register Class of a physical register of the given type, picking the most sub register cl...
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)
Return true if the specified register number is in the physical register namespace.
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.
MI-level stackmap operands.
StackMaps(AsmPrinter &AP)
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 ...
unsigned getVarIdx() const
Get the operand index of the variable list of non-argument operands.
unsigned getReg() const
getReg - Returns the register number.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
mop_iterator operands_begin()
const MCObjectFileInfo * getObjectFileInfo() const
std::underlying_type< E >::type Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
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.
bool needsStackRealignment(const MachineFunction &MF) const
True if storage within the function requires the stack pointer to be aligned more than the normal cal...
static cl::opt< int > StackMapVersion("stackmap-version", cl::init(2), cl::desc("Specify the stackmap encoding version (default = 2)"))