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