1 /* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 #ifndef ECMASCRIPT_LLVM_STACKMAP_TYPE_H 16 #define ECMASCRIPT_LLVM_STACKMAP_TYPE_H 17 18 #include <iostream> 19 #include <memory> 20 #include <tuple> 21 #include <unordered_map> 22 #include <variant> 23 #include <vector> 24 #include "ecmascript/common.h" 25 #include "ecmascript/log_wrapper.h" 26 27 namespace panda::ecmascript::kungfu { 28 using OffsetType = int32_t; 29 using DwarfRegType = uint16_t; 30 using LargeInt = int64_t; 31 using DwarfRegAndOffsetType = std::pair<DwarfRegType, OffsetType>; 32 using CallSiteInfo = std::vector<DwarfRegAndOffsetType>; 33 using Fun2InfoType = std::pair<uintptr_t, DwarfRegAndOffsetType>; 34 using Pc2CallSiteInfo = std::unordered_map<uintptr_t, CallSiteInfo>; 35 using FpDelta = std::pair<int, uint32_t>; 36 using Func2FpDelta = std::unordered_map<uintptr_t, FpDelta>; // value: fpDelta & funcSize 37 using ConstInfo = std::vector<OffsetType>; 38 using DeoptInfoType = std::vector<std::variant<OffsetType, LargeInt, DwarfRegAndOffsetType>>; 39 using Pc2Deopt = std::unordered_map<uintptr_t, DeoptInfoType>; 40 41 struct Header { 42 uint8_t stackmapversion; // Stack Map Version (current version is 3) 43 uint8_t Reserved0; // Reserved (expected to be 0) 44 uint16_t Reserved1; // Reserved (expected to be 0) PrintHeader45 void Print() const 46 { 47 LOG_COMPILER(DEBUG) << "----- head ----"; 48 LOG_COMPILER(DEBUG) << " version:" << static_cast<int>(stackmapversion); 49 LOG_COMPILER(DEBUG) << "+++++ head ++++"; 50 } 51 }; 52 53 #pragma pack(1) 54 struct StkSizeRecordTy { 55 uintptr_t functionAddress; 56 uint64_t stackSize; 57 uint64_t recordCount; PrintStkSizeRecordTy58 void Print() const 59 { 60 LOG_COMPILER(DEBUG) << " functionAddress:0x" << std::hex << functionAddress; 61 LOG_COMPILER(DEBUG) << " stackSize:0x" << std::hex << stackSize; 62 LOG_COMPILER(DEBUG) << " recordCount:" << std::hex << recordCount; 63 } 64 }; 65 #pragma pack() 66 67 struct ConstantsTy { 68 uintptr_t LargeConstant; PrintConstantsTy69 void Print() const 70 { 71 LOG_COMPILER(DEBUG) << " LargeConstant:0x" << std::hex << LargeConstant; 72 } 73 }; 74 75 struct StkMapRecordHeadTy { 76 uint64_t PatchPointID; 77 uint32_t InstructionOffset; 78 uint16_t Reserved; 79 uint16_t NumLocations; PrintStkMapRecordHeadTy80 void Print() const 81 { 82 LOG_COMPILER(DEBUG) << " PatchPointID:0x" << std::hex << PatchPointID; 83 LOG_COMPILER(DEBUG) << " instructionOffset:0x" << std::hex << InstructionOffset; 84 LOG_COMPILER(DEBUG) << " Reserved:0x" << std::hex << Reserved; 85 LOG_COMPILER(DEBUG) << " NumLocations:0x" << std::hex << NumLocations; 86 } 87 }; 88 89 struct LocationTy { 90 enum class Kind: uint8_t { 91 REGISTER = 1, 92 DIRECT = 2, 93 INDIRECT = 3, 94 CONSTANT = 4, 95 CONSTANTNDEX = 5, 96 }; 97 static constexpr int CONSTANT_FIRST_ELEMENT_INDEX = 3; 98 static constexpr int CONSTANT_DEOPT_CNT_INDEX = 2; 99 Kind location; 100 uint8_t Reserved_0; 101 uint16_t LocationSize; 102 uint16_t DwarfRegNum; 103 uint16_t Reserved_1; 104 OffsetType OffsetOrSmallConstant; 105 106 std::string PUBLIC_API TypeToString(Kind loc) const; 107 PrintLocationTy108 void Print() const 109 { 110 LOG_COMPILER(DEBUG) << TypeToString(location); 111 LOG_COMPILER(DEBUG) << ", size:" << std::dec << LocationSize; 112 LOG_COMPILER(DEBUG) << "\tDwarfRegNum:" << DwarfRegNum; 113 LOG_COMPILER(DEBUG) << "\t OffsetOrSmallConstant:" << OffsetOrSmallConstant; 114 } 115 }; 116 117 struct LiveOutsTy { 118 DwarfRegType DwarfRegNum; 119 uint8_t Reserved; 120 uint8_t SizeinBytes; PrintLiveOutsTy121 void Print() const 122 { 123 LOG_COMPILER(DEBUG) << " Dwarf RegNum:" << DwarfRegNum; 124 LOG_COMPILER(DEBUG) << " Reserved:" << Reserved; 125 LOG_COMPILER(DEBUG) << " SizeinBytes:" << SizeinBytes; 126 } 127 }; 128 struct StkMapRecordTy { 129 struct StkMapRecordHeadTy head; 130 std::vector<struct LocationTy> Locations; 131 std::vector<struct LiveOutsTy> LiveOuts; PrintStkMapRecordTy132 void Print() const 133 { 134 head.Print(); 135 auto size = Locations.size(); 136 for (size_t i = 0; i < size; i++) { 137 LOG_COMPILER(DEBUG) << " #" << std::dec << i << ":"; 138 Locations[i].Print(); 139 } 140 size = LiveOuts.size(); 141 for (size_t i = 0; i < size; i++) { 142 LOG_COMPILER(DEBUG) << " liveOuts[" << i << "] info:"; 143 } 144 } 145 }; 146 147 class DataInfo { 148 public: DataInfo(std::unique_ptr<uint8_t[]> data)149 explicit DataInfo(std::unique_ptr<uint8_t[]> data): data_(std::move(data)), offset_(0) {} ~DataInfo()150 ~DataInfo() 151 { 152 data_.reset(); 153 offset_ = 0; 154 } 155 template<class T> Read()156 T Read() 157 { 158 T t = *reinterpret_cast<const T*>(data_.get() + offset_); 159 offset_ += sizeof(T); 160 return t; 161 } GetOffset()162 unsigned int GetOffset() const 163 { 164 return offset_; 165 } 166 private: 167 std::unique_ptr<uint8_t[]> data_ {nullptr}; 168 unsigned int offset_ {0}; 169 }; 170 171 struct LLVMStackMap { 172 struct Header head; 173 std::vector<struct StkSizeRecordTy> StkSizeRecords; 174 std::vector<struct ConstantsTy> Constants; 175 std::vector<struct StkMapRecordTy> StkMapRecord; PrintLLVMStackMap176 void Print() const 177 { 178 head.Print(); 179 for (size_t i = 0; i < StkSizeRecords.size(); i++) { 180 LOG_COMPILER(DEBUG) << "stkSizeRecord[" << i << "] info:"; 181 StkSizeRecords[i].Print(); 182 } 183 for (size_t i = 0; i < Constants.size(); i++) { 184 LOG_COMPILER(DEBUG) << "constants[" << i << "] info:"; 185 Constants[i].Print(); 186 } 187 for (size_t i = 0; i < StkMapRecord.size(); i++) { 188 LOG_COMPILER(DEBUG) << "StkMapRecord[" << i << "] info:"; 189 StkMapRecord[i].Print(); 190 } 191 } 192 }; 193 } // namespace panda::ecmascript::kungfu 194 #endif // ECMASCRIPT_LLVM_STACKMAP_TYPE_H