41 #define DEBUG_TYPE "stackmaps" 45 cl::desc(
"Specify the stackmap encoding version (default = 3)"));
47 const char *StackMaps::WSMP =
"Stack Maps: ";
52 "invalid stackmap definition");
56 : MI(MI), HasDef(MI->getOperand(0).
isReg() && MI->getOperand(0).isDef() &&
57 !MI->getOperand(0).isImplicit()) {
60 while (CheckStartIdx < e && MI->getOperand(CheckStartIdx).
isReg() &&
65 assert(getMetaIdx() == CheckStartIdx &&
66 "Unexpected additional definition in Patchpoint intrinsic.");
76 while (ScratchIdx < e &&
83 assert(ScratchIdx != e &&
"No scratch register available");
98 assert(RegNum >= 0 &&
"Invalid Dwarf register number.");
99 return (
unsigned)RegNum;
111 case StackMaps::DirectMemRefOp: {
114 unsigned Size = DL.getPointerSizeInBits();
115 assert((Size % 8) == 0 &&
"Need pointer size in bytes.");
118 int64_t Imm = (++MOI)->getImm();
123 case StackMaps::IndirectMemRefOp: {
124 int64_t
Size = (++MOI)->getImm();
125 assert(Size > 0 &&
"Need a valid size for indirect memory locations.");
127 int64_t Imm = (++MOI)->getImm();
132 case StackMaps::ConstantOp: {
134 assert(MOI->
isImm() &&
"Expected constant operand.");
135 int64_t Imm = MOI->
getImm();
153 "Virtreg operands should have been rewritten before now.");
159 unsigned LLVMRegNum = TRI->
getLLVMRegNum(DwarfRegNum,
false);
178 OS << WSMP <<
"callsites:\n";
179 for (
const auto &CSI : CSInfos) {
183 OS << WSMP <<
"callsite " << CSI.ID <<
"\n";
184 OS << WSMP <<
" has " << CSLocs.size() <<
" locations\n";
187 for (
const auto &Loc : CSLocs) {
188 OS << WSMP <<
"\t\tLoc " << Idx <<
": ";
191 OS <<
"<Unprocessed operand>";
207 OS <<
" + " << Loc.Offset;
215 OS <<
"+" << Loc.Offset;
218 OS <<
"Constant " << Loc.Offset;
221 OS <<
"Constant Index " << Loc.Offset;
224 OS <<
"\t[encoding: .byte " << Loc.Type <<
", .byte 0" 225 <<
", .short " << Loc.Size <<
", .short " << Loc.Reg <<
", .short 0" 226 <<
", .int " << Loc.Offset <<
"]\n";
230 OS << WSMP <<
"\thas " << LiveOuts.size() <<
" live-out registers\n";
233 for (
const auto &
LO : LiveOuts) {
234 OS << WSMP <<
"\t\tLO " << Idx <<
": ";
239 OS <<
"\t[encoding: .short " <<
LO.DwarfRegNum <<
", .byte 0, .byte " 251 return LiveOutReg(Reg, DwarfRegNum, Size);
257 StackMaps::parseRegisterLiveOutMask(
const uint32_t *
Mask)
const {
258 assert(Mask &&
"No register mask specified");
263 for (
unsigned Reg = 0, NumRegs = TRI->
getNumRegs(); Reg != NumRegs; ++
Reg)
264 if ((Mask[Reg / 32] >> Reg % 32) & 1)
265 LiveOuts.
push_back(createLiveOutReg(Reg, TRI));
271 llvm::sort(LiveOuts, [](
const LiveOutReg &LHS,
const LiveOutReg &RHS) {
273 return LHS.DwarfRegNum < RHS.DwarfRegNum;
276 for (
auto I = LiveOuts.begin(),
E = LiveOuts.end();
I !=
E; ++
I) {
277 for (
auto II = std::next(
I); II !=
E; ++II) {
278 if (
I->DwarfRegNum != II->DwarfRegNum) {
292 [](
const LiveOutReg &
LO) {
return LO.Reg == 0; }),
317 MOI = parseOperand(MOI, MOE, Locations, LiveOuts);
321 for (
auto &Loc : Locations) {
333 (uint64_t)Loc.Offset !=
335 "empty and tombstone keys should fit in 32 bits!");
336 auto Result = ConstPool.
insert(std::make_pair(Loc.Offset, Loc.Offset));
337 Loc.Offset = Result.first - ConstPool.
begin();
347 CSInfos.emplace_back(CSOffsetExpr, ID, std::move(Locations),
348 std::move(LiveOuts));
353 bool HasDynamicFrameSize =
358 if (CurrentIt != FnInfos.
end())
359 CurrentIt->second.RecordCount++;
365 assert(MI.
getOpcode() == TargetOpcode::STACKMAP &&
"expected stackmap");
369 recordStackMapOpers(MI, ID, std::next(MI.
operands_begin(), opers.getVarIdx()),
374 assert(MI.
getOpcode() == TargetOpcode::PATCHPOINT &&
"expected patchpoint");
377 const int64_t ID = opers.getID();
378 auto MOI = std::next(MI.
operands_begin(), opers.getStackMapStartIdx());
380 opers.isAnyReg() && opers.hasDef());
384 auto &Locations = CSInfos.back().Locations;
385 if (opers.isAnyReg()) {
386 unsigned NArgs = opers.getNumCallArgs();
387 for (
unsigned i = 0, e = (opers.hasDef() ? NArgs + 1 : NArgs); i != e; ++i)
389 "anyreg arg must be in reg.");
395 assert(MI.
getOpcode() == TargetOpcode::STATEPOINT &&
"expected statepoint");
400 const unsigned StartIdx = opers.getVarIdx();
401 recordStackMapOpers(MI, opers.getID(), MI.
operands_begin() + StartIdx,
415 void StackMaps::emitStackmapHeader(
MCStreamer &OS) {
428 LLVM_DEBUG(
dbgs() << WSMP <<
"#callsites = " << CSInfos.size() <<
'\n');
439 void StackMaps::emitFunctionFrameRecords(
MCStreamer &OS) {
442 for (
auto const &FR : FnInfos) {
444 <<
" frame size: " << FR.second.StackSize
445 <<
" callsite count: " << FR.second.RecordCount <<
'\n');
455 void StackMaps::emitConstantPoolEntries(
MCStreamer &OS) {
458 for (
const auto &ConstEntry : ConstPool) {
493 void StackMaps::emitCallsiteEntries(
MCStreamer &OS) {
496 for (
const auto &CSI : CSInfos) {
504 if (CSLocs.
size() > UINT16_MAX || LiveOuts.
size() > UINT16_MAX) {
522 for (
const auto &Loc : CSLocs) {
538 for (
const auto &
LO : LiveOuts) {
553 "Expected empty constant pool too!");
555 "Expected empty function record too!");
572 emitStackmapHeader(OS);
573 emitFunctionFrameRecords(OS);
574 emitConstantPoolEntries(OS);
575 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...
mop_iterator operands_end()
unsigned getNextScratchIdx(unsigned StartIdx=0) const
Get the next scratch register operand index.
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
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)
This class represents lattice values for constants.
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.
MCSection * getStackMapSection() const
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.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
bool isRegLiveOut() const
isRegLiveOut - Tests if this is a MO_RegisterLiveOut operand.
void push_back(const T &Elt)
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 ...
unsigned getReg() const
getReg - Returns the register number.
unsigned getSubReg() const
unsigned const TargetRegisterInfo * TRI
MachineFunction * MF
The current machine function.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
unsigned getSpillSize(const TargetRegisterClass &RC) const
Return the size in bytes of the stack slot allocated to hold a spilled copy of a register from class ...
bool isEarlyClobber() const
MCSuperRegIterator enumerates all super-registers of Reg.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
const uint32_t * getRegLiveOut() const
getRegLiveOut - Returns a bit mask of live-out registers.
unsigned getNumOperands() const
Retuns the total number of operands.
Printable printReg(unsigned Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
Base class for the full range of assembler expressions which are needed for parsing.
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 ...
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
int getDwarfRegNum(unsigned RegNum, bool isEH) const
Map a target register to an equivalent dwarf register number.
Context object for machine code objects.
PatchPointOpers(const MachineInstr *MI)
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
SmallVector< LiveOutReg, 8 > LiveOutVec
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.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
bool isSuperRegister(unsigned RegA, unsigned RegB) const
Returns true if RegB is a super-register of RegA.
unsigned getNumRegs() const
Return the number of registers this target has (useful for sizing arrays holding per register informa...
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...
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.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
virtual void SwitchSection(MCSection *Section, const MCExpr *Subsection=nullptr)
Set the current section where code is being emitted to Section.
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.
static cl::opt< int > StackMapVersion("stackmap-version", cl::init(3), cl::Hidden, cl::desc("Specify the stackmap encoding version (default = 3)"))
const MCObjectFileInfo * getObjectFileInfo() const
unsigned getVarIdx() const
Get the operand index of the variable list of non-argument operands.
MI-level patchpoint operands.
auto remove_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range))
Provide wrappers to std::remove_if which take ranges instead of having to pass begin/end explicitly...
unsigned getSubRegIdxOffset(unsigned Idx) const
Get the offset of the bit range covered by a sub-register index.
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...
void sort(IteratorTy Start, IteratorTy End)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
StackMapOpers(const MachineInstr *MI)
constexpr bool isInt< 32 >(int64_t x)
MachineOperand class - Representation of each machine instruction operand.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
unsigned getVarIdx() const
Get the operand index of the variable list of non-argument operands.
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.
bool isValid() const
isValid - returns true if this iterator is not yet at the end.
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
Representation of each machine instruction.
static bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
MI-level stackmap operands.
StackMaps(AsmPrinter &AP)
MI-level Statepoint operands.
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 isReg() const
isReg - Tests if this is a MO_Register operand.
SmallVector< Location, 8 > LocationVec
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool needsStackRealignment(const MachineFunction &MF) const
True if storage within the function requires the stack pointer to be aligned more than the normal cal...
mop_iterator operands_begin()
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.
virtual void EmitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
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...
static unsigned getDwarfRegNum(unsigned Reg, const TargetRegisterInfo *TRI)
Go up the super-register chain until we hit a valid dwarf register number.
const MachineOperand & getOperand(unsigned i) const
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects...
int getLLVMRegNum(unsigned RegNum, bool isEH) const
Map a dwarf register back to a target register.