• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <cmath>
25 #include "ecmascript/base/bit_helper.h"
26 #include "ecmascript/common.h"
27 #include "ecmascript/compiler/assembler/assembler.h"
28 #include "ecmascript/log_wrapper.h"
29 #include "ecmascript/mem/mem.h"
30 
31 #include "libpandabase/utils/leb128.h"
32 
33 namespace panda::ecmascript::kungfu {
34 struct LocationTy {
35     enum class Kind: uint8_t {
36         REGISTER = 1,
37         DIRECT = 2,
38         INDIRECT = 3,
39         CONSTANT = 4,
40         CONSTANTNDEX = 5,
41     };
42     static constexpr int CONSTANT_FIRST_ELEMENT_INDEX = 3;
43     static constexpr int CONSTANT_DEOPT_CNT_INDEX = 2;
44 
45     Kind location;
46     uint8_t reserved_0;
47     uint16_t locationSize;
48     uint16_t dwarfRegNum;
49     uint16_t reserved_1;
50     int32_t offsetOrSmallConstant;
51 
52     std::string PUBLIC_API TypeToString(Kind loc) const;
53 
PrintLocationTy54     void Print() const
55     {
56         LOG_COMPILER(DEBUG)  << TypeToString(location);
57         LOG_COMPILER(DEBUG) << ", size:" << std::dec << locationSize;
58         LOG_COMPILER(DEBUG) << "\tDwarfRegNum:" << dwarfRegNum;
59         LOG_COMPILER(DEBUG) << "\t OffsetOrSmallConstant:" << offsetOrSmallConstant;
60     }
61 };
62 
63 class LLVMStackMapType {
64 public:
65     using OffsetType = int32_t;
66     using DwarfRegType = uint16_t;
67     using IntType = int32_t;
68     using LargeInt = int64_t;
69     using RegType = int8_t;
70     using KindType = int8_t;
71     using VRegId = int16_t;
72     using SLeb128Type = int64_t;
73     using DwarfRegAndOffsetType = std::pair<DwarfRegType, OffsetType>;
74     using CallSiteInfo = std::vector<DwarfRegAndOffsetType>;
75     using Fun2InfoType = std::pair<uintptr_t, DwarfRegAndOffsetType>;
76     using Pc2CallSiteInfo = std::unordered_map<uintptr_t, CallSiteInfo>;
77     using FpDelta = std::pair<int, uint32_t>;
78     using Func2FpDelta = std::unordered_map<uintptr_t, FpDelta>; // value: fpDelta & funcSize
79     using ConstInfo = std::vector<IntType>;
80     using DeoptInfoType = std::vector<std::variant<IntType, LargeInt, DwarfRegAndOffsetType>>;
81     using Pc2Deopt = std::unordered_map<uintptr_t, DeoptInfoType>;
82 
83     static constexpr size_t STACKMAP_ALIGN_BYTES = 2;
84     static constexpr KindType CONSTANT_TYPE = 0;
85     static constexpr KindType OFFSET_TYPE = 1;
86 
87     template <typename T>
EncodeData(std::vector<uint8_t> & outData,size_t & dataSize,T value)88     static void EncodeData(std::vector<uint8_t> &outData, size_t &dataSize, T value)
89     {
90         static_assert(std::is_signed_v<T>, "T must be signed");
91         SLeb128Type data = value;
92         size_t valueSize = panda::leb128::SignedEncodingSize(data);
93         outData.resize(valueSize);
94         dataSize = panda::leb128::EncodeSigned(data, outData.data());
95     }
96 
97     static void EncodeRegAndOffset(std::vector<uint8_t> &regOffset, size_t &regOffsetSize,
98         DwarfRegType reg, OffsetType offset, Triple triple);
99     static void DecodeRegAndOffset(SLeb128Type regOffset, DwarfRegType &reg, OffsetType &offset);
100     static void EncodeVRegsInfo(std::vector<uint8_t> &vregsInfo, size_t &vregsInfoSize,
101         VRegId id, LocationTy::Kind kind);
102     static void DecodeVRegsInfo(SLeb128Type vregsInfo, VRegId &id, KindType &kind);
103 
104 private:
105     static constexpr size_t STACKMAP_TYPE_NUM = 2;
106     static constexpr RegType FP_VALUE = 0;
107     static constexpr RegType SP_VALUE = 1;
108 };
109 
110 struct Header {
111     uint8_t  stackmapversion; // Stack Map Version (current version is 3)
112     uint8_t  reserved0; // Reserved (expected to be 0)
113     uint16_t reserved1; // Reserved (expected to be 0)
PrintHeader114     void Print() const
115     {
116         LOG_COMPILER(DEBUG) << "----- head ----";
117         LOG_COMPILER(DEBUG) << "   version:" << static_cast<int>(stackmapversion);
118         LOG_COMPILER(DEBUG) << "+++++ head ++++";
119     }
120 };
121 
122 #pragma pack(1)
123 struct StkMapSizeRecordTy {
124     uintptr_t functionAddress;
125     uint64_t stackSize;
126     uint64_t recordCount;
PrintStkMapSizeRecordTy127     void Print() const
128     {
129         LOG_COMPILER(DEBUG) << "               functionAddress:0x" << std::hex << functionAddress;
130         LOG_COMPILER(DEBUG) << "               stackSize:0x" << std::hex << stackSize;
131         LOG_COMPILER(DEBUG) << "               recordCount:" << std::hex << recordCount;
132     }
133 };
134 #pragma pack()
135 
136 struct ConstantsTy {
137     uintptr_t largeConstant;
PrintConstantsTy138     void Print() const
139     {
140         LOG_COMPILER(DEBUG) << "               LargeConstant:0x" << std::hex << largeConstant;
141     }
142 };
143 
144 struct StkMapRecordHeadTy {
145     uint64_t patchPointID;
146     uint32_t instructionOffset;
147     uint16_t reserved;
148     uint16_t numLocations;
PrintStkMapRecordHeadTy149     void Print() const
150     {
151         LOG_COMPILER(DEBUG) << "               PatchPointID:0x" << std::hex << patchPointID;
152         LOG_COMPILER(DEBUG) << "               instructionOffset:0x" << std::hex << instructionOffset;
153         LOG_COMPILER(DEBUG) << "               Reserved:0x" << std::hex << reserved;
154         LOG_COMPILER(DEBUG) << "               NumLocations:0x" << std::hex << numLocations;
155     }
156 };
157 struct LiveOutsTy {
158     LLVMStackMapType::DwarfRegType dwarfRegNum;
159     uint8_t reserved;
160     uint8_t sizeinBytes;
PrintLiveOutsTy161     void Print() const
162     {
163         LOG_COMPILER(DEBUG) << "                  Dwarf RegNum:" << dwarfRegNum;
164         LOG_COMPILER(DEBUG) << "                  Reserved:" << reserved;
165         LOG_COMPILER(DEBUG) << "                  SizeinBytes:" << sizeinBytes;
166     }
167 };
168 struct StkMapRecordTy {
169     struct StkMapRecordHeadTy head;
170     std::vector<struct LocationTy> locations;
171     std::vector<struct LiveOutsTy> liveOuts;
PrintStkMapRecordTy172     void Print() const
173     {
174         head.Print();
175         auto size = locations.size();
176         for (size_t i = 0; i < size; i++) {
177             LOG_COMPILER(DEBUG) << "                   #" << std::dec << i << ":";
178             locations[i].Print();
179         }
180         size = liveOuts.size();
181         for (size_t i = 0; i < size; i++) {
182             LOG_COMPILER(DEBUG) << "               liveOuts[" << i << "] info:";
183         }
184     }
185 };
186 
187 class DataInfo {
188 public:
DataInfo(std::unique_ptr<uint8_t[]> data)189     explicit DataInfo(std::unique_ptr<uint8_t[]> data): data_(std::move(data)), offset_(0) {}
~DataInfo()190     ~DataInfo()
191     {
192         data_.reset();
193         offset_ = 0;
194     }
195     template<class T>
Read()196     T Read()
197     {
198         T t = *reinterpret_cast<const T*>(data_.get() + offset_);
199         offset_ += sizeof(T);
200         return t;
201     }
GetOffset()202     unsigned int GetOffset() const
203     {
204         return offset_;
205     }
206 private:
207     std::unique_ptr<uint8_t[]> data_ {nullptr};
208     unsigned int offset_ {0};
209 };
210 
211 struct LLVMStackMap {
212     struct Header head;
213     std::vector<struct StkMapSizeRecordTy> stkSizeRecords;
214     std::vector<struct ConstantsTy> constants;
215     std::vector<struct StkMapRecordTy> stkMapRecord;
PrintLLVMStackMap216     void Print() const
217     {
218         head.Print();
219         for (size_t i = 0; i < stkSizeRecords.size(); i++) {
220             LOG_COMPILER(DEBUG) << "StkSizeRecord[" << i << "] info:";
221             stkSizeRecords[i].Print();
222         }
223         for (size_t i = 0; i < constants.size(); i++) {
224             LOG_COMPILER(DEBUG) << "Constants[" << i << "] info:";
225             constants[i].Print();
226         }
227         for (size_t i = 0; i < stkMapRecord.size(); i++) {
228             LOG_COMPILER(DEBUG) << "StkMapRecord[" << i << "] info:";
229             stkMapRecord[i].Print();
230         }
231     }
232 };
233 } // namespace panda::ecmascript::kungfu
234 #endif  // ECMASCRIPT_LLVM_STACKMAP_TYPE_H