StackMaps.h 14 KB

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