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