• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "ecmascript/compiler/argument_accessor.h"
17 
18 namespace panda::ecmascript::kungfu {
NewCommonArg(const CommonArgIdx argIndex,MachineType machineType,GateType gateType)19 void ArgumentAccessor::NewCommonArg(const CommonArgIdx argIndex, MachineType machineType, GateType gateType)
20 {
21     circuit_->NewArg(machineType, static_cast<size_t>(argIndex), gateType, argRoot_);
22 }
23 
NewArg(const size_t argIndex)24 void ArgumentAccessor::NewArg(const size_t argIndex)
25 {
26     circuit_->NewArg(MachineType::I64, argIndex, GateType::TaggedValue(), argRoot_);
27 }
28 
29 // method must be set
GetActualNumArgs() const30 size_t ArgumentAccessor::GetActualNumArgs() const
31 {
32     ASSERT(method_ != nullptr);
33     auto numArgs = method_->GetNumArgsWithCallField();
34     return static_cast<size_t>(CommonArgIdx::NUM_OF_ARGS) + numArgs;
35 }
36 
37 // method must be set
GetArgGate(const size_t currentVreg) const38 GateRef ArgumentAccessor::GetArgGate(const size_t currentVreg) const
39 {
40     ASSERT(method_ != nullptr);
41     const size_t offsetArgs = method_->GetNumVregsWithCallField();
42     ASSERT(currentVreg >= offsetArgs && currentVreg < offsetArgs + method_->GetNumArgs());
43     auto reg = currentVreg - offsetArgs;
44     auto haveFunc = method_->HaveFuncWithCallField();
45     auto haveNewTarget = method_->HaveNewTargetWithCallField();
46     auto haveThis = method_->HaveThisWithCallField();
47     auto index = GetFunctionArgIndex(reg, haveFunc, haveNewTarget, haveThis);
48     return args_.at(index);
49 }
50 
GetTypedArgGate(const size_t argIndex) const51 GateRef ArgumentAccessor::GetTypedArgGate(const size_t argIndex) const
52 {
53     if (argIndex == static_cast<size_t>(TypedArgIdx::FUNC)) {
54         return GetCommonArgGate(CommonArgIdx::FUNC);
55     }
56     if (argIndex == static_cast<size_t>(TypedArgIdx::NEW_TARGET)) {
57         return GetCommonArgGate(CommonArgIdx::NEW_TARGET);
58     }
59     if (argIndex == static_cast<size_t>(TypedArgIdx::THIS_OBJECT)) {
60         return GetCommonArgGate(CommonArgIdx::THIS_OBJECT);
61     }
62     return args_.at(argIndex - static_cast<size_t>(TypedArgIdx::NUM_OF_TYPED_ARGS) +
63         static_cast<size_t>(CommonArgIdx::NUM_OF_ARGS));
64 }
65 
GetCommonArgGate(const CommonArgIdx arg) const66 GateRef ArgumentAccessor::GetCommonArgGate(const CommonArgIdx arg) const
67 {
68     return args_.at(static_cast<size_t>(arg));
69 }
70 
GetFunctionArgIndex(const size_t currentVreg,const bool haveFunc,const bool haveNewTarget,const bool haveThis) const71 size_t ArgumentAccessor::GetFunctionArgIndex(const size_t currentVreg, const bool haveFunc,
72                                              const bool haveNewTarget, const bool haveThis) const
73 {
74     size_t numCommonArgs = haveFunc + haveNewTarget + haveThis;
75     // 2: number of common args
76     if (numCommonArgs == 2) {
77         if (!haveFunc && currentVreg == 0) {
78             return static_cast<size_t>(CommonArgIdx::NEW_TARGET);
79         }
80         if (!haveFunc && currentVreg == 1) {
81             return static_cast<size_t>(CommonArgIdx::THIS_OBJECT);
82         }
83         if (!haveNewTarget && currentVreg == 0) {
84             return static_cast<size_t>(CommonArgIdx::FUNC);
85         }
86         if (!haveNewTarget && currentVreg == 1) {
87             return static_cast<size_t>(CommonArgIdx::THIS_OBJECT);
88         }
89         if (!haveThis && currentVreg == 0) {
90             return static_cast<size_t>(CommonArgIdx::FUNC);
91         }
92         if (!haveThis && currentVreg == 1) {
93             return static_cast<size_t>(CommonArgIdx::NEW_TARGET);
94         }
95     }
96     // 1: number of common args, 0: the index of currentVreg
97     if (numCommonArgs == 1 && currentVreg == 0) {
98         if (haveFunc) {
99             return static_cast<size_t>(CommonArgIdx::FUNC);
100         }
101         if (haveNewTarget) {
102             return static_cast<size_t>(CommonArgIdx::NEW_TARGET);
103         }
104         if (haveThis) {
105             return static_cast<size_t>(CommonArgIdx::THIS_OBJECT);
106         }
107     }
108     return currentVreg - numCommonArgs + static_cast<size_t>(CommonArgIdx::NUM_OF_ARGS);
109 }
110 
FillArgsGateType(const TypeRecorder * typeRecorder)111 void ArgumentAccessor::FillArgsGateType(const TypeRecorder *typeRecorder)
112 {
113     ASSERT(method_ != nullptr);
114     GateAccessor gateAcc(circuit_);
115     const size_t numOfTypedArgs = method_->GetNumArgsWithCallField() +
116         static_cast<size_t>(TypedArgIdx::NUM_OF_TYPED_ARGS);
117     for (uint32_t argIndex = 0; argIndex < numOfTypedArgs; argIndex++) {
118         auto argType = typeRecorder->GetArgType(argIndex);
119         if (!argType.IsAnyType()) {
120             auto gate = GetTypedArgGate(argIndex);
121             gateAcc.SetGateType(gate, argType);
122         }
123     }
124 }
125 
CollectArgs()126 void ArgumentAccessor::CollectArgs()
127 {
128     if (args_.size() == 0) {
129         GateAccessor(circuit_).GetArgsOuts(args_);
130         std::reverse(args_.begin(), args_.end());
131     }
132 }
133 }  // namespace panda::ecmascript::kungfu
134