- //===- StackMapParser.h - StackMap Parsing Support --------------*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_OBJECT_STACKMAPPARSER_H 
- #define LLVM_OBJECT_STACKMAPPARSER_H 
-   
- #include "llvm/ADT/ArrayRef.h" 
- #include "llvm/ADT/iterator_range.h" 
- #include "llvm/Object/ELF.h" 
- #include "llvm/Support/Endian.h" 
- #include <cassert> 
- #include <cstddef> 
- #include <cstdint> 
- #include <vector> 
-   
- namespace llvm { 
-   
- /// A parser for the latest stackmap format.  At the moment, latest=V3. 
- template <support::endianness Endianness> 
- class StackMapParser { 
- public: 
-   template <typename AccessorT> 
-   class AccessorIterator { 
-   public: 
-     AccessorIterator(AccessorT A) : A(A) {} 
-   
-     AccessorIterator& operator++() { A = A.next(); return *this; } 
-     AccessorIterator operator++(int) { 
-       auto tmp = *this; 
-       ++*this; 
-       return tmp; 
-     } 
-   
-     bool operator==(const AccessorIterator &Other) const { 
-       return A.P == Other.A.P; 
-     } 
-   
-     bool operator!=(const AccessorIterator &Other) const { 
-       return !(*this == Other); 
-     } 
-   
-     AccessorT& operator*() { return A; } 
-     AccessorT* operator->() { return &A; } 
-   
-   private: 
-     AccessorT A; 
-   }; 
-   
-   /// Accessor for function records. 
-   class FunctionAccessor { 
-     friend class StackMapParser; 
-   
-   public: 
-     /// Get the function address. 
-     uint64_t getFunctionAddress() const { 
-       return read<uint64_t>(P); 
-     } 
-   
-     /// Get the function's stack size. 
-     uint64_t getStackSize() const { 
-       return read<uint64_t>(P + sizeof(uint64_t)); 
-     } 
-   
-     /// Get the number of callsite records. 
-     uint64_t getRecordCount() const { 
-       return read<uint64_t>(P + (2 * sizeof(uint64_t))); 
-     } 
-   
-   private: 
-     FunctionAccessor(const uint8_t *P) : P(P) {} 
-   
-     const static int FunctionAccessorSize = 3 * sizeof(uint64_t); 
-   
-     FunctionAccessor next() const { 
-       return FunctionAccessor(P + FunctionAccessorSize); 
-     } 
-   
-     const uint8_t *P; 
-   }; 
-   
-   /// Accessor for constants. 
-   class ConstantAccessor { 
-     friend class StackMapParser; 
-   
-   public: 
-     /// Return the value of this constant. 
-     uint64_t getValue() const { return read<uint64_t>(P); } 
-   
-   private: 
-     ConstantAccessor(const uint8_t *P) : P(P) {} 
-   
-     const static int ConstantAccessorSize = sizeof(uint64_t); 
-   
-     ConstantAccessor next() const { 
-       return ConstantAccessor(P + ConstantAccessorSize); 
-     } 
-   
-     const uint8_t *P; 
-   }; 
-   
-   enum class LocationKind : uint8_t { 
-     Register = 1, Direct = 2, Indirect = 3, Constant = 4, ConstantIndex = 5 
-   }; 
-   
-   /// Accessor for location records. 
-   class LocationAccessor { 
-     friend class StackMapParser; 
-     friend class RecordAccessor; 
-   
-   public: 
-     /// Get the Kind for this location. 
-     LocationKind getKind() const { 
-       return LocationKind(P[KindOffset]); 
-     } 
-   
-     /// Get the Size for this location. 
-     unsigned getSizeInBytes() const { 
-         return read<uint16_t>(P + SizeOffset); 
-   
-     } 
-   
-     /// Get the Dwarf register number for this location. 
-     uint16_t getDwarfRegNum() const { 
-       return read<uint16_t>(P + DwarfRegNumOffset); 
-     } 
-   
-     /// Get the small-constant for this location. (Kind must be Constant). 
-     uint32_t getSmallConstant() const { 
-       assert(getKind() == LocationKind::Constant && "Not a small constant."); 
-       return read<uint32_t>(P + SmallConstantOffset); 
-     } 
-   
-     /// Get the constant-index for this location. (Kind must be ConstantIndex). 
-     uint32_t getConstantIndex() const { 
-       assert(getKind() == LocationKind::ConstantIndex && 
-              "Not a constant-index."); 
-       return read<uint32_t>(P + SmallConstantOffset); 
-     } 
-   
-     /// Get the offset for this location. (Kind must be Direct or Indirect). 
-     int32_t getOffset() const { 
-       assert((getKind() == LocationKind::Direct || 
-               getKind() == LocationKind::Indirect) && 
-              "Not direct or indirect."); 
-       return read<int32_t>(P + SmallConstantOffset); 
-     } 
-   
-   private: 
-     LocationAccessor(const uint8_t *P) : P(P) {} 
-   
-     LocationAccessor next() const { 
-       return LocationAccessor(P + LocationAccessorSize); 
-     } 
-   
-     static const int KindOffset = 0; 
-     static const int SizeOffset = KindOffset + sizeof(uint16_t); 
-     static const int DwarfRegNumOffset = SizeOffset + sizeof(uint16_t); 
-     static const int SmallConstantOffset = DwarfRegNumOffset + sizeof(uint32_t); 
-     static const int LocationAccessorSize = sizeof(uint64_t) + sizeof(uint32_t); 
-   
-     const uint8_t *P; 
-   }; 
-   
-   /// Accessor for stackmap live-out fields. 
-   class LiveOutAccessor { 
-     friend class StackMapParser; 
-     friend class RecordAccessor; 
-   
-   public: 
-     /// Get the Dwarf register number for this live-out. 
-     uint16_t getDwarfRegNum() const { 
-       return read<uint16_t>(P + DwarfRegNumOffset); 
-     } 
-   
-     /// Get the size in bytes of live [sub]register. 
-     unsigned getSizeInBytes() const { 
-       return read<uint8_t>(P + SizeOffset); 
-     } 
-   
-   private: 
-     LiveOutAccessor(const uint8_t *P) : P(P) {} 
-   
-     LiveOutAccessor next() const { 
-       return LiveOutAccessor(P + LiveOutAccessorSize); 
-     } 
-   
-     static const int DwarfRegNumOffset = 0; 
-     static const int SizeOffset = 
-       DwarfRegNumOffset + sizeof(uint16_t) + sizeof(uint8_t); 
-     static const int LiveOutAccessorSize = sizeof(uint32_t); 
-   
-     const uint8_t *P; 
-   }; 
-   
-   /// Accessor for stackmap records. 
-   class RecordAccessor { 
-     friend class StackMapParser; 
-   
-   public: 
-     using location_iterator = AccessorIterator<LocationAccessor>; 
-     using liveout_iterator = AccessorIterator<LiveOutAccessor>; 
-   
-     /// Get the patchpoint/stackmap ID for this record. 
-     uint64_t getID() const { 
-       return read<uint64_t>(P + PatchpointIDOffset); 
-     } 
-   
-     /// Get the instruction offset (from the start of the containing function) 
-     /// for this record. 
-     uint32_t getInstructionOffset() const { 
-       return read<uint32_t>(P + InstructionOffsetOffset); 
-     } 
-   
-     /// Get the number of locations contained in this record. 
-     uint16_t getNumLocations() const { 
-       return read<uint16_t>(P + NumLocationsOffset); 
-     } 
-   
-     /// Get the location with the given index. 
-     LocationAccessor getLocation(unsigned LocationIndex) const { 
-       unsigned LocationOffset = 
-         LocationListOffset + LocationIndex * LocationSize; 
-       return LocationAccessor(P + LocationOffset); 
-     } 
-   
-     /// Begin iterator for locations. 
-     location_iterator location_begin() const { 
-       return location_iterator(getLocation(0)); 
-     } 
-   
-     /// End iterator for locations. 
-     location_iterator location_end() const { 
-       return location_iterator(getLocation(getNumLocations())); 
-     } 
-   
-     /// Iterator range for locations. 
-     iterator_range<location_iterator> locations() const { 
-       return make_range(location_begin(), location_end()); 
-     } 
-   
-     /// Get the number of liveouts contained in this record. 
-     uint16_t getNumLiveOuts() const { 
-       return read<uint16_t>(P + getNumLiveOutsOffset()); 
-     } 
-   
-     /// Get the live-out with the given index. 
-     LiveOutAccessor getLiveOut(unsigned LiveOutIndex) const { 
-       unsigned LiveOutOffset = 
-         getNumLiveOutsOffset() + sizeof(uint16_t) + LiveOutIndex * LiveOutSize; 
-       return LiveOutAccessor(P + LiveOutOffset); 
-     } 
-   
-     /// Begin iterator for live-outs. 
-     liveout_iterator liveouts_begin() const { 
-       return liveout_iterator(getLiveOut(0)); 
-     } 
-   
-     /// End iterator for live-outs. 
-     liveout_iterator liveouts_end() const { 
-       return liveout_iterator(getLiveOut(getNumLiveOuts())); 
-     } 
-   
-     /// Iterator range for live-outs. 
-     iterator_range<liveout_iterator> liveouts() const { 
-       return make_range(liveouts_begin(), liveouts_end()); 
-     } 
-   
-   private: 
-     RecordAccessor(const uint8_t *P) : P(P) {} 
-   
-     unsigned getNumLiveOutsOffset() const { 
-       unsigned LocOffset =  
-           ((LocationListOffset + LocationSize * getNumLocations()) + 7) & ~0x7;  
-       return LocOffset + sizeof(uint16_t); 
-     } 
-   
-     unsigned getSizeInBytes() const { 
-       unsigned RecordSize = 
-         getNumLiveOutsOffset() + sizeof(uint16_t) + getNumLiveOuts() * LiveOutSize; 
-       return (RecordSize + 7) & ~0x7; 
-     } 
-   
-     RecordAccessor next() const { 
-       return RecordAccessor(P + getSizeInBytes()); 
-     } 
-   
-     static const unsigned PatchpointIDOffset = 0; 
-     static const unsigned InstructionOffsetOffset = 
-       PatchpointIDOffset + sizeof(uint64_t); 
-     static const unsigned NumLocationsOffset = 
-       InstructionOffsetOffset + sizeof(uint32_t) + sizeof(uint16_t); 
-     static const unsigned LocationListOffset = 
-       NumLocationsOffset + sizeof(uint16_t); 
-     static const unsigned LocationSize = sizeof(uint64_t) + sizeof(uint32_t); 
-     static const unsigned LiveOutSize = sizeof(uint32_t); 
-   
-     const uint8_t *P; 
-   }; 
-   
-   /// Construct a parser for a version-3 stackmap. StackMap data will be read 
-   /// from the given array. 
-   StackMapParser(ArrayRef<uint8_t> StackMapSection) 
-       : StackMapSection(StackMapSection) { 
-     ConstantsListOffset = FunctionListOffset + getNumFunctions() * FunctionSize; 
-   
-     assert(StackMapSection[0] == 3 && 
-            "StackMapParser can only parse version 3 stackmaps"); 
-   
-     unsigned CurrentRecordOffset = 
-       ConstantsListOffset + getNumConstants() * ConstantSize; 
-   
-     for (unsigned I = 0, E = getNumRecords(); I != E; ++I) { 
-       StackMapRecordOffsets.push_back(CurrentRecordOffset); 
-       CurrentRecordOffset += 
-         RecordAccessor(&StackMapSection[CurrentRecordOffset]).getSizeInBytes(); 
-     } 
-   } 
-   
-   /// Validates the header of the specified stack map section. 
-   static Error validateHeader(ArrayRef<uint8_t> StackMapSection) { 
-     // See the comment for StackMaps::emitStackmapHeader(). 
-     if (StackMapSection.size() < 16) 
-       return object::createError( 
-           "the stack map section size (" + Twine(StackMapSection.size()) + 
-           ") is less than the minimum possible size of its header (16)"); 
-   
-     unsigned Version = StackMapSection[0]; 
-     if (Version != 3) 
-       return object::createError( 
-           "the version (" + Twine(Version) + 
-           ") of the stack map section is unsupported, the " 
-           "supported version is 3"); 
-     return Error::success(); 
-   } 
-   
-   using function_iterator = AccessorIterator<FunctionAccessor>; 
-   using constant_iterator = AccessorIterator<ConstantAccessor>; 
-   using record_iterator = AccessorIterator<RecordAccessor>; 
-   
-   /// Get the version number of this stackmap. (Always returns 3). 
-   unsigned getVersion() const { return 3; } 
-   
-   /// Get the number of functions in the stack map. 
-   uint32_t getNumFunctions() const { 
-     return read<uint32_t>(&StackMapSection[NumFunctionsOffset]); 
-   } 
-   
-   /// Get the number of large constants in the stack map. 
-   uint32_t getNumConstants() const { 
-     return read<uint32_t>(&StackMapSection[NumConstantsOffset]); 
-   } 
-   
-   /// Get the number of stackmap records in the stackmap. 
-   uint32_t getNumRecords() const { 
-     return read<uint32_t>(&StackMapSection[NumRecordsOffset]); 
-   } 
-   
-   /// Return an FunctionAccessor for the given function index. 
-   FunctionAccessor getFunction(unsigned FunctionIndex) const { 
-     return FunctionAccessor(StackMapSection.data() + 
-                             getFunctionOffset(FunctionIndex)); 
-   } 
-   
-   /// Begin iterator for functions. 
-   function_iterator functions_begin() const { 
-     return function_iterator(getFunction(0)); 
-   } 
-   
-   /// End iterator for functions. 
-   function_iterator functions_end() const { 
-     return function_iterator( 
-              FunctionAccessor(StackMapSection.data() + 
-                               getFunctionOffset(getNumFunctions()))); 
-   } 
-   
-   /// Iterator range for functions. 
-   iterator_range<function_iterator> functions() const { 
-     return make_range(functions_begin(), functions_end()); 
-   } 
-   
-   /// Return the large constant at the given index. 
-   ConstantAccessor getConstant(unsigned ConstantIndex) const { 
-     return ConstantAccessor(StackMapSection.data() + 
-                             getConstantOffset(ConstantIndex)); 
-   } 
-   
-   /// Begin iterator for constants. 
-   constant_iterator constants_begin() const { 
-     return constant_iterator(getConstant(0)); 
-   } 
-   
-   /// End iterator for constants. 
-   constant_iterator constants_end() const { 
-     return constant_iterator( 
-              ConstantAccessor(StackMapSection.data() + 
-                               getConstantOffset(getNumConstants()))); 
-   } 
-   
-   /// Iterator range for constants. 
-   iterator_range<constant_iterator> constants() const { 
-     return make_range(constants_begin(), constants_end()); 
-   } 
-   
-   /// Return a RecordAccessor for the given record index. 
-   RecordAccessor getRecord(unsigned RecordIndex) const { 
-     std::size_t RecordOffset = StackMapRecordOffsets[RecordIndex]; 
-     return RecordAccessor(StackMapSection.data() + RecordOffset); 
-   } 
-   
-   /// Begin iterator for records. 
-   record_iterator records_begin() const { 
-     if (getNumRecords() == 0) 
-       return record_iterator(RecordAccessor(nullptr)); 
-     return record_iterator(getRecord(0)); 
-   } 
-   
-   /// End iterator for records. 
-   record_iterator records_end() const { 
-     // Records need to be handled specially, since we cache the start addresses 
-     // for them: We can't just compute the 1-past-the-end address, we have to 
-     // look at the last record and use the 'next' method. 
-     if (getNumRecords() == 0) 
-       return record_iterator(RecordAccessor(nullptr)); 
-     return record_iterator(getRecord(getNumRecords() - 1).next()); 
-   } 
-   
-   /// Iterator range for records. 
-   iterator_range<record_iterator> records() const { 
-     return make_range(records_begin(), records_end()); 
-   } 
-   
- private: 
-   template <typename T> 
-   static T read(const uint8_t *P) { 
-     return support::endian::read<T, Endianness, 1>(P); 
-   } 
-   
-   static const unsigned HeaderOffset = 0; 
-   static const unsigned NumFunctionsOffset = HeaderOffset + sizeof(uint32_t); 
-   static const unsigned NumConstantsOffset = NumFunctionsOffset + sizeof(uint32_t); 
-   static const unsigned NumRecordsOffset = NumConstantsOffset + sizeof(uint32_t); 
-   static const unsigned FunctionListOffset = NumRecordsOffset + sizeof(uint32_t); 
-   
-   static const unsigned FunctionSize = 3 * sizeof(uint64_t); 
-   static const unsigned ConstantSize = sizeof(uint64_t); 
-   
-   std::size_t getFunctionOffset(unsigned FunctionIndex) const { 
-     return FunctionListOffset + FunctionIndex * FunctionSize; 
-   } 
-   
-   std::size_t getConstantOffset(unsigned ConstantIndex) const { 
-     return ConstantsListOffset + ConstantIndex * ConstantSize; 
-   } 
-   
-   ArrayRef<uint8_t> StackMapSection; 
-   unsigned ConstantsListOffset; 
-   std::vector<unsigned> StackMapRecordOffsets; 
- }; 
-   
- } // end namespace llvm 
-   
- #endif // LLVM_OBJECT_STACKMAPPARSER_H 
-