• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #ifndef ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_H
17 #define ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_H
18 
19 #include "ecmascript/base/number_helper.h"
20 #include "ecmascript/compiler/assembler/assembler.h"
21 #include "ecmascript/compiler/builtins/builtins_call_signature.h"
22 #include "ecmascript/compiler/circuit.h"
23 #include "ecmascript/compiler/call_signature.h"
24 #include "ecmascript/compiler/gate.h"
25 #include "ecmascript/compiler/gate_accessor.h"
26 #include "ecmascript/compiler/variable_type.h"
27 #include "ecmascript/global_env_constants.h"
28 #include "ecmascript/jspandafile/constpool_value.h"
29 #include "ecmascript/js_hclass.h"
30 #include "ecmascript/js_runtime_options.h"
31 #include "ecmascript/js_tagged_value.h"
32 #include "ecmascript/tagged_array.h"
33 
34 namespace panda::ecmascript::kungfu {
35 using namespace panda::ecmascript;
36 #define DEFVAlUE(varname, cirBuilder, type, val) \
37         Variable varname(cirBuilder, type, cirBuilder->NextVariableId(), val)
38 
39 class Environment;
40 class Label;
41 class Variable;
42 class StubBuilder;
43 class TSHCRLowering;
44 class NTypeHCRLowering;
45 class SlowPathLowering;
46 
47 #define BINARY_ARITHMETIC_METHOD_LIST_WITH_BITWIDTH(V)                    \
48     V(Int16Add, Add, MachineType::I16)                                    \
49     V(Int32Add, Add, MachineType::I32)                                    \
50     V(Int64Add, Add, MachineType::I64)                                    \
51     V(DoubleAdd, Add, MachineType::F64)                                   \
52     V(PtrAdd, Add, MachineType::ARCH)                                     \
53     V(Int16Sub, Sub, MachineType::I16)                                    \
54     V(Int32Sub, Sub, MachineType::I32)                                    \
55     V(Int64Sub, Sub, MachineType::I64)                                    \
56     V(DoubleSub, Sub, MachineType::F64)                                   \
57     V(PtrSub, Sub, MachineType::ARCH)                                     \
58     V(Int32Mul, Mul, MachineType::I32)                                    \
59     V(Int64Mul, Mul, MachineType::I64)                                    \
60     V(DoubleMul, Mul, MachineType::F64)                                   \
61     V(PtrMul, Mul, MachineType::ARCH)                                     \
62     V(Int32Div, Sdiv, MachineType::I32)                                   \
63     V(Int64Div, Sdiv, MachineType::I64)                                   \
64     V(DoubleDiv, Fdiv, MachineType::F64)                                  \
65     V(Int32Mod, Smod, MachineType::I32)                                   \
66     V(DoubleMod, Smod, MachineType::F64)                                  \
67     V(BoolAnd, And, MachineType::I1)                                      \
68     V(Int8And, And, MachineType::I8)                                      \
69     V(Int32And, And, MachineType::I32)                                    \
70     V(Int64And, And, MachineType::I64)                                    \
71     V(BoolOr, Or, MachineType::I1)                                        \
72     V(Int32Or, Or, MachineType::I32)                                      \
73     V(Int64Or, Or, MachineType::I64)                                      \
74     V(Int32Xor, Xor, MachineType::I32)                                    \
75     V(Int64Xor, Xor, MachineType::I64)                                    \
76     V(Int16LSL, Lsl, MachineType::I16)                                    \
77     V(Int32LSL, Lsl, MachineType::I32)                                    \
78     V(Int64LSL, Lsl, MachineType::I64)                                    \
79     V(Int8LSR, Lsr, MachineType::I8)                                      \
80     V(Int32LSR, Lsr, MachineType::I32)                                    \
81     V(Int64LSR, Lsr, MachineType::I64)                                    \
82     V(Int32ASR, Asr, MachineType::I32)
83 
84 #define UNARY_ARITHMETIC_METHOD_LIST_WITH_BITWIDTH(V)                  \
85     V(BoolNot, Rev, MachineType::I1)                                   \
86     V(Int32Not, Rev, MachineType::I32)                                 \
87     V(Int64Not, Rev, MachineType::I64)                                 \
88     V(CastDoubleToInt64, Bitcast, MachineType::I64)                    \
89     V(CastInt64ToFloat64, Bitcast, MachineType::F64)                   \
90     V(CastInt32ToFloat32, Bitcast, MachineType::F32)                   \
91     V(SExtInt32ToInt64, Sext, MachineType::I64)                        \
92     V(SExtInt1ToInt64, Sext, MachineType::I64)                         \
93     V(SExtInt1ToInt32, Sext, MachineType::I32)                         \
94     V(ZExtInt8ToInt16, Zext, MachineType::I16)                         \
95     V(ZExtInt32ToInt64, Zext, MachineType::I64)                        \
96     V(ZExtInt1ToInt64, Zext, MachineType::I64)                         \
97     V(ZExtInt1ToInt32, Zext, MachineType::I32)                         \
98     V(ZExtInt8ToInt32, Zext, MachineType::I32)                         \
99     V(ZExtInt8ToInt64, Zext, MachineType::I64)                         \
100     V(ZExtInt8ToPtr, Zext, MachineType::ARCH)                          \
101     V(ZExtInt16ToPtr, Zext, MachineType::ARCH)                         \
102     V(ZExtInt32ToPtr, Zext, MachineType::ARCH)                         \
103     V(SExtInt32ToPtr, Sext, MachineType::ARCH)                         \
104     V(ZExtInt16ToInt32, Zext, MachineType::I32)                        \
105     V(ZExtInt16ToInt64, Zext, MachineType::I64)                        \
106     V(TruncInt16ToInt8, Trunc, MachineType::I8)                        \
107     V(TruncInt64ToInt32, Trunc, MachineType::I32)                      \
108     V(TruncPtrToInt32, Trunc, MachineType::I32)                        \
109     V(TruncInt64ToInt1, Trunc, MachineType::I1)                        \
110     V(TruncInt64ToInt16, Trunc, MachineType::I16)                      \
111     V(TruncInt32ToInt1, Trunc, MachineType::I1)                        \
112     V(TruncInt32ToInt8, Trunc, MachineType::I8)                        \
113     V(TruncInt32ToInt16, Trunc, MachineType::I16)                      \
114     V(TruncFloatToInt64, TruncFloatToInt64, MachineType::I64)          \
115     V(TruncFloatToInt32, TruncFloatToInt32, MachineType::I32)          \
116     V(ExtFloat32ToDouble, Fext, MachineType::F64)                      \
117     V(TruncDoubleToFloat32, Ftrunc, MachineType::F32)                  \
118     V(ChangeInt32ToFloat64, SignedIntToFloat, MachineType::F64)        \
119     V(ChangeInt32ToFloat32, SignedIntToFloat, MachineType::F32)        \
120     V(ChangeUInt32ToFloat64, UnsignedIntToFloat, MachineType::F64)     \
121     V(ChangeFloat64ToInt32, FloatToSignedInt, MachineType::I32)        \
122     V(SExtInt16ToInt64, Sext, MachineType::I64)                        \
123     V(SExtInt16ToInt32, Sext, MachineType::I32)                        \
124     V(SExtInt8ToInt32, Sext, MachineType::I32)                         \
125     V(SExtInt8ToInt64, Sext, MachineType::I64)
126 
127 #define UNARY_ARITHMETIC_METHOD_LIST_WITH_BITWIDTH_PRIVATE(V)          \
128     V(ChangeTaggedPointerToInt64, TaggedToInt64, MachineType::I64)
129 
130 #define BINARY_CMP_METHOD_LIST_WITHOUT_BITWIDTH(V)                                      \
131     V(DoubleLessThan, Fcmp, static_cast<BitField>(FCmpCondition::OLT))                  \
132     V(DoubleLessThanOrEqual, Fcmp, static_cast<BitField>(FCmpCondition::OLE))           \
133     V(DoubleGreaterThan, Fcmp, static_cast<BitField>(FCmpCondition::OGT))               \
134     V(DoubleGreaterThanOrEqual, Fcmp, static_cast<BitField>(FCmpCondition::OGE))        \
135     V(DoubleEqual, Fcmp, static_cast<BitField>(FCmpCondition::OEQ))                     \
136     V(DoubleNotEqual, Fcmp, static_cast<BitField>(FCmpCondition::ONE))                  \
137     V(Int32LessThan, Icmp, static_cast<BitField>(ICmpCondition::SLT))                   \
138     V(Int32LessThanOrEqual, Icmp, static_cast<BitField>(ICmpCondition::SLE))            \
139     V(Int32GreaterThan, Icmp, static_cast<BitField>(ICmpCondition::SGT))                \
140     V(Int32GreaterThanOrEqual, Icmp, static_cast<BitField>(ICmpCondition::SGE))         \
141     V(Int32UnsignedLessThan, Icmp, static_cast<BitField>(ICmpCondition::ULT))           \
142     V(Int32UnsignedLessThanOrEqual, Icmp, static_cast<BitField>(ICmpCondition::ULE))    \
143     V(Int32UnsignedGreaterThan, Icmp, static_cast<BitField>(ICmpCondition::UGT))        \
144     V(Int32UnsignedGreaterThanOrEqual, Icmp, static_cast<BitField>(ICmpCondition::UGE)) \
145     V(Int64LessThan, Icmp, static_cast<BitField>(ICmpCondition::SLT))                   \
146     V(Int64LessThanOrEqual, Icmp, static_cast<BitField>(ICmpCondition::SLE))            \
147     V(Int64GreaterThan, Icmp, static_cast<BitField>(ICmpCondition::SGT))                \
148     V(Int64GreaterThanOrEqual, Icmp, static_cast<BitField>(ICmpCondition::SGE))         \
149     V(Int64UnsignedLessThanOrEqual, Icmp, static_cast<BitField>(ICmpCondition::ULE))
150 
151 class CompilationConfig {
152 public:
153     explicit CompilationConfig(const std::string &triple, const JSRuntimeOptions *options = nullptr)
tripleStr_(triple)154         : tripleStr_(triple), triple_(GetTripleFromString(triple))
155     {
156         if (options != nullptr) {
157             isTraceBc_ = options->IsTraceBC();
158             profiling_ = options->GetOptCodeProfiler();
159             stressDeopt_ = options->GetStressDeopt();
160             verifyVTable_ = options->GetVerifyVTable();
161         }
162     }
163     ~CompilationConfig() = default;
164 
Is32Bit()165     inline bool Is32Bit() const
166     {
167         return triple_ == Triple::TRIPLE_ARM32;
168     }
169 
IsAArch64()170     inline bool IsAArch64() const
171     {
172         return triple_ == Triple::TRIPLE_AARCH64;
173     }
174 
IsAmd64()175     inline bool IsAmd64() const
176     {
177         return triple_ == Triple::TRIPLE_AMD64;
178     }
179 
Is64Bit()180     inline bool Is64Bit() const
181     {
182         return IsAArch64() || IsAmd64();
183     }
184 
GetTriple()185     Triple GetTriple() const
186     {
187         return triple_;
188     }
189 
GetTripleStr()190     std::string GetTripleStr() const
191     {
192         return tripleStr_;
193     }
194 
IsTraceBC()195     bool IsTraceBC() const
196     {
197         return isTraceBc_;
198     }
199 
IsProfiling()200     bool IsProfiling() const
201     {
202         return profiling_;
203     }
204 
IsStressDeopt()205     bool IsStressDeopt() const
206     {
207         return stressDeopt_;
208     }
209 
IsVerifyVTbale()210     bool IsVerifyVTbale() const
211     {
212         return verifyVTable_;
213     }
214 
215 private:
GetTripleFromString(const std::string & triple)216     inline Triple GetTripleFromString(const std::string &triple)
217     {
218         if (triple.compare(TARGET_X64) == 0) {
219             return Triple::TRIPLE_AMD64;
220         }
221 
222         if (triple.compare(TARGET_AARCH64) == 0) {
223             return Triple::TRIPLE_AARCH64;
224         }
225 
226         if (triple.compare(TARGET_ARM32) == 0) {
227             return Triple::TRIPLE_ARM32;
228         }
229         LOG_ECMA(FATAL) << "this branch is unreachable";
230         UNREACHABLE();
231     }
232     std::string tripleStr_;
233     Triple triple_;
234     bool isTraceBc_ {false};
235     bool profiling_ {false};
236     bool stressDeopt_ {false};
237     bool verifyVTable_ {false};
238 };
239 
240 class CircuitBuilder {
241 public:
CircuitBuilder(Circuit * circuit)242     explicit CircuitBuilder(Circuit *circuit) : circuit_(circuit), acc_(circuit) {}
CircuitBuilder(Circuit * circuit,CompilationConfig * cmpCfg)243     CircuitBuilder(Circuit *circuit, CompilationConfig *cmpCfg)
244         : circuit_(circuit), acc_(circuit), cmpCfg_(cmpCfg)
245     {
246     }
247     ~CircuitBuilder() = default;
248     NO_MOVE_SEMANTIC(CircuitBuilder);
249     NO_COPY_SEMANTIC(CircuitBuilder);
250     static constexpr uint32_t GATE_TWO_VALUESIN = 2;
251     // low level interface
252     GateRef HeapObjectCheck(GateRef gate, GateRef frameState);
253     GateRef StableArrayCheck(GateRef gate, ElementsKind kind, ArrayMetaDataAccessor::Mode mode);
254     GateRef COWArrayCheck(GateRef gate);
255     GateRef HClassStableArrayCheck(GateRef gate, GateRef frameState, ArrayMetaDataAccessor accessor);
256     GateRef ArrayGuardianCheck(GateRef frameState);
257     GateRef TypedArrayCheck(GateType type, GateRef gate);
258     GateRef LoadTypedArrayLength(GateType type, GateRef gate);
259     GateRef RangeGuard(GateRef gate, uint32_t left, uint32_t right);
260     GateRef IndexCheck(GateType type, GateRef gate, GateRef index);
261     GateRef ObjectTypeCheck(GateType type, bool isHeapObject, GateRef gate, GateRef hclassIndex);
262     GateRef ObjectTypeCompare(GateType type, bool isHeapObject, GateRef gate, GateRef hclassIndex);
263     GateRef TryPrimitiveTypeCheck(GateType type, GateRef gate);
264     GateRef CallTargetCheck(GateRef gate, GateRef function, GateRef id, GateRef param, const char* comment = nullptr);
265     GateRef JSCallTargetFromDefineFuncCheck(GateType type, GateRef func, GateRef gate);
266     template<TypedCallTargetCheckOp Op>
267     GateRef JSCallTargetTypeCheck(GateType type, GateRef func, GateRef methodIndex, GateRef gate);
268     template<TypedCallTargetCheckOp Op>
269     GateRef JSCallThisTargetTypeCheck(GateType type, GateRef func, GateRef gate);
270     template<TypedCallTargetCheckOp Op>
271     inline GateRef JSNoGCCallThisTargetTypeCheck(GateType type, GateRef func, GateRef methodId, GateRef gate);
272     GateRef DeoptCheck(GateRef condition, GateRef frameState, DeoptType type);
273     GateRef TypedCallOperator(GateRef hirGate, MachineType type, const std::initializer_list<GateRef>& args);
274     inline GateRef TypedCallBuiltin(GateRef hirGate, GateRef x, BuiltinsStubCSigns::ID id);
275     inline GateRef TypedCallThis3Builtin(GateRef hirGate, GateRef thisObj, GateRef a0, GateRef a1, GateRef a2,
276                                          BuiltinsStubCSigns::ID id);
277     GateRef TypeConvert(MachineType type, GateType typeFrom, GateType typeTo, const std::vector<GateRef>& inList);
278     GateRef AddWithOverflow(GateRef left, GateRef right);
279     GateRef SubWithOverflow(GateRef left, GateRef right);
280     GateRef MulWithOverflow(GateRef left, GateRef right);
281     GateRef ExtractValue(MachineType mt, GateRef pointer, GateRef index);
282     GateRef Sqrt(GateRef param);
283     GateRef Int32CheckRightIsZero(GateRef right);
284     GateRef Float64CheckRightIsZero(GateRef right);
285     GateRef ValueCheckNegOverflow(GateRef value);
286     GateRef OverflowCheck(GateRef value);
287     GateRef LexVarIsHoleCheck(GateRef value);
288     GateRef Int32UnsignedUpperBoundCheck(GateRef value, GateRef upperBound);
289     GateRef Int32DivWithCheck(GateRef left, GateRef right);
290     MachineType GetMachineTypeOfValueType(ValueType type);
291     GateType GetGateTypeOfValueType(ValueType type);
292     GateRef IsJsCOWArray(GateRef obj);
293     GateRef IsCOWArray(GateRef objectType);
294     GateRef GetElementsArray(GateRef object);
295     GateRef Convert(GateRef gate, ValueType src, ValueType dst);
296     GateRef ConvertBoolToTaggedBoolean(GateRef gate);
297     GateRef ConvertTaggedBooleanToBool(GateRef gate);
298     GateRef ConvertInt32ToBool(GateRef gate);
299     GateRef ConvertFloat64ToBool(GateRef gate);
300     GateRef ConvertInt32ToTaggedInt(GateRef gate);
301     GateRef ConvertFloat64ToTaggedDouble(GateRef gate);
302     GateRef ConvertFloat64ToInt32(GateRef gate);
303     GateRef ConvertInt32ToFloat64(GateRef gate);
304     GateRef ConvertBoolToInt32(GateRef gate, ConvertSupport support);
305     GateRef ConvertBoolToFloat64(GateRef gate, ConvertSupport support);
306     GateRef ConvertUInt32ToBool(GateRef gate);
307     GateRef ConvertUInt32ToTaggedNumber(GateRef gate);
308     GateRef ConvertUInt32ToFloat64(GateRef gate);
309     GateRef CheckAndConvert(
310         GateRef gate, ValueType src, ValueType dst, ConvertSupport support = ConvertSupport::ENABLE);
311     GateRef ConvertHoleAsUndefined(GateRef receiver);
312     GateRef CheckUInt32AndConvertToInt32(GateRef gate);
313     GateRef CheckTaggedIntAndConvertToInt32(GateRef gate);
314     GateRef CheckTaggedDoubleAndConvertToInt32(GateRef gate);
315     GateRef CheckTaggedNumberAndConvertToInt32(GateRef gate);
316     GateRef CheckTaggedIntAndConvertToFloat64(GateRef gate);
317     GateRef CheckTaggedDoubleAndConvertToFloat64(GateRef gate);
318     GateRef CheckTaggedNumberAndConvertToFloat64(GateRef gate);
319     GateRef CheckTaggedNumberAndConvertToBool(GateRef gate);
320     GateRef CheckTaggedBooleanAndConvertToBool(GateRef gate);
321     GateRef TypedConditionJump(MachineType type, TypedJumpOp jumpOp, GateType typeVal,
322                                const std::vector<GateRef>& inList);
323     GateRef TypedNewAllocateThis(GateRef ctor, GateRef hclassIndex, GateRef frameState);
324     GateRef TypedSuperAllocateThis(GateRef superCtor, GateRef newTarget, GateRef frameState);
325     GateRef GetSuperConstructor(GateRef ctor);
326     GateRef Arguments(size_t index);
327     GateRef Merge(const std::vector<GateRef> &inList);
328     GateRef Selector(OpCode opcode, MachineType machineType, GateRef control, const std::vector<GateRef> &values,
329         int valueCounts, VariableType type = VariableType::VOID());
330     GateRef Selector(OpCode opcode, GateRef control, const std::vector<GateRef> &values,
331         int valueCounts, VariableType type = VariableType::VOID());
332     GateRef Int8(int8_t val);
333     GateRef Int16(int16_t val);
334     GateRef Int32(int32_t value);
335     GateRef Int64(int64_t value);
336     GateRef IntPtr(int64_t val);
337     GateRef StringPtr(const std::string &str);
338     GateRef Boolean(bool value);
339     GateRef Double(double value);
340     GateRef UndefineConstant();
341     GateRef HoleConstant();
342     GateRef NullPtrConstant();
343     GateRef NullConstant();
344     GateRef ExceptionConstant();
345     GateRef RelocatableData(uint64_t val);
346     GateRef Alloca(size_t size);
347     GateRef Branch(GateRef state, GateRef condition);
348     GateRef SwitchBranch(GateRef state, GateRef index, int caseCounts);
349     GateRef Return(GateRef state, GateRef depend, GateRef value);
350     GateRef ReturnVoid(GateRef state, GateRef depend);
351     GateRef Goto(GateRef state);
352     GateRef LoopBegin(GateRef state);
353     GateRef LoopEnd(GateRef state);
354     GateRef IfTrue(GateRef ifBranch);
355     GateRef IfFalse(GateRef ifBranch);
356     GateRef SwitchCase(GateRef switchBranch, int64_t value);
357     GateRef DefaultCase(GateRef switchBranch);
358     GateRef DependRelay(GateRef state, GateRef depend);
359     GateRef ReadSp();
360     GateRef BinaryArithmetic(const GateMetaData* meta, MachineType machineType,
361         GateRef left, GateRef right, GateType gateType = GateType::Empty());
362     GateRef BinaryCmp(const GateMetaData* meta, GateRef left, GateRef right);
363     static MachineType GetMachineTypeFromVariableType(VariableType type);
364     GateRef GetCallBuiltinId(GateRef method);
GetCircuit()365     Circuit *GetCircuit() const
366     {
367         return circuit_;
368     }
369     // constant
370     inline GateRef True();
371     inline GateRef False();
372     inline GateRef Undefined();
373     inline GateRef Hole();
374 
375     // call operation
376     GateRef CallBCHandler(GateRef glue, GateRef target, const std::vector<GateRef> &args,
377                           const char* comment = nullptr);
378     GateRef CallBCDebugger(GateRef glue, GateRef target, const std::vector<GateRef> &args,
379                            const char* comment = nullptr);
380     GateRef CallBuiltin(GateRef glue, GateRef target, const std::vector<GateRef> &args,
381                         const char* comment = nullptr);
382     GateRef CallBuiltinWithArgv(GateRef glue, GateRef target, const std::vector<GateRef> &args,
383                                 const char* comment = nullptr);
384     GateRef CallRuntimeVarargs(GateRef glue, int index, GateRef argc, GateRef argv, const char* comment = nullptr);
385     GateRef CallRuntime(GateRef glue, int index, GateRef depend, const std::vector<GateRef> &args, GateRef hirGate,
386                         const char* comment = nullptr);
387     GateRef CallNGCRuntime(GateRef glue, GateRef gate, int index, const std::vector<GateRef> &args, bool useLabel);
388 
389     GateRef CallNGCRuntime(GateRef glue, int index, GateRef depend, const std::vector<GateRef> &args,
390                            GateRef hirGate, const char* comment = nullptr);
391     GateRef FastCallOptimized(GateRef glue, GateRef code, GateRef depend, const std::vector<GateRef> &args,
392                               GateRef hirGate);
393     GateRef CallOptimized(GateRef glue, GateRef code, GateRef depend, const std::vector<GateRef> &args,
394                           GateRef hirGate);
395 
396     GateRef CallStub(GateRef glue, GateRef hirGate, int index, const std::vector<GateRef> &args,
397                      const char* comment = nullptr);
398     GateRef CallBuiltinRuntime(GateRef glue, GateRef depend, const std::vector<GateRef> &args,
399                                bool isNew = false, const char* comment = nullptr);
400     GateRef Call(const CallSignature* cs, GateRef glue, GateRef target, GateRef depend,
401                  const std::vector<GateRef> &args, GateRef hirGate, const char* comment = nullptr);
402     GateRef NoLabelCallRuntime(GateRef glue, GateRef depend, size_t index, std::vector<GateRef> &args, GateRef hirGate);
403 
404     void StartCallTimer(GateRef glue, GateRef gate, const std::vector<GateRef> &args, bool useLabel);
405     void EndCallTimer(GateRef glue, GateRef gate, const std::vector<GateRef> &args, bool useLabel);
406 
407     // memory
408     inline GateRef Load(VariableType type, GateRef base, GateRef offset);
409     inline GateRef Load(VariableType type, GateRef base, GateRef offset, GateRef depend);
410     void Store(VariableType type, GateRef glue, GateRef base, GateRef offset, GateRef value);
411     void StoreWithNoBarrier(VariableType type, GateRef base, GateRef offset, GateRef value);
412 
413 #define ARITHMETIC_BINARY_OP_WITH_BITWIDTH(NAME, OPCODEID, MACHINETYPEID)                 \
414     inline GateRef NAME(GateRef x, GateRef y, GateType type = GateType::Empty())          \
415     {                                                                                     \
416         return BinaryArithmetic(circuit_->OPCODEID(), MACHINETYPEID, x, y, type);         \
417     }
418 
419     BINARY_ARITHMETIC_METHOD_LIST_WITH_BITWIDTH(ARITHMETIC_BINARY_OP_WITH_BITWIDTH)
420 #undef ARITHMETIC_BINARY_OP_WITH_BITWIDTH
421 
422 #define ARITHMETIC_UNARY_OP_WITH_BITWIDTH(NAME, OPCODEID, MACHINETYPEID)                            \
423     inline GateRef NAME(GateRef x)                                                                  \
424     {                                                                                               \
425         return circuit_->NewGate(circuit_->OPCODEID(), MACHINETYPEID, { x }, GateType::NJSValue()); \
426     }
427 
428     UNARY_ARITHMETIC_METHOD_LIST_WITH_BITWIDTH(ARITHMETIC_UNARY_OP_WITH_BITWIDTH)
429 #undef ARITHMETIC_UNARY_OP_WITH_BITWIDTH
430 
431 #define CMP_BINARY_OP_WITHOUT_BITWIDTH(NAME, OPCODEID, CONDITION)                         \
432     inline GateRef NAME(GateRef x, GateRef y)                                             \
433     {                                                                                     \
434         return BinaryCmp(circuit_->OPCODEID(static_cast<uint64_t>(CONDITION)), x, y);     \
435     }
436 
437     BINARY_CMP_METHOD_LIST_WITHOUT_BITWIDTH(CMP_BINARY_OP_WITHOUT_BITWIDTH)
438 #undef CMP_BINARY_OP_WITHOUT_BITWIDTH
439 
440     inline GateRef Equal(GateRef x, GateRef y);
441     inline GateRef NotEqual(GateRef x, GateRef y);
442 
443     // js world
444     // cast operation
445     inline GateRef GetInt64OfTInt(GateRef x);
446     inline GateRef GetInt32OfTInt(GateRef x);
447     inline GateRef TaggedCastToIntPtr(GateRef x);
448     inline GateRef GetDoubleOfTDouble(GateRef x);
449     inline GateRef GetBooleanOfTBoolean(GateRef x);
450     inline GateRef GetDoubleOfTNumber(GateRef x);
451     inline GateRef DoubleToInt(GateRef x, Label *exit);
452     inline GateRef Int32ToTaggedPtr(GateRef x);
453     inline GateRef Int64ToTaggedPtr(GateRef x);
454     inline GateRef Int32ToTaggedInt(GateRef x);
455     // bit operation
456     inline GateRef IsSpecial(GateRef x, JSTaggedType type);
457     inline GateRef TaggedIsInt(GateRef x);
458     inline GateRef TaggedIsDouble(GateRef x);
459     inline GateRef TaggedIsObject(GateRef x);
460     inline GateRef TaggedIsNumber(GateRef x);
461     inline GateRef TaggedIsNumeric(GateRef x);
462     inline GateRef TaggedIsNotHole(GateRef x);
463     inline GateRef TaggedIsHole(GateRef x);
464     inline GateRef TaggedIsNullPtr(GateRef x);
465     inline GateRef TaggedIsUndefined(GateRef x);
466     inline GateRef TaggedIsException(GateRef x);
467     inline GateRef TaggedIsSpecial(GateRef x);
468     inline GateRef TaggedIsHeapObject(GateRef x);
469     inline GateRef TaggedIsAsyncGeneratorObject(GateRef x);
470     inline GateRef TaggedIsJSGlobalObject(GateRef x);
471     inline GateRef TaggedIsGeneratorObject(GateRef x);
472     inline GateRef TaggedIsJSArray(GateRef x);
473     inline GateRef TaggedIsPropertyBox(GateRef x);
474     inline GateRef TaggedIsWeak(GateRef x);
475     inline GateRef TaggedIsPrototypeHandler(GateRef x);
476     inline GateRef TaggedIsTransitionHandler(GateRef x);
477     inline GateRef TaggedIsStoreTSHandler(GateRef x);
478     inline GateRef TaggedIsTransWithProtoHandler(GateRef x);
479     inline GateRef TaggedIsUndefinedOrNull(GateRef x);
480     inline GateRef TaggedIsTrue(GateRef x);
481     inline GateRef TaggedIsFalse(GateRef x);
482     inline GateRef TaggedIsNull(GateRef x);
483     inline GateRef TaggedIsBoolean(GateRef x);
484     inline GateRef IsAOTLiteralInfo(GateRef x);
485     inline GateRef TaggedGetInt(GateRef x);
486     inline GateRef ToTaggedInt(GateRef x);
487     inline GateRef ToTaggedIntPtr(GateRef x);
488     inline GateRef DoubleToTaggedDoublePtr(GateRef x);
489     inline GateRef BooleanToTaggedBooleanPtr(GateRef x);
490     inline GateRef BooleanToInt32(GateRef x);
491     inline GateRef BooleanToFloat64(GateRef x);
492     inline GateRef Float32ToTaggedDoublePtr(GateRef x);
493     inline GateRef TaggedDoublePtrToFloat32(GateRef x);
494     inline GateRef TaggedIntPtrToFloat32(GateRef x);
495     inline GateRef DoubleToTaggedDouble(GateRef x);
496     inline GateRef DoubleToTagged(GateRef x);
497     inline GateRef DoubleIsNAN(GateRef x);
498     inline GateRef TaggedTrue();
499     inline GateRef TaggedFalse();
500     // Pointer/Arithmetic/Logic Operations
501     inline GateRef IntPtrDiv(GateRef x, GateRef y);
502     inline GateRef IntPtrOr(GateRef x, GateRef y);
503     inline GateRef IntPtrLSL(GateRef x, GateRef y);
504     inline GateRef IntPtrLSR(GateRef x, GateRef y);
505     inline GateRef Int64NotEqual(GateRef x, GateRef y);
506     inline GateRef Int32NotEqual(GateRef x, GateRef y);
507     inline GateRef Int64Equal(GateRef x, GateRef y);
508     inline GateRef Int8Equal(GateRef x, GateRef y);
509     inline GateRef Int32Equal(GateRef x, GateRef y);
510     inline GateRef IntPtrGreaterThan(GateRef x, GateRef y);
511     template<OpCode Op, MachineType Type>
512     inline GateRef BinaryOp(GateRef x, GateRef y);
513     template<OpCode Op, MachineType Type>
514     inline GateRef BinaryOpWithOverflow(GateRef x, GateRef y);
515     inline GateRef GetLengthFromTaggedArray(GateRef array);
516     inline GateRef GetValueFromTaggedArray(GateRef array, GateRef index);
517     inline void SetValueToTaggedArray(VariableType valType, GateRef glue, GateRef array, GateRef index, GateRef val);
518     GateRef TaggedIsString(GateRef obj);
519     GateRef TaggedIsStringOrSymbol(GateRef obj);
520     inline GateRef GetGlobalConstantString(ConstantIndex index);
521     inline GateRef LoadObjectFromWeakRef(GateRef x);
522     GateRef ComputeTaggedArraySize(GateRef length);
523 
524     GateRef IsJSHClass(GateRef obj);
525     GateRef HasPendingException(GateRef glue);
526     // middle ir: operations with any type
527     template<TypedBinOp Op>
528     inline GateRef TypedBinaryOp(GateRef x, GateRef y, GateType xType, GateType yType, GateType gateType,
529         PGOSampleType sampleType);
530     template<TypedUnOp Op>
531     inline GateRef TypedUnaryOp(GateRef x, GateType xType, GateType gateType);
532     template<TypedJumpOp Op>
533     inline GateRef TypedConditionJump(GateRef x, GateType xType);
534     inline GateRef PrimitiveToNumber(GateRef x, VariableType type);
535 
536     // middle ir: object operations
537     GateRef ToLength(GateRef receiver);
538     template<TypedLoadOp Op>
539     GateRef LoadElement(GateRef receiver, GateRef index);
540     template<TypedStoreOp Op>
541     GateRef StoreElement(GateRef receiver, GateRef index, GateRef value);
542     GateRef StoreMemory(MemoryType Op, VariableType type, GateRef receiver, GateRef index, GateRef value);
543     GateRef LoadProperty(GateRef receiver, GateRef propertyLookupResult, bool isFunction);
544     GateRef StoreProperty(GateRef receiver, GateRef propertyLookupResult, GateRef value);
545     GateRef LoadArrayLength(GateRef array);
546     GateRef Construct(GateRef hirGate, std::vector<GateRef> args);
547     GateRef TypedCall(GateRef hirGate, std::vector<GateRef> args, bool isNoGC);
548     GateRef TypedFastCall(GateRef hirGate, std::vector<GateRef> args, bool isNoGC);
549     GateRef CallGetter(GateRef hirGate, GateRef receiver, GateRef propertyLookupResult, const char* comment = nullptr);
550     GateRef CallSetter(GateRef hirGate, GateRef receiver, GateRef propertyLookupResult,
551                        GateRef value, const char* comment = nullptr);
552     GateRef GetConstPool(GateRef jsFunc);
553     GateRef GetGlobalEnv();
554     GateRef GetGlobalEnvObjHClass(GateRef env, size_t index);
555     GateRef GetGlobalConstantValue(ConstantIndex index);
556     GateRef LoadConstOffset(VariableType type, GateRef receiver, size_t offset);
557     GateRef StoreConstOffset(VariableType type, GateRef receiver, size_t offset, GateRef value);
558     GateRef LoadObjectFromConstPool(GateRef jsFunc, GateRef index);
559     // Object Operations
560     inline GateRef LoadHClass(GateRef object);
561     inline GateRef IsJSFunction(GateRef obj);
562     inline GateRef IsJSFunctionWithBit(GateRef obj);
563     inline GateRef IsOptimizedAndNotFastCall(GateRef obj);
564     inline GateRef IsOptimized(GateRef obj);
565     inline GateRef IsOptimizedWithBitField(GateRef bitfield);
566     inline GateRef CanFastCall(GateRef obj);
567     inline GateRef CanFastCallWithBitField(GateRef bitfield);
568     inline GateRef IsDictionaryMode(GateRef object);
569     inline void StoreHClass(GateRef glue, GateRef object, GateRef hClass);
570     inline GateRef IsJsType(GateRef object, JSType type);
571     inline GateRef GetObjectType(GateRef hClass);
572     inline GateRef IsDictionaryModeByHClass(GateRef hClass);
573     inline GateRef GetElementsKindByHClass(GateRef hClass);
574     inline GateRef IsIsStableElementsByHClass(GateRef hClass);
575     inline GateRef IsStableElements(GateRef hClass);
576     inline GateRef IsStableArguments(GateRef hClass);
577     inline GateRef IsStableArray(GateRef hClass);
578     inline GateRef DoubleIsINF(GateRef x);
579     inline GateRef IsDictionaryElement(GateRef hClass);
580     inline GateRef IsClassConstructor(GateRef object);
581     inline GateRef IsClassConstructorWithBitField(GateRef bitfield);
582     inline GateRef IsConstructor(GateRef object);
583     inline GateRef IsClassPrototype(GateRef object);
584     inline GateRef IsExtensible(GateRef object);
585     inline GateRef GetExpectedNumOfArgs(GateRef method);
586     inline GateRef TaggedObjectIsEcmaObject(GateRef obj);
587     inline GateRef IsJSObject(GateRef obj);
588     inline GateRef TaggedObjectIsString(GateRef obj);
589     inline GateRef TaggedObjectBothAreString(GateRef x, GateRef y);
590     inline GateRef IsCallable(GateRef obj);
591     inline GateRef IsCallableFromBitField(GateRef bitfield);
592     inline GateRef LogicAnd(GateRef x, GateRef y);
593     inline GateRef LogicOr(GateRef x, GateRef y);
594     inline GateRef BothAreString(GateRef x, GateRef y);
595     inline GateRef GetObjectSizeFromHClass(GateRef hClass);
596     GateRef GetGlobalObject(GateRef glue);
597     GateRef GetMethodFromFunction(GateRef function);
598     GateRef GetModuleFromFunction(GateRef function);
599     GateRef GetHomeObjectFromFunction(GateRef function);
600     GateRef FunctionIsResolved(GateRef function);
601     GateRef GetLengthFromString(GateRef value);
602     GateRef GetHashcodeFromString(GateRef glue, GateRef value);
603     GateRef TryGetHashcodeFromString(GateRef string);
604     GateRef IsUtf16String(GateRef string);
605     GateRef TaggedIsBigInt(GateRef obj);
606     void SetLexicalEnvToFunction(GateRef glue, GateRef function, GateRef value);
607     GateRef GetFunctionLexicalEnv(GateRef function);
608     void SetModuleToFunction(GateRef glue, GateRef function, GateRef value);
609     void SetPropertyInlinedProps(GateRef glue, GateRef obj, GateRef hClass,
610         GateRef value, GateRef attrOffset, VariableType type);
611     void SetHomeObjectToFunction(GateRef glue, GateRef function, GateRef value);
612     GateRef GetConstPoolFromFunction(GateRef jsFunc);
613     GateRef GetCodeAddr(GateRef method);
614     GateRef GetObjectFromConstPool(GateRef glue, GateRef hirGate, GateRef jsFunc, GateRef index, ConstPoolType type);
615     GateRef GetObjectFromConstPool(GateRef glue, GateRef hirGate, GateRef constPool, GateRef module, GateRef index,
616                                    ConstPoolType type);
617     void ClearConstantCache(GateRef gate);
618 
619     // middle ir: create new obj
620     GateRef StartAllocate();
621     GateRef FinishAllocate();
622     GateRef HeapAlloc(GateRef size, GateType type, RegionSpaceFlag flag);
623     GateRef CreateArray(size_t arraySize);
624     GateRef CreateArrayWithBuffer(size_t arraySize, GateRef constPoolIndex, GateRef elementIndex);
625 
SetEnvironment(Environment * env)626     void SetEnvironment(Environment *env)
627     {
628         env_ = env;
629     }
GetCurrentEnvironment()630     Environment *GetCurrentEnvironment() const
631     {
632         return env_;
633     }
SetCompilationConfig(CompilationConfig * cmpCfg)634     void SetCompilationConfig(CompilationConfig *cmpCfg)
635     {
636         cmpCfg_ = cmpCfg;
637     }
GetCompilationConfig()638     CompilationConfig *GetCompilationConfig() const
639     {
640         return cmpCfg_;
641     }
642     // label related
643     void NewEnvironment(GateRef hir);
644     void DeleteCurrentEnvironment();
645     inline int NextVariableId();
646     inline void HandleException(GateRef result, Label *success, Label *exception, Label *exit);
647     inline void HandleException(GateRef result, Label *success, Label *fail, Label *exit, GateRef exceptionVal);
648     inline void SubCfgEntry(Label *entry);
649     inline void SubCfgExit();
650     inline GateRef Return(GateRef value);
651     inline GateRef Return();
652     inline void Bind(Label *label);
653     inline void Bind(Label *label, bool justSlowPath);
654     void Jump(Label *label);
655     void Branch(GateRef condition, Label *trueLabel, Label *falseLabel);
656     void Switch(GateRef index, Label *defaultLabel, int64_t *keysValue, Label *keysLabel, int numberOfKeys);
657     void LoopBegin(Label *loopHead);
658     void LoopEnd(Label *loopHead);
659     inline Label *GetCurrentLabel() const;
660     inline GateRef GetState() const;
661     inline GateRef GetDepend() const;
662     inline StateDepend GetStateDepend() const;
663 
664     GateRef GetGlobalEnvValue(VariableType type, GateRef env, size_t index);
665     GateRef IsBase(GateRef ctor);
666     inline GateRef GetMethodId(GateRef func);
667     inline GateRef LoadFromTaggedArray(GateRef array, size_t index);
668     inline GateRef StoreToTaggedArray(GateRef array, size_t index, GateRef value);
669 
670 private:
671     inline void SetDepend(GateRef depend);
672     inline void SetState(GateRef state);
673 
674 #define ARITHMETIC_UNARY_OP_WITH_BITWIDTH(NAME, OPCODEID, MACHINETYPEID)                            \
675     inline GateRef NAME(GateRef x)                                                                  \
676     {                                                                                               \
677         return circuit_->NewGate(circuit_->OPCODEID(), MACHINETYPEID, { x }, GateType::NJSValue()); \
678     }
679 
UNARY_ARITHMETIC_METHOD_LIST_WITH_BITWIDTH_PRIVATE(ARITHMETIC_UNARY_OP_WITH_BITWIDTH)680     UNARY_ARITHMETIC_METHOD_LIST_WITH_BITWIDTH_PRIVATE(ARITHMETIC_UNARY_OP_WITH_BITWIDTH)
681 #undef ARITHMETIC_UNARY_OP_WITH_BITWIDTH
682 
683     Circuit *circuit_ {nullptr};
684     GateAccessor acc_;
685     Environment *env_ {nullptr};
686     CompilationConfig *cmpCfg_ {nullptr};
687     friend StubBuilder;
688     friend TSHCRLowering;
689     friend NTypeHCRLowering;
690     friend SlowPathLowering;
691 };
692 
693 class Label {
694 public:
695     Label() = default;
696     explicit Label(Environment *env);
697     explicit Label(CircuitBuilder *cirBuilder);
698     ~Label() = default;
699     Label(Label const &label) = default;
700     Label &operator=(Label const &label) = default;
701     Label(Label &&label) = default;
702     Label &operator=(Label &&label) = default;
703     inline void Seal();
WriteVariable(Variable * var,GateRef value)704     inline void WriteVariable(Variable *var, GateRef value)
705     {
706         impl_->WriteVariable(var, value);
707     }
ReadVariable(Variable * var)708     inline GateRef ReadVariable(Variable *var)
709     {
710         return impl_->ReadVariable(var);
711     }
712     inline void Bind();
713     inline void MergeAllControl();
714     inline void MergeAllDepend();
715     inline void AppendPredecessor(const Label *predecessor);
716     inline std::vector<Label> GetPredecessors() const;
717     inline void SetControl(GateRef control);
718     inline void SetPreControl(GateRef control);
719     inline void MergeControl(GateRef control);
720     inline GateRef GetControl() const;
721     inline GateRef GetDepend() const;
722     inline void SetDepend(GateRef depend);
723 
724 private:
725     class LabelImpl {
726     public:
LabelImpl(Environment * env,GateRef control)727         LabelImpl(Environment *env, GateRef control)
728             : env_(env), control_(control), predeControl_(-1), isSealed_(false)
729         {
730         }
731         ~LabelImpl() = default;
732         NO_MOVE_SEMANTIC(LabelImpl);
733         NO_COPY_SEMANTIC(LabelImpl);
734         void Seal();
735         void WriteVariable(Variable *var, GateRef value);
736         GateRef ReadVariable(Variable *var);
737         void Bind();
738         void MergeAllControl();
739         void MergeAllDepend();
740         void AppendPredecessor(LabelImpl *predecessor);
GetPredecessors()741         std::vector<LabelImpl *> GetPredecessors() const
742         {
743             return predecessors_;
744         }
SetControl(GateRef control)745         void SetControl(GateRef control)
746         {
747             control_ = control;
748         }
SetPreControl(GateRef control)749         void SetPreControl(GateRef control)
750         {
751             predeControl_ = control;
752         }
MergeControl(GateRef control)753         void MergeControl(GateRef control)
754         {
755             if (predeControl_ == Circuit::NullGate()) {
756                 predeControl_ = control;
757                 control_ = predeControl_;
758             } else {
759                 otherPredeControls_.push_back(control);
760             }
761         }
GetControl()762         GateRef GetControl() const
763         {
764             return control_;
765         }
SetDepend(GateRef depend)766         void SetDepend(GateRef depend)
767         {
768             depend_ = depend;
769         }
GetDepend()770         GateRef GetDepend() const
771         {
772             return depend_;
773         }
774 
775     private:
776         bool IsNeedSeal() const;
IsSealed()777         bool IsSealed() const
778         {
779             return isSealed_;
780         }
781         bool IsLoopHead() const;
782         bool IsControlCase() const;
783         GateRef ReadVariableRecursive(Variable *var);
784         Environment *env_;
785         GateRef control_;
786         GateRef predeControl_ {Circuit::NullGate()};
787         GateRef depend_ {Circuit::NullGate()};
788         GateRef loopDepend_ {Circuit::NullGate()};
789         std::vector<GateRef> otherPredeControls_;
790         bool isSealed_ {false};
791         std::map<Variable *, GateRef> valueMap_;
792         std::vector<GateRef> phi;
793         std::vector<LabelImpl *> predecessors_;
794         std::map<Variable *, GateRef> incompletePhis_;
795     };
796 
Label(LabelImpl * impl)797     explicit Label(LabelImpl *impl) : impl_(impl) {}
798     friend class Environment;
GetRawLabel()799     LabelImpl *GetRawLabel() const
800     {
801         return impl_;
802     }
803     LabelImpl *impl_ {nullptr};
804 };
805 
806 class Environment {
807 public:
808     using LabelImpl = Label::LabelImpl;
809     Environment(GateRef hir, Circuit *circuit, CircuitBuilder *builder);
810     Environment(GateRef stateEntry, GateRef dependEntry, const std::initializer_list<GateRef>& args,
811                 Circuit *circuit, CircuitBuilder *builder);
812     Environment(size_t arguments, CircuitBuilder *builder);
813     ~Environment();
GetCurrentLabel()814     Label *GetCurrentLabel() const
815     {
816         return currentLabel_;
817     }
SetCurrentLabel(Label * label)818     void SetCurrentLabel(Label *label)
819     {
820         currentLabel_ = label;
821     }
GetBuilder()822     CircuitBuilder *GetBuilder() const
823     {
824         return circuitBuilder_;
825     }
GetCircuit()826     Circuit *GetCircuit() const
827     {
828         return circuit_;
829     }
NextVariableId()830     int NextVariableId()
831     {
832         return nextVariableId_++;
833     }
SetCompilationConfig(const CompilationConfig * cfg)834     void SetCompilationConfig(const CompilationConfig *cfg)
835     {
836         ccfg_ = cfg;
837     }
GetCompilationConfig()838     const CompilationConfig *GetCompilationConfig() const
839     {
840         return ccfg_;
841     }
Is32Bit()842     inline bool Is32Bit() const
843     {
844         return ccfg_->Is32Bit();
845     }
IsAArch64()846     inline bool IsAArch64() const
847     {
848         return ccfg_->IsAArch64();
849     }
IsAmd64()850     inline bool IsAmd64() const
851     {
852         return ccfg_->IsAmd64();
853     }
IsArch64Bit()854     inline bool IsArch64Bit() const
855     {
856         return ccfg_->IsAmd64() ||  ccfg_->IsAArch64();
857     }
IsAsmInterp()858     inline bool IsAsmInterp() const
859     {
860         return circuit_->GetFrameType() == FrameType::ASM_INTERPRETER_FRAME;
861     }
IsArch32Bit()862     inline bool IsArch32Bit() const
863     {
864         return ccfg_->Is32Bit();
865     }
GetArgument(size_t index)866     inline GateRef GetArgument(size_t index) const
867     {
868         return arguments_.at(index);
869     }
870 
871     inline Label GetLabelFromSelector(GateRef sel);
872     inline void AddSelectorToLabel(GateRef sel, Label label);
873     inline LabelImpl *NewLabel(Environment *env, GateRef control = -1);
874     inline void SubCfgEntry(Label *entry);
875     inline void SubCfgExit();
876     inline GateRef GetInput(size_t index) const;
877 
878 private:
879     Label *currentLabel_ {nullptr};
880     Circuit *circuit_ {nullptr};
881     CircuitBuilder *circuitBuilder_ {nullptr};
882     std::unordered_map<GateRef, LabelImpl *> phiToLabels_;
883     std::vector<GateRef> inputList_;
884     Label entry_;
885     std::vector<LabelImpl *> rawLabels_;
886     std::stack<Label *> stack_;
887     int nextVariableId_ {0};
888     std::vector<GateRef> arguments_;
889     const CompilationConfig *ccfg_ {nullptr};
890 };
891 
892 class Variable {
893 public:
Variable(Environment * env,VariableType type,uint32_t id,GateRef value)894     Variable(Environment *env, VariableType type, uint32_t id, GateRef value) : id_(id), type_(type), env_(env)
895     {
896         Bind(value);
897         env_->GetCurrentLabel()->WriteVariable(this, value);
898     }
Variable(CircuitBuilder * cirbuilder,VariableType type,uint32_t id,GateRef value)899     Variable(CircuitBuilder *cirbuilder, VariableType type, uint32_t id, GateRef value)
900         : id_(id), type_(type), env_(cirbuilder->GetCurrentEnvironment())
901     {
902         Bind(value);
903         env_->GetCurrentLabel()->WriteVariable(this, value);
904     }
905     ~Variable() = default;
906     NO_MOVE_SEMANTIC(Variable);
907     NO_COPY_SEMANTIC(Variable);
Bind(GateRef value)908     void Bind(GateRef value)
909     {
910         currentValue_ = value;
911     }
Value()912     GateRef Value() const
913     {
914         return currentValue_;
915     }
Type()916     VariableType Type() const
917     {
918         return type_;
919     }
IsBound()920     bool IsBound() const
921     {
922         return currentValue_ != 0;
923     }
924     Variable &operator=(const GateRef value)
925     {
926         env_->GetCurrentLabel()->WriteVariable(this, value);
927         Bind(value);
928         return *this;
929     }
930     GateRef operator*()
931     {
932         return env_->GetCurrentLabel()->ReadVariable(this);
933     }
ReadVariable()934     GateRef ReadVariable()
935     {
936         return env_->GetCurrentLabel()->ReadVariable(this);
937     }
WriteVariable(GateRef value)938     void WriteVariable(GateRef value)
939     {
940         env_->GetCurrentLabel()->WriteVariable(this, value);
941         Bind(value);
942     }
943     GateRef AddPhiOperand(GateRef val);
944     GateRef AddOperandToSelector(GateRef val, size_t idx, GateRef in);
945     GateRef TryRemoveTrivialPhi(GateRef phi);
GetId()946     uint32_t GetId() const
947     {
948         return id_;
949     }
950 
951 private:
GetCircuit()952     Circuit* GetCircuit() const
953     {
954         return env_->GetCircuit();
955     }
956 
957     uint32_t id_;
958     VariableType type_;
959     GateRef currentValue_ {0};
960     Environment *env_;
961 };
962 }  // namespace panda::ecmascript::kungfu
963 
964 #endif  // ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_H
965