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