17330f729Sjoerg //===- StackMapParser.h - StackMap Parsing Support --------------*- C++ -*-===// 27330f729Sjoerg // 37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information. 57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 67330f729Sjoerg // 77330f729Sjoerg //===----------------------------------------------------------------------===// 87330f729Sjoerg 9*82d56013Sjoerg #ifndef LLVM_OBJECT_STACKMAPPARSER_H 10*82d56013Sjoerg #define LLVM_OBJECT_STACKMAPPARSER_H 117330f729Sjoerg 127330f729Sjoerg #include "llvm/ADT/ArrayRef.h" 137330f729Sjoerg #include "llvm/ADT/iterator_range.h" 14*82d56013Sjoerg #include "llvm/Object/ELF.h" 157330f729Sjoerg #include "llvm/Support/Endian.h" 167330f729Sjoerg #include <cassert> 177330f729Sjoerg #include <cstddef> 187330f729Sjoerg #include <cstdint> 197330f729Sjoerg #include <vector> 207330f729Sjoerg 217330f729Sjoerg namespace llvm { 227330f729Sjoerg 237330f729Sjoerg /// A parser for the latest stackmap format. At the moment, latest=V3. 247330f729Sjoerg template <support::endianness Endianness> 257330f729Sjoerg class StackMapParser { 267330f729Sjoerg public: 277330f729Sjoerg template <typename AccessorT> 287330f729Sjoerg class AccessorIterator { 297330f729Sjoerg public: AccessorIterator(AccessorT A)307330f729Sjoerg AccessorIterator(AccessorT A) : A(A) {} 317330f729Sjoerg 327330f729Sjoerg AccessorIterator& operator++() { A = A.next(); return *this; } 337330f729Sjoerg AccessorIterator operator++(int) { 347330f729Sjoerg auto tmp = *this; 357330f729Sjoerg ++*this; 367330f729Sjoerg return tmp; 377330f729Sjoerg } 387330f729Sjoerg 39*82d56013Sjoerg bool operator==(const AccessorIterator &Other) const { 407330f729Sjoerg return A.P == Other.A.P; 417330f729Sjoerg } 427330f729Sjoerg 43*82d56013Sjoerg bool operator!=(const AccessorIterator &Other) const { 44*82d56013Sjoerg return !(*this == Other); 45*82d56013Sjoerg } 467330f729Sjoerg 477330f729Sjoerg AccessorT& operator*() { return A; } 487330f729Sjoerg AccessorT* operator->() { return &A; } 497330f729Sjoerg 507330f729Sjoerg private: 517330f729Sjoerg AccessorT A; 527330f729Sjoerg }; 537330f729Sjoerg 547330f729Sjoerg /// Accessor for function records. 557330f729Sjoerg class FunctionAccessor { 567330f729Sjoerg friend class StackMapParser; 577330f729Sjoerg 587330f729Sjoerg public: 597330f729Sjoerg /// Get the function address. getFunctionAddress()607330f729Sjoerg uint64_t getFunctionAddress() const { 617330f729Sjoerg return read<uint64_t>(P); 627330f729Sjoerg } 637330f729Sjoerg 647330f729Sjoerg /// Get the function's stack size. getStackSize()657330f729Sjoerg uint64_t getStackSize() const { 667330f729Sjoerg return read<uint64_t>(P + sizeof(uint64_t)); 677330f729Sjoerg } 687330f729Sjoerg 697330f729Sjoerg /// Get the number of callsite records. getRecordCount()707330f729Sjoerg uint64_t getRecordCount() const { 717330f729Sjoerg return read<uint64_t>(P + (2 * sizeof(uint64_t))); 727330f729Sjoerg } 737330f729Sjoerg 747330f729Sjoerg private: FunctionAccessor(const uint8_t * P)757330f729Sjoerg FunctionAccessor(const uint8_t *P) : P(P) {} 767330f729Sjoerg 777330f729Sjoerg const static int FunctionAccessorSize = 3 * sizeof(uint64_t); 787330f729Sjoerg next()797330f729Sjoerg FunctionAccessor next() const { 807330f729Sjoerg return FunctionAccessor(P + FunctionAccessorSize); 817330f729Sjoerg } 827330f729Sjoerg 837330f729Sjoerg const uint8_t *P; 847330f729Sjoerg }; 857330f729Sjoerg 867330f729Sjoerg /// Accessor for constants. 877330f729Sjoerg class ConstantAccessor { 887330f729Sjoerg friend class StackMapParser; 897330f729Sjoerg 907330f729Sjoerg public: 917330f729Sjoerg /// Return the value of this constant. getValue()927330f729Sjoerg uint64_t getValue() const { return read<uint64_t>(P); } 937330f729Sjoerg 947330f729Sjoerg private: ConstantAccessor(const uint8_t * P)957330f729Sjoerg ConstantAccessor(const uint8_t *P) : P(P) {} 967330f729Sjoerg 977330f729Sjoerg const static int ConstantAccessorSize = sizeof(uint64_t); 987330f729Sjoerg next()997330f729Sjoerg ConstantAccessor next() const { 1007330f729Sjoerg return ConstantAccessor(P + ConstantAccessorSize); 1017330f729Sjoerg } 1027330f729Sjoerg 1037330f729Sjoerg const uint8_t *P; 1047330f729Sjoerg }; 1057330f729Sjoerg 1067330f729Sjoerg enum class LocationKind : uint8_t { 1077330f729Sjoerg Register = 1, Direct = 2, Indirect = 3, Constant = 4, ConstantIndex = 5 1087330f729Sjoerg }; 1097330f729Sjoerg 1107330f729Sjoerg /// Accessor for location records. 1117330f729Sjoerg class LocationAccessor { 1127330f729Sjoerg friend class StackMapParser; 1137330f729Sjoerg friend class RecordAccessor; 1147330f729Sjoerg 1157330f729Sjoerg public: 1167330f729Sjoerg /// Get the Kind for this location. getKind()1177330f729Sjoerg LocationKind getKind() const { 1187330f729Sjoerg return LocationKind(P[KindOffset]); 1197330f729Sjoerg } 1207330f729Sjoerg 1217330f729Sjoerg /// Get the Size for this location. getSizeInBytes()1227330f729Sjoerg unsigned getSizeInBytes() const { 1237330f729Sjoerg return read<uint16_t>(P + SizeOffset); 1247330f729Sjoerg 1257330f729Sjoerg } 1267330f729Sjoerg 1277330f729Sjoerg /// Get the Dwarf register number for this location. getDwarfRegNum()1287330f729Sjoerg uint16_t getDwarfRegNum() const { 1297330f729Sjoerg return read<uint16_t>(P + DwarfRegNumOffset); 1307330f729Sjoerg } 1317330f729Sjoerg 1327330f729Sjoerg /// Get the small-constant for this location. (Kind must be Constant). getSmallConstant()1337330f729Sjoerg uint32_t getSmallConstant() const { 1347330f729Sjoerg assert(getKind() == LocationKind::Constant && "Not a small constant."); 1357330f729Sjoerg return read<uint32_t>(P + SmallConstantOffset); 1367330f729Sjoerg } 1377330f729Sjoerg 1387330f729Sjoerg /// Get the constant-index for this location. (Kind must be ConstantIndex). getConstantIndex()1397330f729Sjoerg uint32_t getConstantIndex() const { 1407330f729Sjoerg assert(getKind() == LocationKind::ConstantIndex && 1417330f729Sjoerg "Not a constant-index."); 1427330f729Sjoerg return read<uint32_t>(P + SmallConstantOffset); 1437330f729Sjoerg } 1447330f729Sjoerg 1457330f729Sjoerg /// Get the offset for this location. (Kind must be Direct or Indirect). getOffset()1467330f729Sjoerg int32_t getOffset() const { 1477330f729Sjoerg assert((getKind() == LocationKind::Direct || 1487330f729Sjoerg getKind() == LocationKind::Indirect) && 1497330f729Sjoerg "Not direct or indirect."); 1507330f729Sjoerg return read<int32_t>(P + SmallConstantOffset); 1517330f729Sjoerg } 1527330f729Sjoerg 1537330f729Sjoerg private: LocationAccessor(const uint8_t * P)1547330f729Sjoerg LocationAccessor(const uint8_t *P) : P(P) {} 1557330f729Sjoerg next()1567330f729Sjoerg LocationAccessor next() const { 1577330f729Sjoerg return LocationAccessor(P + LocationAccessorSize); 1587330f729Sjoerg } 1597330f729Sjoerg 1607330f729Sjoerg static const int KindOffset = 0; 1617330f729Sjoerg static const int SizeOffset = KindOffset + sizeof(uint16_t); 1627330f729Sjoerg static const int DwarfRegNumOffset = SizeOffset + sizeof(uint16_t); 1637330f729Sjoerg static const int SmallConstantOffset = DwarfRegNumOffset + sizeof(uint32_t); 1647330f729Sjoerg static const int LocationAccessorSize = sizeof(uint64_t) + sizeof(uint32_t); 1657330f729Sjoerg 1667330f729Sjoerg const uint8_t *P; 1677330f729Sjoerg }; 1687330f729Sjoerg 1697330f729Sjoerg /// Accessor for stackmap live-out fields. 1707330f729Sjoerg class LiveOutAccessor { 1717330f729Sjoerg friend class StackMapParser; 1727330f729Sjoerg friend class RecordAccessor; 1737330f729Sjoerg 1747330f729Sjoerg public: 1757330f729Sjoerg /// Get the Dwarf register number for this live-out. getDwarfRegNum()1767330f729Sjoerg uint16_t getDwarfRegNum() const { 1777330f729Sjoerg return read<uint16_t>(P + DwarfRegNumOffset); 1787330f729Sjoerg } 1797330f729Sjoerg 1807330f729Sjoerg /// Get the size in bytes of live [sub]register. getSizeInBytes()1817330f729Sjoerg unsigned getSizeInBytes() const { 1827330f729Sjoerg return read<uint8_t>(P + SizeOffset); 1837330f729Sjoerg } 1847330f729Sjoerg 1857330f729Sjoerg private: LiveOutAccessor(const uint8_t * P)1867330f729Sjoerg LiveOutAccessor(const uint8_t *P) : P(P) {} 1877330f729Sjoerg next()1887330f729Sjoerg LiveOutAccessor next() const { 1897330f729Sjoerg return LiveOutAccessor(P + LiveOutAccessorSize); 1907330f729Sjoerg } 1917330f729Sjoerg 1927330f729Sjoerg static const int DwarfRegNumOffset = 0; 1937330f729Sjoerg static const int SizeOffset = 1947330f729Sjoerg DwarfRegNumOffset + sizeof(uint16_t) + sizeof(uint8_t); 1957330f729Sjoerg static const int LiveOutAccessorSize = sizeof(uint32_t); 1967330f729Sjoerg 1977330f729Sjoerg const uint8_t *P; 1987330f729Sjoerg }; 1997330f729Sjoerg 2007330f729Sjoerg /// Accessor for stackmap records. 2017330f729Sjoerg class RecordAccessor { 2027330f729Sjoerg friend class StackMapParser; 2037330f729Sjoerg 2047330f729Sjoerg public: 2057330f729Sjoerg using location_iterator = AccessorIterator<LocationAccessor>; 2067330f729Sjoerg using liveout_iterator = AccessorIterator<LiveOutAccessor>; 2077330f729Sjoerg 2087330f729Sjoerg /// Get the patchpoint/stackmap ID for this record. getID()2097330f729Sjoerg uint64_t getID() const { 2107330f729Sjoerg return read<uint64_t>(P + PatchpointIDOffset); 2117330f729Sjoerg } 2127330f729Sjoerg 2137330f729Sjoerg /// Get the instruction offset (from the start of the containing function) 2147330f729Sjoerg /// for this record. getInstructionOffset()2157330f729Sjoerg uint32_t getInstructionOffset() const { 2167330f729Sjoerg return read<uint32_t>(P + InstructionOffsetOffset); 2177330f729Sjoerg } 2187330f729Sjoerg 2197330f729Sjoerg /// Get the number of locations contained in this record. getNumLocations()2207330f729Sjoerg uint16_t getNumLocations() const { 2217330f729Sjoerg return read<uint16_t>(P + NumLocationsOffset); 2227330f729Sjoerg } 2237330f729Sjoerg 2247330f729Sjoerg /// Get the location with the given index. getLocation(unsigned LocationIndex)2257330f729Sjoerg LocationAccessor getLocation(unsigned LocationIndex) const { 2267330f729Sjoerg unsigned LocationOffset = 2277330f729Sjoerg LocationListOffset + LocationIndex * LocationSize; 2287330f729Sjoerg return LocationAccessor(P + LocationOffset); 2297330f729Sjoerg } 2307330f729Sjoerg 2317330f729Sjoerg /// Begin iterator for locations. location_begin()2327330f729Sjoerg location_iterator location_begin() const { 2337330f729Sjoerg return location_iterator(getLocation(0)); 2347330f729Sjoerg } 2357330f729Sjoerg 2367330f729Sjoerg /// End iterator for locations. location_end()2377330f729Sjoerg location_iterator location_end() const { 2387330f729Sjoerg return location_iterator(getLocation(getNumLocations())); 2397330f729Sjoerg } 2407330f729Sjoerg 2417330f729Sjoerg /// Iterator range for locations. locations()2427330f729Sjoerg iterator_range<location_iterator> locations() const { 2437330f729Sjoerg return make_range(location_begin(), location_end()); 2447330f729Sjoerg } 2457330f729Sjoerg 2467330f729Sjoerg /// Get the number of liveouts contained in this record. getNumLiveOuts()2477330f729Sjoerg uint16_t getNumLiveOuts() const { 2487330f729Sjoerg return read<uint16_t>(P + getNumLiveOutsOffset()); 2497330f729Sjoerg } 2507330f729Sjoerg 2517330f729Sjoerg /// Get the live-out with the given index. getLiveOut(unsigned LiveOutIndex)2527330f729Sjoerg LiveOutAccessor getLiveOut(unsigned LiveOutIndex) const { 2537330f729Sjoerg unsigned LiveOutOffset = 2547330f729Sjoerg getNumLiveOutsOffset() + sizeof(uint16_t) + LiveOutIndex * LiveOutSize; 2557330f729Sjoerg return LiveOutAccessor(P + LiveOutOffset); 2567330f729Sjoerg } 2577330f729Sjoerg 2587330f729Sjoerg /// Begin iterator for live-outs. liveouts_begin()2597330f729Sjoerg liveout_iterator liveouts_begin() const { 2607330f729Sjoerg return liveout_iterator(getLiveOut(0)); 2617330f729Sjoerg } 2627330f729Sjoerg 2637330f729Sjoerg /// End iterator for live-outs. liveouts_end()2647330f729Sjoerg liveout_iterator liveouts_end() const { 2657330f729Sjoerg return liveout_iterator(getLiveOut(getNumLiveOuts())); 2667330f729Sjoerg } 2677330f729Sjoerg 2687330f729Sjoerg /// Iterator range for live-outs. liveouts()2697330f729Sjoerg iterator_range<liveout_iterator> liveouts() const { 2707330f729Sjoerg return make_range(liveouts_begin(), liveouts_end()); 2717330f729Sjoerg } 2727330f729Sjoerg 2737330f729Sjoerg private: RecordAccessor(const uint8_t * P)2747330f729Sjoerg RecordAccessor(const uint8_t *P) : P(P) {} 2757330f729Sjoerg getNumLiveOutsOffset()2767330f729Sjoerg unsigned getNumLiveOutsOffset() const { 2777330f729Sjoerg unsigned LocOffset = 2787330f729Sjoerg ((LocationListOffset + LocationSize * getNumLocations()) + 7) & ~0x7; 2797330f729Sjoerg return LocOffset + sizeof(uint16_t); 2807330f729Sjoerg } 2817330f729Sjoerg getSizeInBytes()2827330f729Sjoerg unsigned getSizeInBytes() const { 2837330f729Sjoerg unsigned RecordSize = 2847330f729Sjoerg getNumLiveOutsOffset() + sizeof(uint16_t) + getNumLiveOuts() * LiveOutSize; 2857330f729Sjoerg return (RecordSize + 7) & ~0x7; 2867330f729Sjoerg } 2877330f729Sjoerg next()2887330f729Sjoerg RecordAccessor next() const { 2897330f729Sjoerg return RecordAccessor(P + getSizeInBytes()); 2907330f729Sjoerg } 2917330f729Sjoerg 2927330f729Sjoerg static const unsigned PatchpointIDOffset = 0; 2937330f729Sjoerg static const unsigned InstructionOffsetOffset = 2947330f729Sjoerg PatchpointIDOffset + sizeof(uint64_t); 2957330f729Sjoerg static const unsigned NumLocationsOffset = 2967330f729Sjoerg InstructionOffsetOffset + sizeof(uint32_t) + sizeof(uint16_t); 2977330f729Sjoerg static const unsigned LocationListOffset = 2987330f729Sjoerg NumLocationsOffset + sizeof(uint16_t); 2997330f729Sjoerg static const unsigned LocationSize = sizeof(uint64_t) + sizeof(uint32_t); 3007330f729Sjoerg static const unsigned LiveOutSize = sizeof(uint32_t); 3017330f729Sjoerg 3027330f729Sjoerg const uint8_t *P; 3037330f729Sjoerg }; 3047330f729Sjoerg 3057330f729Sjoerg /// Construct a parser for a version-3 stackmap. StackMap data will be read 3067330f729Sjoerg /// from the given array. StackMapParser(ArrayRef<uint8_t> StackMapSection)3077330f729Sjoerg StackMapParser(ArrayRef<uint8_t> StackMapSection) 3087330f729Sjoerg : StackMapSection(StackMapSection) { 3097330f729Sjoerg ConstantsListOffset = FunctionListOffset + getNumFunctions() * FunctionSize; 3107330f729Sjoerg 3117330f729Sjoerg assert(StackMapSection[0] == 3 && 3127330f729Sjoerg "StackMapParser can only parse version 3 stackmaps"); 3137330f729Sjoerg 3147330f729Sjoerg unsigned CurrentRecordOffset = 3157330f729Sjoerg ConstantsListOffset + getNumConstants() * ConstantSize; 3167330f729Sjoerg 3177330f729Sjoerg for (unsigned I = 0, E = getNumRecords(); I != E; ++I) { 3187330f729Sjoerg StackMapRecordOffsets.push_back(CurrentRecordOffset); 3197330f729Sjoerg CurrentRecordOffset += 3207330f729Sjoerg RecordAccessor(&StackMapSection[CurrentRecordOffset]).getSizeInBytes(); 3217330f729Sjoerg } 3227330f729Sjoerg } 3237330f729Sjoerg 324*82d56013Sjoerg /// Validates the header of the specified stack map section. validateHeader(ArrayRef<uint8_t> StackMapSection)325*82d56013Sjoerg static Error validateHeader(ArrayRef<uint8_t> StackMapSection) { 326*82d56013Sjoerg // See the comment for StackMaps::emitStackmapHeader(). 327*82d56013Sjoerg if (StackMapSection.size() < 16) 328*82d56013Sjoerg return object::createError( 329*82d56013Sjoerg "the stack map section size (" + Twine(StackMapSection.size()) + 330*82d56013Sjoerg ") is less than the minimum possible size of its header (16)"); 331*82d56013Sjoerg 332*82d56013Sjoerg unsigned Version = StackMapSection[0]; 333*82d56013Sjoerg if (Version != 3) 334*82d56013Sjoerg return object::createError( 335*82d56013Sjoerg "the version (" + Twine(Version) + 336*82d56013Sjoerg ") of the stack map section is unsupported, the " 337*82d56013Sjoerg "supported version is 3"); 338*82d56013Sjoerg return Error::success(); 339*82d56013Sjoerg } 340*82d56013Sjoerg 3417330f729Sjoerg using function_iterator = AccessorIterator<FunctionAccessor>; 3427330f729Sjoerg using constant_iterator = AccessorIterator<ConstantAccessor>; 3437330f729Sjoerg using record_iterator = AccessorIterator<RecordAccessor>; 3447330f729Sjoerg 3457330f729Sjoerg /// Get the version number of this stackmap. (Always returns 3). getVersion()3467330f729Sjoerg unsigned getVersion() const { return 3; } 3477330f729Sjoerg 3487330f729Sjoerg /// Get the number of functions in the stack map. getNumFunctions()3497330f729Sjoerg uint32_t getNumFunctions() const { 3507330f729Sjoerg return read<uint32_t>(&StackMapSection[NumFunctionsOffset]); 3517330f729Sjoerg } 3527330f729Sjoerg 3537330f729Sjoerg /// Get the number of large constants in the stack map. getNumConstants()3547330f729Sjoerg uint32_t getNumConstants() const { 3557330f729Sjoerg return read<uint32_t>(&StackMapSection[NumConstantsOffset]); 3567330f729Sjoerg } 3577330f729Sjoerg 3587330f729Sjoerg /// Get the number of stackmap records in the stackmap. getNumRecords()3597330f729Sjoerg uint32_t getNumRecords() const { 3607330f729Sjoerg return read<uint32_t>(&StackMapSection[NumRecordsOffset]); 3617330f729Sjoerg } 3627330f729Sjoerg 3637330f729Sjoerg /// Return an FunctionAccessor for the given function index. getFunction(unsigned FunctionIndex)3647330f729Sjoerg FunctionAccessor getFunction(unsigned FunctionIndex) const { 3657330f729Sjoerg return FunctionAccessor(StackMapSection.data() + 3667330f729Sjoerg getFunctionOffset(FunctionIndex)); 3677330f729Sjoerg } 3687330f729Sjoerg 3697330f729Sjoerg /// Begin iterator for functions. functions_begin()3707330f729Sjoerg function_iterator functions_begin() const { 3717330f729Sjoerg return function_iterator(getFunction(0)); 3727330f729Sjoerg } 3737330f729Sjoerg 3747330f729Sjoerg /// End iterator for functions. functions_end()3757330f729Sjoerg function_iterator functions_end() const { 3767330f729Sjoerg return function_iterator( 3777330f729Sjoerg FunctionAccessor(StackMapSection.data() + 3787330f729Sjoerg getFunctionOffset(getNumFunctions()))); 3797330f729Sjoerg } 3807330f729Sjoerg 3817330f729Sjoerg /// Iterator range for functions. functions()3827330f729Sjoerg iterator_range<function_iterator> functions() const { 3837330f729Sjoerg return make_range(functions_begin(), functions_end()); 3847330f729Sjoerg } 3857330f729Sjoerg 3867330f729Sjoerg /// Return the large constant at the given index. getConstant(unsigned ConstantIndex)3877330f729Sjoerg ConstantAccessor getConstant(unsigned ConstantIndex) const { 3887330f729Sjoerg return ConstantAccessor(StackMapSection.data() + 3897330f729Sjoerg getConstantOffset(ConstantIndex)); 3907330f729Sjoerg } 3917330f729Sjoerg 3927330f729Sjoerg /// Begin iterator for constants. constants_begin()3937330f729Sjoerg constant_iterator constants_begin() const { 3947330f729Sjoerg return constant_iterator(getConstant(0)); 3957330f729Sjoerg } 3967330f729Sjoerg 3977330f729Sjoerg /// End iterator for constants. constants_end()3987330f729Sjoerg constant_iterator constants_end() const { 3997330f729Sjoerg return constant_iterator( 4007330f729Sjoerg ConstantAccessor(StackMapSection.data() + 4017330f729Sjoerg getConstantOffset(getNumConstants()))); 4027330f729Sjoerg } 4037330f729Sjoerg 4047330f729Sjoerg /// Iterator range for constants. constants()4057330f729Sjoerg iterator_range<constant_iterator> constants() const { 4067330f729Sjoerg return make_range(constants_begin(), constants_end()); 4077330f729Sjoerg } 4087330f729Sjoerg 4097330f729Sjoerg /// Return a RecordAccessor for the given record index. getRecord(unsigned RecordIndex)4107330f729Sjoerg RecordAccessor getRecord(unsigned RecordIndex) const { 4117330f729Sjoerg std::size_t RecordOffset = StackMapRecordOffsets[RecordIndex]; 4127330f729Sjoerg return RecordAccessor(StackMapSection.data() + RecordOffset); 4137330f729Sjoerg } 4147330f729Sjoerg 4157330f729Sjoerg /// Begin iterator for records. records_begin()4167330f729Sjoerg record_iterator records_begin() const { 4177330f729Sjoerg if (getNumRecords() == 0) 4187330f729Sjoerg return record_iterator(RecordAccessor(nullptr)); 4197330f729Sjoerg return record_iterator(getRecord(0)); 4207330f729Sjoerg } 4217330f729Sjoerg 4227330f729Sjoerg /// End iterator for records. records_end()4237330f729Sjoerg record_iterator records_end() const { 4247330f729Sjoerg // Records need to be handled specially, since we cache the start addresses 4257330f729Sjoerg // for them: We can't just compute the 1-past-the-end address, we have to 4267330f729Sjoerg // look at the last record and use the 'next' method. 4277330f729Sjoerg if (getNumRecords() == 0) 4287330f729Sjoerg return record_iterator(RecordAccessor(nullptr)); 4297330f729Sjoerg return record_iterator(getRecord(getNumRecords() - 1).next()); 4307330f729Sjoerg } 4317330f729Sjoerg 4327330f729Sjoerg /// Iterator range for records. records()4337330f729Sjoerg iterator_range<record_iterator> records() const { 4347330f729Sjoerg return make_range(records_begin(), records_end()); 4357330f729Sjoerg } 4367330f729Sjoerg 4377330f729Sjoerg private: 4387330f729Sjoerg template <typename T> read(const uint8_t * P)4397330f729Sjoerg static T read(const uint8_t *P) { 4407330f729Sjoerg return support::endian::read<T, Endianness, 1>(P); 4417330f729Sjoerg } 4427330f729Sjoerg 4437330f729Sjoerg static const unsigned HeaderOffset = 0; 4447330f729Sjoerg static const unsigned NumFunctionsOffset = HeaderOffset + sizeof(uint32_t); 4457330f729Sjoerg static const unsigned NumConstantsOffset = NumFunctionsOffset + sizeof(uint32_t); 4467330f729Sjoerg static const unsigned NumRecordsOffset = NumConstantsOffset + sizeof(uint32_t); 4477330f729Sjoerg static const unsigned FunctionListOffset = NumRecordsOffset + sizeof(uint32_t); 4487330f729Sjoerg 4497330f729Sjoerg static const unsigned FunctionSize = 3 * sizeof(uint64_t); 4507330f729Sjoerg static const unsigned ConstantSize = sizeof(uint64_t); 4517330f729Sjoerg getFunctionOffset(unsigned FunctionIndex)4527330f729Sjoerg std::size_t getFunctionOffset(unsigned FunctionIndex) const { 4537330f729Sjoerg return FunctionListOffset + FunctionIndex * FunctionSize; 4547330f729Sjoerg } 4557330f729Sjoerg getConstantOffset(unsigned ConstantIndex)4567330f729Sjoerg std::size_t getConstantOffset(unsigned ConstantIndex) const { 4577330f729Sjoerg return ConstantsListOffset + ConstantIndex * ConstantSize; 4587330f729Sjoerg } 4597330f729Sjoerg 4607330f729Sjoerg ArrayRef<uint8_t> StackMapSection; 4617330f729Sjoerg unsigned ConstantsListOffset; 4627330f729Sjoerg std::vector<unsigned> StackMapRecordOffsets; 4637330f729Sjoerg }; 4647330f729Sjoerg 4657330f729Sjoerg } // end namespace llvm 4667330f729Sjoerg 467*82d56013Sjoerg #endif // LLVM_OBJECT_STACKMAPPARSER_H 468