1 /*
2 * Copyright (c) 2021 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 #ifndef ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_INL_H
16 #define ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_INL_H
17
18 #include "ecmascript/compiler/lcr_circuit_builder.h"
19 #include "ecmascript/compiler/mcr_circuit_builder.h"
20 #include "ecmascript/compiler/hcr_circuit_builder.h"
21 #include "ecmascript/compiler/circuit_builder.h"
22 #include "ecmascript/mem/region.h"
23 #include "ecmascript/method.h"
24
25 namespace panda::ecmascript::kungfu {
26 // constant
True()27 GateRef CircuitBuilder::True()
28 {
29 return Boolean(true);
30 }
31
False()32 GateRef CircuitBuilder::False()
33 {
34 return Boolean(false);
35 }
36
Undefined()37 GateRef CircuitBuilder::Undefined()
38 {
39 return UndefineConstant();
40 }
41
Hole()42 GateRef CircuitBuilder::Hole()
43 {
44 return HoleConstant();
45 }
46
DoubleIsINF(GateRef x)47 GateRef CircuitBuilder::DoubleIsINF(GateRef x)
48 {
49 GateRef infinity = Double(base::POSITIVE_INFINITY);
50 GateRef negativeInfinity = Double(-base::POSITIVE_INFINITY);
51 GateRef diff1 = DoubleEqual(x, infinity);
52 GateRef diff2 = DoubleEqual(x, negativeInfinity);
53 return BitOr(diff1, diff2);
54 }
55
DoubleIsNanOrInf(GateRef x)56 GateRef CircuitBuilder::DoubleIsNanOrInf(GateRef x)
57 {
58 return BitOr(DoubleIsNAN(x), DoubleIsINF(x));
59 }
60
61 // Js World
62 // cast operation
63
GetGlobalConstantOffset(ConstantIndex index)64 GateRef CircuitBuilder::GetGlobalConstantOffset(ConstantIndex index)
65 {
66 return PtrMul(IntPtr(sizeof(JSTaggedValue)), IntPtr(static_cast<int>(index)));
67 }
68
GetExpectedNumOfArgs(GateRef method)69 GateRef CircuitBuilder::GetExpectedNumOfArgs(GateRef method)
70 {
71 GateRef callFieldOffset = IntPtr(Method::CALL_FIELD_OFFSET);
72 GateRef callfield = Load(VariableType::INT64(), method, callFieldOffset);
73 return Int64And(
74 Int64LSR(callfield, Int64(MethodLiteral::NumArgsBits::START_BIT)),
75 Int64((1LU << MethodLiteral::NumArgsBits::SIZE) - 1));
76 }
77
NextVariableId()78 int CircuitBuilder::NextVariableId()
79 {
80 return env_->NextVariableId();
81 }
82
HandleException(GateRef result, Label *success, Label *fail, Label *exit)83 void CircuitBuilder::HandleException(GateRef result, Label *success, Label *fail, Label *exit)
84 {
85 BRANCH_CIR2(Equal(result, ExceptionConstant()), fail, success);
86 Bind(fail);
87 {
88 Jump(exit);
89 }
90 }
91
HandleException(GateRef result, Label *success, Label *fail, Label *exit, GateRef exceptionVal)92 void CircuitBuilder::HandleException(GateRef result, Label *success, Label *fail, Label *exit, GateRef exceptionVal)
93 {
94 BRANCH_CIR2(Equal(result, exceptionVal), fail, success);
95 Bind(fail);
96 {
97 Jump(exit);
98 }
99 }
100
SubCfgEntry(Label *entry)101 void CircuitBuilder::SubCfgEntry(Label *entry)
102 {
103 ASSERT(env_ != nullptr);
104 env_->SubCfgEntry(entry);
105 }
106
SubCfgExit()107 void CircuitBuilder::SubCfgExit()
108 {
109 ASSERT(env_ != nullptr);
110 env_->SubCfgExit();
111 }
112
Return(GateRef value)113 GateRef CircuitBuilder::Return(GateRef value)
114 {
115 auto control = GetCurrentLabel()->GetControl();
116 auto depend = GetCurrentLabel()->GetDepend();
117 return Return(control, depend, value);
118 }
119
Return()120 GateRef CircuitBuilder::Return()
121 {
122 auto control = GetCurrentLabel()->GetControl();
123 auto depend = GetCurrentLabel()->GetDepend();
124 return ReturnVoid(control, depend);
125 }
126
Bind(Label *label)127 void CircuitBuilder::Bind(Label *label)
128 {
129 label->Bind();
130 env_->SetCurrentLabel(label);
131 }
132
Bind(Label *label, bool justSlowPath)133 void CircuitBuilder::Bind(Label *label, bool justSlowPath)
134 {
135 if (!justSlowPath) {
136 label->Bind();
137 env_->SetCurrentLabel(label);
138 }
139 }
140
GetState() const141 GateRef CircuitBuilder::GetState() const
142 {
143 return GetCurrentLabel()->GetControl();
144 }
145
GetDepend() const146 GateRef CircuitBuilder::GetDepend() const
147 {
148 return GetCurrentLabel()->GetDepend();
149 }
150
GetStateDepend() const151 StateDepend CircuitBuilder::GetStateDepend() const
152 {
153 return StateDepend(GetState(), GetDepend());
154 }
155
SetDepend(GateRef depend)156 void CircuitBuilder::SetDepend(GateRef depend)
157 {
158 GetCurrentLabel()->SetDepend(depend);
159 }
160
SetState(GateRef state)161 void CircuitBuilder::SetState(GateRef state)
162 {
163 GetCurrentLabel()->SetControl(state);
164 }
165
GetCurrentLabel() const166 Label *CircuitBuilder::GetCurrentLabel() const
167 {
168 return GetCurrentEnvironment()->GetCurrentLabel();
169 }
170
LogicAndBuilder(Environment *env)171 LogicAndBuilder::LogicAndBuilder(Environment *env)
172 : env_(env), builder_(env_->GetBuilder())
173 {
174 subentry_ = new Label(env_);
175 builder_->SubCfgEntry(subentry_);
176 result_ = new Variable(env_, VariableType::BOOL(), builder_->NextVariableId(), builder_->False());
177 exit_ = new Label(env_);
178 }
179
~LogicAndBuilder()180 LogicAndBuilder::~LogicAndBuilder()
181 {
182 ASSERT(exit_ != nullptr);
183 delete exit_;
184 exit_ = nullptr;
185 ASSERT(result_ != nullptr);
186 delete result_;
187 result_ = nullptr;
188 ASSERT(subentry_ != nullptr);
189 delete subentry_;
190 subentry_ = nullptr;
191 for (auto &label : labels_) {
192 ASSERT(label != nullptr);
193 delete label;
194 label = nullptr;
195 }
196 }
197
And(GateRef check)198 LogicAndBuilder &LogicAndBuilder::And(GateRef check)
199 {
200 auto checkTrue = new Label(env_);
201 labels_.push_back(checkTrue);
202 builder_->Branch(check, checkTrue, exit_);
203 builder_->Bind(checkTrue);
204 return *this;
205 }
206
Done()207 GateRef LogicAndBuilder::Done()
208 {
209 *result_ = builder_->True();
210 builder_->Jump(exit_);
211 builder_->Bind(exit_);
212 auto ret = **result_;
213 builder_->SubCfgExit();
214 return ret;
215 }
216
LogicOrBuilder(Environment *env)217 LogicOrBuilder::LogicOrBuilder(Environment *env)
218 : env_(env), builder_(env_->GetBuilder())
219 {
220 subentry_ = new Label(env_);
221 builder_->SubCfgEntry(subentry_);
222 result_ = new Variable(env_, VariableType::BOOL(), builder_->NextVariableId(), builder_->True());
223 exit_ = new Label(env_);
224 }
225
~LogicOrBuilder()226 LogicOrBuilder::~LogicOrBuilder()
227 {
228 ASSERT(exit_ != nullptr);
229 delete exit_;
230 exit_ = nullptr;
231 ASSERT(result_ != nullptr);
232 delete result_;
233 result_ = nullptr;
234 ASSERT(subentry_ != nullptr);
235 delete subentry_;
236 subentry_ = nullptr;
237 for (auto &label : labels_) {
238 ASSERT(label != nullptr);
239 delete label;
240 label = nullptr;
241 }
242 }
243
Or(GateRef check)244 LogicOrBuilder &LogicOrBuilder::Or(GateRef check)
245 {
246 auto checkFalse = new Label(env_);
247 labels_.push_back(checkFalse);
248 builder_->Branch(check, exit_, checkFalse);
249 builder_->Bind(checkFalse);
250 return *this;
251 }
252
Done()253 GateRef LogicOrBuilder::Done()
254 {
255 *result_ = builder_->False();
256 builder_->Jump(exit_);
257 builder_->Bind(exit_);
258 auto ret = **result_;
259 builder_->SubCfgExit();
260 return ret;
261 }
262 } // namespace panda::ecmascript::kungfu
263
264 #endif
265