• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef ECMASCRIPT_COMPILER_GATE_META_DATA_H
17 #define ECMASCRIPT_COMPILER_GATE_META_DATA_H
18 
19 #include <string>
20 
21 #include "ecmascript/compiler/bytecodes.h"
22 #include "ecmascript/compiler/type.h"
23 #include "ecmascript/mem/chunk.h"
24 #include "ecmascript/mem/chunk_containers.h"
25 
26 #include "libpandabase/macros.h"
27 
28 namespace panda::ecmascript::kungfu {
29 using GateRef = int32_t;
30 enum MachineType : uint8_t { // Bit width
31     NOVALUE = 0,
32     ANYVALUE,
33     ARCH,
34     FLEX,
35     I1,
36     I8,
37     I16,
38     I32,
39     I64,
40     F32,
41     F64,
42 };
43 
44 enum class TypedBinOp : uint8_t {
45     TYPED_ADD = 0,
46     TYPED_SUB,
47     TYPED_MUL,
48     TYPED_DIV,
49     TYPED_MOD,
50     TYPED_LESS,
51     TYPED_LESSEQ,
52     TYPED_GREATER,
53     TYPED_GREATEREQ,
54     TYPED_EQ,
55     TYPED_NOTEQ,
56     TYPED_SHL,
57     TYPED_SHR,
58     TYPED_ASHR,
59     TYPED_AND,
60     TYPED_OR,
61     TYPED_XOR,
62     TYPED_EXP,
63 };
64 
65 enum class TypedUnOp : uint8_t {
66     TYPED_TONUMBER = 0,
67     TYPED_NEG,
68     TYPED_NOT,
69     TYPED_INC,
70     TYPED_DEC,
71     TYPED_TOBOOL,
72 };
73 
74 enum class DeoptType : uint8_t {
75     NOTCHECK = 0,
76     NOTINT,
77     NOTDOUBLE,
78     NOTNUMBER,
79     NOTBOOL,
80     NOTARRAY,
81     NOTSARRAY,
82     NOTF32ARRAY,
83     WRONGHCLASS,
84     NOTNEWOBJ,
85     NOTARRAYIDX,
86     NOTF32ARRAYIDX,
87     NOTINCOV,
88     NOTDECOV,
89     NOTNEGOV,
90     NOTCALLTGT,
91 };
92 
93 enum class ICmpCondition : uint8_t {
94     EQ = 1,
95     UGT,
96     UGE,
97     ULT,
98     ULE,
99     NE,
100     SGT,
101     SGE,
102     SLT,
103     SLE,
104 };
105 
106 enum class FCmpCondition : uint8_t {
107     ALW_FALSE = 0,
108     OEQ,
109     OGT,
110     OGE,
111     OLT,
112     OLE,
113     ONE,
114     ORD,
115     UNO,
116     UEQ,
117     UGT,
118     UGE,
119     ULT,
120     ULE,
121     UNE,
122     ALW_TRUE,
123 };
124 
125 enum class TypedStoreOp : uint8_t {
126     ARRAY_STORE_ELEMENT = 0,
127     FLOAT32ARRAY_STORE_ELEMENT,
128 };
129 
130 enum class TypedLoadOp : uint8_t {
131     ARRAY_LOAD_ELEMENT = 0,
132     FLOAT32ARRAY_LOAD_ELEMENT,
133 };
134 
135 std::string MachineTypeToStr(MachineType machineType);
136 
137 #define BINARY_GATE_META_DATA_CACHE_LIST(V)                         \
138     V(Add, ADD, GateFlags::NONE_FLAG, 0, 0, 2)                      \
139     V(Sub, SUB, GateFlags::NONE_FLAG, 0, 0, 2)                      \
140     V(Mul, MUL, GateFlags::NONE_FLAG, 0, 0, 2)                      \
141     V(Exp, EXP, GateFlags::NONE_FLAG, 0, 0, 2)                      \
142     V(Sdiv, SDIV, GateFlags::NONE_FLAG, 0, 0, 2)                    \
143     V(Smod, SMOD, GateFlags::NONE_FLAG, 0, 0, 2)                    \
144     V(Udiv, UDIV, GateFlags::NONE_FLAG, 0, 0, 2)                    \
145     V(Umod, UMOD, GateFlags::NONE_FLAG, 0, 0, 2)                    \
146     V(Fdiv, FDIV, GateFlags::NONE_FLAG, 0, 0, 2)                    \
147     V(Fmod, FMOD, GateFlags::NONE_FLAG, 0, 0, 2)                    \
148     V(And, AND, GateFlags::NONE_FLAG, 0, 0, 2)                      \
149     V(Xor, XOR, GateFlags::NONE_FLAG, 0, 0, 2)                      \
150     V(Or, OR, GateFlags::NONE_FLAG, 0, 0, 2)                        \
151     V(Lsl, LSL, GateFlags::NONE_FLAG, 0, 0, 2)                      \
152     V(Lsr, LSR, GateFlags::NONE_FLAG, 0, 0, 2)                      \
153     V(Asr, ASR, GateFlags::NONE_FLAG, 0, 0, 2)
154 
155 #define UNARY_GATE_META_DATA_CACHE_LIST(V)                                       \
156     V(Zext, ZEXT, GateFlags::NONE_FLAG, 0, 0, 1)                                 \
157     V(Sext, SEXT, GateFlags::NONE_FLAG, 0, 0, 1)                                 \
158     V(Trunc, TRUNC, GateFlags::NONE_FLAG, 0, 0, 1)                               \
159     V(Fext, FEXT, GateFlags::NONE_FLAG, 0, 0, 1)                                 \
160     V(Ftrunc, FTRUNC, GateFlags::NONE_FLAG, 0, 0, 1)                             \
161     V(Rev, REV, GateFlags::NONE_FLAG, 0, 0, 1)                                   \
162     V(TruncFloatToInt64, TRUNC_FLOAT_TO_INT64, GateFlags::NONE_FLAG, 0, 0, 1)    \
163     V(TaggedToInt64, TAGGED_TO_INT64, GateFlags::NONE_FLAG, 0, 0, 1)             \
164     V(Int64ToTagged, INT64_TO_TAGGED, GateFlags::NONE_FLAG, 0, 0, 1)             \
165     V(SignedIntToFloat, SIGNED_INT_TO_FLOAT, GateFlags::NONE_FLAG, 0, 0, 1)      \
166     V(UnsignedIntToFloat, UNSIGNED_INT_TO_FLOAT, GateFlags::NONE_FLAG, 0, 0, 1)  \
167     V(FloatToSignedInt, FLOAT_TO_SIGNED_INT, GateFlags::NONE_FLAG, 0, 0, 1)      \
168     V(UnsignedFloatToInt, UNSIGNED_FLOAT_TO_INT, GateFlags::NONE_FLAG, 0, 0, 1)  \
169     V(Bitcast, BITCAST, GateFlags::NONE_FLAG, 0, 0, 1)
170 
171 #define IMMUTABLE_META_DATA_CACHE_LIST(V)                                               \
172     V(CircuitRoot, CIRCUIT_ROOT, GateFlags::NONE_FLAG, 0, 0, 0)                         \
173     V(StateEntry, STATE_ENTRY, GateFlags::ROOT, 0, 0, 0)                                \
174     V(DependEntry, DEPEND_ENTRY, GateFlags::ROOT, 0, 0, 0)                              \
175     V(ReturnList, RETURN_LIST, GateFlags::ROOT, 0, 0, 0)                                \
176     V(ArgList, ARG_LIST, GateFlags::ROOT, 0, 0, 0)                                      \
177     V(Return, RETURN, GateFlags::HAS_ROOT, 1, 1, 1)                                     \
178     V(ReturnVoid, RETURN_VOID, GateFlags::HAS_ROOT, 1, 1, 0)                            \
179     V(Throw, THROW, GateFlags::CONTROL, 1, 1, 1)                                        \
180     V(OrdinaryBlock, ORDINARY_BLOCK, GateFlags::CONTROL, 1, 0, 0)                       \
181     V(IfBranch, IF_BRANCH, GateFlags::CONTROL, 1, 0, 1)                                 \
182     V(IfTrue, IF_TRUE, GateFlags::CONTROL, 1, 0, 0)                                     \
183     V(IfFalse, IF_FALSE, GateFlags::CONTROL, 1, 0, 0)                                   \
184     V(LoopBegin, LOOP_BEGIN, GateFlags::CONTROL, 2, 0, 0)                               \
185     V(LoopBack, LOOP_BACK, GateFlags::CONTROL, 1, 0, 0)                                 \
186     V(DependRelay, DEPEND_RELAY, GateFlags::FIXED, 1, 1, 0)                             \
187     V(DependAnd, DEPEND_AND, GateFlags::FIXED, 0, 2, 0)                                 \
188     V(IfSuccess, IF_SUCCESS, GateFlags::CONTROL, 1, 0, 0)                               \
189     V(IfException, IF_EXCEPTION, GateFlags::CONTROL, 1, 0, 0)                           \
190     V(GetException, GET_EXCEPTION, GateFlags::NONE_FLAG, 0, 1, 0)                       \
191     V(StateSplit, STATE_SPLIT, GateFlags::CHECKABLE, 0, 1, 0)                           \
192     V(Deopt, DEOPT, GateFlags::NONE_FLAG, 0, 1, 3)                                      \
193     V(Load, LOAD, GateFlags::NONE_FLAG, 0, 1, 1)                                        \
194     V(Store, STORE, GateFlags::NONE_FLAG, 0, 1, 2)                                      \
195     V(TypedCallCheck, TYPED_CALL_CHECK, GateFlags::CHECKABLE, 1, 1, 3)                  \
196     V(ArrayCheck, ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1)                           \
197     V(StableArrayCheck, STABLE_ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1)              \
198     V(DeoptCheck, DEOPT_CHECK, GateFlags::NONE_FLAG, 1, 1, 3)                           \
199     V(LoadProperty, LOAD_PROPERTY, GateFlags::NO_WRITE, 1, 1, 2)                        \
200     V(StoreProperty, STORE_PROPERTY, GateFlags::NONE_FLAG, 1, 1, 3)                     \
201     V(ToLength, TO_LENGTH, GateFlags::NONE_FLAG, 1, 1, 1)                               \
202     V(DefaultCase, DEFAULT_CASE, GateFlags::CONTROL, 1, 0, 0)                           \
203     V(LoadArrayLength, LOAD_ARRAY_LENGTH, GateFlags::NO_WRITE, 1, 1, 1)                 \
204     V(TypedNewAllocateThis, TYPED_NEW_ALLOCATE_THIS, GateFlags::CHECKABLE, 1, 1, 2)     \
205     V(TypedSuperAllocateThis, TYPED_SUPER_ALLOCATE_THIS, GateFlags::CHECKABLE, 1, 1, 2) \
206     V(GetSuperConstructor, GET_SUPER_CONSTRUCTOR, GateFlags::NO_WRITE, 1, 1, 1)         \
207     V(UpdateHotness, UPDATE_HOTNESS, GateFlags::NO_WRITE, 1, 1, 1)                      \
208     BINARY_GATE_META_DATA_CACHE_LIST(V)                                                 \
209     UNARY_GATE_META_DATA_CACHE_LIST(V)
210 
211 #define GATE_META_DATA_LIST_WITH_VALUE_IN(V)                                             \
212     V(ValueSelector, VALUE_SELECTOR, GateFlags::FIXED, 1, 0, value)                      \
213     V(TypedCall, TYPED_CALL, GateFlags::NONE_FLAG, 1, 1, value)                          \
214     V(Construct, CONSTRUCT, GateFlags::NONE_FLAG, 1, 1, value)                           \
215     V(FrameState, FRAME_STATE, GateFlags::NONE_FLAG, 0, 0, value)                        \
216     V(RuntimeCall, RUNTIME_CALL, GateFlags::NONE_FLAG, 0, 1, value)                      \
217     V(RuntimeCallWithArgv, RUNTIME_CALL_WITH_ARGV, GateFlags::NONE_FLAG, 0, 1, value)    \
218     V(NoGcRuntimeCall, NOGC_RUNTIME_CALL, GateFlags::NONE_FLAG, 0, 1, value)             \
219     V(Call, CALL, GateFlags::NONE_FLAG, 0, 1, value)                                     \
220     V(BytecodeCall, BYTECODE_CALL, GateFlags::NONE_FLAG, 0, 1, value)                    \
221     V(DebuggerBytecodeCall, DEBUGGER_BYTECODE_CALL, GateFlags::NONE_FLAG, 0, 1, value)   \
222     V(BuiltinsCallWithArgv, BUILTINS_CALL_WITH_ARGV, GateFlags::NONE_FLAG, 0, 1, value)  \
223     V(BuiltinsCall, BUILTINS_CALL, GateFlags::NONE_FLAG, 0, 1, value)                    \
224     V(SaveRegister, SAVE_REGISTER, GateFlags::NONE_FLAG, 0, 1, value)                    \
225 
226 #define GATE_META_DATA_LIST_WITH_SIZE(V)                                            \
227     V(Merge, MERGE, GateFlags::CONTROL, value, 0, 0)                                \
228     V(DependSelector, DEPEND_SELECTOR, GateFlags::FIXED, 1, value, 0)               \
229     GATE_META_DATA_LIST_WITH_VALUE_IN(V)
230 
231 #define GATE_META_DATA_LIST_WITH_GATE_TYPE(V)                                  \
232     V(PrimitiveTypeCheck, PRIMITIVE_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
233     V(ObjectTypeCheck, OBJECT_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 2)       \
234     V(TypedArrayCheck, TYPED_ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1)       \
235     V(IndexCheck, INDEX_CHECK, GateFlags::CHECKABLE, 1, 1, 2)                  \
236     V(Int32OverflowCheck, INT32_OVERFLOW_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
237     V(TypedUnaryOp, TYPED_UNARY_OP, GateFlags::NO_WRITE, 1, 1, 1)              \
238     V(TypedConvert, TYPE_CONVERT, GateFlags::NO_WRITE, 1, 1, 1)                \
239 
240 #define GATE_META_DATA_LIST_WITH_VALUE(V)                                \
241     V(Icmp, ICMP, GateFlags::NONE_FLAG, 0, 0, 2)                         \
242     V(Fcmp, FCMP, GateFlags::NONE_FLAG, 0, 0, 2)                         \
243     V(Alloca, ALLOCA, GateFlags::NONE_FLAG, 0, 0, 0)                     \
244     V(SwitchBranch, SWITCH_BRANCH, GateFlags::CONTROL, 1, 0, 1)          \
245     V(SwitchCase, SWITCH_CASE, GateFlags::CONTROL, 1, 0, 0)              \
246     V(HeapAlloc, HEAP_ALLOC, GateFlags::NONE_FLAG, 1, 1, 1)              \
247     V(LoadElement, LOAD_ELEMENT, GateFlags::NO_WRITE, 1, 1, 2)           \
248     V(StoreElement, STORE_ELEMENT, GateFlags::NONE_FLAG, 1, 1, 3)        \
249     V(RestoreRegister, RESTORE_REGISTER, GateFlags::NONE_FLAG, 0, 1, 0)  \
250     V(ConstData, CONST_DATA, GateFlags::NONE_FLAG, 0, 0, 0)              \
251     V(Constant, CONSTANT, GateFlags::NONE_FLAG, 0, 0, 0)                 \
252     V(RelocatableData, RELOCATABLE_DATA, GateFlags::NONE_FLAG, 0, 0, 0)
253 
254 #define GATE_META_DATA_LIST_WITH_ONE_PARAMETER(V)         \
255     V(Arg, ARG, GateFlags::HAS_ROOT, 0, 0, 0)             \
256     GATE_META_DATA_LIST_WITH_VALUE(V)                     \
257     GATE_META_DATA_LIST_WITH_GATE_TYPE(V)
258 
259 #define GATE_OPCODE_LIST(V)     \
260     V(JS_BYTECODE)              \
261     V(TYPED_BINARY_OP)          \
262     V(CONSTSTRING)
263 
264 enum class OpCode : uint8_t {
265     NOP = 0,
266 #define DECLARE_GATE_OPCODE(NAME, OP, R, S, D, V) OP,
267     IMMUTABLE_META_DATA_CACHE_LIST(DECLARE_GATE_OPCODE)
268     GATE_META_DATA_LIST_WITH_SIZE(DECLARE_GATE_OPCODE)
269     GATE_META_DATA_LIST_WITH_ONE_PARAMETER(DECLARE_GATE_OPCODE)
270 #undef DECLARE_GATE_OPCODE
271 #define DECLARE_GATE_OPCODE(NAME) NAME,
272     GATE_OPCODE_LIST(DECLARE_GATE_OPCODE)
273 #undef DECLARE_GATE_OPCODE
274 };
275 
276 enum GateFlags : uint8_t {
277     NONE_FLAG = 0,
278     NO_WRITE = 1 << 0,
279     HAS_ROOT = 1 << 1,
280     HAS_FRAME_STATE = 1 << 2,
281     CONTROL = NO_WRITE,
282     CHECKABLE = NO_WRITE | HAS_FRAME_STATE,
283     ROOT = NO_WRITE | HAS_ROOT,
284     FIXED = NO_WRITE,
285 };
286 
287 class GateMetaData : public ChunkObject {
288 public:
289     enum class Kind : uint8_t {
290         IMMUTABLE = 0,
291         MUTABLE_WITH_SIZE,
292         IMMUTABLE_ONE_PARAMETER,
293         MUTABLE_ONE_PARAMETER,
294         MUTABLE_STRING,
295         JSBYTECODE,
296         TYPED_BINARY_OP,
297     };
298     GateMetaData() = default;
GateMetaData(OpCode opcode,GateFlags flags,uint32_t statesIn,uint16_t dependsIn,uint32_t valuesIn)299     GateMetaData(OpCode opcode, GateFlags flags,
300         uint32_t statesIn, uint16_t dependsIn, uint32_t valuesIn)
301         : opcode_(opcode), flags_(flags),
302         statesIn_(statesIn), dependsIn_(dependsIn), valuesIn_(valuesIn) {}
303 
GetStateCount()304     size_t GetStateCount() const
305     {
306         return statesIn_;
307     }
308 
GetDependCount()309     size_t GetDependCount() const
310     {
311         return dependsIn_;
312     }
313 
GetInValueCount()314     size_t GetInValueCount() const
315     {
316         return valuesIn_;
317     }
318 
GetRootCount()319     size_t GetRootCount() const
320     {
321         return HasRoot() ? 1 : 0;
322     }
323 
GetInFrameStateCount()324     size_t GetInFrameStateCount() const
325     {
326         return HasFrameState() ? 1 : 0;
327     }
328 
GetNumIns()329     size_t GetNumIns() const
330     {
331         return GetStateCount() + GetDependCount() + GetInValueCount()
332             + GetInFrameStateCount() + GetRootCount();
333     }
334 
GetInValueStarts()335     size_t GetInValueStarts() const
336     {
337         return GetStateCount() + GetDependCount();
338     }
339 
GetInFrameStateStarts()340     size_t GetInFrameStateStarts() const
341     {
342         return GetInValueStarts() + GetInValueCount();
343     }
344 
GetOpCode()345     OpCode GetOpCode() const
346     {
347         return opcode_;
348     }
349 
GetKind()350     Kind GetKind() const
351     {
352         return kind_;
353     }
354 
AssertKind(Kind kind)355     void AssertKind([[maybe_unused]] Kind kind) const
356     {
357         ASSERT(GetKind() == kind);
358     }
359 
IsOneParameterKind()360     bool IsOneParameterKind() const
361     {
362         return GetKind() == Kind::IMMUTABLE_ONE_PARAMETER || GetKind() == Kind::MUTABLE_ONE_PARAMETER ||
363             GetKind() == Kind::TYPED_BINARY_OP;
364     }
365 
IsStringType()366     bool IsStringType() const
367     {
368         return GetKind() == Kind::MUTABLE_STRING;
369     }
370 
371     bool IsRoot() const;
372     bool IsProlog() const;
373     bool IsFixed() const;
374     bool IsSchedulable() const;
375     bool IsState() const;  // note: IsState(STATE_ENTRY) == false
376     bool IsGeneralState() const;
377     bool IsTerminalState() const;
378     bool IsCFGMerge() const;
379     bool IsControlCase() const;
380     bool IsLoopHead() const;
381     bool IsNop() const;
382     bool IsConstant() const;
383     bool IsDependSelector() const;
384     bool IsTypedOperator() const;
385     bool IsCheckWithOneIn() const;
386     bool IsCheckWithTwoIns() const;
HasFrameState()387     bool HasFrameState() const
388     {
389         return HasFlag(GateFlags::HAS_FRAME_STATE);
390     }
391 
IsNotWrite()392     bool IsNotWrite() const
393     {
394         return HasFlag(GateFlags::NO_WRITE);
395     }
396 
397     ~GateMetaData() = default;
398 
399     static std::string Str(OpCode opcode);
Str()400     std::string Str() const
401     {
402         return Str(opcode_);
403     }
404 protected:
SetKind(Kind kind)405     void SetKind(Kind kind)
406     {
407         kind_ = kind;
408     }
409 
SetFlags(GateFlags flags)410     void SetFlags(GateFlags flags)
411     {
412         flags_ = flags;
413     }
414 
DecreaseIn(size_t idx)415     void DecreaseIn(size_t idx)
416     {
417         ASSERT(GetKind() == Kind::MUTABLE_WITH_SIZE);
418         if (idx < statesIn_) {
419             statesIn_--;
420         } else if (idx < statesIn_ + dependsIn_) {
421             dependsIn_--;
422         } else {
423             valuesIn_--;
424         }
425     }
426 
HasRoot()427     bool HasRoot() const
428     {
429         return HasFlag(GateFlags::HAS_ROOT);
430     }
431 
HasFlag(GateFlags flag)432     bool HasFlag(GateFlags flag) const
433     {
434         return (GetFlags() & flag) == flag;
435     }
436 
GetFlags()437     GateFlags GetFlags() const
438     {
439         return flags_;
440     }
441 
442 private:
443     friend class Gate;
444     friend class Circuit;
445     friend class GateMetaBuilder;
446 
447     OpCode opcode_ { OpCode::NOP };
448     Kind kind_ { Kind::IMMUTABLE };
449     GateFlags flags_ { GateFlags::NONE_FLAG };
450     uint32_t statesIn_ { 0 };
451     uint32_t dependsIn_ { 0 };
452     uint32_t valuesIn_ { 0 };
453 };
454 
455 inline std::ostream& operator<<(std::ostream& os, OpCode opcode)
456 {
457     return os << GateMetaData::Str(opcode);
458 }
459 
460 class JSBytecodeMetaData : public GateMetaData {
461 public:
JSBytecodeMetaData(size_t valuesIn,EcmaOpcode opcode,uint32_t bcIndex,GateFlags flags)462     explicit JSBytecodeMetaData(size_t valuesIn, EcmaOpcode opcode, uint32_t bcIndex, GateFlags flags)
463         : GateMetaData(OpCode::JS_BYTECODE, flags, 1, 1, valuesIn),
464         opcode_(opcode), bcIndex_(bcIndex)
465     {
466         SetKind(GateMetaData::Kind::JSBYTECODE);
467     }
468 
Cast(const GateMetaData * meta)469     static const JSBytecodeMetaData* Cast(const GateMetaData* meta)
470     {
471         meta->AssertKind(GateMetaData::Kind::JSBYTECODE);
472         return static_cast<const JSBytecodeMetaData*>(meta);
473     }
474 
GetBytecodeIndex()475     uint32_t GetBytecodeIndex() const
476     {
477         return bcIndex_;
478     }
479 
GetByteCodeOpcode()480     EcmaOpcode GetByteCodeOpcode() const
481     {
482         return opcode_;
483     }
484 private:
485     EcmaOpcode opcode_;
486     uint32_t bcIndex_;
487 };
488 
489 class OneParameterMetaData : public GateMetaData {
490 public:
OneParameterMetaData(OpCode opcode,GateFlags flags,uint32_t statesIn,uint16_t dependsIn,uint32_t valuesIn,uint64_t value)491     OneParameterMetaData(OpCode opcode, GateFlags flags, uint32_t statesIn,
492         uint16_t dependsIn, uint32_t valuesIn, uint64_t value)
493         : GateMetaData(opcode, flags, statesIn, dependsIn, valuesIn), value_(value)
494     {
495         SetKind(GateMetaData::Kind::IMMUTABLE_ONE_PARAMETER);
496     }
497 
Cast(const GateMetaData * meta)498     static const OneParameterMetaData* Cast(const GateMetaData* meta)
499     {
500         ASSERT(meta->IsOneParameterKind());
501         return static_cast<const OneParameterMetaData*>(meta);
502     }
503 
GetValue()504     uint64_t GetValue() const
505     {
506         return value_;
507     }
508 
509 private:
510     uint64_t value_ { 0 };
511 };
512 
513 class TypedBinaryMegaData : public OneParameterMetaData {
514 public:
TypedBinaryMegaData(uint64_t value,TypedBinOp binOp)515     TypedBinaryMegaData(uint64_t value, TypedBinOp binOp)
516         : OneParameterMetaData(OpCode::TYPED_BINARY_OP, GateFlags::NO_WRITE, 1, 1, 2, value), // 2: valuesIn
517         binOp_(binOp)
518     {
519         SetKind(GateMetaData::Kind::TYPED_BINARY_OP);
520     }
521 
Cast(const GateMetaData * meta)522     static const TypedBinaryMegaData* Cast(const GateMetaData* meta)
523     {
524         meta->AssertKind(GateMetaData::Kind::TYPED_BINARY_OP);
525         return static_cast<const TypedBinaryMegaData*>(meta);
526     }
527 
GetTypedBinaryOp()528     TypedBinOp GetTypedBinaryOp() const
529     {
530         return binOp_;
531     }
532 private:
533     TypedBinOp binOp_;
534 };
535 
536 class GateTypeAccessor {
537 public:
GateTypeAccessor(uint64_t value)538     explicit GateTypeAccessor(uint64_t value)
539         : type_(static_cast<uint32_t>(value)) {}
540 
GetGateType()541     GateType GetGateType() const
542     {
543         return type_;
544     }
545 
ToValue(GateType type)546     static uint64_t ToValue(GateType type)
547     {
548         return static_cast<uint64_t>(type.Value());
549     }
550 private:
551     GateType type_;
552 };
553 
554 class GatePairTypeAccessor {
555 public:
556     // type bits shift
557     static constexpr int OPRAND_TYPE_BITS = 32;
GatePairTypeAccessor(uint64_t value)558     explicit GatePairTypeAccessor(uint64_t value) : bitField_(value) {}
559 
GetLeftType()560     GateType GetLeftType() const
561     {
562         return GateType(LeftBits::Get(bitField_));
563     }
564 
GetRightType()565     GateType GetRightType() const
566     {
567         return GateType(RightBits::Get(bitField_));
568     }
569 
ToValue(GateType leftType,GateType rightType)570     static uint64_t ToValue(GateType leftType, GateType rightType)
571     {
572         return LeftBits::Encode(leftType.Value()) | RightBits::Encode(rightType.Value());
573     }
574 
575 private:
576     using LeftBits = panda::BitField<uint32_t, 0, OPRAND_TYPE_BITS>;
577     using RightBits = LeftBits::NextField<uint32_t, OPRAND_TYPE_BITS>;
578 
579     uint64_t bitField_;
580 };
581 
582 class TypedUnaryAccessor {
583 public:
584     // type bits shift
585     static constexpr int OPRAND_TYPE_BITS = 32;
TypedUnaryAccessor(uint64_t value)586     explicit TypedUnaryAccessor(uint64_t value) : bitField_(value) {}
587 
GetTypeValue()588     GateType GetTypeValue() const
589     {
590         return GateType(TypedValueBits::Get(bitField_));
591     }
592 
GetTypedUnOp()593     TypedUnOp GetTypedUnOp() const
594     {
595         return TypedUnOpBits::Get(bitField_);
596     }
597 
ToValue(GateType typeValue,TypedUnOp unaryOp)598     static uint64_t ToValue(GateType typeValue, TypedUnOp unaryOp)
599     {
600         return TypedValueBits::Encode(typeValue.Value())
601             | TypedUnOpBits::Encode(unaryOp);
602     }
603 
604 private:
605     using TypedValueBits = panda::BitField<uint32_t, 0, OPRAND_TYPE_BITS>;
606     using TypedUnOpBits = TypedValueBits::NextField<TypedUnOp, OPRAND_TYPE_BITS>;
607 
608     uint64_t bitField_;
609 };
610 } // namespace panda::ecmascript::kungfu
611 
612 #endif  // ECMASCRIPT_COMPILER_GATE_META_DATA_H
613