• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 #include "ecmascript/stackmap/litecg/litecg_stackmap_type.h"
16 
17 namespace panda::ecmascript::kungfu {
DecodeSLEB128(const std::vector<uint8_t> & bytes,size_t & index)18 static int64_t DecodeSLEB128(const std::vector<uint8_t> &bytes, size_t &index)
19 {
20     uint64_t res = 0;
21     uint64_t shift = 0;
22     constexpr uint8_t FLAG_MASK = 0x40;
23     constexpr uint8_t LOW_7_BITS_MASK = 0x7f;
24     constexpr uint8_t NEXT_BYTE_FLAG_MASK = 0x80;
25     constexpr uint8_t DATA_BITS_SHIFT = 7;
26     constexpr uint64_t BIT_SIZE_64 = 64;
27     bool needDecodeNextByte = false;
28     uint8_t byte = 0;
29     do {
30         byte = bytes[index];
31         needDecodeNextByte = ((byte & NEXT_BYTE_FLAG_MASK) != 0);
32         uint8_t low7Bit = (byte & LOW_7_BITS_MASK);
33         res |= (static_cast<uint64_t>(low7Bit) << shift);
34         shift += DATA_BITS_SHIFT;
35         index++;
36     } while (needDecodeNextByte);
37 
38     if (shift < BIT_SIZE_64 && (byte & FLAG_MASK) != 0) {
39         res |= UINT64_MAX << shift;
40     }
41     return static_cast<int64_t>(res);
42 }
43 
ConvertToLLVMPc2CallSiteInfo(LLVMPc2CallSiteInfo & pc2CallSiteInfo,const LiteCGPc2CallSiteInfo & liteCGPc2CallSiteInfo,int fpReg) const44 void LiteCGStackMapInfo::ConvertToLLVMPc2CallSiteInfo(LLVMPc2CallSiteInfo &pc2CallSiteInfo,
45                                                       const LiteCGPc2CallSiteInfo &liteCGPc2CallSiteInfo,
46                                                       int fpReg) const
47 {
48     for (const auto &elem : liteCGPc2CallSiteInfo) {
49         const auto &litecgCallSiteInfo = elem.second;
50         LLVMCallSiteInfo llvmCallSiteInfo;
51         // parse std::vector<uint8_t>
52         size_t index = 0;
53         while (index < litecgCallSiteInfo.size()) {
54             int64_t kind = DecodeSLEB128(litecgCallSiteInfo, index);
55             int64_t value = DecodeSLEB128(litecgCallSiteInfo, index);
56             if (kind == 2) {  // kind is 2 means register
57                 llvmCallSiteInfo.push_back(LLVMDwarfRegAndOffsetType(0xFFFFU, static_cast<LLVMOffsetType>(value)));
58             } else if (kind == 1) { // stack
59                 llvmCallSiteInfo.push_back(LLVMDwarfRegAndOffsetType(fpReg, static_cast<LLVMOffsetType>(value)));
60             } else {
61                 LOG_ECMA(FATAL) << "only stack and reigster is supported currently";
62                 UNREACHABLE();
63             }
64         }
65         uintptr_t pc = static_cast<uintptr_t>(elem.first);
66         pc2CallSiteInfo[pc] = llvmCallSiteInfo;
67     }
68 }
69 
ConvertToLLVMPv2Deopt(LLVMPc2Deopt & pc2DeoptInfo,const LiteCGPc2Deopt & liteCGPc2DeoptInfo,int fpReg) const70 void LiteCGStackMapInfo::ConvertToLLVMPv2Deopt(LLVMPc2Deopt &pc2DeoptInfo, const LiteCGPc2Deopt &liteCGPc2DeoptInfo,
71                                                int fpReg) const
72 {
73     for (const auto &elem : liteCGPc2DeoptInfo) {
74         const auto &litecgDeoptInfo = elem.second;
75         LLVMDeoptInfoType llvmDeoptInfo;
76         // parse std::vector<uint8_t>
77         size_t index = 0;
78         while (index < litecgDeoptInfo.size()) {
79             int64_t deoptVreg = DecodeSLEB128(litecgDeoptInfo, index);
80             int64_t kind = DecodeSLEB128(litecgDeoptInfo, index);
81             int64_t value = DecodeSLEB128(litecgDeoptInfo, index);
82             llvmDeoptInfo.push_back(static_cast<LLVMIntType>(deoptVreg));
83             if (kind == 2) { // kind is 2 means register
84                 llvmDeoptInfo.push_back(LLVMDwarfRegAndOffsetType(0xFFFFU, static_cast<LLVMOffsetType>(value)));
85             } else if (kind == 1) { // stack
86                 llvmDeoptInfo.push_back(LLVMDwarfRegAndOffsetType(fpReg, static_cast<LLVMOffsetType>(value)));
87             } else if (value > INT32_MAX || value < INT32_MIN) {  // large imm
88                 llvmDeoptInfo.push_back(static_cast<LLVMLargeInt>(value));
89             } else {  // imm
90                 llvmDeoptInfo.push_back(static_cast<LLVMIntType>(value));
91             }
92         }
93         pc2DeoptInfo[elem.first] = llvmDeoptInfo;
94     }
95 }
96 
ConvertToLLVMStackMapInfo(std::vector<LLVMPc2CallSiteInfo> & pc2StackMapsVec,std::vector<LLVMPc2Deopt> & pc2DeoptInfoVec,Triple triple) const97 void LiteCGStackMapInfo::ConvertToLLVMStackMapInfo(std::vector<LLVMPc2CallSiteInfo> &pc2StackMapsVec,
98                                                    std::vector<LLVMPc2Deopt> &pc2DeoptInfoVec, Triple triple) const
99 {
100     auto fpReg = GCStackMapRegisters::GetFpRegByTriple(triple);
101     for (const auto &callSiteInfo : pc2CallSiteInfoVec_) {
102         LLVMPc2CallSiteInfo pc2CallSiteInfo;
103         ConvertToLLVMPc2CallSiteInfo(pc2CallSiteInfo, callSiteInfo, fpReg);
104         pc2StackMapsVec.push_back(pc2CallSiteInfo);
105     }
106     for (const auto &deoptInfo : pc2DeoptVec_) {
107         LLVMPc2Deopt pc2DeoptInfo;
108         ConvertToLLVMPv2Deopt(pc2DeoptInfo, deoptInfo, fpReg);
109         pc2DeoptInfoVec.push_back(pc2DeoptInfo);
110     }
111 }
112 }  // namespace panda::ecmascript::kungfu