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