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
ConvertToLLVMStackMapInfo(std::vector<LLVMStackMapType::Pc2CallSiteInfo> & pc2StackMapsVec,std::vector<LLVMStackMapType::Pc2Deopt> & pc2DeoptInfoVec,Triple triple) const44 void LiteCGStackMapInfo::ConvertToLLVMStackMapInfo(
45 std::vector<LLVMStackMapType::Pc2CallSiteInfo> &pc2StackMapsVec,
46 std::vector<LLVMStackMapType::Pc2Deopt> &pc2DeoptInfoVec, Triple triple) const
47 {
48 auto fpReg = GCStackMapRegisters::GetFpRegByTriple(triple);
49 for (const auto &callSiteInfo : pc2CallSiteInfoVec_) {
50 LLVMStackMapType::Pc2CallSiteInfo pc2CallSiteInfo;
51 for (const auto &elem : callSiteInfo) {
52 const std::vector<uint8_t> &litecgCallSiteInfo = elem.second;
53 LLVMStackMapType::CallSiteInfo llvmCallSiteInfo;
54 // parse std::vector<uint8_t>
55 size_t index = 0;
56 while (index < litecgCallSiteInfo.size()) {
57 int64_t kind = DecodeSLEB128(litecgCallSiteInfo, index);
58 int64_t value = DecodeSLEB128(litecgCallSiteInfo, index);
59 if (kind == 2) { // kind is 2 means register
60 llvmCallSiteInfo.push_back(std::pair<uint16_t, uint32_t>(0xFFFFU, static_cast<int32_t>(value)));
61 } else if (kind == 1) { // stack
62 llvmCallSiteInfo.push_back(std::pair<uint16_t, uint32_t>(fpReg, static_cast<int32_t>(value)));
63 } else {
64 LOG_ECMA(FATAL) << "only stack and reigster is supported currently";
65 UNREACHABLE();
66 }
67 }
68 uintptr_t pc = static_cast<uintptr_t>(elem.first);
69 pc2CallSiteInfo[pc] = llvmCallSiteInfo;
70 }
71 pc2StackMapsVec.push_back(pc2CallSiteInfo);
72 }
73 for (const auto &deoptInfo : pc2DeoptVec_) {
74 LLVMStackMapType::Pc2Deopt pc2DeoptInfo;
75 for (const auto &elem : deoptInfo) {
76 const std::vector<uint8_t> &litecgDeoptInfo = elem.second;
77 LLVMStackMapType::DeoptInfoType llvmDeoptInfo;
78 // parse std::vector<uint8_t>
79 size_t index = 0;
80 while (index < litecgDeoptInfo.size()) {
81 int64_t deoptVreg = DecodeSLEB128(litecgDeoptInfo, index);
82 int64_t kind = DecodeSLEB128(litecgDeoptInfo, index);
83 int64_t value = DecodeSLEB128(litecgDeoptInfo, index);
84 llvmDeoptInfo.push_back(static_cast<int32_t>(deoptVreg));
85 if (kind == 2) { // kind is 2 means register
86 llvmDeoptInfo.push_back(std::pair<uint16_t, uint32_t>(0xFFFFU, static_cast<int32_t>(value)));
87 } else if (kind == 1) { // stack
88 llvmDeoptInfo.push_back(std::pair<uint16_t, uint32_t>(fpReg, static_cast<int32_t>(value)));
89 } else { // imm
90 llvmDeoptInfo.push_back(static_cast<int32_t>(value));
91 }
92 }
93 pc2DeoptInfo[elem.first] = llvmDeoptInfo;
94 }
95
96 pc2DeoptInfoVec.push_back(pc2DeoptInfo);
97 }
98 }
99 } // namespace panda::ecmascript::kungfu