LLVM  3.7.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/Support/Debug.h"
14 #include "llvm/Support/Endian.h"
15 #include <map>
16 #include <vector>
17 
18 namespace llvm {
19 
20 template <support::endianness Endianness>
22 public:
23 
24  template <typename AccessorT>
26  public:
27 
28  AccessorIterator(AccessorT A) : A(A) {}
29  AccessorIterator& operator++() { A = A.next(); return *this; }
31  auto tmp = *this;
32  ++*this;
33  return tmp;
34  }
35 
37  return A.P == Other.A.P;
38  }
39 
40  bool operator!=(const AccessorIterator &Other) { return !(*this == Other); }
41 
42  AccessorT& operator*() { return A; }
43  AccessorT* operator->() { return &A; }
44 
45  private:
46  AccessorT A;
47  };
48 
49  /// Accessor for function records.
51  friend class StackMapV1Parser;
52  public:
53 
54  /// Get the function address.
55  uint64_t getFunctionAddress() const {
56  return read<uint64_t>(P);
57  }
58 
59  /// Get the function's stack size.
60  uint32_t getStackSize() const {
61  return read<uint64_t>(P + sizeof(uint64_t));
62  }
63 
64  private:
65  FunctionAccessor(const uint8_t *P) : P(P) {}
66 
67  const static int FunctionAccessorSize = 2 * sizeof(uint64_t);
68 
69  FunctionAccessor next() const {
70  return FunctionAccessor(P + FunctionAccessorSize);
71  }
72 
73  const uint8_t *P;
74  };
75 
76  /// Accessor for constants.
78  friend class StackMapV1Parser;
79  public:
80 
81  /// Return the value of this constant.
82  uint64_t getValue() const { return read<uint64_t>(P); }
83 
84  private:
85 
86  ConstantAccessor(const uint8_t *P) : P(P) {}
87 
88  const static int ConstantAccessorSize = sizeof(uint64_t);
89 
90  ConstantAccessor next() const {
91  return ConstantAccessor(P + ConstantAccessorSize);
92  }
93 
94  const uint8_t *P;
95  };
96 
97  // Forward-declare RecordAccessor so we can friend it below.
98  class RecordAccessor;
99 
100  enum class LocationKind : uint8_t {
101  Register = 1, Direct = 2, Indirect = 3, Constant = 4, ConstantIndex = 5
102  };
103 
104 
105  /// Accessor for location records.
107  friend class StackMapV1Parser;
108  friend class RecordAccessor;
109  public:
110 
111  /// Get the Kind for this location.
113  return LocationKind(P[KindOffset]);
114  }
115 
116  /// Get the Dwarf register number for this location.
117  uint16_t getDwarfRegNum() const {
118  return read<uint16_t>(P + DwarfRegNumOffset);
119  }
120 
121  /// Get the small-constant for this location. (Kind must be Constant).
122  uint32_t getSmallConstant() const {
123  assert(getKind() == LocationKind::Constant && "Not a small constant.");
124  return read<uint32_t>(P + SmallConstantOffset);
125  }
126 
127  /// Get the constant-index for this location. (Kind must be ConstantIndex).
128  uint32_t getConstantIndex() const {
129  assert(getKind() == LocationKind::ConstantIndex &&
130  "Not a constant-index.");
131  return read<uint32_t>(P + SmallConstantOffset);
132  }
133 
134  /// Get the offset for this location. (Kind must be Direct or Indirect).
135  int32_t getOffset() const {
136  assert((getKind() == LocationKind::Direct ||
138  "Not direct or indirect.");
139  return read<int32_t>(P + SmallConstantOffset);
140  }
141 
142  private:
143 
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 StackMapV1Parser;
161  friend class RecordAccessor;
162  public:
163 
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 
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 StackMapV1Parser;
193  public:
194 
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.
205  uint32_t getInstructionOffset() const {
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.
229  }
230 
231  /// Iterator range for locations.
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 
254  /// End iterator for live-outs.
257  }
258 
259  /// Iterator range for live-outs.
262  }
263 
264  private:
265 
266  RecordAccessor(const uint8_t *P) : P(P) {}
267 
268  unsigned getNumLiveOutsOffset() const {
269  return LocationListOffset + LocationSize * getNumLocations() +
270  sizeof(uint16_t);
271  }
272 
273  unsigned getSizeInBytes() const {
274  unsigned RecordSize =
275  getNumLiveOutsOffset() + sizeof(uint16_t) + getNumLiveOuts() * LiveOutSize;
276  return (RecordSize + 7) & ~0x7;
277  }
278 
279  RecordAccessor next() const {
280  return RecordAccessor(P + getSizeInBytes());
281  }
282 
283  static const unsigned PatchpointIDOffset = 0;
284  static const unsigned InstructionOffsetOffset =
285  PatchpointIDOffset + sizeof(uint64_t);
286  static const unsigned NumLocationsOffset =
287  InstructionOffsetOffset + sizeof(uint32_t) + sizeof(uint16_t);
288  static const unsigned LocationListOffset =
289  NumLocationsOffset + sizeof(uint16_t);
290  static const unsigned LocationSize = sizeof(uint64_t);
291  static const unsigned LiveOutSize = sizeof(uint32_t);
292 
293  const uint8_t *P;
294  };
295 
296  /// Construct a parser for a version-1 stackmap. StackMap data will be read
297  /// from the given array.
299  : StackMapSection(StackMapSection) {
300  ConstantsListOffset = FunctionListOffset + getNumFunctions() * FunctionSize;
301 
302  assert(StackMapSection[0] == 1 &&
303  "StackMapV1Parser can only parse version 1 stackmaps");
304 
305  unsigned CurrentRecordOffset =
306  ConstantsListOffset + getNumConstants() * ConstantSize;
307 
308  for (unsigned I = 0, E = getNumRecords(); I != E; ++I) {
309  StackMapRecordOffsets.push_back(CurrentRecordOffset);
310  CurrentRecordOffset +=
311  RecordAccessor(&StackMapSection[CurrentRecordOffset]).getSizeInBytes();
312  }
313  }
314 
318 
319  /// Get the version number of this stackmap. (Always returns 1).
320  unsigned getVersion() const { return 1; }
321 
322  /// Get the number of functions in the stack map.
323  uint32_t getNumFunctions() const {
324  return read<uint32_t>(&StackMapSection[NumFunctionsOffset]);
325  }
326 
327  /// Get the number of large constants in the stack map.
328  uint32_t getNumConstants() const {
329  return read<uint32_t>(&StackMapSection[NumConstantsOffset]);
330  }
331 
332  /// Get the number of stackmap records in the stackmap.
333  uint32_t getNumRecords() const {
334  return read<uint32_t>(&StackMapSection[NumRecordsOffset]);
335  }
336 
337  /// Return an FunctionAccessor for the given function index.
338  FunctionAccessor getFunction(unsigned FunctionIndex) const {
339  return FunctionAccessor(StackMapSection.data() +
340  getFunctionOffset(FunctionIndex));
341  }
342 
343  /// Begin iterator for functions.
345  return function_iterator(getFunction(0));
346  }
347 
348  /// End iterator for functions.
350  return function_iterator(
351  FunctionAccessor(StackMapSection.data() +
352  getFunctionOffset(getNumFunctions())));
353  }
354 
355  /// Iterator range for functions.
358  }
359 
360  /// Return the large constant at the given index.
361  ConstantAccessor getConstant(unsigned ConstantIndex) const {
362  return ConstantAccessor(StackMapSection.data() +
363  getConstantOffset(ConstantIndex));
364  }
365 
366  /// Begin iterator for constants.
368  return constant_iterator(getConstant(0));
369  }
370 
371  /// End iterator for constants.
373  return constant_iterator(
374  ConstantAccessor(StackMapSection.data() +
375  getConstantOffset(getNumConstants())));
376  }
377 
378  /// Iterator range for constants.
381  }
382 
383  /// Return a RecordAccessor for the given record index.
384  RecordAccessor getRecord(unsigned RecordIndex) const {
385  std::size_t RecordOffset = StackMapRecordOffsets[RecordIndex];
386  return RecordAccessor(StackMapSection.data() + RecordOffset);
387  }
388 
389  /// Begin iterator for records.
391  if (getNumRecords() == 0)
392  return record_iterator(RecordAccessor(nullptr));
393  return record_iterator(getRecord(0));
394  }
395 
396  /// End iterator for records.
398  // Records need to be handled specially, since we cache the start addresses
399  // for them: We can't just compute the 1-past-the-end address, we have to
400  // look at the last record and use the 'next' method.
401  if (getNumRecords() == 0)
402  return record_iterator(RecordAccessor(nullptr));
403  return record_iterator(getRecord(getNumRecords() - 1).next());
404  }
405 
406  /// Iterator range for records.
408  return make_range(records_begin(), records_end());
409  }
410 
411 private:
412 
413  template <typename T>
414  static T read(const uint8_t *P) {
415  return support::endian::read<T, Endianness, 1>(P);
416  }
417 
418  static const unsigned HeaderOffset = 0;
419  static const unsigned NumFunctionsOffset = HeaderOffset + sizeof(uint32_t);
420  static const unsigned NumConstantsOffset = NumFunctionsOffset + sizeof(uint32_t);
421  static const unsigned NumRecordsOffset = NumConstantsOffset + sizeof(uint32_t);
422  static const unsigned FunctionListOffset = NumRecordsOffset + sizeof(uint32_t);
423 
424  static const unsigned FunctionSize = 2 * sizeof(uint64_t);
425  static const unsigned ConstantSize = sizeof(uint64_t);
426 
427  std::size_t getFunctionOffset(unsigned FunctionIndex) const {
428  return FunctionListOffset + FunctionIndex * FunctionSize;
429  }
430 
431  std::size_t getConstantOffset(unsigned ConstantIndex) const {
432  return ConstantsListOffset + ConstantIndex * ConstantSize;
433  }
434 
435  ArrayRef<uint8_t> StackMapSection;
436  unsigned ConstantsListOffset;
437  std::vector<unsigned> StackMapRecordOffsets;
438 };
439 
440 }
441 
442 #endif
LocationAccessor getLocation(unsigned LocationIndex) const
Get the location with the given index.
AccessorIterator< LiveOutAccessor > liveout_iterator
LiveOutAccessor getLiveOut(unsigned LiveOutIndex) const
Get the live-out with the given index.
value_type read(const void *memory)
Read a value of a particular endianness from memory.
Definition: Endian.h:49
record_iterator records_begin() const
Begin iterator for records.
StackMapV1Parser(ArrayRef< uint8_t > StackMapSection)
Construct a parser for a version-1 stackmap.
liveout_iterator liveouts_end() const
End iterator for live-outs.
constant_iterator constants_end() const
End iterator for constants.
uint32_t getInstructionOffset() const
Get the instruction offset (from the start of the containing function) for this record.
function_iterator functions_end() const
End iterator for functions.
unsigned getVersion() const
Get the version number of this stackmap. (Always returns 1).
iterator_range< location_iterator > locations() const
Iterator range for locations.
FunctionAccessor getFunction(unsigned FunctionIndex) const
Return an FunctionAccessor for the given function index.
Accessor for function records.
iterator_range< liveout_iterator > liveouts() const
Iterator range for live-outs.
ELFYAML::ELF_STO Other
Definition: ELFYAML.cpp:591
location_iterator location_end() const
End iterator for locations.
uint64_t getID() const
Get the patchpoint/stackmap ID for this record.
function_iterator functions_begin() const
Begin iterator for functions.
liveout_iterator liveouts_begin() const
Begin iterator for live-outs.
uint32_t getNumConstants() const
Get the number of large constants in the stack map.
uint16_t getDwarfRegNum() const
Get the Dwarf register number for this location.
uint32_t getNumFunctions() const
Get the number of functions in the stack map.
AccessorIterator< RecordAccessor > record_iterator
AccessorIterator< ConstantAccessor > constant_iterator
#define P(N)
Accessor for location records.
RecordAccessor getRecord(unsigned RecordIndex) const
Return a RecordAccessor for the given record index.
uint16_t getDwarfRegNum() const
Get the Dwarf register number for this live-out.
This is an important base class in LLVM.
Definition: Constant.h:41
record_iterator records_end() const
End iterator for records.
bool operator==(const AccessorIterator &Other)
Accessor for stackmap records.
unsigned getSizeInBytes() const
Get the size in bytes of live [sub]register.
int32_t getOffset() const
Get the offset for this location. (Kind must be Direct or Indirect).
iterator_range< record_iterator > records() const
Iterator range for records.
uint32_t getConstantIndex() const
Get the constant-index for this location. (Kind must be ConstantIndex).
uint32_t getNumRecords() const
Get the number of stackmap records in the stackmap.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
Accessor for stackmap live-out fields.
uint64_t getFunctionAddress() const
Get the function address.
iterator_range< constant_iterator > constants() const
Iterator range for constants.
AccessorIterator< LocationAccessor > location_iterator
A range adaptor for a pair of iterators.
uint32_t getSmallConstant() const
Get the small-constant for this location. (Kind must be Constant).
location_iterator location_begin() const
Begin iterator for locations.
bool operator!=(const AccessorIterator &Other)
AccessorIterator< FunctionAccessor > function_iterator
uint16_t getNumLocations() const
Get the number of locations contained in this record.
#define I(x, y, z)
Definition: MD5.cpp:54
constant_iterator constants_begin() const
Begin iterator for constants.
uint64_t getValue() const
Return the value of this constant.
ConstantAccessor getConstant(unsigned ConstantIndex) const
Return the large constant at the given index.
uint16_t getNumLiveOuts() const
Get the number of liveouts contained in this record.
uint32_t getStackSize() const
Get the function's stack size.
iterator_range< function_iterator > functions() const
Iterator range for functions.
const T * data() const
Definition: ArrayRef.h:131
LocationKind getKind() const
Get the Kind for this location.