1/* 2 * Copyright (c) 2024 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 16#ifndef ECMASCRIPT_BASELINE_BASELINE_ASSEMBLER_H 17#define ECMASCRIPT_BASELINE_BASELINE_ASSEMBLER_H 18 19#include "ecmascript/ecma_vm.h" 20#include "ecmascript/compiler/assembler/macro_assembler.h" 21#include "ecmascript/method.h" 22 23namespace panda::ecmascript::kungfu { 24enum class SpecialRegister : uint8_t { 25 NEW_TARGET, 26 CALL_SIZE, // jumpSizeAfterCall 27 ENV, 28 ACC_REGISTER, 29 THIS_OBJECT, // this 30 FUNC, // callTarget 31}; 32 33using BaselineParameter = std::variant<int8_t, int16_t, int32_t, int64_t, BaselineSpecialParameter, VirtualRegister>; 34 35class StackOffsetDescriptor { 36public: 37 StackOffsetDescriptor(uint64_t inputCallField) : callField(inputCallField) 38 { 39 numVregs = Method::GetNumVregsWithCallField(callField); 40 haveNewTarget = Method::HaveNewTargetWithCallField(callField); 41 // Add stack slot info as required 42 } 43 ~StackOffsetDescriptor() = default; 44 45 int32_t GetVregOffset(VirtualRegister virtualReg) 46 { 47 VRegIDType vregId = virtualReg.GetId(); 48 return (vregId) * FRAME_SLOT_SIZE; 49 } 50 51 int32_t GetSpecialRegisterOffset(SpecialRegister reg) 52 { 53 switch (reg) { 54 case SpecialRegister::NEW_TARGET: 55 return ((3 + numVregs) * FRAME_SLOT_SIZE); // +3: contains numVregs, undefined, callTarget, newTarget 56 case SpecialRegister::CALL_SIZE: 57 return -(5 * FRAME_SLOT_SIZE); // -5: contains frametype, rbp, pc, sp, callsize(jumpSizeAfterCall) 58 case SpecialRegister::ENV: 59 return -(6 * FRAME_SLOT_SIZE); // -6: contains frametype, rbp, pc, sp, callsize, env, 60 case SpecialRegister::ACC_REGISTER: 61 return -(7 * FRAME_SLOT_SIZE); // -7: contains frametype, rbp, pc, sp, callsize, env, acc, 62 case SpecialRegister::THIS_OBJECT: 63 return -(8 * FRAME_SLOT_SIZE); // -8: contains frametype, rbp, pc, sp, callsize, env, acc, thisObj 64 case SpecialRegister::FUNC: 65 // -9: contains frametype, rbp, pc, sp, callsize, env, acc, thisObj, call-target 66 return -(9 * FRAME_SLOT_SIZE); 67 default: 68 LOG_ECMA(FATAL) << "this branch is unreachable"; 69 UNREACHABLE(); 70 return 0; 71 } 72 } 73private: 74 uint64_t callField = 0; 75 uint32_t numVregs = 0; 76 bool haveNewTarget = false; 77 static constexpr int32_t FRAME_SLOT_SIZE = 8; 78}; 79 80class BaselineAssembler { 81public: 82 explicit BaselineAssembler(const std::string &tripleStr); 83 uint8_t *GetBuffer() const 84 { 85 return macroAssembler->GetBegin(); 86 } 87 88 size_t GetBufferSize() const 89 { 90 return macroAssembler->GetBufferCurrentSize(); 91 } 92 93 void SetStackOffsetDescriptor(const StackOffsetDescriptor &inputStackOffsetDesc) 94 { 95 stackOffsetDescriptor = inputStackOffsetDesc; 96 } 97 98 MacroAssembler &GetMacroAssembler() 99 { 100 ASSERT(macroAssembler != nullptr); 101 return *macroAssembler; 102 } 103 104 virtual ~BaselineAssembler() 105 { 106 if (macroAssembler != nullptr) { 107 delete macroAssembler; 108 macroAssembler = nullptr; 109 } 110 } 111 void Move(VirtualRegister interpreterDestReg, Immediate value); 112 void Move(SpecialRegister destReg, Immediate value); 113 void Move(SpecialRegister destReg, SpecialRegister srcReg); 114 void Move(VirtualRegister interpreterDestReg, VirtualRegister interpreterSrcReg); 115 void Move(SpecialRegister destReg, VirtualRegister interpreterSrcReg); 116 void Move(VirtualRegister interpreterDestReg, SpecialRegister srcReg); 117 void Cmp(SpecialRegister reg, Immediate value); 118 119 void Bind(JumpLabel &label) 120 { 121 macroAssembler->Bind(label); 122 } 123 124 void Jz(JumpLabel &label) 125 { 126 macroAssembler->Jz(label); 127 } 128 129 void Jnz(JumpLabel &label) 130 { 131 macroAssembler->Jnz(label); 132 } 133 134 void Jump(JumpLabel &label) 135 { 136 macroAssembler->Jump(label); 137 } 138 139 void SaveResultIntoAcc(); 140 void CallBuiltin(Address funcAddress, 141 const std::vector<BaselineParameter> ¶meters); 142 143private: 144 MacroAssembler *macroAssembler; 145 StackOffsetDescriptor stackOffsetDescriptor; 146}; 147} // namespace panda::ecmascript::kungfu 148#endif // ECMASCRIPT_BASELINE_BASELINE_ASSEMBLER_H 149