1 //===------------------- StackMaps.h - StackMaps ----------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef LLVM_CODEGEN_STACKMAPS_H 11 #define LLVM_CODEGEN_STACKMAPS_H 12 13 #include "llvm/ADT/MapVector.h" 14 #include "llvm/ADT/SmallVector.h" 15 #include "llvm/CodeGen/MachineInstr.h" 16 #include "llvm/MC/MCSymbol.h" 17 #include <vector> 18 19 namespace llvm { 20 21 class AsmPrinter; 22 class MCExpr; 23 class MCStreamer; 24 25 /// \brief MI-level patchpoint operands. 26 /// 27 /// MI patchpoint operations take the form: 28 /// [<def>], <id>, <numBytes>, <target>, <numArgs>, <cc>, ... 29 /// 30 /// IR patchpoint intrinsics do not have the <cc> operand because calling 31 /// convention is part of the subclass data. 32 /// 33 /// SD patchpoint nodes do not have a def operand because it is part of the 34 /// SDValue. 35 /// 36 /// Patchpoints following the anyregcc convention are handled specially. For 37 /// these, the stack map also records the location of the return value and 38 /// arguments. 39 class PatchPointOpers { 40 public: 41 /// Enumerate the meta operands. 42 enum { IDPos, NBytesPos, TargetPos, NArgPos, CCPos, MetaEnd }; 43 44 private: 45 const MachineInstr *MI; 46 bool HasDef; 47 bool IsAnyReg; 48 49 public: 50 explicit PatchPointOpers(const MachineInstr *MI); 51 52 bool isAnyReg() const { return IsAnyReg; } 53 bool hasDef() const { return HasDef; } 54 55 unsigned getMetaIdx(unsigned Pos = 0) const { 56 assert(Pos < MetaEnd && "Meta operand index out of range."); 57 return (HasDef ? 1 : 0) + Pos; 58 } 59 60 const MachineOperand &getMetaOper(unsigned Pos) { 61 return MI->getOperand(getMetaIdx(Pos)); 62 } 63 64 unsigned getArgIdx() const { return getMetaIdx() + MetaEnd; } 65 66 /// Get the operand index of the variable list of non-argument operands. 67 /// These hold the "live state". 68 unsigned getVarIdx() const { 69 return getMetaIdx() + MetaEnd + 70 MI->getOperand(getMetaIdx(NArgPos)).getImm(); 71 } 72 73 /// Get the index at which stack map locations will be recorded. 74 /// Arguments are not recorded unless the anyregcc convention is used. 75 unsigned getStackMapStartIdx() const { 76 if (IsAnyReg) 77 return getArgIdx(); 78 return getVarIdx(); 79 } 80 81 /// \brief Get the next scratch register operand index. 82 unsigned getNextScratchIdx(unsigned StartIdx = 0) const; 83 }; 84 85 /// MI-level Statepoint operands 86 /// 87 /// Statepoint operands take the form: 88 /// <id>, <num patch bytes >, <num call arguments>, <call target>, 89 /// [call arguments], <StackMaps::ConstantOp>, <calling convention>, 90 /// <StackMaps::ConstantOp>, <statepoint flags>, 91 /// <StackMaps::ConstantOp>, <num other args>, [other args], 92 /// [gc values] 93 class StatepointOpers { 94 private: 95 // These values are aboolute offsets into the operands of the statepoint 96 // instruction. 97 enum { IDPos, NBytesPos, NCallArgsPos, CallTargetPos, MetaEnd }; 98 99 // These values are relative offests from the start of the statepoint meta 100 // arguments (i.e. the end of the call arguments). 101 enum { CCOffset = 1, FlagsOffset = 3, NumVMSArgsOffset = 5 }; 102 103 public: 104 explicit StatepointOpers(const MachineInstr *MI) : MI(MI) {} 105 106 /// Get starting index of non call related arguments 107 /// (calling convention, statepoint flags, vm state and gc state). 108 unsigned getVarIdx() const { 109 return MI->getOperand(NCallArgsPos).getImm() + MetaEnd; 110 } 111 112 /// Return the ID for the given statepoint. 113 uint64_t getID() const { return MI->getOperand(IDPos).getImm(); } 114 115 /// Return the number of patchable bytes the given statepoint should emit. 116 uint32_t getNumPatchBytes() const { 117 return MI->getOperand(NBytesPos).getImm(); 118 } 119 120 /// Returns the target of the underlying call. 121 const MachineOperand &getCallTarget() const { 122 return MI->getOperand(CallTargetPos); 123 } 124 125 private: 126 const MachineInstr *MI; 127 }; 128 129 class StackMaps { 130 public: 131 struct Location { 132 enum LocationType { 133 Unprocessed, 134 Register, 135 Direct, 136 Indirect, 137 Constant, 138 ConstantIndex 139 }; 140 LocationType Type; 141 unsigned Size; 142 unsigned Reg; 143 int64_t Offset; 144 Location() : Type(Unprocessed), Size(0), Reg(0), Offset(0) {} 145 Location(LocationType Type, unsigned Size, unsigned Reg, int64_t Offset) 146 : Type(Type), Size(Size), Reg(Reg), Offset(Offset) {} 147 }; 148 149 struct LiveOutReg { 150 unsigned short Reg; 151 unsigned short DwarfRegNum; 152 unsigned short Size; 153 154 LiveOutReg() : Reg(0), DwarfRegNum(0), Size(0) {} 155 LiveOutReg(unsigned short Reg, unsigned short DwarfRegNum, 156 unsigned short Size) 157 : Reg(Reg), DwarfRegNum(DwarfRegNum), Size(Size) {} 158 }; 159 160 // OpTypes are used to encode information about the following logical 161 // operand (which may consist of several MachineOperands) for the 162 // OpParser. 163 typedef enum { DirectMemRefOp, IndirectMemRefOp, ConstantOp } OpType; 164 165 StackMaps(AsmPrinter &AP); 166 167 void reset() { 168 CSInfos.clear(); 169 ConstPool.clear(); 170 FnStackSize.clear(); 171 } 172 173 /// \brief Generate a stackmap record for a stackmap instruction. 174 /// 175 /// MI must be a raw STACKMAP, not a PATCHPOINT. 176 void recordStackMap(const MachineInstr &MI); 177 178 /// \brief Generate a stackmap record for a patchpoint instruction. 179 void recordPatchPoint(const MachineInstr &MI); 180 181 /// \brief Generate a stackmap record for a statepoint instruction. 182 void recordStatepoint(const MachineInstr &MI); 183 184 /// If there is any stack map data, create a stack map section and serialize 185 /// the map info into it. This clears the stack map data structures 186 /// afterwards. 187 void serializeToStackMapSection(); 188 189 private: 190 static const char *WSMP; 191 typedef SmallVector<Location, 8> LocationVec; 192 typedef SmallVector<LiveOutReg, 8> LiveOutVec; 193 typedef MapVector<uint64_t, uint64_t> ConstantPool; 194 typedef MapVector<const MCSymbol *, uint64_t> FnStackSizeMap; 195 196 struct CallsiteInfo { 197 const MCExpr *CSOffsetExpr; 198 uint64_t ID; 199 LocationVec Locations; 200 LiveOutVec LiveOuts; 201 CallsiteInfo() : CSOffsetExpr(nullptr), ID(0) {} 202 CallsiteInfo(const MCExpr *CSOffsetExpr, uint64_t ID, 203 LocationVec &&Locations, LiveOutVec &&LiveOuts) 204 : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(std::move(Locations)), 205 LiveOuts(std::move(LiveOuts)) {} 206 }; 207 208 typedef std::vector<CallsiteInfo> CallsiteInfoList; 209 210 AsmPrinter &AP; 211 CallsiteInfoList CSInfos; 212 ConstantPool ConstPool; 213 FnStackSizeMap FnStackSize; 214 215 MachineInstr::const_mop_iterator 216 parseOperand(MachineInstr::const_mop_iterator MOI, 217 MachineInstr::const_mop_iterator MOE, LocationVec &Locs, 218 LiveOutVec &LiveOuts) const; 219 220 /// \brief Create a live-out register record for the given register @p Reg. 221 LiveOutReg createLiveOutReg(unsigned Reg, 222 const TargetRegisterInfo *TRI) const; 223 224 /// \brief Parse the register live-out mask and return a vector of live-out 225 /// registers that need to be recorded in the stackmap. 226 LiveOutVec parseRegisterLiveOutMask(const uint32_t *Mask) const; 227 228 /// This should be called by the MC lowering code _immediately_ before 229 /// lowering the MI to an MCInst. It records where the operands for the 230 /// instruction are stored, and outputs a label to record the offset of 231 /// the call from the start of the text section. In special cases (e.g. AnyReg 232 /// calling convention) the return register is also recorded if requested. 233 void recordStackMapOpers(const MachineInstr &MI, uint64_t ID, 234 MachineInstr::const_mop_iterator MOI, 235 MachineInstr::const_mop_iterator MOE, 236 bool recordResult = false); 237 238 /// \brief Emit the stackmap header. 239 void emitStackmapHeader(MCStreamer &OS); 240 241 /// \brief Emit the function frame record for each function. 242 void emitFunctionFrameRecords(MCStreamer &OS); 243 244 /// \brief Emit the constant pool. 245 void emitConstantPoolEntries(MCStreamer &OS); 246 247 /// \brief Emit the callsite info for each stackmap/patchpoint intrinsic call. 248 void emitCallsiteEntries(MCStreamer &OS); 249 250 void print(raw_ostream &OS); 251 void debug() { print(dbgs()); } 252 }; 253 } 254 255 #endif 256