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 #include "ecmascript/stackmap/llvm/llvm_stackmap_type.h"
16
17 namespace panda::ecmascript::kungfu {
EncodeRegAndOffset(std::vector<uint8_t> & regOffset,size_t & regOffsetSize,DwarfRegType reg,OffsetType offset,Triple triple,bool isBaseDerivedEq)18 void LLVMStackMapType::EncodeRegAndOffset(std::vector<uint8_t> ®Offset, size_t ®OffsetSize,
19 DwarfRegType reg, OffsetType offset, Triple triple, bool isBaseDerivedEq)
20 {
21 SLeb128Type dwarfRegAndOff = offset;
22 auto fpReg = GCStackMapRegisters::GetFpRegByTriple(triple);
23 auto spReg = GCStackMapRegisters::GetSpRegByTriple(triple);
24 if (offset % STACKMAP_OFFSET_MUL != 0) {
25 LOG_ECMA(FATAL) << "offset is not multiple of 8";
26 }
27 if (reg == fpReg) {
28 dwarfRegAndOff = dwarfRegAndOff | FP_VALUE; // use last digit for fp/sp reg
29 } else if (reg == spReg) {
30 dwarfRegAndOff = dwarfRegAndOff | SP_VALUE;
31 } else {
32 LOG_ECMA(FATAL) << "dwarfreg branch is unreachable";
33 UNREACHABLE();
34 }
35 if (isBaseDerivedEq) {
36 dwarfRegAndOff |= NO_DERIVED; // use the second to last digit for base ref/has derived ref
37 }
38 size_t valueSize = panda::leb128::SignedEncodingSize(dwarfRegAndOff);
39 regOffset.resize(valueSize);
40 regOffsetSize = panda::leb128::EncodeSigned(dwarfRegAndOff, regOffset.data());
41 }
42
IsBaseEqualDerive(SLeb128Type regOffset)43 bool LLVMStackMapType::IsBaseEqualDerive(SLeb128Type regOffset)
44 {
45 return (static_cast<uint64_t>(regOffset) & NO_DERIVED) != 0;
46 }
GetOffsetFromRegOff(SLeb128Type regOffset)47 LLVMStackMapType::OffsetType LLVMStackMapType::GetOffsetFromRegOff(SLeb128Type regOffset)
48 {
49 return static_cast<LLVMStackMapType::OffsetType>(static_cast<uint64_t>(regOffset) & STACKMAP_OFFSET_MASK);
50 }
51
DecodeRegAndOffset(SLeb128Type regOffset,DwarfRegType & reg,OffsetType & offset)52 bool LLVMStackMapType::DecodeRegAndOffset(SLeb128Type regOffset, DwarfRegType ®, OffsetType &offset)
53 {
54 if (regOffset % STACKMAP_TYPE_NUM == LLVMStackMapType::FP_VALUE) {
55 reg = GCStackMapRegisters::FP;
56 } else {
57 reg = GCStackMapRegisters::SP;
58 }
59
60 // last three bits set to 0
61 offset = GetOffsetFromRegOff(regOffset);
62 ASSERT(offset % STACKMAP_OFFSET_MUL == 0);
63 return IsBaseEqualDerive(regOffset);
64 }
65
EncodeVRegsInfo(std::vector<uint8_t> & vregsInfo,size_t & vregsInfoSize,VRegId id,LocationTy::Kind kind)66 void LLVMStackMapType::EncodeVRegsInfo(std::vector<uint8_t> &vregsInfo, size_t &vregsInfoSize,
67 VRegId id, LocationTy::Kind kind)
68 {
69 SLeb128Type vregIdAndKind = id;
70 if (kind == LocationTy::Kind::CONSTANT || kind == LocationTy::Kind::CONSTANTNDEX) {
71 vregIdAndKind = (vregIdAndKind << 1) + CONSTANT_TYPE;
72 } else if (kind == LocationTy::Kind::INDIRECT) {
73 vregIdAndKind = (vregIdAndKind << 1) + OFFSET_TYPE;
74 } else {
75 LOG_ECMA(FATAL) << "vreg kind branch is unreachable";
76 UNREACHABLE();
77 }
78 size_t vregIdAndKindSize = panda::leb128::SignedEncodingSize(vregIdAndKind);
79 vregsInfo.resize(vregIdAndKindSize);
80 vregsInfoSize = panda::leb128::EncodeSigned(vregIdAndKind, vregsInfo.data());
81 }
82
DecodeVRegsInfo(SLeb128Type vregsInfo,VRegId & id,KindType & kind)83 void LLVMStackMapType::DecodeVRegsInfo(SLeb128Type vregsInfo, VRegId &id, KindType &kind)
84 {
85 if (vregsInfo % STACKMAP_TYPE_NUM == CONSTANT_TYPE) {
86 kind = CONSTANT_TYPE;
87 } else {
88 kind = OFFSET_TYPE;
89 }
90 id = static_cast<VRegId>(vregsInfo >> 1);
91 }
92 } // namespace panda::ecmascript::kungfu