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