14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2021 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_COMPILER_GATE_H 174514f5e3Sopenharmony_ci#define ECMASCRIPT_COMPILER_GATE_H 184514f5e3Sopenharmony_ci 194514f5e3Sopenharmony_ci#include <array> 204514f5e3Sopenharmony_ci#include <iostream> 214514f5e3Sopenharmony_ci#include <map> 224514f5e3Sopenharmony_ci#include <optional> 234514f5e3Sopenharmony_ci#include <set> 244514f5e3Sopenharmony_ci#include <sstream> 254514f5e3Sopenharmony_ci#include <string> 264514f5e3Sopenharmony_ci#include <type_traits> 274514f5e3Sopenharmony_ci#include <vector> 284514f5e3Sopenharmony_ci 294514f5e3Sopenharmony_ci#include "ecmascript/compiler/share_gate_meta_data.h" 304514f5e3Sopenharmony_ci#include "ecmascript/compiler/hcr_gate_meta_data.h" 314514f5e3Sopenharmony_ci#include "ecmascript/compiler/mcr_gate_meta_data.h" 324514f5e3Sopenharmony_ci#include "ecmascript/compiler/lcr_gate_meta_data.h" 334514f5e3Sopenharmony_ci#include "ecmascript/compiler/type.h" 344514f5e3Sopenharmony_ci 354514f5e3Sopenharmony_ci#include "libpandabase/macros.h" 364514f5e3Sopenharmony_ci 374514f5e3Sopenharmony_cinamespace panda::ecmascript::kungfu { 384514f5e3Sopenharmony_ciusing BitField = uint64_t; 394514f5e3Sopenharmony_ciusing GateRef = int32_t; // for external users 404514f5e3Sopenharmony_ciusing GateId = uint32_t; 414514f5e3Sopenharmony_ciusing GateOp = uint8_t; 424514f5e3Sopenharmony_ciusing GateMark = uint8_t; 434514f5e3Sopenharmony_ciusing TimeStamp = uint8_t; 444514f5e3Sopenharmony_ciusing SecondaryOp = uint8_t; 454514f5e3Sopenharmony_ciusing OutIdx = uint32_t; 464514f5e3Sopenharmony_ciclass Gate; 474514f5e3Sopenharmony_ciclass BytecodeCircuitBuilder; 484514f5e3Sopenharmony_ci 494514f5e3Sopenharmony_cienum MarkCode : GateMark { 504514f5e3Sopenharmony_ci NO_MARK = 0, 514514f5e3Sopenharmony_ci PREVISIT, 524514f5e3Sopenharmony_ci VISITED, 534514f5e3Sopenharmony_ci FINISHED, 544514f5e3Sopenharmony_ci}; 554514f5e3Sopenharmony_ci 564514f5e3Sopenharmony_ciclass Out { 574514f5e3Sopenharmony_cipublic: 584514f5e3Sopenharmony_ci Out() = default; 594514f5e3Sopenharmony_ci void SetNextOut(const Out *ptr); 604514f5e3Sopenharmony_ci [[nodiscard]] Out *GetNextOut(); 614514f5e3Sopenharmony_ci [[nodiscard]] const Out *GetNextOutConst() const; 624514f5e3Sopenharmony_ci void SetPrevOut(const Out *ptr); 634514f5e3Sopenharmony_ci [[nodiscard]] Out *GetPrevOut(); 644514f5e3Sopenharmony_ci [[nodiscard]] const Out *GetPrevOutConst() const; 654514f5e3Sopenharmony_ci void SetIndex(OutIdx idx); 664514f5e3Sopenharmony_ci [[nodiscard]] OutIdx GetIndex() const; 674514f5e3Sopenharmony_ci [[nodiscard]] Gate *GetGate(); 684514f5e3Sopenharmony_ci [[nodiscard]] const Gate *GetGateConst() const; 694514f5e3Sopenharmony_ci void SetPrevOutNull(); 704514f5e3Sopenharmony_ci [[nodiscard]] bool IsPrevOutNull() const; 714514f5e3Sopenharmony_ci void SetNextOutNull(); 724514f5e3Sopenharmony_ci [[nodiscard]] bool IsNextOutNull() const; 734514f5e3Sopenharmony_ci [[nodiscard]] bool IsStateEdge() const; 744514f5e3Sopenharmony_ci ~Out() = default; 754514f5e3Sopenharmony_ci 764514f5e3Sopenharmony_ciprivate: 774514f5e3Sopenharmony_ci GateRef nextOut_; 784514f5e3Sopenharmony_ci GateRef prevOut_; 794514f5e3Sopenharmony_ci OutIdx idx_; 804514f5e3Sopenharmony_ci}; 814514f5e3Sopenharmony_ci 824514f5e3Sopenharmony_ciclass In { 834514f5e3Sopenharmony_cipublic: 844514f5e3Sopenharmony_ci In() = default; 854514f5e3Sopenharmony_ci void SetGate(const Gate *ptr); 864514f5e3Sopenharmony_ci [[nodiscard]] Gate *GetGate(); 874514f5e3Sopenharmony_ci [[nodiscard]] const Gate *GetGateConst() const; 884514f5e3Sopenharmony_ci void SetGateNull(); 894514f5e3Sopenharmony_ci [[nodiscard]] bool IsGateNull() const; 904514f5e3Sopenharmony_ci ~In() = default; 914514f5e3Sopenharmony_ci 924514f5e3Sopenharmony_ciprivate: 934514f5e3Sopenharmony_ci GateRef gatePtr_; 944514f5e3Sopenharmony_ci}; 954514f5e3Sopenharmony_ci 964514f5e3Sopenharmony_ci// Gate structure 974514f5e3Sopenharmony_ci// for example: 984514f5e3Sopenharmony_ci// ``` 994514f5e3Sopenharmony_ci// g0 = op0(...) 1004514f5e3Sopenharmony_ci// g1 = op1(...) 1014514f5e3Sopenharmony_ci// g2 = op2(g0, g1) 1024514f5e3Sopenharmony_ci// g3 = op3(g2) 1034514f5e3Sopenharmony_ci// g4 = op4(g2, g0, g1) 1044514f5e3Sopenharmony_ci// g5 = op5(g3, g4) 1054514f5e3Sopenharmony_ci 1064514f5e3Sopenharmony_ci// +---- out[1] ----+---- out[0] ----+-------- g2 --------+-- in[0] --+-- in[1] --+ 1074514f5e3Sopenharmony_ci// | | | | | | 1084514f5e3Sopenharmony_ci// | next=null | next=null | ... | | | 1094514f5e3Sopenharmony_ci// | idx=1 | idx=0 | | g0 | g1 | 1104514f5e3Sopenharmony_ci// | prev=g4.out[2] | prev=g4.out[1] | firstOut=g4.out[0] | | | 1114514f5e3Sopenharmony_ci// | | | | | | 1124514f5e3Sopenharmony_ci// +----------------+----------------+--------------------+-----------+-----------+ 1134514f5e3Sopenharmony_ci// ^ ^ 1144514f5e3Sopenharmony_ci// | | 1154514f5e3Sopenharmony_ci// | | 1164514f5e3Sopenharmony_ci// | | +---- out[0] ----+-------- g3 --------+-- in[0] --+ 1174514f5e3Sopenharmony_ci// | | | | | | 1184514f5e3Sopenharmony_ci// | | | next=null | ... | | 1194514f5e3Sopenharmony_ci// | | | idx=0 | | g2 | 1204514f5e3Sopenharmony_ci// | | | prev=g4.out[0] | firstOut=g5.out[0] | | 1214514f5e3Sopenharmony_ci// | | | | | | 1224514f5e3Sopenharmony_ci// | | +----------------+--------------------+-----------+ 1234514f5e3Sopenharmony_ci// | | ^ 1244514f5e3Sopenharmony_ci// | | | 1254514f5e3Sopenharmony_ci// | | | 1264514f5e3Sopenharmony_ci// V V V 1274514f5e3Sopenharmony_ci// +---- out[2] ----+---- out[1] ----+---- out[0] ----+-------- g4 --------+-- in[0] --+-- in[1] --+-- in[2] --+ 1284514f5e3Sopenharmony_ci// | | | | | | | | 1294514f5e3Sopenharmony_ci// | next=g2.out[1] | next=g2.out[0] | next=g3.out[0] | ... | | | | 1304514f5e3Sopenharmony_ci// | idx=2 | idx=1 | idx=0 | | g2 | g0 | g1 | 1314514f5e3Sopenharmony_ci// | prev=null | prev=null | prev=null | firstOut=g5.out[1] | | | | 1324514f5e3Sopenharmony_ci// | | | | | | | | 1334514f5e3Sopenharmony_ci// +----------------+----------------+----------------+--------------------+-----------+-----------+-----------+ 1344514f5e3Sopenharmony_ci// ``` 1354514f5e3Sopenharmony_ci 1364514f5e3Sopenharmony_ciclass Gate { 1374514f5e3Sopenharmony_cipublic: 1384514f5e3Sopenharmony_ci // NOLINTNEXTLINE(modernize-avoid-c-arrays) 1394514f5e3Sopenharmony_ci Gate(const GateMetaData* meta, GateId id, Gate *inList[], MachineType machineType, GateType type); 1404514f5e3Sopenharmony_ci static size_t GetGateSize(size_t numIns) 1414514f5e3Sopenharmony_ci { 1424514f5e3Sopenharmony_ci numIns = (numIns == 0) ? 1 : numIns; 1434514f5e3Sopenharmony_ci return numIns * (sizeof(In) + sizeof(Out)) + sizeof(Gate); 1444514f5e3Sopenharmony_ci } 1454514f5e3Sopenharmony_ci static size_t GetOutListSize(size_t numIns) 1464514f5e3Sopenharmony_ci { 1474514f5e3Sopenharmony_ci numIns = (numIns == 0) ? 1 : numIns; 1484514f5e3Sopenharmony_ci return numIns * sizeof(Out); 1494514f5e3Sopenharmony_ci } 1504514f5e3Sopenharmony_ci void NewIn(size_t idx, Gate *in); 1514514f5e3Sopenharmony_ci void ModifyIn(size_t idx, Gate *in); 1524514f5e3Sopenharmony_ci void DeleteIn(size_t idx); 1534514f5e3Sopenharmony_ci void DeleteGate(); 1544514f5e3Sopenharmony_ci static constexpr GateRef InvalidGateRef = -1; 1554514f5e3Sopenharmony_ci [[nodiscard]] Out *GetOut(size_t idx); 1564514f5e3Sopenharmony_ci [[nodiscard]] Out *GetFirstOut(); 1574514f5e3Sopenharmony_ci [[nodiscard]] const Out *GetOutConst(size_t idx) const; 1584514f5e3Sopenharmony_ci [[nodiscard]] const Out *GetFirstOutConst() const; 1594514f5e3Sopenharmony_ci // note: GetFirstOut() is not equal to GetOut(0) 1604514f5e3Sopenharmony_ci // note: behavior of GetFirstOut() is undefined when there are no Outs 1614514f5e3Sopenharmony_ci // note: use IsFirstOutNull() to check first if there may be no Outs 1624514f5e3Sopenharmony_ci void SetFirstOut(const Out *firstOut); 1634514f5e3Sopenharmony_ci void SetFirstOutNull(); 1644514f5e3Sopenharmony_ci [[nodiscard]] bool IsFirstOutNull() const; 1654514f5e3Sopenharmony_ci [[nodiscard]] In *GetIn(size_t idx); 1664514f5e3Sopenharmony_ci [[nodiscard]] const In *GetInConst(size_t idx) const; 1674514f5e3Sopenharmony_ci [[nodiscard]] Gate *GetInGate(size_t idx); 1684514f5e3Sopenharmony_ci [[nodiscard]] const Gate *GetInGateConst(size_t idx) const; 1694514f5e3Sopenharmony_ci // note: behavior of GetInGate(idx) is undefined when Ins[idx] is deleted or not assigned 1704514f5e3Sopenharmony_ci // note: use IsInGateNull(idx) to check first if Ins[idx] may be deleted or not assigned 1714514f5e3Sopenharmony_ci [[nodiscard]] bool IsInGateNull(size_t idx) const; 1724514f5e3Sopenharmony_ci [[nodiscard]] OpCode GetOpCode() const; 1734514f5e3Sopenharmony_ci [[nodiscard]] GateId GetId() const; 1744514f5e3Sopenharmony_ci [[nodiscard]] size_t GetNumIns() const; 1754514f5e3Sopenharmony_ci [[nodiscard]] size_t GetStateCount() const; 1764514f5e3Sopenharmony_ci [[nodiscard]] size_t GetDependCount() const; 1774514f5e3Sopenharmony_ci [[nodiscard]] size_t GetInValueCount() const; 1784514f5e3Sopenharmony_ci [[nodiscard]] size_t GetInFrameStateCount() const; 1794514f5e3Sopenharmony_ci [[nodiscard]] size_t GetInValueStarts() const; 1804514f5e3Sopenharmony_ci [[nodiscard]] size_t GetRootCount() const; 1814514f5e3Sopenharmony_ci [[nodiscard]] size_t GetInFrameStateStarts() const; 1824514f5e3Sopenharmony_ci void Print(std::string bytecode = "", bool inListPreview = false, size_t highlightIdx = -1, 1834514f5e3Sopenharmony_ci std::string_view comment = "") const; 1844514f5e3Sopenharmony_ci std::string ToString(std::string bytecode = "", bool inListPreview = false, size_t highlightIdx = -1, 1854514f5e3Sopenharmony_ci std::string_view comment = "") const; 1864514f5e3Sopenharmony_ci void ShortPrint(std::string bytecode = "", bool inListPreview = false, size_t highlightIdx = -1) const; 1874514f5e3Sopenharmony_ci size_t PrintInGate(size_t numIns, size_t idx, size_t size, bool inListPreview, size_t highlightIdx, 1884514f5e3Sopenharmony_ci std::ostringstream &log, bool isEnd = false) const; 1894514f5e3Sopenharmony_ci void PrintGateWithAdditionOp(std::string additionOp, std::string_view comment) const; 1904514f5e3Sopenharmony_ci void PrintWithBytecode(std::string_view comment) const; 1914514f5e3Sopenharmony_ci void CheckNullInput() const; 1924514f5e3Sopenharmony_ci void CheckStateInput() const; 1934514f5e3Sopenharmony_ci void CheckValueInput(bool isArch64) const; 1944514f5e3Sopenharmony_ci void CheckDependInput() const; 1954514f5e3Sopenharmony_ci void CheckRootInput() const; 1964514f5e3Sopenharmony_ci void CheckFrameStateInput() const; 1974514f5e3Sopenharmony_ci void CheckStateOutput(const std::string& methodName) const; 1984514f5e3Sopenharmony_ci std::string GetValueInAndOut(bool inListPreview = false, size_t highlightIdx = -1) const; 1994514f5e3Sopenharmony_ci void CheckBranchOutput() const; 2004514f5e3Sopenharmony_ci void CheckNOP() const; 2014514f5e3Sopenharmony_ci void CheckSelector() const; 2024514f5e3Sopenharmony_ci void CheckRelay() const; 2034514f5e3Sopenharmony_ci void Verify(bool isArch64, const std::string& methodName) const; 2044514f5e3Sopenharmony_ci [[nodiscard]] MarkCode GetMark(TimeStamp stamp) const; 2054514f5e3Sopenharmony_ci void SetMark(MarkCode mark, TimeStamp stamp); 2064514f5e3Sopenharmony_ci MachineType GetMachineType() const 2074514f5e3Sopenharmony_ci { 2084514f5e3Sopenharmony_ci return machineType_; 2094514f5e3Sopenharmony_ci } 2104514f5e3Sopenharmony_ci void SetMachineType(MachineType machineType) 2114514f5e3Sopenharmony_ci { 2124514f5e3Sopenharmony_ci machineType_ = machineType; 2134514f5e3Sopenharmony_ci } 2144514f5e3Sopenharmony_ci GateType GetGateType() const 2154514f5e3Sopenharmony_ci { 2164514f5e3Sopenharmony_ci return type_; 2174514f5e3Sopenharmony_ci } 2184514f5e3Sopenharmony_ci void SetGateType(GateType type) 2194514f5e3Sopenharmony_ci { 2204514f5e3Sopenharmony_ci type_ = type; 2214514f5e3Sopenharmony_ci } 2224514f5e3Sopenharmony_ci const GateMetaData* GetMetaData() const 2234514f5e3Sopenharmony_ci { 2244514f5e3Sopenharmony_ci return meta_; 2254514f5e3Sopenharmony_ci } 2264514f5e3Sopenharmony_ci 2274514f5e3Sopenharmony_ci const OneParameterMetaData* GetOneParameterMetaData() const 2284514f5e3Sopenharmony_ci { 2294514f5e3Sopenharmony_ci return OneParameterMetaData::Cast(meta_); 2304514f5e3Sopenharmony_ci } 2314514f5e3Sopenharmony_ci 2324514f5e3Sopenharmony_ci const StringMetaData* GetStringMetaData() const 2334514f5e3Sopenharmony_ci { 2344514f5e3Sopenharmony_ci ASSERT(meta_->IsStringType()); 2354514f5e3Sopenharmony_ci return static_cast<const StringMetaData*>(meta_); 2364514f5e3Sopenharmony_ci } 2374514f5e3Sopenharmony_ci 2384514f5e3Sopenharmony_ci const JSBytecodeMetaData* GetJSBytecodeMetaData() const 2394514f5e3Sopenharmony_ci { 2404514f5e3Sopenharmony_ci return JSBytecodeMetaData::Cast(meta_); 2414514f5e3Sopenharmony_ci } 2424514f5e3Sopenharmony_ci 2434514f5e3Sopenharmony_ci const BoolMetaData* GetBoolMetaData() const 2444514f5e3Sopenharmony_ci { 2454514f5e3Sopenharmony_ci return BoolMetaData::Cast(meta_); 2464514f5e3Sopenharmony_ci } 2474514f5e3Sopenharmony_ci 2484514f5e3Sopenharmony_ci const TypedCallMetaData* GetTypedCallMetaData() const 2494514f5e3Sopenharmony_ci { 2504514f5e3Sopenharmony_ci return TypedCallMetaData::Cast(meta_); 2514514f5e3Sopenharmony_ci } 2524514f5e3Sopenharmony_ci 2534514f5e3Sopenharmony_ci const NewConstructMetaData* GetNewConstructMetaData() const 2544514f5e3Sopenharmony_ci { 2554514f5e3Sopenharmony_ci return NewConstructMetaData::Cast(meta_); 2564514f5e3Sopenharmony_ci } 2574514f5e3Sopenharmony_ci 2584514f5e3Sopenharmony_ci std::string MachineTypeStr(MachineType machineType) const; 2594514f5e3Sopenharmony_ci std::string GateTypeStr(GateType gateType) const; 2604514f5e3Sopenharmony_ci ~Gate() = default; 2614514f5e3Sopenharmony_ci 2624514f5e3Sopenharmony_ciprivate: 2634514f5e3Sopenharmony_ci friend class Circuit; 2644514f5e3Sopenharmony_ci friend class GateAccessor; 2654514f5e3Sopenharmony_ci void CheckInputOpcode(size_t idx, OpCode expected) const; 2664514f5e3Sopenharmony_ci void CheckInputMachineType(size_t idx, MachineType expected, bool isArch64) const; 2674514f5e3Sopenharmony_ci void CheckNotInputMachineType(size_t idx, MachineType notExpected) const; 2684514f5e3Sopenharmony_ci void CheckState(size_t idx) const; 2694514f5e3Sopenharmony_ci void CheckGeneralState(size_t idx) const; 2704514f5e3Sopenharmony_ci void CheckFailed(std::string errorString, size_t highlightIdx) const; 2714514f5e3Sopenharmony_ci void SetMetaData(const GateMetaData* meta) 2724514f5e3Sopenharmony_ci { 2734514f5e3Sopenharmony_ci meta_ = meta; 2744514f5e3Sopenharmony_ci } 2754514f5e3Sopenharmony_ci uint64_t TryGetValue() const 2764514f5e3Sopenharmony_ci { 2774514f5e3Sopenharmony_ci if (meta_->IsOneParameterKind()) { 2784514f5e3Sopenharmony_ci return GetOneParameterMetaData()->GetValue(); 2794514f5e3Sopenharmony_ci } 2804514f5e3Sopenharmony_ci return 0; 2814514f5e3Sopenharmony_ci } 2824514f5e3Sopenharmony_ci void DumpHeader(std::ostringstream &oss, const std::string& additionOp) const; 2834514f5e3Sopenharmony_ci 2844514f5e3Sopenharmony_ci void DumpInputs(std::ostringstream &oss, bool inListPreview, size_t highlightIdx) const; 2854514f5e3Sopenharmony_ci 2864514f5e3Sopenharmony_ci void DumpOutputs(std::ostringstream &oss, bool inListPreview) const; 2874514f5e3Sopenharmony_ci std::string GetBytecodeStr() const; 2884514f5e3Sopenharmony_ci 2894514f5e3Sopenharmony_ci // ... 2904514f5e3Sopenharmony_ci // out(2) 2914514f5e3Sopenharmony_ci // out(1) 2924514f5e3Sopenharmony_ci // out(0) 2934514f5e3Sopenharmony_ci const GateMetaData *meta_ { nullptr }; // uintptr_t 2944514f5e3Sopenharmony_ci GateId id_ { 0 }; // uint32_t 2954514f5e3Sopenharmony_ci GateType type_ { GateType::Empty() }; // uint32_t 2964514f5e3Sopenharmony_ci MachineType machineType_ { MachineType::NOVALUE }; // uint8_t 2974514f5e3Sopenharmony_ci TimeStamp stamp_ { 0 }; // uint8_t 2984514f5e3Sopenharmony_ci MarkCode mark_ { MarkCode::NO_MARK }; // uint8_t 2994514f5e3Sopenharmony_ci uint8_t bitField_ { 0 }; 3004514f5e3Sopenharmony_ci GateRef firstOut_ { 0 }; // int32_t 3014514f5e3Sopenharmony_ci // in(0) 3024514f5e3Sopenharmony_ci // in(1) 3034514f5e3Sopenharmony_ci // in(2) 3044514f5e3Sopenharmony_ci // ... 3054514f5e3Sopenharmony_ci}; 3064514f5e3Sopenharmony_ci} // namespace panda::ecmascript::kungfu 3074514f5e3Sopenharmony_ci 3084514f5e3Sopenharmony_ci#endif // ECMASCRIPT_COMPILER_GATE_H 309