]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | //===------------------- StackMaps.h - StackMaps ----------------*- C++ -*-===// |
2 | ||
3 | // | |
4 | // The LLVM Compiler Infrastructure | |
5 | // | |
6 | // This file is distributed under the University of Illinois Open Source | |
7 | // License. See LICENSE.TXT for details. | |
8 | // | |
9 | //===----------------------------------------------------------------------===// | |
10 | ||
11 | #ifndef LLVM_CODEGEN_STACKMAPS_H | |
12 | #define LLVM_CODEGEN_STACKMAPS_H | |
13 | ||
14 | #include "llvm/ADT/MapVector.h" | |
15 | #include "llvm/ADT/SmallVector.h" | |
16 | #include "llvm/CodeGen/MachineInstr.h" | |
17 | #include <map> | |
18 | #include <vector> | |
19 | ||
20 | namespace llvm { | |
21 | ||
22 | class AsmPrinter; | |
23 | class MCExpr; | |
24 | class MCStreamer; | |
25 | ||
26 | /// \brief MI-level patchpoint operands. | |
27 | /// | |
28 | /// MI patchpoint operations take the form: | |
29 | /// [<def>], <id>, <numBytes>, <target>, <numArgs>, <cc>, ... | |
30 | /// | |
31 | /// IR patchpoint intrinsics do not have the <cc> operand because calling | |
32 | /// convention is part of the subclass data. | |
33 | /// | |
34 | /// SD patchpoint nodes do not have a def operand because it is part of the | |
35 | /// SDValue. | |
36 | /// | |
37 | /// Patchpoints following the anyregcc convention are handled specially. For | |
38 | /// these, the stack map also records the location of the return value and | |
39 | /// arguments. | |
40 | class PatchPointOpers { | |
41 | public: | |
42 | /// Enumerate the meta operands. | |
43 | enum { IDPos, NBytesPos, TargetPos, NArgPos, CCPos, MetaEnd }; | |
44 | private: | |
45 | const MachineInstr *MI; | |
46 | bool HasDef; | |
47 | bool IsAnyReg; | |
48 | public: | |
49 | explicit PatchPointOpers(const MachineInstr *MI); | |
50 | ||
51 | bool isAnyReg() const { return IsAnyReg; } | |
52 | bool hasDef() const { return HasDef; } | |
53 | ||
54 | unsigned getMetaIdx(unsigned Pos = 0) const { | |
55 | assert(Pos < MetaEnd && "Meta operand index out of range."); | |
56 | return (HasDef ? 1 : 0) + Pos; | |
57 | } | |
58 | ||
59 | const MachineOperand &getMetaOper(unsigned Pos) { | |
60 | return MI->getOperand(getMetaIdx(Pos)); | |
61 | } | |
62 | ||
63 | unsigned getArgIdx() const { return getMetaIdx() + MetaEnd; } | |
64 | ||
65 | /// Get the operand index of the variable list of non-argument operands. | |
66 | /// These hold the "live state". | |
67 | unsigned getVarIdx() const { | |
68 | return getMetaIdx() + MetaEnd | |
69 | + MI->getOperand(getMetaIdx(NArgPos)).getImm(); | |
70 | } | |
71 | ||
72 | /// Get the index at which stack map locations will be recorded. | |
73 | /// Arguments are not recorded unless the anyregcc convention is used. | |
74 | unsigned getStackMapStartIdx() const { | |
75 | if (IsAnyReg) | |
76 | return getArgIdx(); | |
77 | return getVarIdx(); | |
78 | } | |
79 | ||
80 | /// \brief Get the next scratch register operand index. | |
81 | unsigned getNextScratchIdx(unsigned StartIdx = 0) const; | |
82 | }; | |
83 | ||
85aaf69f SL |
84 | /// MI-level Statepoint operands |
85 | /// | |
86 | /// Statepoint operands take the form: | |
87 | /// <num call arguments>, <call target>, [call arguments], | |
88 | /// <StackMaps::ConstantOp>, <flags>, | |
89 | /// <StackMaps::ConstantOp>, <num other args>, [other args], | |
90 | /// [gc values] | |
91 | class StatepointOpers { | |
92 | private: | |
93 | enum { | |
94 | NCallArgsPos = 0, | |
95 | CallTargetPos = 1 | |
96 | }; | |
97 | ||
98 | public: | |
99 | explicit StatepointOpers(const MachineInstr *MI): | |
100 | MI(MI) { } | |
101 | ||
102 | /// Get starting index of non call related arguments | |
103 | /// (statepoint flags, vm state and gc state). | |
104 | unsigned getVarIdx() const { | |
105 | return MI->getOperand(NCallArgsPos).getImm() + 2; | |
106 | } | |
107 | ||
108 | /// Returns the index of the operand containing the number of non-gc non-call | |
109 | /// arguments. | |
110 | unsigned getNumVMSArgsIdx() const { | |
111 | return getVarIdx() + 3; | |
112 | } | |
113 | ||
114 | /// Returns the number of non-gc non-call arguments attached to the | |
115 | /// statepoint. Note that this is the number of arguments, not the number of | |
116 | /// operands required to represent those arguments. | |
117 | unsigned getNumVMSArgs() const { | |
118 | return MI->getOperand(getNumVMSArgsIdx()).getImm(); | |
119 | } | |
120 | ||
121 | /// Returns the target of the underlying call. | |
122 | const MachineOperand &getCallTarget() const { | |
123 | return MI->getOperand(CallTargetPos); | |
124 | } | |
125 | ||
126 | private: | |
127 | const MachineInstr *MI; | |
128 | }; | |
129 | ||
1a4d82fc JJ |
130 | class StackMaps { |
131 | public: | |
132 | struct Location { | |
133 | enum LocationType { Unprocessed, Register, Direct, Indirect, Constant, | |
134 | ConstantIndex }; | |
135 | LocationType LocType; | |
136 | unsigned Size; | |
137 | unsigned Reg; | |
138 | int64_t Offset; | |
139 | Location() : LocType(Unprocessed), Size(0), Reg(0), Offset(0) {} | |
140 | Location(LocationType LocType, unsigned Size, unsigned Reg, int64_t Offset) | |
141 | : LocType(LocType), Size(Size), Reg(Reg), Offset(Offset) {} | |
142 | }; | |
143 | ||
144 | struct LiveOutReg { | |
145 | unsigned short Reg; | |
146 | unsigned short RegNo; | |
147 | unsigned short Size; | |
148 | ||
149 | LiveOutReg() : Reg(0), RegNo(0), Size(0) {} | |
150 | LiveOutReg(unsigned short Reg, unsigned short RegNo, unsigned short Size) | |
151 | : Reg(Reg), RegNo(RegNo), Size(Size) {} | |
152 | ||
153 | void MarkInvalid() { Reg = 0; } | |
154 | ||
155 | // Only sort by the dwarf register number. | |
156 | bool operator< (const LiveOutReg &LO) const { return RegNo < LO.RegNo; } | |
157 | static bool IsInvalid(const LiveOutReg &LO) { return LO.Reg == 0; } | |
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 | ||
85aaf69f SL |
181 | /// \brief Generate a stackmap record for a statepoint instruction. |
182 | void recordStatepoint(const MachineInstr &MI); | |
183 | ||
1a4d82fc JJ |
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; | |
1a4d82fc JJ |
191 | typedef SmallVector<Location, 8> LocationVec; |
192 | typedef SmallVector<LiveOutReg, 8> LiveOutVec; | |
85aaf69f | 193 | typedef MapVector<uint64_t, uint64_t> ConstantPool; |
1a4d82fc JJ |
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, | |
85aaf69f SL |
203 | LocationVec &&Locations, LiveOutVec &&LiveOuts) |
204 | : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(std::move(Locations)), | |
205 | LiveOuts(std::move(LiveOuts)) {} | |
1a4d82fc JJ |
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, | |
218 | LocationVec &Locs, 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, const TargetRegisterInfo *TRI); | |
249 | }; | |
250 | ||
251 | } | |
252 | ||
253 | #endif |