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