1/*
2 * Copyright (c) 2022 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_COMPILER_ARGUMENT_ACCESSOR_H
17#define ECMASCRIPT_COMPILER_ARGUMENT_ACCESSOR_H
18
19#include "ecmascript/compiler/circuit.h"
20#include "ecmascript/compiler/gate.h"
21#include "ecmascript/compiler/gate_accessor.h"
22#include "ecmascript/method.h"
23
24namespace panda::ecmascript::kungfu {
25enum class CommonArgIdx : uint8_t {
26    GLUE = 0,
27    ACTUAL_ARGC,
28    ACTUAL_ARGV,
29    FUNC,
30    NEW_TARGET,
31    THIS_OBJECT,
32    NUM_OF_ARGS,
33};
34
35enum class FastCallArgIdx : uint8_t {
36    GLUE = 0,
37    FUNC,
38    THIS_OBJECT,
39    NUM_OF_ARGS,
40};
41
42enum class FrameArgIdx : uint8_t {
43    FUNC = 0,
44    NEW_TARGET,
45    THIS_OBJECT,
46    ACTUAL_ARGC,
47    ACTUAL_ARGV,
48    SHARED_CONST_POOL,
49    UNSHARED_CONST_POOL,
50    NUM_OF_ARGS,
51};
52
53class ArgumentAccessor {
54public:
55    explicit ArgumentAccessor(
56        Circuit *circuit, const MethodLiteral *methodLiteral = nullptr)
57        : circuit_(circuit),
58          method_(methodLiteral),
59          argRoot_(circuit->GetArgRoot()),
60          args_(0),
61          frameArgs_{Circuit::NullGate()}
62    {
63        CollectArgs();
64    }
65    ~ArgumentAccessor() = default;
66
67    void NewCommonArg(const CommonArgIdx argIndex, MachineType machineType, GateType gateType);
68    void NewArg(const size_t argIndex);
69    // method must be set
70    size_t GetActualNumArgs() const;
71    // method must be set
72    GateRef GetArgGate(const size_t currentVreg) const;
73    bool ArgGateNotExisted(const size_t currentVreg);
74    GateRef ArgsAt(const size_t index) const
75    {
76        return args_.at(index);
77    }
78    size_t ArgsCount() const
79    {
80        return args_.size();
81    }
82    void CollectArgs();
83    static size_t GetFixArgsNum()
84    {
85        return static_cast<size_t>(CommonArgIdx::NUM_OF_ARGS) - static_cast<size_t>(CommonArgIdx::FUNC);
86    }
87
88    static size_t GetExtraArgsNum()
89    {
90        return static_cast<size_t>(CommonArgIdx::ACTUAL_ARGV) - static_cast<size_t>(CommonArgIdx::GLUE);
91    }
92
93    GateRef GetFrameArgs() const
94    {
95        return frameArgs_;
96    }
97
98    void SetFrameArgs(GateRef frameArgs)
99    {
100        frameArgs_ = frameArgs;
101    }
102    GateRef GetFrameArgsIn(GateRef gate, FrameArgIdx idx);
103
104private:
105    // Disables using this interface during lowering, only allows it to be used during building graph.
106    GateRef GetCommonArgGate(const CommonArgIdx arg) const;
107    size_t GetFunctionArgIndex(const size_t currentVreg, const bool haveFunc,
108                               const bool haveNewTarget, const bool haveThis) const;
109
110    Circuit *circuit_ {nullptr};
111    const MethodLiteral *method_ {nullptr};
112    GateRef argRoot_;
113    std::vector<GateRef> args_;
114    GateRef frameArgs_;
115
116    friend class BytecodeCircuitBuilder;
117    friend class AsyncFunctionLowering;
118    friend class InitializationAnalysis;
119};
120}
121#endif  // ECMASCRIPT_COMPILER_ARGUMENT_ACCESSOR_H
122