LLVM  10.0.0svn
StackMapParser.h
Go to the documentation of this file.
1 //===- StackMapParser.h - StackMap Parsing Support --------------*- 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_STACKMAPPARSER_H
10 #define LLVM_CODEGEN_STACKMAPPARSER_H
11 
12 #include "llvm/ADT/ArrayRef.h"
14 #include "llvm/Support/Endian.h"
15 #include <cassert>
16 #include <cstddef>
17 #include <cstdint>
18 #include <vector>
19 
20 namespace llvm {
21 
22 /// A parser for the latest stackmap format. At the moment, latest=V3.
23 template <support::endianness Endianness>
25 public:
26  template <typename AccessorT>
28  public:
29  AccessorIterator(AccessorT A) : A(A) {}
30 
31  AccessorIterator& operator++() { A = A.next(); return *this; }
33  auto tmp = *this;
34  ++*this;
35  return tmp;
36  }
37 
38  bool operator==(const AccessorIterator &Other) {
39  return A.P == Other.A.P;
40  }
41 
42  bool operator!=(const AccessorIterator &Other) { return !(*this == Other); }
43 
44  AccessorT& operator*() { return A; }
45  AccessorT* operator->() { return &A; }
46 
47  private:
48  AccessorT A;
49  };
50 
51  /// Accessor for function records.
53  friend class StackMapParser;
54 
55  public:
56  /// Get the function address.
57  uint64_t getFunctionAddress() const {
58  return read<uint64_t>(P);
59  }
60 
61  /// Get the function's stack size.
62  uint64_t getStackSize() const {
63  return read<uint64_t>(P + sizeof(uint64_t));
64  }
65 
66  /// Get the number of callsite records.
67  uint64_t getRecordCount() const {
68  return read<uint64_t>(P + (2 * sizeof(uint64_t)));
69  }
70 
71  private:
72  FunctionAccessor(const uint8_t *P) : P(P) {}
73 
74  const static int FunctionAccessorSize = 3 * sizeof(uint64_t);
75 
76  FunctionAccessor next() const {
77  return FunctionAccessor(P + FunctionAccessorSize);
78  }
79 
80  const uint8_t *P;
81  };
82 
83  /// Accessor for constants.
85  friend class StackMapParser;
86 
87  public:
88  /// Return the value of this constant.
89  uint64_t getValue() const { return read<uint64_t>(P); }
90 
91  private:
92  ConstantAccessor(const uint8_t *P) : P(P) {}
93 
94  const static int ConstantAccessorSize = sizeof(uint64_t);
95 
96  ConstantAccessor next() const {
97  return ConstantAccessor(P + ConstantAccessorSize);
98  }
99 
100  const uint8_t *P;
101  };
102 
103  enum class LocationKind : uint8_t {
104  Register = 1, Direct = 2, Indirect = 3, Constant = 4, ConstantIndex = 5
105  };
106 
107  /// Accessor for location records.
109  friend class StackMapParser;
110  friend class RecordAccessor;
111 
112  public:
113  /// Get the Kind for this location.
115  return LocationKind(P[KindOffset]);
116  }
117 
118  /// Get the Size for this location.
119  unsigned getSizeInBytes() const {
120  return read<uint16_t>(P + SizeOffset);
121 
122  }
123 
124  /// Get the Dwarf register number for this location.
125  uint16_t getDwarfRegNum() const {
126  return read<uint16_t>(P + DwarfRegNumOffset);
127  }
128 
129  /// Get the small-constant for this location. (Kind must be Constant).
131  assert(getKind() == LocationKind::Constant && "Not a small constant.");
132  return read<uint32_t>(P + SmallConstantOffset);
133  }
134 
135  /// Get the constant-index for this location. (Kind must be ConstantIndex).
137  assert(getKind() == LocationKind::ConstantIndex &&
138  "Not a constant-index.");
139  return read<uint32_t>(P + SmallConstantOffset);
140  }
141 
142  /// Get the offset for this location. (Kind must be Direct or Indirect).
143  int32_t getOffset() const {
144  assert((getKind() == LocationKind::Direct ||
145  getKind() == LocationKind::Indirect) &&
146  "Not direct or indirect.");
147  return read<int32_t>(P + SmallConstantOffset);
148  }
149 
150  private:
151  LocationAccessor(const uint8_t *P) : P(P) {}
152 
153  LocationAccessor next() const {
154  return LocationAccessor(P + LocationAccessorSize);
155  }
156 
157  static const int KindOffset = 0;
158  static const int SizeOffset = KindOffset + sizeof(uint16_t);
159  static const int DwarfRegNumOffset = SizeOffset + sizeof(uint16_t);
160  static const int SmallConstantOffset = DwarfRegNumOffset + sizeof(uint32_t);
161  static const int LocationAccessorSize = sizeof(uint64_t) + sizeof(uint32_t);
162 
163  const uint8_t *P;
164  };
165 
166  /// Accessor for stackmap live-out fields.
168  friend class StackMapParser;
169  friend class RecordAccessor;
170 
171  public:
172  /// Get the Dwarf register number for this live-out.
173  uint16_t getDwarfRegNum() const {
174  return read<uint16_t>(P + DwarfRegNumOffset);
175  }
176 
177  /// Get the size in bytes of live [sub]register.
178  unsigned getSizeInBytes() const {
179  return read<uint8_t>(P + SizeOffset);
180  }
181 
182  private:
183  LiveOutAccessor(const uint8_t *P) : P(P) {}
184 
185  LiveOutAccessor next() const {
186  return LiveOutAccessor(P + LiveOutAccessorSize);
187  }
188 
189  static const int DwarfRegNumOffset = 0;
190  static const int SizeOffset =
191  DwarfRegNumOffset + sizeof(uint16_t) + sizeof(uint8_t);
192  static const int LiveOutAccessorSize = sizeof(uint32_t);
193 
194  const uint8_t *P;
195  };
196 
197  /// Accessor for stackmap records.
199  friend class StackMapParser;
200 
201  public:
204 
205  /// Get the patchpoint/stackmap ID for this record.
206  uint64_t getID() const {
207  return read<uint64_t>(P + PatchpointIDOffset);
208  }
209 
210  /// Get the instruction offset (from the start of the containing function)
211  /// for this record.
213  return read<uint32_t>(P + InstructionOffsetOffset);
214  }
215 
216  /// Get the number of locations contained in this record.
217  uint16_t getNumLocations() const {
218  return read<uint16_t>(P + NumLocationsOffset);
219  }
220 
221  /// Get the location with the given index.
222  LocationAccessor getLocation(unsigned LocationIndex) const {
223  unsigned LocationOffset =
224  LocationListOffset + LocationIndex * LocationSize;
225  return LocationAccessor(P + LocationOffset);
226  }
227 
228  /// Begin iterator for locations.
230  return location_iterator(getLocation(0));
231  }
232 
233  /// End iterator for locations.
235  return location_iterator(getLocation(getNumLocations()));
236  }
237 
238  /// Iterator range for locations.
240  return make_range(location_begin(), location_end());
241  }
242 
243  /// Get the number of liveouts contained in this record.
244  uint16_t getNumLiveOuts() const {
245  return read<uint16_t>(P + getNumLiveOutsOffset());
246  }
247 
248  /// Get the live-out with the given index.
249  LiveOutAccessor getLiveOut(unsigned LiveOutIndex) const {
250  unsigned LiveOutOffset =
251  getNumLiveOutsOffset() + sizeof(uint16_t) + LiveOutIndex * LiveOutSize;
252  return LiveOutAccessor(P + LiveOutOffset);
253  }
254 
255  /// Begin iterator for live-outs.
257  return liveout_iterator(getLiveOut(0));
258  }
259 
260  /// End iterator for live-outs.
262  return liveout_iterator(getLiveOut(getNumLiveOuts()));
263  }
264 
265  /// Iterator range for live-outs.
267  return make_range(liveouts_begin(), liveouts_end());
268  }
269 
270  private:
271  RecordAccessor(const uint8_t *P) : P(P) {}
272 
273  unsigned getNumLiveOutsOffset() const {
274  unsigned LocOffset =
275  ((LocationListOffset + LocationSize * getNumLocations()) + 7) & ~0x7;
276  return LocOffset + sizeof(uint16_t);
277  }
278 
279  unsigned getSizeInBytes() const {
280  unsigned RecordSize =
281  getNumLiveOutsOffset() + sizeof(uint16_t) + getNumLiveOuts() * LiveOutSize;
282  return (RecordSize + 7) & ~0x7;
283  }
284 
285  RecordAccessor next() const {
286  return RecordAccessor(P + getSizeInBytes());
287  }
288 
289  static const unsigned PatchpointIDOffset = 0;
290  static const unsigned InstructionOffsetOffset =
291  PatchpointIDOffset + sizeof(uint64_t);
292  static const unsigned NumLocationsOffset =
293  InstructionOffsetOffset + sizeof(uint32_t) + sizeof(uint16_t);
294  static const unsigned LocationListOffset =
295  NumLocationsOffset + sizeof(uint16_t);
296  static const unsigned LocationSize = sizeof(uint64_t) + sizeof(uint32_t);
297  static const unsigned LiveOutSize = sizeof(uint32_t);
298 
299  const uint8_t *P;
300  };
301 
302  /// Construct a parser for a version-3 stackmap. StackMap data will be read
303  /// from the given array.
305  : StackMapSection(StackMapSection) {
306  ConstantsListOffset = FunctionListOffset + getNumFunctions() * FunctionSize;
307 
308  assert(StackMapSection[0] == 3 &&
309  "StackMapParser can only parse version 3 stackmaps");
310 
311  unsigned CurrentRecordOffset =
312  ConstantsListOffset + getNumConstants() * ConstantSize;
313 
314  for (unsigned I = 0, E = getNumRecords(); I != E; ++I) {
315  StackMapRecordOffsets.push_back(CurrentRecordOffset);
316  CurrentRecordOffset +=
317  RecordAccessor(&StackMapSection[CurrentRecordOffset]).getSizeInBytes();
318  }
319  }
320 
324 
325  /// Get the version number of this stackmap. (Always returns 3).
326  unsigned getVersion() const { return 3; }
327 
328  /// Get the number of functions in the stack map.
330  return read<uint32_t>(&StackMapSection[NumFunctionsOffset]);
331  }
332 
333  /// Get the number of large constants in the stack map.
335  return read<uint32_t>(&StackMapSection[NumConstantsOffset]);
336  }
337 
338  /// Get the number of stackmap records in the stackmap.
340  return read<uint32_t>(&StackMapSection[NumRecordsOffset]);
341  }
342 
343  /// Return an FunctionAccessor for the given function index.
344  FunctionAccessor getFunction(unsigned FunctionIndex) const {
345  return FunctionAccessor(StackMapSection.data() +
346  getFunctionOffset(FunctionIndex));
347  }
348 
349  /// Begin iterator for functions.
351  return function_iterator(getFunction(0));
352  }
353 
354  /// End iterator for functions.
356  return function_iterator(
357  FunctionAccessor(StackMapSection.data() +
358  getFunctionOffset(getNumFunctions())));
359  }
360 
361  /// Iterator range for functions.
364  }
365 
366  /// Return the large constant at the given index.
367  ConstantAccessor getConstant(unsigned ConstantIndex) const {
368  return ConstantAccessor(StackMapSection.data() +
369  getConstantOffset(ConstantIndex));
370  }
371 
372  /// Begin iterator for constants.
374  return constant_iterator(getConstant(0));
375  }
376 
377  /// End iterator for constants.
379  return constant_iterator(
380  ConstantAccessor(StackMapSection.data() +
381  getConstantOffset(getNumConstants())));
382  }
383 
384  /// Iterator range for constants.
387  }
388 
389  /// Return a RecordAccessor for the given record index.
390  RecordAccessor getRecord(unsigned RecordIndex) const {
391  std::size_t RecordOffset = StackMapRecordOffsets[RecordIndex];
392  return RecordAccessor(StackMapSection.data() + RecordOffset);
393  }
394 
395  /// Begin iterator for records.
397  if (getNumRecords() == 0)
398  return record_iterator(RecordAccessor(nullptr));
399  return record_iterator(getRecord(0));
400  }
401 
402  /// End iterator for records.
404  // Records need to be handled specially, since we cache the start addresses
405  // for them: We can't just compute the 1-past-the-end address, we have to
406  // look at the last record and use the 'next' method.
407  if (getNumRecords() == 0)
408  return record_iterator(RecordAccessor(nullptr));
409  return record_iterator(getRecord(getNumRecords() - 1).next());
410  }
411 
412  /// Iterator range for records.
414  return make_range(records_begin(), records_end());
415  }
416 
417 private:
418  template <typename T>
419  static T read(const uint8_t *P) {
420  return support::endian::read<T, Endianness, 1>(P);
421  }
422 
423  static const unsigned HeaderOffset = 0;
424  static const unsigned NumFunctionsOffset = HeaderOffset + sizeof(uint32_t);
425  static const unsigned NumConstantsOffset = NumFunctionsOffset + sizeof(uint32_t);
426  static const unsigned NumRecordsOffset = NumConstantsOffset + sizeof(uint32_t);
427  static const unsigned FunctionListOffset = NumRecordsOffset + sizeof(uint32_t);
428 
429  static const unsigned FunctionSize = 3 * sizeof(uint64_t);
430  static const unsigned ConstantSize = sizeof(uint64_t);
431 
432  std::size_t getFunctionOffset(unsigned FunctionIndex) const {
433  return FunctionListOffset + FunctionIndex * FunctionSize;
434  }
435 
436  std::size_t getConstantOffset(unsigned ConstantIndex) const {
437  return ConstantsListOffset + ConstantIndex * ConstantSize;
438  }
439 
440  ArrayRef<uint8_t> StackMapSection;
441  unsigned ConstantsListOffset;
442  std::vector<unsigned> StackMapRecordOffsets;
443 };
444 
445 } // end namespace llvm
446 
447 #endif // LLVM_CODEGEN_STACKMAPPARSER_H
unsigned getVersion() const
Get the version number of this stackmap. (Always returns 3).
unsigned getSizeInBytes() const
Get the Size for this location.
uint16_t getDwarfRegNum() const
Get the Dwarf register number for this location.
uint64_t getRecordCount() const
Get the number of callsite records.
Accessor for stackmap live-out fields.
This class represents lattice values for constants.
Definition: AllocatorList.h:23
liveout_iterator liveouts_begin() const
Begin iterator for live-outs.
AccessorIterator< ConstantAccessor > constant_iterator
This provides a very simple, boring adaptor for a begin and end iterator into a range type...
uint64_t getStackSize() const
Get the function&#39;s stack size.
iterator_range< liveout_iterator > liveouts() const
Iterator range for live-outs.
uint32_t getNumConstants() const
Get the number of large constants in the stack map.
uint32_t getConstantIndex() const
Get the constant-index for this location. (Kind must be ConstantIndex).
Accessor for stackmap records.
location_iterator location_begin() const
Begin iterator for locations.
unsigned getSizeInBytes() const
Get the size in bytes of live [sub]register.
uint64_t getID() const
Get the patchpoint/stackmap ID for this record.
uint64_t getFunctionAddress() const
Get the function address.
constant_iterator constants_end() const
End iterator for constants.
#define P(N)
bool operator!=(const AccessorIterator &Other)
function_iterator functions_begin() const
Begin iterator for functions.
constant_iterator constants_begin() const
Begin iterator for constants.
liveout_iterator liveouts_end() const
End iterator for live-outs.
Accessor for function records.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This is an important base class in LLVM.
Definition: Constant.h:41
function_iterator functions_end() const
End iterator for functions.
RecordAccessor getRecord(unsigned RecordIndex) const
Return a RecordAccessor for the given record index.
iterator_range< function_iterator > functions() const
Iterator range for functions.
uint16_t getNumLocations() const
Get the number of locations contained in this record.
uint32_t getInstructionOffset() const
Get the instruction offset (from the start of the containing function) for this record.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
uint32_t getNumRecords() const
Get the number of stackmap records in the stackmap.
uint16_t getDwarfRegNum() const
Get the Dwarf register number for this live-out.
iterator_range< location_iterator > locations() const
Iterator range for locations.
iterator_range< constant_iterator > constants() const
Iterator range for constants.
location_iterator location_end() const
End iterator for locations.
bool operator==(const AccessorIterator &Other)
A range adaptor for a pair of iterators.
uint32_t getNumFunctions() const
Get the number of functions in the stack map.
uint16_t getNumLiveOuts() const
Get the number of liveouts contained in this record.
AccessorIterator< FunctionAccessor > function_iterator
A parser for the latest stackmap format. At the moment, latest=V3.
value_type read(const void *memory, endianness endian)
Read a value of a particular endianness from memory.
Definition: Endian.h:65
#define I(x, y, z)
Definition: MD5.cpp:58
Accessor for location records.
record_iterator records_begin() const
Begin iterator for records.
AccessorIterator< RecordAccessor > record_iterator
static MemoryLocation getLocation(Instruction *I, AliasAnalysis *AA)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
FunctionAccessor getFunction(unsigned FunctionIndex) const
Return an FunctionAccessor for the given function index.
int32_t getOffset() const
Get the offset for this location. (Kind must be Direct or Indirect).
LocationAccessor getLocation(unsigned LocationIndex) const
Get the location with the given index.
LiveOutAccessor getLiveOut(unsigned LiveOutIndex) const
Get the live-out with the given index.
uint64_t getValue() const
Return the value of this constant.
StackMapParser(ArrayRef< uint8_t > StackMapSection)
Construct a parser for a version-3 stackmap.
iterator_range< record_iterator > records() const
Iterator range for records.
LocationKind getKind() const
Get the Kind for this location.
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
record_iterator records_end() const
End iterator for records.
uint32_t getSmallConstant() const
Get the small-constant for this location. (Kind must be Constant).
ConstantAccessor getConstant(unsigned ConstantIndex) const
Return the large constant at the given index.