14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2021-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_COMPILER_CIRCUIT_BUILDER_HELPER_H
174514f5e3Sopenharmony_ci#define ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_HELPER_H
184514f5e3Sopenharmony_ci
194514f5e3Sopenharmony_ci#include "ecmascript/compiler/circuit_builder.h"
204514f5e3Sopenharmony_ci
214514f5e3Sopenharmony_cinamespace panda::ecmascript {
224514f5e3Sopenharmony_ci    class JSRuntimeOptions;
234514f5e3Sopenharmony_ci} // namespace panda::ecmascript
244514f5e3Sopenharmony_ci
254514f5e3Sopenharmony_cinamespace panda::ecmascript::kungfu {
264514f5e3Sopenharmony_ci
274514f5e3Sopenharmony_ciclass CompilationConfig {
284514f5e3Sopenharmony_cipublic:
294514f5e3Sopenharmony_ci    explicit CompilationConfig(const std::string &triple, const JSRuntimeOptions *options = nullptr);
304514f5e3Sopenharmony_ci    ~CompilationConfig() = default;
314514f5e3Sopenharmony_ci
324514f5e3Sopenharmony_ci    inline bool Is32Bit() const
334514f5e3Sopenharmony_ci    {
344514f5e3Sopenharmony_ci        return triple_ == Triple::TRIPLE_ARM32;
354514f5e3Sopenharmony_ci    }
364514f5e3Sopenharmony_ci
374514f5e3Sopenharmony_ci    inline bool IsAArch64() const
384514f5e3Sopenharmony_ci    {
394514f5e3Sopenharmony_ci        return triple_ == Triple::TRIPLE_AARCH64;
404514f5e3Sopenharmony_ci    }
414514f5e3Sopenharmony_ci
424514f5e3Sopenharmony_ci    inline bool IsAmd64() const
434514f5e3Sopenharmony_ci    {
444514f5e3Sopenharmony_ci        return triple_ == Triple::TRIPLE_AMD64;
454514f5e3Sopenharmony_ci    }
464514f5e3Sopenharmony_ci
474514f5e3Sopenharmony_ci    inline bool Is64Bit() const
484514f5e3Sopenharmony_ci    {
494514f5e3Sopenharmony_ci        return IsAArch64() || IsAmd64();
504514f5e3Sopenharmony_ci    }
514514f5e3Sopenharmony_ci
524514f5e3Sopenharmony_ci    Triple GetTriple() const
534514f5e3Sopenharmony_ci    {
544514f5e3Sopenharmony_ci        return triple_;
554514f5e3Sopenharmony_ci    }
564514f5e3Sopenharmony_ci
574514f5e3Sopenharmony_ci    std::string GetTripleStr() const
584514f5e3Sopenharmony_ci    {
594514f5e3Sopenharmony_ci        return tripleStr_;
604514f5e3Sopenharmony_ci    }
614514f5e3Sopenharmony_ci
624514f5e3Sopenharmony_ci    bool IsTraceBC() const
634514f5e3Sopenharmony_ci    {
644514f5e3Sopenharmony_ci        return isTraceBc_;
654514f5e3Sopenharmony_ci    }
664514f5e3Sopenharmony_ci
674514f5e3Sopenharmony_ci    bool IsProfiling() const
684514f5e3Sopenharmony_ci    {
694514f5e3Sopenharmony_ci        return profiling_;
704514f5e3Sopenharmony_ci    }
714514f5e3Sopenharmony_ci
724514f5e3Sopenharmony_ci    bool IsStressDeopt() const
734514f5e3Sopenharmony_ci    {
744514f5e3Sopenharmony_ci        return stressDeopt_;
754514f5e3Sopenharmony_ci    }
764514f5e3Sopenharmony_ci
774514f5e3Sopenharmony_ci    bool IsVerifyVTbale() const
784514f5e3Sopenharmony_ci    {
794514f5e3Sopenharmony_ci        return verifyVTable_;
804514f5e3Sopenharmony_ci    }
814514f5e3Sopenharmony_ci
824514f5e3Sopenharmony_ci    bool IsTypedOpProfiling() const
834514f5e3Sopenharmony_ci    {
844514f5e3Sopenharmony_ci        return typedOpProfiling_;
854514f5e3Sopenharmony_ci    }
864514f5e3Sopenharmony_ci
874514f5e3Sopenharmony_ciprivate:
884514f5e3Sopenharmony_ci    inline Triple GetTripleFromString(const std::string &triple)
894514f5e3Sopenharmony_ci    {
904514f5e3Sopenharmony_ci        if (triple.compare(TARGET_X64) == 0) {
914514f5e3Sopenharmony_ci            return Triple::TRIPLE_AMD64;
924514f5e3Sopenharmony_ci        }
934514f5e3Sopenharmony_ci
944514f5e3Sopenharmony_ci        if (triple.compare(TARGET_AARCH64) == 0) {
954514f5e3Sopenharmony_ci            return Triple::TRIPLE_AARCH64;
964514f5e3Sopenharmony_ci        }
974514f5e3Sopenharmony_ci
984514f5e3Sopenharmony_ci        if (triple.compare(TARGET_ARM32) == 0) {
994514f5e3Sopenharmony_ci            return Triple::TRIPLE_ARM32;
1004514f5e3Sopenharmony_ci        }
1014514f5e3Sopenharmony_ci        LOG_ECMA(FATAL) << "this branch is unreachable";
1024514f5e3Sopenharmony_ci        UNREACHABLE();
1034514f5e3Sopenharmony_ci    }
1044514f5e3Sopenharmony_ci    std::string tripleStr_;
1054514f5e3Sopenharmony_ci    Triple triple_;
1064514f5e3Sopenharmony_ci    bool isTraceBc_ {false};
1074514f5e3Sopenharmony_ci    bool profiling_ {false};
1084514f5e3Sopenharmony_ci    bool stressDeopt_ {false};
1094514f5e3Sopenharmony_ci    bool verifyVTable_ {false};
1104514f5e3Sopenharmony_ci    bool typedOpProfiling_ {false};
1114514f5e3Sopenharmony_ci};
1124514f5e3Sopenharmony_ci
1134514f5e3Sopenharmony_ciclass Label {
1144514f5e3Sopenharmony_cipublic:
1154514f5e3Sopenharmony_ci    Label() = default;
1164514f5e3Sopenharmony_ci    explicit Label(Environment *env);
1174514f5e3Sopenharmony_ci    explicit Label(CircuitBuilder *cirBuilder);
1184514f5e3Sopenharmony_ci    ~Label() = default;
1194514f5e3Sopenharmony_ci    Label(Label const &label) = default;
1204514f5e3Sopenharmony_ci    Label &operator=(Label const &label) = default;
1214514f5e3Sopenharmony_ci    Label(Label &&label) = default;
1224514f5e3Sopenharmony_ci    Label &operator=(Label &&label) = default;
1234514f5e3Sopenharmony_ci    inline void Seal()
1244514f5e3Sopenharmony_ci    {
1254514f5e3Sopenharmony_ci        return impl_->Seal();
1264514f5e3Sopenharmony_ci    }
1274514f5e3Sopenharmony_ci    inline void WriteVariable(Variable *var, GateRef value)
1284514f5e3Sopenharmony_ci    {
1294514f5e3Sopenharmony_ci        impl_->WriteVariable(var, value);
1304514f5e3Sopenharmony_ci    }
1314514f5e3Sopenharmony_ci    inline GateRef ReadVariable(Variable *var)
1324514f5e3Sopenharmony_ci    {
1334514f5e3Sopenharmony_ci        return impl_->ReadVariable(var);
1344514f5e3Sopenharmony_ci    }
1354514f5e3Sopenharmony_ci    inline void Bind()
1364514f5e3Sopenharmony_ci    {
1374514f5e3Sopenharmony_ci        impl_->Bind();
1384514f5e3Sopenharmony_ci    }
1394514f5e3Sopenharmony_ci    inline void MergeAllControl()
1404514f5e3Sopenharmony_ci    {
1414514f5e3Sopenharmony_ci        impl_->MergeAllControl();
1424514f5e3Sopenharmony_ci    }
1434514f5e3Sopenharmony_ci    inline void MergeAllDepend()
1444514f5e3Sopenharmony_ci    {
1454514f5e3Sopenharmony_ci        impl_->MergeAllDepend();
1464514f5e3Sopenharmony_ci    }
1474514f5e3Sopenharmony_ci    inline void AppendPredecessor(const Label *predecessor)
1484514f5e3Sopenharmony_ci    {
1494514f5e3Sopenharmony_ci        impl_->AppendPredecessor(predecessor->GetRawLabel());
1504514f5e3Sopenharmony_ci    }
1514514f5e3Sopenharmony_ci    inline std::vector<Label> GetPredecessors() const
1524514f5e3Sopenharmony_ci    {
1534514f5e3Sopenharmony_ci        std::vector<Label> labels;
1544514f5e3Sopenharmony_ci        for (auto rawlabel : impl_->GetPredecessors()) {
1554514f5e3Sopenharmony_ci            labels.emplace_back(Label(rawlabel));
1564514f5e3Sopenharmony_ci        }
1574514f5e3Sopenharmony_ci        return labels;
1584514f5e3Sopenharmony_ci    }
1594514f5e3Sopenharmony_ci    inline void SetControl(GateRef control)
1604514f5e3Sopenharmony_ci    {
1614514f5e3Sopenharmony_ci        impl_->SetControl(control);
1624514f5e3Sopenharmony_ci    }
1634514f5e3Sopenharmony_ci    inline void SetPreControl(GateRef control)
1644514f5e3Sopenharmony_ci    {
1654514f5e3Sopenharmony_ci        impl_->SetPreControl(control);
1664514f5e3Sopenharmony_ci    }
1674514f5e3Sopenharmony_ci    inline void MergeControl(GateRef control)
1684514f5e3Sopenharmony_ci    {
1694514f5e3Sopenharmony_ci        impl_->MergeControl(control);
1704514f5e3Sopenharmony_ci    }
1714514f5e3Sopenharmony_ci    inline GateRef GetControl() const
1724514f5e3Sopenharmony_ci    {
1734514f5e3Sopenharmony_ci        return impl_->GetControl();
1744514f5e3Sopenharmony_ci    }
1754514f5e3Sopenharmony_ci    inline GateRef GetDepend() const
1764514f5e3Sopenharmony_ci    {
1774514f5e3Sopenharmony_ci        return impl_->GetDepend();
1784514f5e3Sopenharmony_ci    }
1794514f5e3Sopenharmony_ci    inline void SetDepend(GateRef depend)
1804514f5e3Sopenharmony_ci    {
1814514f5e3Sopenharmony_ci        return impl_->SetDepend(depend);
1824514f5e3Sopenharmony_ci    }
1834514f5e3Sopenharmony_ci
1844514f5e3Sopenharmony_ciprivate:
1854514f5e3Sopenharmony_ci    class LabelImpl {
1864514f5e3Sopenharmony_ci    public:
1874514f5e3Sopenharmony_ci        LabelImpl(Environment *env, GateRef control)
1884514f5e3Sopenharmony_ci            : env_(env), control_(control), predeControl_(-1), isSealed_(false)
1894514f5e3Sopenharmony_ci        {
1904514f5e3Sopenharmony_ci        }
1914514f5e3Sopenharmony_ci        ~LabelImpl() = default;
1924514f5e3Sopenharmony_ci        NO_MOVE_SEMANTIC(LabelImpl);
1934514f5e3Sopenharmony_ci        NO_COPY_SEMANTIC(LabelImpl);
1944514f5e3Sopenharmony_ci        void Seal();
1954514f5e3Sopenharmony_ci        void WriteVariable(Variable *var, GateRef value);
1964514f5e3Sopenharmony_ci        GateRef ReadVariable(Variable *var);
1974514f5e3Sopenharmony_ci        void Bind();
1984514f5e3Sopenharmony_ci        void MergeAllControl();
1994514f5e3Sopenharmony_ci        void MergeAllDepend();
2004514f5e3Sopenharmony_ci        void AppendPredecessor(LabelImpl *predecessor);
2014514f5e3Sopenharmony_ci        std::vector<LabelImpl *> GetPredecessors() const
2024514f5e3Sopenharmony_ci        {
2034514f5e3Sopenharmony_ci            return predecessors_;
2044514f5e3Sopenharmony_ci        }
2054514f5e3Sopenharmony_ci        void SetControl(GateRef control)
2064514f5e3Sopenharmony_ci        {
2074514f5e3Sopenharmony_ci            control_ = control;
2084514f5e3Sopenharmony_ci        }
2094514f5e3Sopenharmony_ci        void SetPreControl(GateRef control)
2104514f5e3Sopenharmony_ci        {
2114514f5e3Sopenharmony_ci            predeControl_ = control;
2124514f5e3Sopenharmony_ci        }
2134514f5e3Sopenharmony_ci        void MergeControl(GateRef control)
2144514f5e3Sopenharmony_ci        {
2154514f5e3Sopenharmony_ci            if (predeControl_ == Circuit::NullGate()) {
2164514f5e3Sopenharmony_ci                predeControl_ = control;
2174514f5e3Sopenharmony_ci                control_ = predeControl_;
2184514f5e3Sopenharmony_ci            } else {
2194514f5e3Sopenharmony_ci                otherPredeControls_.push_back(control);
2204514f5e3Sopenharmony_ci            }
2214514f5e3Sopenharmony_ci        }
2224514f5e3Sopenharmony_ci        GateRef GetControl() const
2234514f5e3Sopenharmony_ci        {
2244514f5e3Sopenharmony_ci            return control_;
2254514f5e3Sopenharmony_ci        }
2264514f5e3Sopenharmony_ci        void SetDepend(GateRef depend)
2274514f5e3Sopenharmony_ci        {
2284514f5e3Sopenharmony_ci            depend_ = depend;
2294514f5e3Sopenharmony_ci        }
2304514f5e3Sopenharmony_ci        GateRef GetDepend() const
2314514f5e3Sopenharmony_ci        {
2324514f5e3Sopenharmony_ci            return depend_;
2334514f5e3Sopenharmony_ci        }
2344514f5e3Sopenharmony_ci
2354514f5e3Sopenharmony_ci    private:
2364514f5e3Sopenharmony_ci        bool IsNeedSeal() const;
2374514f5e3Sopenharmony_ci        bool IsSealed() const
2384514f5e3Sopenharmony_ci        {
2394514f5e3Sopenharmony_ci            return isSealed_;
2404514f5e3Sopenharmony_ci        }
2414514f5e3Sopenharmony_ci        bool IsLoopHead() const;
2424514f5e3Sopenharmony_ci        bool IsControlCase() const;
2434514f5e3Sopenharmony_ci        GateRef ReadVariableRecursive(Variable *var);
2444514f5e3Sopenharmony_ci        Environment *env_;
2454514f5e3Sopenharmony_ci        GateRef control_;
2464514f5e3Sopenharmony_ci        GateRef predeControl_ {Circuit::NullGate()};
2474514f5e3Sopenharmony_ci        GateRef depend_ {Circuit::NullGate()};
2484514f5e3Sopenharmony_ci        GateRef loopDepend_ {Circuit::NullGate()};
2494514f5e3Sopenharmony_ci        std::vector<GateRef> otherPredeControls_;
2504514f5e3Sopenharmony_ci        bool isSealed_ {false};
2514514f5e3Sopenharmony_ci        std::map<Variable *, GateRef> valueMap_;
2524514f5e3Sopenharmony_ci        std::vector<GateRef> phi;
2534514f5e3Sopenharmony_ci        std::vector<LabelImpl *> predecessors_;
2544514f5e3Sopenharmony_ci        std::map<Variable *, GateRef> incompletePhis_;
2554514f5e3Sopenharmony_ci    };
2564514f5e3Sopenharmony_ci
2574514f5e3Sopenharmony_ci    explicit Label(LabelImpl *impl) : impl_(impl) {}
2584514f5e3Sopenharmony_ci    friend class Environment;
2594514f5e3Sopenharmony_ci    LabelImpl *GetRawLabel() const
2604514f5e3Sopenharmony_ci    {
2614514f5e3Sopenharmony_ci        return impl_;
2624514f5e3Sopenharmony_ci    }
2634514f5e3Sopenharmony_ci    LabelImpl *impl_ {nullptr};
2644514f5e3Sopenharmony_ci};
2654514f5e3Sopenharmony_ci
2664514f5e3Sopenharmony_ciclass Environment {
2674514f5e3Sopenharmony_cipublic:
2684514f5e3Sopenharmony_ci    using LabelImpl = Label::LabelImpl;
2694514f5e3Sopenharmony_ci    Environment(GateRef hir, Circuit *circuit, CircuitBuilder *builder);
2704514f5e3Sopenharmony_ci    Environment(GateRef stateEntry, GateRef dependEntry, const std::initializer_list<GateRef>& args,
2714514f5e3Sopenharmony_ci                Circuit *circuit, CircuitBuilder *builder);
2724514f5e3Sopenharmony_ci    Environment(size_t arguments, CircuitBuilder *builder);
2734514f5e3Sopenharmony_ci    ~Environment();
2744514f5e3Sopenharmony_ci    Label *GetCurrentLabel() const
2754514f5e3Sopenharmony_ci    {
2764514f5e3Sopenharmony_ci        return currentLabel_;
2774514f5e3Sopenharmony_ci    }
2784514f5e3Sopenharmony_ci    void SetCurrentLabel(Label *label)
2794514f5e3Sopenharmony_ci    {
2804514f5e3Sopenharmony_ci        currentLabel_ = label;
2814514f5e3Sopenharmony_ci    }
2824514f5e3Sopenharmony_ci    CircuitBuilder *GetBuilder() const
2834514f5e3Sopenharmony_ci    {
2844514f5e3Sopenharmony_ci        return circuitBuilder_;
2854514f5e3Sopenharmony_ci    }
2864514f5e3Sopenharmony_ci    Circuit *GetCircuit() const
2874514f5e3Sopenharmony_ci    {
2884514f5e3Sopenharmony_ci        return circuit_;
2894514f5e3Sopenharmony_ci    }
2904514f5e3Sopenharmony_ci    int NextVariableId()
2914514f5e3Sopenharmony_ci    {
2924514f5e3Sopenharmony_ci        return nextVariableId_++;
2934514f5e3Sopenharmony_ci    }
2944514f5e3Sopenharmony_ci    void SetCompilationConfig(const CompilationConfig *cfg)
2954514f5e3Sopenharmony_ci    {
2964514f5e3Sopenharmony_ci        ccfg_ = cfg;
2974514f5e3Sopenharmony_ci    }
2984514f5e3Sopenharmony_ci    const CompilationConfig *GetCompilationConfig() const
2994514f5e3Sopenharmony_ci    {
3004514f5e3Sopenharmony_ci        return ccfg_;
3014514f5e3Sopenharmony_ci    }
3024514f5e3Sopenharmony_ci    inline bool Is32Bit() const
3034514f5e3Sopenharmony_ci    {
3044514f5e3Sopenharmony_ci        return ccfg_->Is32Bit();
3054514f5e3Sopenharmony_ci    }
3064514f5e3Sopenharmony_ci    inline bool IsAArch64() const
3074514f5e3Sopenharmony_ci    {
3084514f5e3Sopenharmony_ci        return ccfg_->IsAArch64();
3094514f5e3Sopenharmony_ci    }
3104514f5e3Sopenharmony_ci    inline bool IsAmd64() const
3114514f5e3Sopenharmony_ci    {
3124514f5e3Sopenharmony_ci        return ccfg_->IsAmd64();
3134514f5e3Sopenharmony_ci    }
3144514f5e3Sopenharmony_ci    inline bool IsArch64Bit() const
3154514f5e3Sopenharmony_ci    {
3164514f5e3Sopenharmony_ci        return ccfg_->IsAmd64() ||  ccfg_->IsAArch64();
3174514f5e3Sopenharmony_ci    }
3184514f5e3Sopenharmony_ci    inline bool IsAsmInterp() const
3194514f5e3Sopenharmony_ci    {
3204514f5e3Sopenharmony_ci        return circuit_->GetFrameType() == FrameType::ASM_INTERPRETER_FRAME;
3214514f5e3Sopenharmony_ci    }
3224514f5e3Sopenharmony_ci    inline bool IsBaselineBuiltin() const
3234514f5e3Sopenharmony_ci    {
3244514f5e3Sopenharmony_ci        return circuit_->GetFrameType() == FrameType::BASELINE_BUILTIN_FRAME;
3254514f5e3Sopenharmony_ci    }
3264514f5e3Sopenharmony_ci    inline bool IsArch32Bit() const
3274514f5e3Sopenharmony_ci    {
3284514f5e3Sopenharmony_ci        return ccfg_->Is32Bit();
3294514f5e3Sopenharmony_ci    }
3304514f5e3Sopenharmony_ci    inline GateRef GetArgument(size_t index) const
3314514f5e3Sopenharmony_ci    {
3324514f5e3Sopenharmony_ci        return arguments_.at(index);
3334514f5e3Sopenharmony_ci    }
3344514f5e3Sopenharmony_ci    inline Label GetLabelFromSelector(GateRef sel)
3354514f5e3Sopenharmony_ci    {
3364514f5e3Sopenharmony_ci        Label::LabelImpl *rawlabel = phiToLabels_[sel];
3374514f5e3Sopenharmony_ci        return Label(rawlabel);
3384514f5e3Sopenharmony_ci    }
3394514f5e3Sopenharmony_ci    inline void AddSelectorToLabel(GateRef sel, Label label)
3404514f5e3Sopenharmony_ci    {
3414514f5e3Sopenharmony_ci        phiToLabels_[sel] = label.GetRawLabel();
3424514f5e3Sopenharmony_ci    }
3434514f5e3Sopenharmony_ci    inline LabelImpl *NewLabel(Environment *env, GateRef control = -1)
3444514f5e3Sopenharmony_ci    {
3454514f5e3Sopenharmony_ci        auto impl = new Label::LabelImpl(env, control);
3464514f5e3Sopenharmony_ci        rawLabels_.emplace_back(impl);
3474514f5e3Sopenharmony_ci        return impl;
3484514f5e3Sopenharmony_ci    }
3494514f5e3Sopenharmony_ci    void SubCfgEntry(Label *entry)
3504514f5e3Sopenharmony_ci    {
3514514f5e3Sopenharmony_ci        if (currentLabel_ != nullptr) {
3524514f5e3Sopenharmony_ci            GateRef control = currentLabel_->GetControl();
3534514f5e3Sopenharmony_ci            GateRef depend = currentLabel_->GetDepend();
3544514f5e3Sopenharmony_ci            stack_.push(currentLabel_);
3554514f5e3Sopenharmony_ci            currentLabel_ = entry;
3564514f5e3Sopenharmony_ci            currentLabel_->SetControl(control);
3574514f5e3Sopenharmony_ci            currentLabel_->SetDepend(depend);
3584514f5e3Sopenharmony_ci        }
3594514f5e3Sopenharmony_ci    }
3604514f5e3Sopenharmony_ci    void SubCfgExit()
3614514f5e3Sopenharmony_ci    {
3624514f5e3Sopenharmony_ci        if (currentLabel_ != nullptr) {
3634514f5e3Sopenharmony_ci            GateRef control = currentLabel_->GetControl();
3644514f5e3Sopenharmony_ci            GateRef depend = currentLabel_->GetDepend();
3654514f5e3Sopenharmony_ci            if (!stack_.empty()) {
3664514f5e3Sopenharmony_ci                currentLabel_ = stack_.top();
3674514f5e3Sopenharmony_ci                currentLabel_->SetControl(control);
3684514f5e3Sopenharmony_ci                currentLabel_->SetDepend(depend);
3694514f5e3Sopenharmony_ci                stack_.pop();
3704514f5e3Sopenharmony_ci            }
3714514f5e3Sopenharmony_ci        }
3724514f5e3Sopenharmony_ci    }
3734514f5e3Sopenharmony_ci    inline GateRef GetInput(size_t index) const
3744514f5e3Sopenharmony_ci    {
3754514f5e3Sopenharmony_ci        return inputList_.at(index);
3764514f5e3Sopenharmony_ci    }
3774514f5e3Sopenharmony_ci
3784514f5e3Sopenharmony_ciprivate:
3794514f5e3Sopenharmony_ci    Label *currentLabel_ {nullptr};
3804514f5e3Sopenharmony_ci    Circuit *circuit_ {nullptr};
3814514f5e3Sopenharmony_ci    CircuitBuilder *circuitBuilder_ {nullptr};
3824514f5e3Sopenharmony_ci    std::unordered_map<GateRef, LabelImpl *> phiToLabels_;
3834514f5e3Sopenharmony_ci    std::vector<GateRef> inputList_;
3844514f5e3Sopenharmony_ci    Label entry_;
3854514f5e3Sopenharmony_ci    std::vector<LabelImpl *> rawLabels_;
3864514f5e3Sopenharmony_ci    std::stack<Label *> stack_;
3874514f5e3Sopenharmony_ci    int nextVariableId_ {0};
3884514f5e3Sopenharmony_ci    std::vector<GateRef> arguments_;
3894514f5e3Sopenharmony_ci    const CompilationConfig *ccfg_ {nullptr};
3904514f5e3Sopenharmony_ci};
3914514f5e3Sopenharmony_ci
3924514f5e3Sopenharmony_ciclass Variable {
3934514f5e3Sopenharmony_cipublic:
3944514f5e3Sopenharmony_ci    Variable(Environment *env, VariableType type, uint32_t id, GateRef value) : id_(id), type_(type), env_(env)
3954514f5e3Sopenharmony_ci    {
3964514f5e3Sopenharmony_ci        Bind(value);
3974514f5e3Sopenharmony_ci        env_->GetCurrentLabel()->WriteVariable(this, value);
3984514f5e3Sopenharmony_ci    }
3994514f5e3Sopenharmony_ci    Variable(CircuitBuilder *cirbuilder, VariableType type, uint32_t id, GateRef value)
4004514f5e3Sopenharmony_ci        : id_(id), type_(type), env_(cirbuilder->GetCurrentEnvironment())
4014514f5e3Sopenharmony_ci    {
4024514f5e3Sopenharmony_ci        Bind(value);
4034514f5e3Sopenharmony_ci        env_->GetCurrentLabel()->WriteVariable(this, value);
4044514f5e3Sopenharmony_ci    }
4054514f5e3Sopenharmony_ci    ~Variable() = default;
4064514f5e3Sopenharmony_ci    NO_MOVE_SEMANTIC(Variable);
4074514f5e3Sopenharmony_ci    NO_COPY_SEMANTIC(Variable);
4084514f5e3Sopenharmony_ci    void Bind(GateRef value)
4094514f5e3Sopenharmony_ci    {
4104514f5e3Sopenharmony_ci        currentValue_ = value;
4114514f5e3Sopenharmony_ci    }
4124514f5e3Sopenharmony_ci    GateRef Value() const
4134514f5e3Sopenharmony_ci    {
4144514f5e3Sopenharmony_ci        return currentValue_;
4154514f5e3Sopenharmony_ci    }
4164514f5e3Sopenharmony_ci    VariableType Type() const
4174514f5e3Sopenharmony_ci    {
4184514f5e3Sopenharmony_ci        return type_;
4194514f5e3Sopenharmony_ci    }
4204514f5e3Sopenharmony_ci    bool IsBound() const
4214514f5e3Sopenharmony_ci    {
4224514f5e3Sopenharmony_ci        return currentValue_ != 0;
4234514f5e3Sopenharmony_ci    }
4244514f5e3Sopenharmony_ci    Variable &operator=(const GateRef value)
4254514f5e3Sopenharmony_ci    {
4264514f5e3Sopenharmony_ci        env_->GetCurrentLabel()->WriteVariable(this, value);
4274514f5e3Sopenharmony_ci        Bind(value);
4284514f5e3Sopenharmony_ci        return *this;
4294514f5e3Sopenharmony_ci    }
4304514f5e3Sopenharmony_ci    GateRef operator*()
4314514f5e3Sopenharmony_ci    {
4324514f5e3Sopenharmony_ci        return env_->GetCurrentLabel()->ReadVariable(this);
4334514f5e3Sopenharmony_ci    }
4344514f5e3Sopenharmony_ci    GateRef ReadVariable()
4354514f5e3Sopenharmony_ci    {
4364514f5e3Sopenharmony_ci        return env_->GetCurrentLabel()->ReadVariable(this);
4374514f5e3Sopenharmony_ci    }
4384514f5e3Sopenharmony_ci    void WriteVariable(GateRef value)
4394514f5e3Sopenharmony_ci    {
4404514f5e3Sopenharmony_ci        env_->GetCurrentLabel()->WriteVariable(this, value);
4414514f5e3Sopenharmony_ci        Bind(value);
4424514f5e3Sopenharmony_ci    }
4434514f5e3Sopenharmony_ci    GateRef AddPhiOperand(GateRef val);
4444514f5e3Sopenharmony_ci    GateRef AddOperandToSelector(GateRef val, size_t idx, GateRef in);
4454514f5e3Sopenharmony_ci    GateRef TryRemoveTrivialPhi(GateRef phi);
4464514f5e3Sopenharmony_ci    uint32_t GetId() const
4474514f5e3Sopenharmony_ci    {
4484514f5e3Sopenharmony_ci        return id_;
4494514f5e3Sopenharmony_ci    }
4504514f5e3Sopenharmony_ci
4514514f5e3Sopenharmony_ciprivate:
4524514f5e3Sopenharmony_ci    Circuit* GetCircuit() const
4534514f5e3Sopenharmony_ci    {
4544514f5e3Sopenharmony_ci        return env_->GetCircuit();
4554514f5e3Sopenharmony_ci    }
4564514f5e3Sopenharmony_ci
4574514f5e3Sopenharmony_ci    uint32_t id_;
4584514f5e3Sopenharmony_ci    VariableType type_;
4594514f5e3Sopenharmony_ci    GateRef currentValue_ {0};
4604514f5e3Sopenharmony_ci    Environment *env_;
4614514f5e3Sopenharmony_ci};
4624514f5e3Sopenharmony_ci
4634514f5e3Sopenharmony_ci}
4644514f5e3Sopenharmony_ci
4654514f5e3Sopenharmony_ci#endif  // ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_H
466