14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#ifndef ECMASCRIPT_BASELINE_BASELINE_ASSEMBLER_H 174514f5e3Sopenharmony_ci#define ECMASCRIPT_BASELINE_BASELINE_ASSEMBLER_H 184514f5e3Sopenharmony_ci 194514f5e3Sopenharmony_ci#include "ecmascript/ecma_vm.h" 204514f5e3Sopenharmony_ci#include "ecmascript/compiler/assembler/macro_assembler.h" 214514f5e3Sopenharmony_ci#include "ecmascript/method.h" 224514f5e3Sopenharmony_ci 234514f5e3Sopenharmony_cinamespace panda::ecmascript::kungfu { 244514f5e3Sopenharmony_cienum class SpecialRegister : uint8_t { 254514f5e3Sopenharmony_ci NEW_TARGET, 264514f5e3Sopenharmony_ci CALL_SIZE, // jumpSizeAfterCall 274514f5e3Sopenharmony_ci ENV, 284514f5e3Sopenharmony_ci ACC_REGISTER, 294514f5e3Sopenharmony_ci THIS_OBJECT, // this 304514f5e3Sopenharmony_ci FUNC, // callTarget 314514f5e3Sopenharmony_ci}; 324514f5e3Sopenharmony_ci 334514f5e3Sopenharmony_ciusing BaselineParameter = std::variant<int8_t, int16_t, int32_t, int64_t, BaselineSpecialParameter, VirtualRegister>; 344514f5e3Sopenharmony_ci 354514f5e3Sopenharmony_ciclass StackOffsetDescriptor { 364514f5e3Sopenharmony_cipublic: 374514f5e3Sopenharmony_ci StackOffsetDescriptor(uint64_t inputCallField) : callField(inputCallField) 384514f5e3Sopenharmony_ci { 394514f5e3Sopenharmony_ci numVregs = Method::GetNumVregsWithCallField(callField); 404514f5e3Sopenharmony_ci haveNewTarget = Method::HaveNewTargetWithCallField(callField); 414514f5e3Sopenharmony_ci // Add stack slot info as required 424514f5e3Sopenharmony_ci } 434514f5e3Sopenharmony_ci ~StackOffsetDescriptor() = default; 444514f5e3Sopenharmony_ci 454514f5e3Sopenharmony_ci int32_t GetVregOffset(VirtualRegister virtualReg) 464514f5e3Sopenharmony_ci { 474514f5e3Sopenharmony_ci VRegIDType vregId = virtualReg.GetId(); 484514f5e3Sopenharmony_ci return (vregId) * FRAME_SLOT_SIZE; 494514f5e3Sopenharmony_ci } 504514f5e3Sopenharmony_ci 514514f5e3Sopenharmony_ci int32_t GetSpecialRegisterOffset(SpecialRegister reg) 524514f5e3Sopenharmony_ci { 534514f5e3Sopenharmony_ci switch (reg) { 544514f5e3Sopenharmony_ci case SpecialRegister::NEW_TARGET: 554514f5e3Sopenharmony_ci return ((3 + numVregs) * FRAME_SLOT_SIZE); // +3: contains numVregs, undefined, callTarget, newTarget 564514f5e3Sopenharmony_ci case SpecialRegister::CALL_SIZE: 574514f5e3Sopenharmony_ci return -(5 * FRAME_SLOT_SIZE); // -5: contains frametype, rbp, pc, sp, callsize(jumpSizeAfterCall) 584514f5e3Sopenharmony_ci case SpecialRegister::ENV: 594514f5e3Sopenharmony_ci return -(6 * FRAME_SLOT_SIZE); // -6: contains frametype, rbp, pc, sp, callsize, env, 604514f5e3Sopenharmony_ci case SpecialRegister::ACC_REGISTER: 614514f5e3Sopenharmony_ci return -(7 * FRAME_SLOT_SIZE); // -7: contains frametype, rbp, pc, sp, callsize, env, acc, 624514f5e3Sopenharmony_ci case SpecialRegister::THIS_OBJECT: 634514f5e3Sopenharmony_ci return -(8 * FRAME_SLOT_SIZE); // -8: contains frametype, rbp, pc, sp, callsize, env, acc, thisObj 644514f5e3Sopenharmony_ci case SpecialRegister::FUNC: 654514f5e3Sopenharmony_ci // -9: contains frametype, rbp, pc, sp, callsize, env, acc, thisObj, call-target 664514f5e3Sopenharmony_ci return -(9 * FRAME_SLOT_SIZE); 674514f5e3Sopenharmony_ci default: 684514f5e3Sopenharmony_ci LOG_ECMA(FATAL) << "this branch is unreachable"; 694514f5e3Sopenharmony_ci UNREACHABLE(); 704514f5e3Sopenharmony_ci return 0; 714514f5e3Sopenharmony_ci } 724514f5e3Sopenharmony_ci } 734514f5e3Sopenharmony_ciprivate: 744514f5e3Sopenharmony_ci uint64_t callField = 0; 754514f5e3Sopenharmony_ci uint32_t numVregs = 0; 764514f5e3Sopenharmony_ci bool haveNewTarget = false; 774514f5e3Sopenharmony_ci static constexpr int32_t FRAME_SLOT_SIZE = 8; 784514f5e3Sopenharmony_ci}; 794514f5e3Sopenharmony_ci 804514f5e3Sopenharmony_ciclass BaselineAssembler { 814514f5e3Sopenharmony_cipublic: 824514f5e3Sopenharmony_ci explicit BaselineAssembler(const std::string &tripleStr); 834514f5e3Sopenharmony_ci uint8_t *GetBuffer() const 844514f5e3Sopenharmony_ci { 854514f5e3Sopenharmony_ci return macroAssembler->GetBegin(); 864514f5e3Sopenharmony_ci } 874514f5e3Sopenharmony_ci 884514f5e3Sopenharmony_ci size_t GetBufferSize() const 894514f5e3Sopenharmony_ci { 904514f5e3Sopenharmony_ci return macroAssembler->GetBufferCurrentSize(); 914514f5e3Sopenharmony_ci } 924514f5e3Sopenharmony_ci 934514f5e3Sopenharmony_ci void SetStackOffsetDescriptor(const StackOffsetDescriptor &inputStackOffsetDesc) 944514f5e3Sopenharmony_ci { 954514f5e3Sopenharmony_ci stackOffsetDescriptor = inputStackOffsetDesc; 964514f5e3Sopenharmony_ci } 974514f5e3Sopenharmony_ci 984514f5e3Sopenharmony_ci MacroAssembler &GetMacroAssembler() 994514f5e3Sopenharmony_ci { 1004514f5e3Sopenharmony_ci ASSERT(macroAssembler != nullptr); 1014514f5e3Sopenharmony_ci return *macroAssembler; 1024514f5e3Sopenharmony_ci } 1034514f5e3Sopenharmony_ci 1044514f5e3Sopenharmony_ci virtual ~BaselineAssembler() 1054514f5e3Sopenharmony_ci { 1064514f5e3Sopenharmony_ci if (macroAssembler != nullptr) { 1074514f5e3Sopenharmony_ci delete macroAssembler; 1084514f5e3Sopenharmony_ci macroAssembler = nullptr; 1094514f5e3Sopenharmony_ci } 1104514f5e3Sopenharmony_ci } 1114514f5e3Sopenharmony_ci void Move(VirtualRegister interpreterDestReg, Immediate value); 1124514f5e3Sopenharmony_ci void Move(SpecialRegister destReg, Immediate value); 1134514f5e3Sopenharmony_ci void Move(SpecialRegister destReg, SpecialRegister srcReg); 1144514f5e3Sopenharmony_ci void Move(VirtualRegister interpreterDestReg, VirtualRegister interpreterSrcReg); 1154514f5e3Sopenharmony_ci void Move(SpecialRegister destReg, VirtualRegister interpreterSrcReg); 1164514f5e3Sopenharmony_ci void Move(VirtualRegister interpreterDestReg, SpecialRegister srcReg); 1174514f5e3Sopenharmony_ci void Cmp(SpecialRegister reg, Immediate value); 1184514f5e3Sopenharmony_ci 1194514f5e3Sopenharmony_ci void Bind(JumpLabel &label) 1204514f5e3Sopenharmony_ci { 1214514f5e3Sopenharmony_ci macroAssembler->Bind(label); 1224514f5e3Sopenharmony_ci } 1234514f5e3Sopenharmony_ci 1244514f5e3Sopenharmony_ci void Jz(JumpLabel &label) 1254514f5e3Sopenharmony_ci { 1264514f5e3Sopenharmony_ci macroAssembler->Jz(label); 1274514f5e3Sopenharmony_ci } 1284514f5e3Sopenharmony_ci 1294514f5e3Sopenharmony_ci void Jnz(JumpLabel &label) 1304514f5e3Sopenharmony_ci { 1314514f5e3Sopenharmony_ci macroAssembler->Jnz(label); 1324514f5e3Sopenharmony_ci } 1334514f5e3Sopenharmony_ci 1344514f5e3Sopenharmony_ci void Jump(JumpLabel &label) 1354514f5e3Sopenharmony_ci { 1364514f5e3Sopenharmony_ci macroAssembler->Jump(label); 1374514f5e3Sopenharmony_ci } 1384514f5e3Sopenharmony_ci 1394514f5e3Sopenharmony_ci void SaveResultIntoAcc(); 1404514f5e3Sopenharmony_ci void CallBuiltin(Address funcAddress, 1414514f5e3Sopenharmony_ci const std::vector<BaselineParameter> ¶meters); 1424514f5e3Sopenharmony_ci 1434514f5e3Sopenharmony_ciprivate: 1444514f5e3Sopenharmony_ci MacroAssembler *macroAssembler; 1454514f5e3Sopenharmony_ci StackOffsetDescriptor stackOffsetDescriptor; 1464514f5e3Sopenharmony_ci}; 1474514f5e3Sopenharmony_ci} // namespace panda::ecmascript::kungfu 1484514f5e3Sopenharmony_ci#endif // ECMASCRIPT_BASELINE_BASELINE_ASSEMBLER_H 149