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