StackMaps.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. //===- StackMaps.h - StackMaps ----------------------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #ifndef LLVM_CODEGEN_STACKMAPS_H
  9. #define LLVM_CODEGEN_STACKMAPS_H
  10. #include "llvm/ADT/MapVector.h"
  11. #include "llvm/ADT/SmallVector.h"
  12. #include "llvm/CodeGen/MachineInstr.h"
  13. #include "llvm/IR/CallingConv.h"
  14. #include "llvm/MC/MCSymbol.h"
  15. #include "llvm/Support/Debug.h"
  16. #include <algorithm>
  17. #include <cassert>
  18. #include <cstdint>
  19. #include <vector>
  20. namespace llvm {
  21. class AsmPrinter;
  22. class MCExpr;
  23. class MCStreamer;
  24. class raw_ostream;
  25. class TargetRegisterInfo;
  26. /// MI-level stackmap operands.
  27. ///
  28. /// MI stackmap operations take the form:
  29. /// <id>, <numBytes>, live args...
  30. class StackMapOpers {
  31. public:
  32. /// Enumerate the meta operands.
  33. enum { IDPos, NBytesPos };
  34. private:
  35. const MachineInstr* MI;
  36. public:
  37. explicit StackMapOpers(const MachineInstr *MI);
  38. /// Return the ID for the given stackmap
  39. uint64_t getID() const { return MI->getOperand(IDPos).getImm(); }
  40. /// Return the number of patchable bytes the given stackmap should emit.
  41. uint32_t getNumPatchBytes() const {
  42. return MI->getOperand(NBytesPos).getImm();
  43. }
  44. /// Get the operand index of the variable list of non-argument operands.
  45. /// These hold the "live state".
  46. unsigned getVarIdx() const {
  47. // Skip ID, nShadowBytes.
  48. return 2;
  49. }
  50. };
  51. /// MI-level patchpoint operands.
  52. ///
  53. /// MI patchpoint operations take the form:
  54. /// [<def>], <id>, <numBytes>, <target>, <numArgs>, <cc>, ...
  55. ///
  56. /// IR patchpoint intrinsics do not have the <cc> operand because calling
  57. /// convention is part of the subclass data.
  58. ///
  59. /// SD patchpoint nodes do not have a def operand because it is part of the
  60. /// SDValue.
  61. ///
  62. /// Patchpoints following the anyregcc convention are handled specially. For
  63. /// these, the stack map also records the location of the return value and
  64. /// arguments.
  65. class PatchPointOpers {
  66. public:
  67. /// Enumerate the meta operands.
  68. enum { IDPos, NBytesPos, TargetPos, NArgPos, CCPos, MetaEnd };
  69. private:
  70. const MachineInstr *MI;
  71. bool HasDef;
  72. unsigned getMetaIdx(unsigned Pos = 0) const {
  73. assert(Pos < MetaEnd && "Meta operand index out of range.");
  74. return (HasDef ? 1 : 0) + Pos;
  75. }
  76. const MachineOperand &getMetaOper(unsigned Pos) const {
  77. return MI->getOperand(getMetaIdx(Pos));
  78. }
  79. public:
  80. explicit PatchPointOpers(const MachineInstr *MI);
  81. bool isAnyReg() const { return (getCallingConv() == CallingConv::AnyReg); }
  82. bool hasDef() const { return HasDef; }
  83. /// Return the ID for the given patchpoint.
  84. uint64_t getID() const { return getMetaOper(IDPos).getImm(); }
  85. /// Return the number of patchable bytes the given patchpoint should emit.
  86. uint32_t getNumPatchBytes() const {
  87. return getMetaOper(NBytesPos).getImm();
  88. }
  89. /// Returns the target of the underlying call.
  90. const MachineOperand &getCallTarget() const {
  91. return getMetaOper(TargetPos);
  92. }
  93. /// Returns the calling convention
  94. CallingConv::ID getCallingConv() const {
  95. return getMetaOper(CCPos).getImm();
  96. }
  97. unsigned getArgIdx() const { return getMetaIdx() + MetaEnd; }
  98. /// Return the number of call arguments
  99. uint32_t getNumCallArgs() const {
  100. return MI->getOperand(getMetaIdx(NArgPos)).getImm();
  101. }
  102. /// Get the operand index of the variable list of non-argument operands.
  103. /// These hold the "live state".
  104. unsigned getVarIdx() const {
  105. return getMetaIdx() + MetaEnd + getNumCallArgs();
  106. }
  107. /// Get the index at which stack map locations will be recorded.
  108. /// Arguments are not recorded unless the anyregcc convention is used.
  109. unsigned getStackMapStartIdx() const {
  110. if (isAnyReg())
  111. return getArgIdx();
  112. return getVarIdx();
  113. }
  114. /// Get the next scratch register operand index.
  115. unsigned getNextScratchIdx(unsigned StartIdx = 0) const;
  116. };
  117. /// MI-level Statepoint operands
  118. ///
  119. /// Statepoint operands take the form:
  120. /// <id>, <num patch bytes >, <num call arguments>, <call target>,
  121. /// [call arguments...],
  122. /// <StackMaps::ConstantOp>, <calling convention>,
  123. /// <StackMaps::ConstantOp>, <statepoint flags>,
  124. /// <StackMaps::ConstantOp>, <num deopt args>, [deopt args...],
  125. /// <StackMaps::ConstantOp>, <num gc pointer args>, [gc pointer args...],
  126. /// <StackMaps::ConstantOp>, <num gc allocas>, [gc allocas args...],
  127. /// <StackMaps::ConstantOp>, <num entries in gc map>, [base/derived pairs]
  128. /// base/derived pairs in gc map are logical indices into <gc pointer args>
  129. /// section.
  130. /// All gc pointers assigned to VRegs produce new value (in form of MI Def
  131. /// operand) and are tied to it.
  132. class StatepointOpers {
  133. // TODO:: we should change the STATEPOINT representation so that CC and
  134. // Flags should be part of meta operands, with args and deopt operands, and
  135. // gc operands all prefixed by their length and a type code. This would be
  136. // much more consistent.
  137. // These values are absolute offsets into the operands of the statepoint
  138. // instruction.
  139. enum { IDPos, NBytesPos, NCallArgsPos, CallTargetPos, MetaEnd };
  140. // These values are relative offsets from the start of the statepoint meta
  141. // arguments (i.e. the end of the call arguments).
  142. enum { CCOffset = 1, FlagsOffset = 3, NumDeoptOperandsOffset = 5 };
  143. public:
  144. explicit StatepointOpers(const MachineInstr *MI) : MI(MI) {
  145. NumDefs = MI->getNumDefs();
  146. }
  147. /// Get index of statepoint ID operand.
  148. unsigned getIDPos() const { return NumDefs + IDPos; }
  149. /// Get index of Num Patch Bytes operand.
  150. unsigned getNBytesPos() const { return NumDefs + NBytesPos; }
  151. /// Get index of Num Call Arguments operand.
  152. unsigned getNCallArgsPos() const { return NumDefs + NCallArgsPos; }
  153. /// Get starting index of non call related arguments
  154. /// (calling convention, statepoint flags, vm state and gc state).
  155. unsigned getVarIdx() const {
  156. return MI->getOperand(NumDefs + NCallArgsPos).getImm() + MetaEnd + NumDefs;
  157. }
  158. /// Get index of Calling Convention operand.
  159. unsigned getCCIdx() const { return getVarIdx() + CCOffset; }
  160. /// Get index of Flags operand.
  161. unsigned getFlagsIdx() const { return getVarIdx() + FlagsOffset; }
  162. /// Get index of Number Deopt Arguments operand.
  163. unsigned getNumDeoptArgsIdx() const {
  164. return getVarIdx() + NumDeoptOperandsOffset;
  165. }
  166. /// Return the ID for the given statepoint.
  167. uint64_t getID() const { return MI->getOperand(NumDefs + IDPos).getImm(); }
  168. /// Return the number of patchable bytes the given statepoint should emit.
  169. uint32_t getNumPatchBytes() const {
  170. return MI->getOperand(NumDefs + NBytesPos).getImm();
  171. }
  172. /// Return the target of the underlying call.
  173. const MachineOperand &getCallTarget() const {
  174. return MI->getOperand(NumDefs + CallTargetPos);
  175. }
  176. /// Return the calling convention.
  177. CallingConv::ID getCallingConv() const {
  178. return MI->getOperand(getCCIdx()).getImm();
  179. }
  180. /// Return the statepoint flags.
  181. uint64_t getFlags() const { return MI->getOperand(getFlagsIdx()).getImm(); }
  182. uint64_t getNumDeoptArgs() const {
  183. return MI->getOperand(getNumDeoptArgsIdx()).getImm();
  184. }
  185. /// Get index of number of gc map entries.
  186. unsigned getNumGcMapEntriesIdx();
  187. /// Get index of number of gc allocas.
  188. unsigned getNumAllocaIdx();
  189. /// Get index of number of GC pointers.
  190. unsigned getNumGCPtrIdx();
  191. /// Get index of first GC pointer operand of -1 if there are none.
  192. int getFirstGCPtrIdx();
  193. /// Get vector of base/derived pairs from statepoint.
  194. /// Elements are indices into GC Pointer operand list (logical).
  195. /// Returns number of elements in GCMap.
  196. unsigned
  197. getGCPointerMap(SmallVectorImpl<std::pair<unsigned, unsigned>> &GCMap);
  198. private:
  199. const MachineInstr *MI;
  200. unsigned NumDefs;
  201. };
  202. class StackMaps {
  203. public:
  204. struct Location {
  205. enum LocationType {
  206. Unprocessed,
  207. Register,
  208. Direct,
  209. Indirect,
  210. Constant,
  211. ConstantIndex
  212. };
  213. LocationType Type = Unprocessed;
  214. unsigned Size = 0;
  215. unsigned Reg = 0;
  216. int64_t Offset = 0;
  217. Location() = default;
  218. Location(LocationType Type, unsigned Size, unsigned Reg, int64_t Offset)
  219. : Type(Type), Size(Size), Reg(Reg), Offset(Offset) {}
  220. };
  221. struct LiveOutReg {
  222. unsigned short Reg = 0;
  223. unsigned short DwarfRegNum = 0;
  224. unsigned short Size = 0;
  225. LiveOutReg() = default;
  226. LiveOutReg(unsigned short Reg, unsigned short DwarfRegNum,
  227. unsigned short Size)
  228. : Reg(Reg), DwarfRegNum(DwarfRegNum), Size(Size) {}
  229. };
  230. // OpTypes are used to encode information about the following logical
  231. // operand (which may consist of several MachineOperands) for the
  232. // OpParser.
  233. using OpType = enum { DirectMemRefOp, IndirectMemRefOp, ConstantOp };
  234. StackMaps(AsmPrinter &AP);
  235. /// Get index of next meta operand.
  236. /// Similar to parseOperand, but does not actually parses operand meaning.
  237. static unsigned getNextMetaArgIdx(const MachineInstr *MI, unsigned CurIdx);
  238. void reset() {
  239. CSInfos.clear();
  240. ConstPool.clear();
  241. FnInfos.clear();
  242. }
  243. using LocationVec = SmallVector<Location, 8>;
  244. using LiveOutVec = SmallVector<LiveOutReg, 8>;
  245. using ConstantPool = MapVector<uint64_t, uint64_t>;
  246. struct FunctionInfo {
  247. uint64_t StackSize = 0;
  248. uint64_t RecordCount = 1;
  249. FunctionInfo() = default;
  250. explicit FunctionInfo(uint64_t StackSize) : StackSize(StackSize) {}
  251. };
  252. struct CallsiteInfo {
  253. const MCExpr *CSOffsetExpr = nullptr;
  254. uint64_t ID = 0;
  255. LocationVec Locations;
  256. LiveOutVec LiveOuts;
  257. CallsiteInfo() = default;
  258. CallsiteInfo(const MCExpr *CSOffsetExpr, uint64_t ID,
  259. LocationVec &&Locations, LiveOutVec &&LiveOuts)
  260. : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(std::move(Locations)),
  261. LiveOuts(std::move(LiveOuts)) {}
  262. };
  263. using FnInfoMap = MapVector<const MCSymbol *, FunctionInfo>;
  264. using CallsiteInfoList = std::vector<CallsiteInfo>;
  265. /// Generate a stackmap record for a stackmap instruction.
  266. ///
  267. /// MI must be a raw STACKMAP, not a PATCHPOINT.
  268. void recordStackMap(const MCSymbol &L,
  269. const MachineInstr &MI);
  270. /// Generate a stackmap record for a patchpoint instruction.
  271. void recordPatchPoint(const MCSymbol &L,
  272. const MachineInstr &MI);
  273. /// Generate a stackmap record for a statepoint instruction.
  274. void recordStatepoint(const MCSymbol &L,
  275. const MachineInstr &MI);
  276. /// If there is any stack map data, create a stack map section and serialize
  277. /// the map info into it. This clears the stack map data structures
  278. /// afterwards.
  279. void serializeToStackMapSection();
  280. /// Get call site info.
  281. CallsiteInfoList &getCSInfos() { return CSInfos; }
  282. /// Get function info.
  283. FnInfoMap &getFnInfos() { return FnInfos; }
  284. private:
  285. static const char *WSMP;
  286. AsmPrinter &AP;
  287. CallsiteInfoList CSInfos;
  288. ConstantPool ConstPool;
  289. FnInfoMap FnInfos;
  290. MachineInstr::const_mop_iterator
  291. parseOperand(MachineInstr::const_mop_iterator MOI,
  292. MachineInstr::const_mop_iterator MOE, LocationVec &Locs,
  293. LiveOutVec &LiveOuts) const;
  294. /// Specialized parser of statepoint operands.
  295. /// They do not directly correspond to StackMap record entries.
  296. void parseStatepointOpers(const MachineInstr &MI,
  297. MachineInstr::const_mop_iterator MOI,
  298. MachineInstr::const_mop_iterator MOE,
  299. LocationVec &Locations, LiveOutVec &LiveOuts);
  300. /// Create a live-out register record for the given register @p Reg.
  301. LiveOutReg createLiveOutReg(unsigned Reg,
  302. const TargetRegisterInfo *TRI) const;
  303. /// Parse the register live-out mask and return a vector of live-out
  304. /// registers that need to be recorded in the stackmap.
  305. LiveOutVec parseRegisterLiveOutMask(const uint32_t *Mask) const;
  306. /// Record the locations of the operands of the provided instruction in a
  307. /// record keyed by the provided label. For instructions w/AnyReg calling
  308. /// convention the return register is also recorded if requested. For
  309. /// STACKMAP, and PATCHPOINT the label is expected to immediately *preceed*
  310. /// lowering of the MI to MCInsts. For STATEPOINT, it expected to
  311. /// immediately *follow*. It's not clear this difference was intentional,
  312. /// but it exists today.
  313. void recordStackMapOpers(const MCSymbol &L,
  314. const MachineInstr &MI, uint64_t ID,
  315. MachineInstr::const_mop_iterator MOI,
  316. MachineInstr::const_mop_iterator MOE,
  317. bool recordResult = false);
  318. /// Emit the stackmap header.
  319. void emitStackmapHeader(MCStreamer &OS);
  320. /// Emit the function frame record for each function.
  321. void emitFunctionFrameRecords(MCStreamer &OS);
  322. /// Emit the constant pool.
  323. void emitConstantPoolEntries(MCStreamer &OS);
  324. /// Emit the callsite info for each stackmap/patchpoint intrinsic call.
  325. void emitCallsiteEntries(MCStreamer &OS);
  326. void print(raw_ostream &OS);
  327. void debug() { print(dbgs()); }
  328. };
  329. } // end namespace llvm
  330. #endif // LLVM_CODEGEN_STACKMAPS_H