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