• 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/builtins/builtins_call_signature.h"
21 #include "ecmascript/compiler/circuit.h"
22 #include "ecmascript/compiler/call_signature.h"
23 #include "ecmascript/compiler/gate.h"
24 #include "ecmascript/compiler/gate_accessor.h"
25 #include "ecmascript/compiler/variable_type.h"
26 #include "ecmascript/global_env_constants.h"
27 #include "ecmascript/jspandafile/constpool_value.h"
28 #include "ecmascript/js_hclass.h"
29 #include "ecmascript/js_tagged_value.h"
30 #include "ecmascript/platform/elf.h"
31 #include "ecmascript/tagged_array.h"
32 
33 namespace panda::ecmascript::kungfu {
34 using namespace panda::ecmascript;
35 #define DEFVAlUE(varname, cirBuilder, type, val) \
36         Variable varname(cirBuilder, type, cirBuilder->NextVariableId(), val)
37 
38 class Environment;
39 class Label;
40 class Variable;
41 
42 #define BINARY_ARITHMETIC_METHOD_LIST_WITH_BITWIDTH(V)                            \
43     V(Int16Add, Add, MachineType::I16)                                    \
44     V(Int32Add, Add, MachineType::I32)                                    \
45     V(Int64Add, Add, MachineType::I64)                                    \
46     V(DoubleAdd, Add, MachineType::F64)                                   \
47     V(PtrAdd, Add, MachineType::ARCH)                                     \
48     V(Int16Sub, Sub, MachineType::I16)                                    \
49     V(Int32Sub, Sub, MachineType::I32)                                    \
50     V(Int64Sub, Sub, MachineType::I64)                                    \
51     V(DoubleSub, Sub, MachineType::F64)                                   \
52     V(PtrSub, Sub, MachineType::ARCH)                                     \
53     V(Int32Mul, Mul, MachineType::I32)                                    \
54     V(Int64Mul, Mul, MachineType::I64)                                    \
55     V(DoubleMul, Mul, MachineType::F64)                                   \
56     V(PtrMul, Mul, MachineType::ARCH)                                     \
57     V(Int32Div, Sdiv, MachineType::I32)                                   \
58     V(Int64Div, Sdiv, MachineType::I64)                                   \
59     V(DoubleDiv, Fdiv, MachineType::F64)                                  \
60     V(Int32Mod, Smod, MachineType::I32)                                   \
61     V(DoubleMod, Smod, MachineType::F64)                                  \
62     V(BoolAnd, And, MachineType::I1)                                      \
63     V(Int8And, And, MachineType::I8)                                      \
64     V(Int32And, And, MachineType::I32)                                    \
65     V(Int64And, And, MachineType::I64)                                    \
66     V(BoolOr, Or, MachineType::I1)                                        \
67     V(Int32Or, Or, MachineType::I32)                                      \
68     V(Int64Or, Or, MachineType::I64)                                      \
69     V(Int32Xor, Xor, MachineType::I32)                                    \
70     V(Int64Xor, Xor, MachineType::I64)                                    \
71     V(Int16LSL, Lsl, MachineType::I16)                                    \
72     V(Int32LSL, Lsl, MachineType::I32)                                    \
73     V(Int64LSL, Lsl, MachineType::I64)                                    \
74     V(Int8LSR, Lsr, MachineType::I8)                                      \
75     V(Int32LSR, Lsr, MachineType::I32)                                    \
76     V(Int64LSR, Lsr, MachineType::I64)                                    \
77     V(Int32ASR, Asr, MachineType::I32)
78 
79 #define UNARY_ARITHMETIC_METHOD_LIST_WITH_BITWIDTH(V)                  \
80     V(BoolNot, Rev, MachineType::I1)                                   \
81     V(Int32Not, Rev, MachineType::I32)                                 \
82     V(Int64Not, Rev, MachineType::I64)                                 \
83     V(CastDoubleToInt64, Bitcast, MachineType::I64)                    \
84     V(CastInt64ToFloat64, Bitcast, MachineType::F64)                   \
85     V(SExtInt32ToInt64, Sext, MachineType::I64)                        \
86     V(SExtInt1ToInt64, Sext, MachineType::I64)                         \
87     V(SExtInt1ToInt32, Sext, MachineType::I32)                         \
88     V(ZExtInt8ToInt16, Zext, MachineType::I16)                         \
89     V(ZExtInt32ToInt64, Zext, MachineType::I64)                        \
90     V(ZExtInt1ToInt64, Zext, MachineType::I64)                         \
91     V(ZExtInt1ToInt32, Zext, MachineType::I32)                         \
92     V(ZExtInt8ToInt32, Zext, MachineType::I32)                         \
93     V(ZExtInt8ToInt64, Zext, MachineType::I64)                         \
94     V(ZExtInt8ToPtr, Zext, MachineType::ARCH)                          \
95     V(ZExtInt16ToPtr, Zext, MachineType::ARCH)                         \
96     V(ZExtInt32ToPtr, Zext, MachineType::ARCH)                         \
97     V(SExtInt32ToPtr, Sext, MachineType::ARCH)                         \
98     V(ZExtInt16ToInt32, Zext, MachineType::I32)                        \
99     V(ZExtInt16ToInt64, Zext, MachineType::I64)                        \
100     V(TruncInt16ToInt8, Trunc, MachineType::I8)                        \
101     V(TruncInt64ToInt32, Trunc, MachineType::I32)                      \
102     V(TruncPtrToInt32, Trunc, MachineType::I32)                        \
103     V(TruncInt64ToInt1, Trunc, MachineType::I1)                        \
104     V(TruncInt64ToInt16, Trunc, MachineType::I16)                      \
105     V(TruncInt32ToInt1, Trunc, MachineType::I1)                        \
106     V(TruncInt32ToInt16, Trunc, MachineType::I16)                      \
107     V(TruncFloatToInt64, TruncFloatToInt64, MachineType::I64)          \
108     V(ExtFloat32ToDouble, Fext, MachineType::F64)                      \
109     V(TruncDoubleToFloat32, Ftrunc, MachineType::F32)                  \
110     V(ChangeTaggedPointerToInt64, TaggedToInt64, MachineType::I64)     \
111     V(ChangeInt32ToFloat64, SignedIntToFloat, MachineType::F64)        \
112     V(ChangeInt32ToFloat32, SignedIntToFloat, MachineType::F32)        \
113     V(ChangeUInt32ToFloat64, UnsignedIntToFloat, MachineType::F64)     \
114     V(ChangeFloat64ToInt32, FloatToSignedInt, MachineType::I32)        \
115     V(SExtInt16ToInt64, Sext, MachineType::I64)        \
116     V(SExtInt16ToInt32, Sext, MachineType::I32)        \
117     V(SExtInt8ToInt64, Sext, MachineType::I64)        \
118 
119 #define BINARY_CMP_METHOD_LIST_WITHOUT_BITWIDTH(V)                                              \
120     V(DoubleLessThan, Fcmp, static_cast<BitField>(FCmpCondition::OLT))                  \
121     V(DoubleLessThanOrEqual, Fcmp, static_cast<BitField>(FCmpCondition::OLE))           \
122     V(DoubleGreaterThan, Fcmp, static_cast<BitField>(FCmpCondition::OGT))               \
123     V(DoubleGreaterThanOrEqual, Fcmp, static_cast<BitField>(FCmpCondition::OGE))        \
124     V(Int32LessThan, Icmp, static_cast<BitField>(ICmpCondition::SLT))                   \
125     V(Int32LessThanOrEqual, Icmp, static_cast<BitField>(ICmpCondition::SLE))            \
126     V(Int32GreaterThan, Icmp, static_cast<BitField>(ICmpCondition::SGT))                \
127     V(Int32GreaterThanOrEqual, Icmp, static_cast<BitField>(ICmpCondition::SGE))         \
128     V(Int32UnsignedLessThan, Icmp, static_cast<BitField>(ICmpCondition::ULT))           \
129     V(Int32UnsignedGreaterThan, Icmp, static_cast<BitField>(ICmpCondition::UGT))        \
130     V(Int32UnsignedGreaterThanOrEqual, Icmp, static_cast<BitField>(ICmpCondition::UGE)) \
131     V(Int64LessThan, Icmp, static_cast<BitField>(ICmpCondition::SLT))                   \
132     V(Int64LessThanOrEqual, Icmp, static_cast<BitField>(ICmpCondition::SLE))            \
133     V(Int64GreaterThan, Icmp, static_cast<BitField>(ICmpCondition::SGT))                \
134     V(Int64GreaterThanOrEqual, Icmp, static_cast<BitField>(ICmpCondition::SGE))         \
135     V(Int64UnsignedLessThanOrEqual, Icmp, static_cast<BitField>(ICmpCondition::ULE))
136 
137 class CompilationConfig {
138 public:
139     explicit CompilationConfig(const std::string &triple, bool enablePGOProfiler = false, bool isTraceBC = false,
140                                bool profiling = false)
triple_(GetTripleFromString (triple))141         : triple_(GetTripleFromString(triple)), isTraceBc_(isTraceBC), enablePGOProfiler_(enablePGOProfiler),
142           profiling_(profiling)
143     {
144     }
145     ~CompilationConfig() = default;
146 
Is32Bit()147     inline bool Is32Bit() const
148     {
149         return triple_ == Triple::TRIPLE_ARM32;
150     }
151 
IsAArch64()152     inline bool IsAArch64() const
153     {
154         return triple_ == Triple::TRIPLE_AARCH64;
155     }
156 
IsAmd64()157     inline bool IsAmd64() const
158     {
159         return triple_ == Triple::TRIPLE_AMD64;
160     }
161 
Is64Bit()162     inline bool Is64Bit() const
163     {
164         return IsAArch64() || IsAmd64();
165     }
166 
GetTriple()167     Triple GetTriple() const
168     {
169         return triple_;
170     }
171 
IsTraceBC()172     bool IsTraceBC() const
173     {
174         return isTraceBc_;
175     }
176 
IsEnablePGOProfiler()177     bool IsEnablePGOProfiler() const
178     {
179         return enablePGOProfiler_;
180     }
181 
IsProfiling()182     bool IsProfiling() const
183     {
184         return profiling_;
185     }
186 
187 private:
GetTripleFromString(const std::string & triple)188     inline Triple GetTripleFromString(const std::string &triple)
189     {
190         if (triple.compare("x86_64-unknown-linux-gnu") == 0) {
191             return Triple::TRIPLE_AMD64;
192         }
193 
194         if (triple.compare("aarch64-unknown-linux-gnu") == 0) {
195             return Triple::TRIPLE_AARCH64;
196         }
197 
198         if (triple.compare("arm-unknown-linux-gnu") == 0) {
199             return Triple::TRIPLE_ARM32;
200         }
201         UNREACHABLE();
202     }
203     Triple triple_;
204     bool isTraceBc_;
205     bool enablePGOProfiler_;
206     bool profiling_;
207 };
208 
209 class CircuitBuilder {
210 public:
CircuitBuilder(Circuit * circuit)211     explicit CircuitBuilder(Circuit *circuit) : circuit_(circuit), acc_(circuit) {}
CircuitBuilder(Circuit * circuit,CompilationConfig * cmpCfg)212     explicit CircuitBuilder(Circuit *circuit, CompilationConfig *cmpCfg)
213         : circuit_(circuit), acc_(circuit), cmpCfg_(cmpCfg)
214     {
215     }
216     ~CircuitBuilder() = default;
217     NO_MOVE_SEMANTIC(CircuitBuilder);
218     NO_COPY_SEMANTIC(CircuitBuilder);
219     // low level interface
220     template<TypedUnOp Op>
221     inline GateRef Int32OverflowCheck(GateRef gate);
222     GateRef ArrayCheck(GateRef gate);
223     GateRef StableArrayCheck(GateRef gate);
224     GateRef TypedArrayCheck(GateType type, GateRef gate);
225     GateRef IndexCheck(GateType type, GateRef gate, GateRef index);
226     GateRef ObjectTypeCheck(GateType type, GateRef gate, GateRef hclassOffset);
227     GateRef PrimitiveTypeCheck(GateType type, GateRef gate);
228     GateRef CallTargetCheck(GateRef function, GateRef id, GateRef param);
229     GateRef DeoptCheck(GateRef condition, GateRef frameState, DeoptType type = DeoptType::NOTCHECK);
230     GateRef TypedBinaryOperator(MachineType type, TypedBinOp binOp, GateType typeLeft, GateType typeRight,
231                                 std::vector<GateRef> inList, GateType gateType);
232     GateRef TypedCallOperator(MachineType type, const std::initializer_list<GateRef>& args);
233     inline GateRef TypedCallBuiltin(GateRef x, BuiltinsStubCSigns::ID id);
234     GateRef TypeConvert(MachineType type, GateType typeFrom, GateType typeTo, const std::vector<GateRef>& inList);
235     GateRef TypedUnaryOperator(MachineType type, TypedUnOp unaryOp, GateType typeVal,
236                                const std::vector<GateRef>& inList, GateType gateType);
237     GateRef TypedNewAllocateThis(GateRef ctor, GateRef hclassIndex, GateRef frameState);
238     GateRef TypedSuperAllocateThis(GateRef superCtor, GateRef newTarget, GateRef frameState);
239     GateRef GetSuperConstructor(GateRef ctor);
240     GateRef Arguments(size_t index);
241     GateRef Merge(const std::vector<GateRef> &inList);
242     GateRef Selector(OpCode opcode, MachineType machineType, GateRef control, const std::vector<GateRef> &values,
243         int valueCounts, VariableType type = VariableType::VOID());
244     GateRef Selector(OpCode opcode, GateRef control, const std::vector<GateRef> &values,
245         int valueCounts, VariableType type = VariableType::VOID());
246     GateRef Int8(int8_t val);
247     GateRef Int16(int16_t val);
248     GateRef Int32(int32_t value);
249     GateRef Int64(int64_t value);
250     GateRef IntPtr(int64_t val);
251     GateRef Boolean(bool value);
252     GateRef Double(double value);
253     GateRef UndefineConstant();
254     GateRef HoleConstant();
255     GateRef NullConstant();
256     GateRef ExceptionConstant();
257     GateRef RelocatableData(uint64_t val);
258     GateRef Alloca(size_t size);
259     GateRef Branch(GateRef state, GateRef condition);
260     GateRef SwitchBranch(GateRef state, GateRef index, int caseCounts);
261     GateRef Return(GateRef state, GateRef depend, GateRef value);
262     GateRef ReturnVoid(GateRef state, GateRef depend);
263     GateRef Goto(GateRef state);
264     GateRef LoopBegin(GateRef state);
265     GateRef LoopEnd(GateRef state);
266     GateRef IfTrue(GateRef ifBranch);
267     GateRef IfFalse(GateRef ifBranch);
268     GateRef SwitchCase(GateRef switchBranch, int64_t value);
269     GateRef DefaultCase(GateRef switchBranch);
270     GateRef DependRelay(GateRef state, GateRef depend);
271     GateRef DependAnd(std::initializer_list<GateRef> args);
272     GateRef BinaryArithmetic(const GateMetaData* meta, MachineType machineType,
273         GateRef left, GateRef right);
274     GateRef BinaryCmp(const GateMetaData* meta, GateRef left, GateRef right);
275     static MachineType GetMachineTypeFromVariableType(VariableType type);
276     GateRef GetCallBuiltinId(GateRef method);
GetCircuit()277     Circuit *GetCircuit() const
278     {
279         return circuit_;
280     }
281     // constant
282     inline GateRef True();
283     inline GateRef False();
284     inline GateRef Undefined();
285 
286     // call operation
287     GateRef CallBCHandler(GateRef glue, GateRef target, const std::vector<GateRef> &args);
288     GateRef CallBCDebugger(GateRef glue, GateRef target, const std::vector<GateRef> &args);
289     GateRef CallBuiltin(GateRef glue, GateRef target, const std::vector<GateRef> &args);
290     GateRef CallBuiltinWithArgv(GateRef glue, GateRef target, const std::vector<GateRef> &args);
291     GateRef CallRuntimeVarargs(GateRef glue, int index, GateRef argc, GateRef argv);
292     GateRef CallRuntime(GateRef glue, int index, GateRef depend, const std::vector<GateRef> &args);
293     GateRef CallNGCRuntime(GateRef glue, int index, GateRef depend, const std::vector<GateRef> &args);
294     GateRef CallStub(GateRef glue, int index, const std::vector<GateRef> &args);
295     GateRef CallBuiltinRuntime(GateRef glue, GateRef depend, const std::vector<GateRef> &args, bool isNew = false);
296     GateRef Call(const CallSignature* cs, GateRef glue, GateRef target, GateRef depend,
297                  const std::vector<GateRef> &args);
298 
299     // memory
300     inline GateRef Load(VariableType type, GateRef base, GateRef offset);
301     void Store(VariableType type, GateRef glue, GateRef base, GateRef offset, GateRef value);
302 
303 #define ARITHMETIC_BINARY_OP_WITH_BITWIDTH(NAME, OPCODEID, MACHINETYPEID)                 \
304     inline GateRef NAME(GateRef x, GateRef y)                                             \
305     {                                                                                     \
306         return BinaryArithmetic(circuit_->OPCODEID(), MACHINETYPEID, x, y);               \
307     }
308 
309     BINARY_ARITHMETIC_METHOD_LIST_WITH_BITWIDTH(ARITHMETIC_BINARY_OP_WITH_BITWIDTH)
310 #undef ARITHMETIC_BINARY_OP_WITH_BITWIDTH
311 
312 #define ARITHMETIC_UNARY_OP_WITH_BITWIDTH(NAME, OPCODEID, MACHINETYPEID)                            \
313     inline GateRef NAME(GateRef x)                                                                  \
314     {                                                                                               \
315         return circuit_->NewGate(circuit_->OPCODEID(), MACHINETYPEID, { x }, GateType::NJSValue()); \
316     }
317 
318     UNARY_ARITHMETIC_METHOD_LIST_WITH_BITWIDTH(ARITHMETIC_UNARY_OP_WITH_BITWIDTH)
319 #undef ARITHMETIC_UNARY_OP_WITH_BITWIDTH
320 
321 #define CMP_BINARY_OP_WITHOUT_BITWIDTH(NAME, OPCODEID, CONDITION)                         \
322     inline GateRef NAME(GateRef x, GateRef y)                                             \
323     {                                                                                     \
324         return BinaryCmp(circuit_->OPCODEID(static_cast<uint64_t>(CONDITION)), x, y);                            \
325     }
326 
327     BINARY_CMP_METHOD_LIST_WITHOUT_BITWIDTH(CMP_BINARY_OP_WITHOUT_BITWIDTH)
328 #undef CMP_BINARY_OP_WITHOUT_BITWIDTH
329 
330     inline GateRef Equal(GateRef x, GateRef y);
331     inline GateRef NotEqual(GateRef x, GateRef y);
332 
333     // js world
334     // cast operation
335     inline GateRef GetInt64OfTInt(GateRef x);
336     inline GateRef GetInt32OfTInt(GateRef x);
337     inline GateRef TaggedCastToIntPtr(GateRef x);
338     inline GateRef GetDoubleOfTDouble(GateRef x);
339     inline GateRef GetDoubleOfTNumber(GateRef x);
340     inline GateRef Int32ToTaggedPtr(GateRef x);
341     inline GateRef Int64ToTaggedPtr(GateRef x);
342     inline GateRef Int32ToTaggedInt(GateRef x);
343     // bit operation
344     inline GateRef IsSpecial(GateRef x, JSTaggedType type);
345     inline GateRef TaggedIsInt(GateRef x);
346     inline GateRef TaggedIsDouble(GateRef x);
347     inline GateRef TaggedIsObject(GateRef x);
348     inline GateRef TaggedIsNumber(GateRef x);
349     inline GateRef TaggedIsNumeric(GateRef x);
350     inline GateRef TaggedIsNotHole(GateRef x);
351     inline GateRef TaggedIsHole(GateRef x);
352     inline GateRef TaggedIsUndefined(GateRef x);
353     inline GateRef TaggedIsException(GateRef x);
354     inline GateRef TaggedIsSpecial(GateRef x);
355     inline GateRef TaggedIsHeapObject(GateRef x);
356     inline GateRef TaggedIsAsyncGeneratorObject(GateRef x);
357     inline GateRef TaggedIsGeneratorObject(GateRef x);
358     inline GateRef TaggedIsPropertyBox(GateRef x);
359     inline GateRef TaggedIsWeak(GateRef x);
360     inline GateRef TaggedIsPrototypeHandler(GateRef x);
361     inline GateRef TaggedIsTransitionHandler(GateRef x);
362     inline GateRef TaggedIsStoreTSHandler(GateRef x);
363     inline GateRef TaggedIsTransWithProtoHandler(GateRef x);
364     inline GateRef TaggedIsUndefinedOrNull(GateRef x);
365     inline GateRef TaggedIsTrue(GateRef x);
366     inline GateRef TaggedIsFalse(GateRef x);
367     inline GateRef TaggedIsNull(GateRef x);
368     inline GateRef TaggedIsBoolean(GateRef x);
369     inline GateRef IsAOTLiteralInfo(GateRef x);
370     inline GateRef TaggedGetInt(GateRef x);
371     inline GateRef ToTaggedInt(GateRef x);
372     inline GateRef ToTaggedIntPtr(GateRef x);
373     inline GateRef DoubleToTaggedDoublePtr(GateRef x);
374     inline GateRef BooleanToTaggedBooleanPtr(GateRef x);
375     inline GateRef Float32ToTaggedDoublePtr(GateRef x);
376     inline GateRef TaggedDoublePtrToFloat32(GateRef x);
377     inline GateRef TaggedIntPtrToFloat32(GateRef x);
378     inline GateRef DoubleToTaggedDouble(GateRef x);
379     inline GateRef DoubleToTagged(GateRef x);
380     inline GateRef DoubleIsNAN(GateRef x);
381     inline GateRef TaggedTrue();
382     inline GateRef TaggedFalse();
383     // Pointer/Arithmetic/Logic Operations
384     inline GateRef IntPtrDiv(GateRef x, GateRef y);
385     inline GateRef IntPtrOr(GateRef x, GateRef y);
386     inline GateRef IntPtrLSL(GateRef x, GateRef y);
387     inline GateRef IntPtrLSR(GateRef x, GateRef y);
388     inline GateRef Int64NotEqual(GateRef x, GateRef y);
389     inline GateRef Int32NotEqual(GateRef x, GateRef y);
390     inline GateRef Int64Equal(GateRef x, GateRef y);
391     inline GateRef DoubleEqual(GateRef x, GateRef y);
392     inline GateRef DoubleNotEqual(GateRef x, GateRef y);
393     inline GateRef Int8Equal(GateRef x, GateRef y);
394     inline GateRef Int32Equal(GateRef x, GateRef y);
395     inline GateRef IntPtrGreaterThan(GateRef x, GateRef y);
396     template<OpCode Op, MachineType Type>
397     inline GateRef BinaryOp(GateRef x, GateRef y);
398     inline GateRef GetValueFromTaggedArray(GateRef array, GateRef index);
399     inline void SetValueToTaggedArray(VariableType valType, GateRef glue, GateRef array, GateRef index, GateRef val);
400     GateRef TaggedIsString(GateRef obj);
401     GateRef TaggedIsStringOrSymbol(GateRef obj);
402     inline GateRef GetGlobalConstantString(ConstantIndex index);
403 
404     GateRef IsJSHClass(GateRef obj);
405     GateRef HasPendingException(GateRef glue);
406 
407     // middle ir: operations with any type
408     template<TypedBinOp Op>
409     inline GateRef TypedBinaryOp(GateRef x, GateRef y, GateType xType, GateType yType, GateType gateType);
410     template<TypedUnOp Op>
411     inline GateRef TypedUnaryOp(GateRef x, GateType xType, GateType gateType);
412 
413     // middle ir: Number operations
414     template<TypedBinOp Op>
415     inline GateRef NumberBinaryOp(GateRef x, GateRef y);
416     inline GateRef PrimitiveToNumber(GateRef x, VariableType type);
417 
418     // middle ir: object operations
419     GateRef ToLength(GateRef receiver);
420     template<TypedLoadOp Op>
421     GateRef LoadElement(GateRef receiver, GateRef index);
422     template<TypedStoreOp Op>
423     GateRef StoreElement(GateRef receiver, GateRef index, GateRef value);
424     GateRef LoadProperty(GateRef receiver, GateRef offset);
425     GateRef StoreProperty(GateRef receiver, GateRef offset, GateRef value);
426     GateRef LoadArrayLength(GateRef array);
427     GateRef HeapAlloc(GateRef initialHClass, GateType type, RegionSpaceFlag flag);
428     GateRef Construct(std::vector<GateRef> args);
429 
430     // Object Operations
431     inline GateRef LoadHClass(GateRef object);
432     inline GateRef IsDictionaryMode(GateRef object);
433     inline void StoreHClass(GateRef glue, GateRef object, GateRef hClass);
434     inline GateRef IsJsType(GateRef object, JSType type);
435     inline GateRef GetObjectType(GateRef hClass);
436     inline GateRef IsDictionaryModeByHClass(GateRef hClass);
437     inline GateRef DoubleIsINF(GateRef x);
438     inline GateRef IsDictionaryElement(GateRef hClass);
439     inline GateRef IsClassConstructor(GateRef object);
440     inline GateRef IsClassPrototype(GateRef object);
441     inline GateRef IsExtensible(GateRef object);
442     inline GateRef TaggedObjectIsEcmaObject(GateRef obj);
443     inline GateRef IsJSObject(GateRef obj);
444     inline GateRef TaggedObjectBothAreString(GateRef x, GateRef y);
445     inline GateRef IsCallable(GateRef obj);
446     inline GateRef IsCallableFromBitField(GateRef bitfield);
447     inline GateRef LogicAnd(GateRef x, GateRef y);
448     inline GateRef LogicOr(GateRef x, GateRef y);
449     inline GateRef BothAreString(GateRef x, GateRef y);
450     inline GateRef GetObjectSizeFromHClass(GateRef hClass);
451     GateRef GetGlobalObject(GateRef glue);
452     GateRef GetMethodFromFunction(GateRef function);
453     GateRef GetModuleFromFunction(GateRef function);
454     GateRef GetHomeObjectFromFunction(GateRef function);
455     GateRef FunctionIsResolved(GateRef function);
456     GateRef GetLengthFromString(GateRef value);
457     GateRef GetHashcodeFromString(GateRef glue, GateRef value);
458     GateRef IsUtf16String(GateRef string);
459     GateRef TaggedIsBigInt(GateRef obj);
460     void SetLexicalEnvToFunction(GateRef glue, GateRef function, GateRef value);
461     GateRef GetFunctionLexicalEnv(GateRef function);
462     void SetModuleToFunction(GateRef glue, GateRef function, GateRef value);
463     void SetPropertyInlinedProps(GateRef glue, GateRef obj, GateRef hClass,
464         GateRef value, GateRef attrOffset, VariableType type);
465     void SetHomeObjectToFunction(GateRef glue, GateRef function, GateRef value);
466     GateRef GetConstPool(GateRef jsFunc);
467     GateRef GetObjectFromConstPool(GateRef glue, GateRef jsFunc, GateRef index, ConstPoolType type);
468     GateRef GetObjectFromConstPool(GateRef glue, GateRef constPool, GateRef module, GateRef index,
469                                    ConstPoolType type);
SetEnvironment(Environment * env)470     void SetEnvironment(Environment *env)
471     {
472         env_ = env;
473     }
GetCurrentEnvironment()474     Environment *GetCurrentEnvironment() const
475     {
476         return env_;
477     }
SetCompilationConfig(CompilationConfig * cmpCfg)478     void SetCompilationConfig(CompilationConfig *cmpCfg)
479     {
480         cmpCfg_ = cmpCfg;
481     }
GetCompilationConfig()482     CompilationConfig *GetCompilationConfig() const
483     {
484         return cmpCfg_;
485     }
486     // label related
487     void NewEnvironment(GateRef hir);
488     void DeleteCurrentEnvironment();
489     inline int NextVariableId();
490     inline void HandleException(GateRef result, Label *success, Label *exception, Label *exit);
491     inline void HandleException(GateRef result, Label *success, Label *fail, Label *exit, GateRef exceptionVal);
492     inline void SubCfgEntry(Label *entry);
493     inline void SubCfgExit();
494     inline GateRef Return(GateRef value);
495     inline GateRef Return();
496     inline void Bind(Label *label);
497     inline void Bind(Label *label, bool justSlowPath);
498     void Jump(Label *label);
499     void Branch(GateRef condition, Label *trueLabel, Label *falseLabel);
500     void Switch(GateRef index, Label *defaultLabel, int64_t *keysValue, Label *keysLabel, int numberOfKeys);
501     void LoopBegin(Label *loopHead);
502     void LoopEnd(Label *loopHead);
503     inline Label *GetCurrentLabel() const;
504     inline GateRef GetState() const;
505     inline GateRef GetDepend() const;
506     inline void SetDepend(GateRef depend);
507     inline void SetState(GateRef state);
508 
509     GateRef GetGlobalEnvValue(VariableType type, GateRef env, size_t index);
510     GateRef GetGlobalConstantValue(VariableType type, GateRef glue, ConstantIndex index);
511     GateRef IsBase(GateRef ctor);
512 
513 private:
514     Circuit *circuit_ {nullptr};
515     GateAccessor acc_;
516     Environment *env_ {nullptr};
517     CompilationConfig *cmpCfg_ {nullptr};
518 };
519 
520 class Label {
521 public:
522     explicit Label() = default;
523     explicit Label(Environment *env);
524     explicit Label(CircuitBuilder *cirBuilder);
525     ~Label() = default;
526     Label(Label const &label) = default;
527     Label &operator=(Label const &label) = default;
528     Label(Label &&label) = default;
529     Label &operator=(Label &&label) = default;
530     inline void Seal();
WriteVariable(Variable * var,GateRef value)531     inline void WriteVariable(Variable *var, GateRef value)
532     {
533         impl_->WriteVariable(var, value);
534     }
ReadVariable(Variable * var)535     inline GateRef ReadVariable(Variable *var)
536     {
537         return impl_->ReadVariable(var);
538     }
539     inline void Bind();
540     inline void MergeAllControl();
541     inline void MergeAllDepend();
542     inline void AppendPredecessor(const Label *predecessor);
543     inline std::vector<Label> GetPredecessors() const;
544     inline void SetControl(GateRef control);
545     inline void SetPreControl(GateRef control);
546     inline void MergeControl(GateRef control);
547     inline GateRef GetControl() const;
548     inline GateRef GetDepend() const;
549     inline void SetDepend(GateRef depend);
550 
551 private:
552     class LabelImpl {
553     public:
LabelImpl(Environment * env,GateRef control)554         LabelImpl(Environment *env, GateRef control)
555             : env_(env), control_(control), predeControl_(-1), isSealed_(false)
556         {
557         }
558         ~LabelImpl() = default;
559         NO_MOVE_SEMANTIC(LabelImpl);
560         NO_COPY_SEMANTIC(LabelImpl);
561         void Seal();
562         void WriteVariable(Variable *var, GateRef value);
563         GateRef ReadVariable(Variable *var);
564         void Bind();
565         void MergeAllControl();
566         void MergeAllDepend();
567         void AppendPredecessor(LabelImpl *predecessor);
GetPredecessors()568         std::vector<LabelImpl *> GetPredecessors() const
569         {
570             return predecessors_;
571         }
SetControl(GateRef control)572         void SetControl(GateRef control)
573         {
574             control_ = control;
575         }
SetPreControl(GateRef control)576         void SetPreControl(GateRef control)
577         {
578             predeControl_ = control;
579         }
MergeControl(GateRef control)580         void MergeControl(GateRef control)
581         {
582             if (predeControl_ == -1) {
583                 predeControl_ = control;
584                 control_ = predeControl_;
585             } else {
586                 otherPredeControls_.push_back(control);
587             }
588         }
GetControl()589         GateRef GetControl() const
590         {
591             return control_;
592         }
SetDepend(GateRef depend)593         void SetDepend(GateRef depend)
594         {
595             depend_ = depend;
596         }
GetDepend()597         GateRef GetDepend() const
598         {
599             return depend_;
600         }
601 
602     private:
603         bool IsNeedSeal() const;
IsSealed()604         bool IsSealed() const
605         {
606             return isSealed_;
607         }
608         bool IsLoopHead() const;
609         bool IsControlCase() const;
610         GateRef ReadVariableRecursive(Variable *var);
611         Environment *env_;
612         GateRef control_;
613         GateRef predeControl_ {-1};
614         GateRef dependRelay_ {-1};
615         GateRef depend_ {-1};
616         GateRef loopDepend_ {-1};
617         std::vector<GateRef> otherPredeControls_;
618         bool isSealed_ {false};
619         std::map<Variable *, GateRef> valueMap_;
620         std::vector<GateRef> phi;
621         std::vector<LabelImpl *> predecessors_;
622         std::map<Variable *, GateRef> incompletePhis_;
623     };
624 
Label(LabelImpl * impl)625     explicit Label(LabelImpl *impl) : impl_(impl) {}
626     friend class Environment;
GetRawLabel()627     LabelImpl *GetRawLabel() const
628     {
629         return impl_;
630     }
631     LabelImpl *impl_ {nullptr};
632 };
633 
634 class Environment {
635 public:
636     using LabelImpl = Label::LabelImpl;
637     Environment(GateRef hir, Circuit *circuit, CircuitBuilder *builder);
638     Environment(GateRef stateEntry, GateRef dependEntry, std::vector<GateRef>& inlist,
639                 Circuit *circuit, CircuitBuilder *builder);
640     Environment(size_t arguments, CircuitBuilder *builder);
641     ~Environment();
GetCurrentLabel()642     Label *GetCurrentLabel() const
643     {
644         return currentLabel_;
645     }
SetCurrentLabel(Label * label)646     void SetCurrentLabel(Label *label)
647     {
648         currentLabel_ = label;
649     }
GetBuilder()650     CircuitBuilder *GetBuilder() const
651     {
652         return circuitBuilder_;
653     }
GetCircuit()654     Circuit *GetCircuit() const
655     {
656         return circuit_;
657     }
NextVariableId()658     int NextVariableId()
659     {
660         return nextVariableId_++;
661     }
SetCompilationConfig(const CompilationConfig * cfg)662     void SetCompilationConfig(const CompilationConfig *cfg)
663     {
664         ccfg_ = cfg;
665     }
GetCompilationConfig()666     const CompilationConfig *GetCompilationConfig() const
667     {
668         return ccfg_;
669     }
Is32Bit()670     inline bool Is32Bit() const
671     {
672         return ccfg_->Is32Bit();
673     }
IsAArch64()674     inline bool IsAArch64() const
675     {
676         return ccfg_->IsAArch64();
677     }
IsAmd64()678     inline bool IsAmd64() const
679     {
680         return ccfg_->IsAmd64();
681     }
IsArch64Bit()682     inline bool IsArch64Bit() const
683     {
684         return ccfg_->IsAmd64() ||  ccfg_->IsAArch64();
685     }
IsAsmInterp()686     inline bool IsAsmInterp() const
687     {
688         return circuit_->GetFrameType() == FrameType::ASM_INTERPRETER_FRAME;
689     }
IsArch32Bit()690     inline bool IsArch32Bit() const
691     {
692         return ccfg_->Is32Bit();
693     }
GetArgument(size_t index)694     inline GateRef GetArgument(size_t index) const
695     {
696         return arguments_.at(index);
697     }
IsEnablePGOProfiler()698     inline bool IsEnablePGOProfiler() const
699     {
700         return ccfg_->IsEnablePGOProfiler();
701     }
702 
703     inline Label GetLabelFromSelector(GateRef sel);
704     inline void AddSelectorToLabel(GateRef sel, Label label);
705     inline LabelImpl *NewLabel(Environment *env, GateRef control = -1);
706     inline void SubCfgEntry(Label *entry);
707     inline void SubCfgExit();
708     inline GateRef GetInput(size_t index) const;
709 
710 private:
711     Label *currentLabel_ {nullptr};
712     Circuit *circuit_ {nullptr};
713     CircuitBuilder *circuitBuilder_ {nullptr};
714     std::unordered_map<GateRef, LabelImpl *> phiToLabels_;
715     std::vector<GateRef> inputList_;
716     Label entry_;
717     std::vector<LabelImpl *> rawLabels_;
718     std::stack<Label *> stack_;
719     int nextVariableId_ {0};
720     std::vector<GateRef> arguments_;
721     const CompilationConfig *ccfg_ {nullptr};
722 };
723 
724 class Variable {
725 public:
Variable(Environment * env,VariableType type,uint32_t id,GateRef value)726     Variable(Environment *env, VariableType type, uint32_t id, GateRef value) : id_(id), type_(type), env_(env)
727     {
728         Bind(value);
729         env_->GetCurrentLabel()->WriteVariable(this, value);
730     }
Variable(CircuitBuilder * cirbuilder,VariableType type,uint32_t id,GateRef value)731     Variable(CircuitBuilder *cirbuilder, VariableType type, uint32_t id, GateRef value)
732         : id_(id), type_(type), env_(cirbuilder->GetCurrentEnvironment())
733     {
734         Bind(value);
735         env_->GetCurrentLabel()->WriteVariable(this, value);
736     }
737     ~Variable() = default;
738     NO_MOVE_SEMANTIC(Variable);
739     NO_COPY_SEMANTIC(Variable);
Bind(GateRef value)740     void Bind(GateRef value)
741     {
742         currentValue_ = value;
743     }
Value()744     GateRef Value() const
745     {
746         return currentValue_;
747     }
Type()748     VariableType Type() const
749     {
750         return type_;
751     }
IsBound()752     bool IsBound() const
753     {
754         return currentValue_ != 0;
755     }
756     Variable &operator=(const GateRef value)
757     {
758         env_->GetCurrentLabel()->WriteVariable(this, value);
759         Bind(value);
760         return *this;
761     }
762     GateRef operator*()
763     {
764         return env_->GetCurrentLabel()->ReadVariable(this);
765     }
ReadVariable()766     GateRef ReadVariable()
767     {
768         return env_->GetCurrentLabel()->ReadVariable(this);
769     }
WriteVariable(GateRef value)770     void WriteVariable(GateRef value)
771     {
772         env_->GetCurrentLabel()->WriteVariable(this, value);
773         Bind(value);
774     }
775     GateRef AddPhiOperand(GateRef val);
776     GateRef AddOperandToSelector(GateRef val, size_t idx, GateRef in);
777     GateRef TryRemoveTrivialPhi(GateRef phi);
GetId()778     uint32_t GetId() const
779     {
780         return id_;
781     }
782 
783 private:
GetCircuit()784     Circuit* GetCircuit() const
785     {
786         return env_->GetCircuit();
787     }
788 
789     uint32_t id_;
790     VariableType type_;
791     GateRef currentValue_ {0};
792     Environment *env_;
793 };
794 }  // namespace panda::ecmascript::kungfu
795 
796 #endif  // ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_H
797