LLVM  8.0.1
StackMapParser.h
Go to the documentation of this file.
1 //===- StackMapParser.h - StackMap Parsing Support --------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef LLVM_CODEGEN_STACKMAPPARSER_H
11 #define LLVM_CODEGEN_STACKMAPPARSER_H
12 
13 #include "llvm/ADT/ArrayRef.h"
15 #include "llvm/Support/Endian.h"
16 #include <cassert>
17 #include <cstddef>
18 #include <cstdint>
19 #include <vector>
20 
21 namespace llvm {
22 
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 StackMapV2Parser;
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 StackMapV2Parser;
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 StackMapV2Parser;
110  friend class RecordAccessor;
111 
112  public:
113  /// Get the Kind for this location.
115  return LocationKind(P[KindOffset]);
116  }
117 
118  /// Get the Dwarf register number for this location.
119  uint16_t getDwarfRegNum() const {
120  return read<uint16_t>(P + DwarfRegNumOffset);
121  }
122 
123  /// Get the small-constant for this location. (Kind must be Constant).
125  assert(getKind() == LocationKind::Constant && "Not a small constant.");
126  return read<uint32_t>(P + SmallConstantOffset);
127  }
128 
129  /// Get the constant-index for this location. (Kind must be ConstantIndex).
131  assert(getKind() == LocationKind::ConstantIndex &&
132  "Not a constant-index.");
133  return read<uint32_t>(P + SmallConstantOffset);
134  }
135 
136  /// Get the offset for this location. (Kind must be Direct or Indirect).
137  int32_t getOffset() const {
138  assert((getKind() == LocationKind::Direct ||
139  getKind() == LocationKind::Indirect) &&
140  "Not direct or indirect.");
141  return read<int32_t>(P + SmallConstantOffset);
142  }
143 
144  private:
145  LocationAccessor(const uint8_t *P) : P(P) {}
146 
147  LocationAccessor next() const {
148  return LocationAccessor(P + LocationAccessorSize);
149  }
150 
151  static const int KindOffset = 0;
152  static const int DwarfRegNumOffset = KindOffset + sizeof(uint16_t);
153  static const int SmallConstantOffset = DwarfRegNumOffset + sizeof(uint16_t);
154  static const int LocationAccessorSize = sizeof(uint64_t);
155 
156  const uint8_t *P;
157  };
158 
159  /// Accessor for stackmap live-out fields.
161  friend class StackMapV2Parser;
162  friend class RecordAccessor;
163 
164  public:
165  /// Get the Dwarf register number for this live-out.
166  uint16_t getDwarfRegNum() const {
167  return read<uint16_t>(P + DwarfRegNumOffset);
168  }
169 
170  /// Get the size in bytes of live [sub]register.
171  unsigned getSizeInBytes() const {
172  return read<uint8_t>(P + SizeOffset);
173  }
174 
175  private:
176  LiveOutAccessor(const uint8_t *P) : P(P) {}
177 
178  LiveOutAccessor next() const {
179  return LiveOutAccessor(P + LiveOutAccessorSize);
180  }
181 
182  static const int DwarfRegNumOffset = 0;
183  static const int SizeOffset =
184  DwarfRegNumOffset + sizeof(uint16_t) + sizeof(uint8_t);
185  static const int LiveOutAccessorSize = sizeof(uint32_t);
186 
187  const uint8_t *P;
188  };
189 
190  /// Accessor for stackmap records.
192  friend class StackMapV2Parser;
193 
194  public:
197 
198  /// Get the patchpoint/stackmap ID for this record.
199  uint64_t getID() const {
200  return read<uint64_t>(P + PatchpointIDOffset);
201  }
202 
203  /// Get the instruction offset (from the start of the containing function)
204  /// for this record.
206  return read<uint32_t>(P + InstructionOffsetOffset);
207  }
208 
209  /// Get the number of locations contained in this record.
210  uint16_t getNumLocations() const {
211  return read<uint16_t>(P + NumLocationsOffset);
212  }
213 
214  /// Get the location with the given index.
215  LocationAccessor getLocation(unsigned LocationIndex) const {
216  unsigned LocationOffset =
217  LocationListOffset + LocationIndex * LocationSize;
218  return LocationAccessor(P + LocationOffset);
219  }
220 
221  /// Begin iterator for locations.
223  return location_iterator(getLocation(0));
224  }
225 
226  /// End iterator for locations.
228  return location_iterator(getLocation(getNumLocations()));
229  }
230 
231  /// Iterator range for locations.
233  return make_range(location_begin(), location_end());
234  }
235 
236  /// Get the number of liveouts contained in this record.
237  uint16_t getNumLiveOuts() const {
238  return read<uint16_t>(P + getNumLiveOutsOffset());
239  }
240 
241  /// Get the live-out with the given index.
242  LiveOutAccessor getLiveOut(unsigned LiveOutIndex) const {
243  unsigned LiveOutOffset =
244  getNumLiveOutsOffset() + sizeof(uint16_t) + LiveOutIndex * LiveOutSize;
245  return LiveOutAccessor(P + LiveOutOffset);
246  }
247 
248  /// Begin iterator for live-outs.
250  return liveout_iterator(getLiveOut(0));
251  }
252 
253  /// End iterator for live-outs.
255  return liveout_iterator(getLiveOut(getNumLiveOuts()));
256  }
257 
258  /// Iterator range for live-outs.
260  return make_range(liveouts_begin(), liveouts_end());
261  }
262 
263  private:
264  RecordAccessor(const uint8_t *P) : P(P) {}
265 
266  unsigned getNumLiveOutsOffset() const {
267  return LocationListOffset + LocationSize * getNumLocations() +
268  sizeof(uint16_t);
269  }
270 
271  unsigned getSizeInBytes() const {
272  unsigned RecordSize =
273  getNumLiveOutsOffset() + sizeof(uint16_t) + getNumLiveOuts() * LiveOutSize;
274  return (RecordSize + 7) & ~0x7;
275  }
276 
277  RecordAccessor next() const {
278  return RecordAccessor(P + getSizeInBytes());
279  }
280 
281  static const unsigned PatchpointIDOffset = 0;
282  static const unsigned InstructionOffsetOffset =
283  PatchpointIDOffset + sizeof(uint64_t);
284  static const unsigned NumLocationsOffset =
285  InstructionOffsetOffset + sizeof(uint32_t) + sizeof(uint16_t);
286  static const unsigned LocationListOffset =
287  NumLocationsOffset + sizeof(uint16_t);
288  static const unsigned LocationSize = sizeof(uint64_t);
289  static const unsigned LiveOutSize = sizeof(uint32_t);
290 
291  const uint8_t *P;
292  };
293 
294  /// Construct a parser for a version-2 stackmap. StackMap data will be read
295  /// from the given array.
297  : StackMapSection(StackMapSection) {
298  ConstantsListOffset = FunctionListOffset + getNumFunctions() * FunctionSize;
299 
300  assert(StackMapSection[0] == 2 &&
301  "StackMapV2Parser can only parse version 2 stackmaps");
302 
303  unsigned CurrentRecordOffset =
304  ConstantsListOffset + getNumConstants() * ConstantSize;
305 
306  for (unsigned I = 0, E = getNumRecords(); I != E; ++I) {
307  StackMapRecordOffsets.push_back(CurrentRecordOffset);
308  CurrentRecordOffset +=
309  RecordAccessor(&StackMapSection[CurrentRecordOffset]).getSizeInBytes();
310  }
311  }
312 
316 
317  /// Get the version number of this stackmap. (Always returns 2).
318  unsigned getVersion() const { return 2; }
319 
320  /// Get the number of functions in the stack map.
322  return read<uint32_t>(&StackMapSection[NumFunctionsOffset]);
323  }
324 
325  /// Get the number of large constants in the stack map.
327  return read<uint32_t>(&StackMapSection[NumConstantsOffset]);
328  }
329 
330  /// Get the number of stackmap records in the stackmap.
332  return read<uint32_t>(&StackMapSection[NumRecordsOffset]);
333  }
334 
335  /// Return an FunctionAccessor for the given function index.
336  FunctionAccessor getFunction(unsigned FunctionIndex) const {
337  return FunctionAccessor(StackMapSection.data() +
338  getFunctionOffset(FunctionIndex));
339  }
340 
341  /// Begin iterator for functions.
343  return function_iterator(getFunction(0));
344  }
345 
346  /// End iterator for functions.
348  return function_iterator(
349  FunctionAccessor(StackMapSection.data() +
350  getFunctionOffset(getNumFunctions())));
351  }
352 
353  /// Iterator range for functions.
356  }
357 
358  /// Return the large constant at the given index.
359  ConstantAccessor getConstant(unsigned ConstantIndex) const {
360  return ConstantAccessor(StackMapSection.data() +
361  getConstantOffset(ConstantIndex));
362  }
363 
364  /// Begin iterator for constants.
366  return constant_iterator(getConstant(0));
367  }
368 
369  /// End iterator for constants.
371  return constant_iterator(
372  ConstantAccessor(StackMapSection.data() +
373  getConstantOffset(getNumConstants())));
374  }
375 
376  /// Iterator range for constants.
379  }
380 
381  /// Return a RecordAccessor for the given record index.
382  RecordAccessor getRecord(unsigned RecordIndex) const {
383  std::size_t RecordOffset = StackMapRecordOffsets[RecordIndex];
384  return RecordAccessor(StackMapSection.data() + RecordOffset);
385  }
386 
387  /// Begin iterator for records.
389  if (getNumRecords() == 0)
390  return record_iterator(RecordAccessor(nullptr));
391  return record_iterator(getRecord(0));
392  }
393 
394  /// End iterator for records.
396  // Records need to be handled specially, since we cache the start addresses
397  // for them: We can't just compute the 1-past-the-end address, we have to
398  // look at the last record and use the 'next' method.
399  if (getNumRecords() == 0)
400  return record_iterator(RecordAccessor(nullptr));
401  return record_iterator(getRecord(getNumRecords() - 1).next());
402  }
403 
404  /// Iterator range for records.
406  return make_range(records_begin(), records_end());
407  }
408 
409 private:
410  template <typename T>
411  static T read(const uint8_t *P) {
412  return support::endian::read<T, Endianness, 1>(P);
413  }
414 
415  static const unsigned HeaderOffset = 0;
416  static const unsigned NumFunctionsOffset = HeaderOffset + sizeof(uint32_t);
417  static const unsigned NumConstantsOffset = NumFunctionsOffset + sizeof(uint32_t);
418  static const unsigned NumRecordsOffset = NumConstantsOffset + sizeof(uint32_t);
419  static const unsigned FunctionListOffset = NumRecordsOffset + sizeof(uint32_t);
420 
421  static const unsigned FunctionSize = 3 * sizeof(uint64_t);
422  static const unsigned ConstantSize = sizeof(uint64_t);
423 
424  std::size_t getFunctionOffset(unsigned FunctionIndex) const {
425  return FunctionListOffset + FunctionIndex * FunctionSize;
426  }
427 
428  std::size_t getConstantOffset(unsigned ConstantIndex) const {
429  return ConstantsListOffset + ConstantIndex * ConstantSize;
430  }
431 
432  ArrayRef<uint8_t> StackMapSection;
433  unsigned ConstantsListOffset;
434  std::vector<unsigned> StackMapRecordOffsets;
435 };
436 
437 } // end namespace llvm
438 
439 #endif // LLVM_CODEGEN_STACKMAPPARSER_H
uint64_t getRecordCount() const
Get the number of callsite records.
uint16_t getNumLocations() const
Get the number of locations contained in this record.
unsigned getVersion() const
Get the version number of this stackmap. (Always returns 2).
This class represents lattice values for constants.
Definition: AllocatorList.h:24
LiveOutAccessor getLiveOut(unsigned LiveOutIndex) const
Get the live-out with the given index.
liveout_iterator liveouts_end() const
End iterator for live-outs.
bool operator!=(const AccessorIterator &Other)
iterator_range< liveout_iterator > liveouts() const
Iterator range for live-outs.
This provides a very simple, boring adaptor for a begin and end iterator into a range type...
LocationAccessor getLocation(unsigned LocationIndex) const
Get the location with the given index.
liveout_iterator liveouts_begin() const
Begin iterator for live-outs.
uint32_t getConstantIndex() const
Get the constant-index for this location. (Kind must be ConstantIndex).
FunctionAccessor getFunction(unsigned FunctionIndex) const
Return an FunctionAccessor for the given function index.
Accessor for stackmap records.
ConstantAccessor getConstant(unsigned ConstantIndex) const
Return the large constant at the given index.
Accessor for function records.
uint64_t getFunctionAddress() const
Get the function address.
uint16_t getDwarfRegNum() const
Get the Dwarf register number for this live-out.
function_iterator functions_begin() const
Begin iterator for functions.
AccessorIterator< RecordAccessor > record_iterator
constant_iterator constants_end() const
End iterator for constants.
uint64_t getValue() const
Return the value of this constant.
#define P(N)
bool operator==(const AccessorIterator &Other)
Accessor for location records.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This is an important base class in LLVM.
Definition: Constant.h:42
record_iterator records_begin() const
Begin iterator for records.
int32_t getOffset() const
Get the offset for this location. (Kind must be Direct or Indirect).
record_iterator records_end() const
End iterator for records.
AccessorIterator< ConstantAccessor > constant_iterator
uint16_t getDwarfRegNum() const
Get the Dwarf register number for this location.
location_iterator location_end() const
End iterator for locations.
AccessorIterator< FunctionAccessor > function_iterator
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
function_iterator functions_end() const
End iterator for functions.
constant_iterator constants_begin() const
Begin iterator for constants.
A range adaptor for a pair of iterators.
iterator_range< record_iterator > records() const
Iterator range for records.
iterator_range< location_iterator > locations() const
Iterator range for locations.
uint16_t getNumLiveOuts() const
Get the number of liveouts contained in this record.
iterator_range< constant_iterator > constants() const
Iterator range for constants.
uint32_t getNumFunctions() const
Get the number of functions in the stack map.
value_type read(const void *memory, endianness endian)
Read a value of a particular endianness from memory.
Definition: Endian.h:66
#define I(x, y, z)
Definition: MD5.cpp:58
uint32_t getNumRecords() const
Get the number of stackmap records in the stackmap.
RecordAccessor getRecord(unsigned RecordIndex) const
Return a RecordAccessor for the given record index.
uint32_t getSmallConstant() const
Get the small-constant for this location. (Kind must be Constant).
uint64_t getID() const
Get the patchpoint/stackmap ID for this record.
iterator_range< function_iterator > functions() const
Iterator range for functions.
static MemoryLocation getLocation(Instruction *I, AliasAnalysis *AA)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
StackMapV2Parser(ArrayRef< uint8_t > StackMapSection)
Construct a parser for a version-2 stackmap.
LocationKind getKind() const
Get the Kind for this location.
uint32_t getNumConstants() const
Get the number of large constants in the stack map.
uint32_t getInstructionOffset() const
Get the instruction offset (from the start of the containing function) for this record.
location_iterator location_begin() const
Begin iterator for locations.
uint64_t getStackSize() const
Get the function&#39;s stack size.
unsigned getSizeInBytes() const
Get the size in bytes of live [sub]register.
Accessor for stackmap live-out fields.