arkcompiler_ets_runtime/ecmascript/compiler/gate_meta_data.h
openharmony_ci fa43111911
!3476 Replace Low IR in LowerTypedNewObjRange and LowerTypedSuperCall
Merge pull request !3476 from dingding/replace_lir
2023-02-06 06:28:55 +00:00

619 lines
20 KiB
C++

/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ECMASCRIPT_COMPILER_GATE_META_DATA_H
#define ECMASCRIPT_COMPILER_GATE_META_DATA_H
#include <string>
#include "ecmascript/compiler/bytecodes.h"
#include "ecmascript/compiler/type.h"
#include "ecmascript/mem/chunk.h"
#include "ecmascript/mem/chunk_containers.h"
#include "libpandabase/macros.h"
namespace panda::ecmascript::kungfu {
using GateRef = int32_t;
enum MachineType : uint8_t { // Bit width
NOVALUE = 0,
ANYVALUE,
ARCH,
FLEX,
I1,
I8,
I16,
I32,
I64,
F32,
F64,
};
enum class TypedBinOp : uint8_t {
TYPED_ADD = 0,
TYPED_SUB,
TYPED_MUL,
TYPED_DIV,
TYPED_MOD,
TYPED_LESS,
TYPED_LESSEQ,
TYPED_GREATER,
TYPED_GREATEREQ,
TYPED_EQ,
TYPED_NOTEQ,
TYPED_SHL,
TYPED_SHR,
TYPED_ASHR,
TYPED_AND,
TYPED_OR,
TYPED_XOR,
TYPED_EXP,
};
enum class TypedUnOp : uint8_t {
TYPED_TONUMBER = 0,
TYPED_NEG,
TYPED_NOT,
TYPED_INC,
TYPED_DEC,
TYPED_TOBOOL,
};
enum class ICmpCondition : uint8_t {
EQ = 1,
UGT,
UGE,
ULT,
ULE,
NE,
SGT,
SGE,
SLT,
SLE,
};
enum class FCmpCondition : uint8_t {
ALW_FALSE = 0,
OEQ,
OGT,
OGE,
OLT,
OLE,
ONE,
ORD,
UNO,
UEQ,
UGT,
UGE,
ULT,
ULE,
UNE,
ALW_TRUE,
};
enum class TypedStoreOp : uint8_t {
ARRAY_STORE_ELEMENT = 0,
FLOAT32ARRAY_STORE_ELEMENT,
};
enum class TypedLoadOp : uint8_t {
ARRAY_LOAD_ELEMENT = 0,
FLOAT32ARRAY_LOAD_ELEMENT,
};
std::string MachineTypeToStr(MachineType machineType);
#define BINARY_GATE_META_DATA_CACHE_LIST(V) \
V(Add, ADD, GateFlags::NONE_FLAG, 0, 0, 2) \
V(Sub, SUB, GateFlags::NONE_FLAG, 0, 0, 2) \
V(Mul, MUL, GateFlags::NONE_FLAG, 0, 0, 2) \
V(Exp, EXP, GateFlags::NONE_FLAG, 0, 0, 2) \
V(Sdiv, SDIV, GateFlags::NONE_FLAG, 0, 0, 2) \
V(Smod, SMOD, GateFlags::NONE_FLAG, 0, 0, 2) \
V(Udiv, UDIV, GateFlags::NONE_FLAG, 0, 0, 2) \
V(Umod, UMOD, GateFlags::NONE_FLAG, 0, 0, 2) \
V(Fdiv, FDIV, GateFlags::NONE_FLAG, 0, 0, 2) \
V(Fmod, FMOD, GateFlags::NONE_FLAG, 0, 0, 2) \
V(And, AND, GateFlags::NONE_FLAG, 0, 0, 2) \
V(Xor, XOR, GateFlags::NONE_FLAG, 0, 0, 2) \
V(Or, OR, GateFlags::NONE_FLAG, 0, 0, 2) \
V(Lsl, LSL, GateFlags::NONE_FLAG, 0, 0, 2) \
V(Lsr, LSR, GateFlags::NONE_FLAG, 0, 0, 2) \
V(Asr, ASR, GateFlags::NONE_FLAG, 0, 0, 2)
#define UNARY_GATE_META_DATA_CACHE_LIST(V) \
V(Zext, ZEXT, GateFlags::NONE_FLAG, 0, 0, 1) \
V(Sext, SEXT, GateFlags::NONE_FLAG, 0, 0, 1) \
V(Trunc, TRUNC, GateFlags::NONE_FLAG, 0, 0, 1) \
V(Fext, FEXT, GateFlags::NONE_FLAG, 0, 0, 1) \
V(Ftrunc, FTRUNC, GateFlags::NONE_FLAG, 0, 0, 1) \
V(Rev, REV, GateFlags::NONE_FLAG, 0, 0, 1) \
V(TruncFloatToInt64, TRUNC_FLOAT_TO_INT64, GateFlags::NONE_FLAG, 0, 0, 1) \
V(TaggedToInt64, TAGGED_TO_INT64, GateFlags::NONE_FLAG, 0, 0, 1) \
V(Int64ToTagged, INT64_TO_TAGGED, GateFlags::NONE_FLAG, 0, 0, 1) \
V(SignedIntToFloat, SIGNED_INT_TO_FLOAT, GateFlags::NONE_FLAG, 0, 0, 1) \
V(UnsignedIntToFloat, UNSIGNED_INT_TO_FLOAT, GateFlags::NONE_FLAG, 0, 0, 1) \
V(FloatToSignedInt, FLOAT_TO_SIGNED_INT, GateFlags::NONE_FLAG, 0, 0, 1) \
V(UnsignedFloatToInt, UNSIGNED_FLOAT_TO_INT, GateFlags::NONE_FLAG, 0, 0, 1) \
V(Bitcast, BITCAST, GateFlags::NONE_FLAG, 0, 0, 1)
#define IMMUTABLE_META_DATA_CACHE_LIST(V) \
V(CircuitRoot, CIRCUIT_ROOT, GateFlags::NONE_FLAG, 0, 0, 0) \
V(StateEntry, STATE_ENTRY, GateFlags::ROOT, 0, 0, 0) \
V(DependEntry, DEPEND_ENTRY, GateFlags::ROOT, 0, 0, 0) \
V(ReturnList, RETURN_LIST, GateFlags::ROOT, 0, 0, 0) \
V(ArgList, ARG_LIST, GateFlags::ROOT, 0, 0, 0) \
V(Return, RETURN, GateFlags::HAS_ROOT, 1, 1, 1) \
V(ReturnVoid, RETURN_VOID, GateFlags::HAS_ROOT, 1, 1, 0) \
V(Throw, THROW, GateFlags::CONTROL, 1, 1, 1) \
V(OrdinaryBlock, ORDINARY_BLOCK, GateFlags::CONTROL, 1, 0, 0) \
V(IfBranch, IF_BRANCH, GateFlags::CONTROL, 1, 0, 1) \
V(IfTrue, IF_TRUE, GateFlags::CONTROL, 1, 0, 0) \
V(IfFalse, IF_FALSE, GateFlags::CONTROL, 1, 0, 0) \
V(LoopBegin, LOOP_BEGIN, GateFlags::CONTROL, 2, 0, 0) \
V(LoopBack, LOOP_BACK, GateFlags::CONTROL, 1, 0, 0) \
V(DependRelay, DEPEND_RELAY, GateFlags::FIXED, 1, 1, 0) \
V(DependAnd, DEPEND_AND, GateFlags::FIXED, 0, 2, 0) \
V(IfSuccess, IF_SUCCESS, GateFlags::CONTROL, 1, 0, 0) \
V(IfException, IF_EXCEPTION, GateFlags::CONTROL, 1, 0, 0) \
V(GetException, GET_EXCEPTION, GateFlags::NONE_FLAG, 0, 1, 0) \
V(StateSplit, STATE_SPLIT, GateFlags::CHECKABLE, 0, 1, 0) \
V(Deopt, DEOPT, GateFlags::NONE_FLAG, 0, 1, 2) \
V(Load, LOAD, GateFlags::NONE_FLAG, 0, 1, 1) \
V(Store, STORE, GateFlags::NONE_FLAG, 0, 1, 2) \
V(TypedCallCheck, TYPED_CALL_CHECK, GateFlags::CHECKABLE, 1, 1, 3) \
V(ArrayCheck, ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
V(StableArrayCheck, STABLE_ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
V(DeoptCheck, DEOPT_CHECK, GateFlags::NONE_FLAG, 1, 1, 2) \
V(LoadProperty, LOAD_PROPERTY, GateFlags::NO_WRITE, 1, 1, 2) \
V(StoreProperty, STORE_PROPERTY, GateFlags::NONE_FLAG, 1, 1, 3) \
V(ToLength, TO_LENGTH, GateFlags::NONE_FLAG, 1, 1, 1) \
V(GetEnv, GET_ENV, GateFlags::NONE_FLAG, 0, 1, 0) \
V(DefaultCase, DEFAULT_CASE, GateFlags::CONTROL, 1, 0, 0) \
V(LoadArrayLength, LOAD_ARRAY_LENGTH, GateFlags::NO_WRITE, 1, 1, 1) \
V(TypedNewAllocateThis, TYPED_NEW_ALLOCATE_THIS, GateFlags::CHECKABLE, 1, 1, 2) \
V(TypedSuperAllocateThis, TYPED_SUPER_ALLOCATE_THIS, GateFlags::CHECKABLE, 1, 1, 2) \
V(GetSuperConstructor, GET_SUPER_CONSTRUCTOR, GateFlags::NO_WRITE, 1, 1, 1) \
BINARY_GATE_META_DATA_CACHE_LIST(V) \
UNARY_GATE_META_DATA_CACHE_LIST(V)
#define GATE_META_DATA_LIST_WITH_VALUE_IN(V) \
V(ValueSelector, VALUE_SELECTOR, GateFlags::FIXED, 1, 0, value) \
V(TypedCall, TYPED_CALL, GateFlags::NONE_FLAG, 1, 1, value) \
V(Construct, CONSTRUCT, GateFlags::NONE_FLAG, 1, 1, value) \
V(FrameState, FRAME_STATE, GateFlags::NONE_FLAG, 0, 0, value) \
V(RuntimeCall, RUNTIME_CALL, GateFlags::NONE_FLAG, 0, 1, value) \
V(RuntimeCallWithArgv, RUNTIME_CALL_WITH_ARGV, GateFlags::NONE_FLAG, 0, 1, value) \
V(NoGcRuntimeCall, NOGC_RUNTIME_CALL, GateFlags::NONE_FLAG, 0, 1, value) \
V(Call, CALL, GateFlags::NONE_FLAG, 0, 1, value) \
V(BytecodeCall, BYTECODE_CALL, GateFlags::NONE_FLAG, 0, 1, value) \
V(DebuggerBytecodeCall, DEBUGGER_BYTECODE_CALL, GateFlags::NONE_FLAG, 0, 1, value) \
V(BuiltinsCallWithArgv, BUILTINS_CALL_WITH_ARGV, GateFlags::NONE_FLAG, 0, 1, value) \
V(BuiltinsCall, BUILTINS_CALL, GateFlags::NONE_FLAG, 0, 1, value) \
V(SaveRegister, SAVE_REGISTER, GateFlags::NONE_FLAG, 0, 1, value) \
#define GATE_META_DATA_LIST_WITH_SIZE(V) \
V(Merge, MERGE, GateFlags::CONTROL, value, 0, 0) \
V(DependSelector, DEPEND_SELECTOR, GateFlags::FIXED, 1, value, 0) \
GATE_META_DATA_LIST_WITH_VALUE_IN(V)
#define GATE_META_DATA_LIST_WITH_GATE_TYPE(V) \
V(PrimitiveTypeCheck, PRIMITIVE_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
V(ObjectTypeCheck, OBJECT_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
V(TypedArrayCheck, TYPED_ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
V(IndexCheck, INDEX_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
V(Int32OverflowCheck, INT32_OVERFLOW_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
V(TypedUnaryOp, TYPED_UNARY_OP, GateFlags::NO_WRITE, 1, 1, 1) \
V(TypedConvert, TYPE_CONVERT, GateFlags::NO_WRITE, 1, 1, 1) \
#define GATE_META_DATA_LIST_WITH_VALUE(V) \
V(Icmp, ICMP, GateFlags::NONE_FLAG, 0, 0, 2) \
V(Fcmp, FCMP, GateFlags::NONE_FLAG, 0, 0, 2) \
V(Alloca, ALLOCA, GateFlags::NONE_FLAG, 0, 0, 0) \
V(SwitchBranch, SWITCH_BRANCH, GateFlags::CONTROL, 1, 0, 1) \
V(SwitchCase, SWITCH_CASE, GateFlags::CONTROL, 1, 0, 0) \
V(HeapAlloc, HEAP_ALLOC, GateFlags::NONE_FLAG, 1, 1, 1) \
V(LoadElement, LOAD_ELEMENT, GateFlags::NO_WRITE, 1, 1, 2) \
V(StoreElement, STORE_ELEMENT, GateFlags::NONE_FLAG, 1, 1, 3) \
V(RestoreRegister, RESTORE_REGISTER, GateFlags::NONE_FLAG, 0, 1, 0) \
V(ConstData, CONST_DATA, GateFlags::NONE_FLAG, 0, 0, 0) \
V(Constant, CONSTANT, GateFlags::NONE_FLAG, 0, 0, 0) \
V(RelocatableData, RELOCATABLE_DATA, GateFlags::NONE_FLAG, 0, 0, 0)
#define GATE_META_DATA_LIST_WITH_ONE_PARAMETER(V) \
V(Arg, ARG, GateFlags::HAS_ROOT, 0, 0, 0) \
GATE_META_DATA_LIST_WITH_VALUE(V) \
GATE_META_DATA_LIST_WITH_GATE_TYPE(V)
#define GATE_OPCODE_LIST(V) \
V(JS_BYTECODE) \
V(TYPED_BINARY_OP) \
V(CONSTSTRING)
enum class OpCode : uint8_t {
NOP = 0,
#define DECLARE_GATE_OPCODE(NAME, OP, R, S, D, V) OP,
IMMUTABLE_META_DATA_CACHE_LIST(DECLARE_GATE_OPCODE)
GATE_META_DATA_LIST_WITH_SIZE(DECLARE_GATE_OPCODE)
GATE_META_DATA_LIST_WITH_ONE_PARAMETER(DECLARE_GATE_OPCODE)
#undef DECLARE_GATE_OPCODE
#define DECLARE_GATE_OPCODE(NAME) NAME,
GATE_OPCODE_LIST(DECLARE_GATE_OPCODE)
#undef DECLARE_GATE_OPCODE
};
enum GateFlags : uint8_t {
NONE_FLAG = 0,
NO_WRITE = 1 << 0,
HAS_ROOT = 1 << 1,
HAS_FRAME_STATE = 1 << 2,
CONTROL = NO_WRITE,
CHECKABLE = NO_WRITE | HAS_FRAME_STATE,
ROOT = NO_WRITE | HAS_ROOT,
FIXED = NO_WRITE,
};
class GateMetaData : public ChunkObject {
public:
enum class Kind : uint8_t {
IMMUTABLE = 0,
MUTABLE_WITH_SIZE,
IMMUTABLE_ONE_PARAMETER,
MUTABLE_ONE_PARAMETER,
MUTABLE_STRING,
JSBYTECODE,
TYPED_BINARY_OP,
};
GateMetaData() = default;
GateMetaData(OpCode opcode, GateFlags flags,
uint32_t statesIn, uint16_t dependsIn, uint32_t valuesIn)
: opcode_(opcode), flags_(flags),
statesIn_(statesIn), dependsIn_(dependsIn), valuesIn_(valuesIn) {}
size_t GetStateCount() const
{
return statesIn_;
}
size_t GetDependCount() const
{
return dependsIn_;
}
size_t GetInValueCount() const
{
return valuesIn_;
}
size_t GetRootCount() const
{
return HasRoot() ? 1 : 0;
}
size_t GetInFrameStateCount() const
{
return HasFrameState() ? 1 : 0;
}
size_t GetNumIns() const
{
return GetStateCount() + GetDependCount() + GetInValueCount()
+ GetInFrameStateCount() + GetRootCount();
}
size_t GetInValueStarts() const
{
return GetStateCount() + GetDependCount();
}
size_t GetInFrameStateStarts() const
{
return GetInValueStarts() + GetInValueCount();
}
OpCode GetOpCode() const
{
return opcode_;
}
Kind GetKind() const
{
return kind_;
}
void AssertKind([[maybe_unused]] Kind kind) const
{
ASSERT(GetKind() == kind);
}
bool IsOneParameterKind() const
{
return GetKind() == Kind::IMMUTABLE_ONE_PARAMETER || GetKind() == Kind::MUTABLE_ONE_PARAMETER ||
GetKind() == Kind::TYPED_BINARY_OP;
}
bool IsStringType() const
{
return GetKind() == Kind::MUTABLE_STRING;
}
bool IsRoot() const;
bool IsProlog() const;
bool IsFixed() const;
bool IsSchedulable() const;
bool IsState() const; // note: IsState(STATE_ENTRY) == false
bool IsGeneralState() const;
bool IsTerminalState() const;
bool IsCFGMerge() const;
bool IsControlCase() const;
bool IsLoopHead() const;
bool IsNop() const;
bool IsConstant() const;
bool IsDependSelector() const;
bool IsTypedOperator() const;
bool IsCheckWithOneIn() const;
bool IsCheckWithTwoIns() const;
bool HasFrameState() const
{
return HasFlag(GateFlags::HAS_FRAME_STATE);
}
bool IsNotWrite() const
{
return HasFlag(GateFlags::NO_WRITE);
}
~GateMetaData() = default;
static std::string Str(OpCode opcode);
std::string Str() const
{
return Str(opcode_);
}
protected:
void SetKind(Kind kind)
{
kind_ = kind;
}
void SetFlags(GateFlags flags)
{
flags_ = flags;
}
void DecreaseIn(size_t idx)
{
ASSERT(GetKind() == Kind::MUTABLE_WITH_SIZE);
if (idx < statesIn_) {
statesIn_--;
} else if (idx < statesIn_ + dependsIn_) {
dependsIn_--;
} else {
valuesIn_--;
}
}
bool HasRoot() const
{
return HasFlag(GateFlags::HAS_ROOT);
}
bool HasFlag(GateFlags flag) const
{
return (GetFlags() & flag) == flag;
}
GateFlags GetFlags() const
{
return flags_;
}
private:
friend class Gate;
friend class Circuit;
friend class GateMetaBuilder;
OpCode opcode_ { OpCode::NOP };
Kind kind_ { Kind::IMMUTABLE };
GateFlags flags_ { GateFlags::NONE_FLAG };
uint32_t statesIn_ { 0 };
uint32_t dependsIn_ { 0 };
uint32_t valuesIn_ { 0 };
};
inline std::ostream& operator<<(std::ostream& os, OpCode opcode)
{
return os << GateMetaData::Str(opcode);
}
class JSBytecodeMetaData : public GateMetaData {
public:
explicit JSBytecodeMetaData(size_t valuesIn, EcmaOpcode opcode, uint32_t bcIndex, GateFlags flags)
: GateMetaData(OpCode::JS_BYTECODE, flags, 1, 1, valuesIn),
opcode_(opcode), bcIndex_(bcIndex)
{
SetKind(GateMetaData::Kind::JSBYTECODE);
}
static const JSBytecodeMetaData* Cast(const GateMetaData* meta)
{
meta->AssertKind(GateMetaData::Kind::JSBYTECODE);
return static_cast<const JSBytecodeMetaData*>(meta);
}
uint32_t GetBytecodeIndex() const
{
return bcIndex_;
}
EcmaOpcode GetByteCodeOpcode() const
{
return opcode_;
}
private:
EcmaOpcode opcode_;
uint32_t bcIndex_;
};
class OneParameterMetaData : public GateMetaData {
public:
OneParameterMetaData(OpCode opcode, GateFlags flags, uint32_t statesIn,
uint16_t dependsIn, uint32_t valuesIn, uint64_t value)
: GateMetaData(opcode, flags, statesIn, dependsIn, valuesIn), value_(value)
{
SetKind(GateMetaData::Kind::IMMUTABLE_ONE_PARAMETER);
}
static const OneParameterMetaData* Cast(const GateMetaData* meta)
{
ASSERT(meta->IsOneParameterKind());
return static_cast<const OneParameterMetaData*>(meta);
}
uint64_t GetValue() const
{
return value_;
}
private:
uint64_t value_ { 0 };
};
class TypedBinaryMegaData : public OneParameterMetaData {
public:
TypedBinaryMegaData(uint64_t value, TypedBinOp binOp)
: OneParameterMetaData(OpCode::TYPED_BINARY_OP, GateFlags::NO_WRITE, 1, 1, 2, value), // 2: valuesIn
binOp_(binOp)
{
SetKind(GateMetaData::Kind::TYPED_BINARY_OP);
}
static const TypedBinaryMegaData* Cast(const GateMetaData* meta)
{
meta->AssertKind(GateMetaData::Kind::TYPED_BINARY_OP);
return static_cast<const TypedBinaryMegaData*>(meta);
}
TypedBinOp GetTypedBinaryOp() const
{
return binOp_;
}
private:
TypedBinOp binOp_;
};
class StringMetaData : public GateMetaData {
public:
StringMetaData(Chunk* chunk, const std::string &str)
: GateMetaData(OpCode::CONSTSTRING, GateFlags::NONE_FLAG, 0, 0, 0),
stringData_(str.size() + 1, chunk)
{
auto srcLength = str.size();
auto destlength = stringData_.size();
auto dest = stringData_.data();
auto src = str.c_str();
if (destlength <= static_cast<size_t>(srcLength) || strcpy_s(dest, destlength, src) != EOK) {
LOG_COMPILER(FATAL) << "StringMetaData strcpy_s failed";
}
SetKind(GateMetaData::Kind::MUTABLE_STRING);
}
const ChunkVector<char> &GetString() const
{
return stringData_;
}
private:
ChunkVector<char> stringData_;
};
class GateTypeAccessor {
public:
explicit GateTypeAccessor(uint64_t value)
: type_(static_cast<uint32_t>(value)) {}
GateType GetGateType() const
{
return type_;
}
static uint64_t ToValue(GateType type)
{
return static_cast<uint64_t>(type.Value());
}
private:
GateType type_;
};
class GatePairTypeAccessor {
public:
// type bits shift
static constexpr int OPRAND_TYPE_BITS = 32;
explicit GatePairTypeAccessor(uint64_t value) : bitField_(value) {}
GateType GetLeftType() const
{
return GateType(LeftBits::Get(bitField_));
}
GateType GetRightType() const
{
return GateType(RightBits::Get(bitField_));
}
static uint64_t ToValue(GateType leftType, GateType rightType)
{
return LeftBits::Encode(leftType.Value()) | RightBits::Encode(rightType.Value());
}
private:
using LeftBits = panda::BitField<uint32_t, 0, OPRAND_TYPE_BITS>;
using RightBits = LeftBits::NextField<uint32_t, OPRAND_TYPE_BITS>;
uint64_t bitField_;
};
class TypedUnaryAccessor {
public:
// type bits shift
static constexpr int OPRAND_TYPE_BITS = 32;
explicit TypedUnaryAccessor(uint64_t value) : bitField_(value) {}
GateType GetTypeValue() const
{
return GateType(TypedValueBits::Get(bitField_));
}
TypedUnOp GetTypedUnOp() const
{
return TypedUnOpBits::Get(bitField_);
}
static uint64_t ToValue(GateType typeValue, TypedUnOp unaryOp)
{
return TypedValueBits::Encode(typeValue.Value())
| TypedUnOpBits::Encode(unaryOp);
}
private:
using TypedValueBits = panda::BitField<uint32_t, 0, OPRAND_TYPE_BITS>;
using TypedUnOpBits = TypedValueBits::NextField<TypedUnOp, OPRAND_TYPE_BITS>;
uint64_t bitField_;
};
} // namespace panda::ecmascript::kungfu
#endif // ECMASCRIPT_COMPILER_GATE_META_DATA_H