/**
 * Copyright (c) 2021-2024 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.
 */



// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define OPCODE_LIST(DEF) \
    DEF( Neg                 , UnaryOperation      , ACC_WRITE|ACC_READ|IFCVT ) \
    DEF( Abs                 , UnaryOperation      , ACC_WRITE|IFCVT ) \
    DEF( Sqrt                , UnaryOperation      , ACC_WRITE|IFCVT ) \
    DEF( Not                 , UnaryOperation      , ACC_WRITE|ACC_READ|IFCVT ) \
    DEF( Add                 , BinaryOperation     , COMMUTATIVE|ACC_WRITE|ACC_READ|IFCVT ) \
    DEF( Sub                 , BinaryOperation     , ACC_WRITE|ACC_READ|IFCVT ) \
    DEF( Mul                 , BinaryOperation     , COMMUTATIVE|ACC_WRITE|ACC_READ|IFCVT ) \
    DEF( MulOverflowCheck    , FixedInputsInst<3>  , NO_DCE|NO_HOIST|NO_CSE|BARRIER|ACC_READ|REQUIRE_STATE|CAN_DEOPTIMIZE ) \
    DEF( Div                 , BinaryOperation     , ACC_WRITE|ACC_READ ) \
    DEF( Mod                 , BinaryOperation     , ACC_WRITE|ACC_READ ) \
    DEF( Min                 , BinaryOperation     , COMMUTATIVE|IFCVT ) \
    DEF( Max                 , BinaryOperation     , COMMUTATIVE|IFCVT ) \
    DEF( Shl                 , BinaryOperation     , ACC_WRITE|ACC_READ|IFCVT ) \
    DEF( Shr                 , BinaryOperation     , ACC_WRITE|ACC_READ|IFCVT ) \
    DEF( AShr                , BinaryOperation     , ACC_WRITE|ACC_READ|IFCVT ) \
    DEF( And                 , BinaryOperation     , COMMUTATIVE|ACC_WRITE|ACC_READ|IFCVT ) \
    DEF( Or                  , BinaryOperation     , COMMUTATIVE|ACC_WRITE|ACC_READ|IFCVT ) \
    DEF( Xor                 , BinaryOperation     , COMMUTATIVE|ACC_WRITE|ACC_READ|IFCVT ) \
    DEF( ExtractBitfield     , ExtractBitfieldInst , ACC_WRITE|ACC_READ ) \
    DEF( Compare             , CompareInst         , ACC_READ|ACC_WRITE|IFCVT ) \
    DEF( Cmp                 , CmpInst             , ACC_READ|ACC_WRITE|IFCVT ) \
    DEF( CompareAnyType      , CompareAnyTypeInst  , ACC_READ|ACC_WRITE|IFCVT ) \
    DEF( GetAnyTypeName      , GetAnyTypeNameInst  , ACC_READ|ACC_WRITE|IFCVT|NO_HOIST|REF_SPECIAL ) \
    DEF( CastAnyTypeValue    , CastAnyTypeValueInst, ACC_READ|ACC_WRITE ) \
    DEF( CastValueToAnyType  , CastValueToAnyTypeInst, ACC_READ|ACC_WRITE ) \
    DEF( Cast                , CastInst            , ACC_READ|ACC_WRITE|IFCVT ) \
    DEF( Bitcast             , CastInst            , IFCVT ) \
    DEF( Constant            , ConstantInst        , NO_CSE|IFCVT ) \
    DEF( Parameter           , ParameterInst       , NO_CSE|NO_HOIST ) \
    DEF( NullPtr             , FixedInputsInst<0>  , NO_CSE|NO_HOIST|IFCVT ) \
    DEF( LoadUniqueObject    , FixedInputsInst<0>  , LOAD ) \
    DEF( NewArray            , NewArrayInst        , CAN_THROW|NO_DCE|NO_HOIST|NO_CSE|ALLOC|REQUIRE_STATE|RUNTIME_CALL|MEM_BARRIER ) \
    DEF( NewObject           , NewObjectInst       , CAN_THROW|NO_DCE|NO_HOIST|NO_CSE|ALLOC|REQUIRE_STATE|RUNTIME_CALL|MEM_BARRIER ) \
    DEF( InitObject          , CallInst            , CAN_THROW|NO_DCE|NO_HOIST|NO_CSE|ALLOC|REQUIRE_STATE|RUNTIME_CALL|ACC_WRITE ) \
    DEF( InitEmptyString     , FixedInputsInst<1>  , CAN_THROW|NO_DCE|NO_HOIST|NO_CSE|ALLOC|REQUIRE_STATE|RUNTIME_CALL|ACC_WRITE ) \
    DEF( InitString          , InitStringInst      , CAN_THROW|NO_DCE|NO_HOIST|NO_CSE|BARRIER|ALLOC|REQUIRE_STATE|RUNTIME_CALL|ACC_WRITE ) \
    DEF( LoadArray           , LoadInst            , LOAD|NO_HOIST|NO_CSE|ACC_READ|ACC_WRITE|READ_BARRIER ) \
    DEF( LoadCompressedStringChar, LoadCompressedStringCharInst, LOAD|NO_CSE|ACC_READ|ACC_WRITE ) \
    DEF( StoreArray          , StoreInst           , STORE|NO_DCE|NO_HOIST|NO_CSE|ACC_READ|REQUIRE_TMP|WRITE_BARRIER|NO_DST ) \
    DEF( LoadObject          , LoadObjectInst      , LOAD|NO_HOIST|NO_CSE|ACC_WRITE|READ_BARRIER ) \
    DEF( LoadObjectDynamic   , LoadObjectDynamicInst, LOAD|NO_HOIST|NO_CSE|ACC_WRITE|BARRIER ) \
    DEF( Load                , LoadMemInst         , NATIVE|LOW_LEVEL|LOAD|NO_HOIST|NO_CSE|READ_BARRIER ) \
    DEF( LoadNative          , LoadMemInst         , NATIVE|LOAD|NO_HOIST|NO_CSE ) \
    DEF( LoadI               , LoadMemInstI        , NATIVE|LOW_LEVEL|LOAD|NO_HOIST|NO_CSE|READ_BARRIER ) \
    DEF( Store               , StoreMemInst        , NATIVE|LOW_LEVEL|STORE|NO_DCE|NO_HOIST|NO_CSE|WRITE_BARRIER|NO_DST ) \
    DEF( StoreNative         , StoreMemInst        , NATIVE|STORE|NO_DCE|NO_HOIST|NO_CSE|NO_DST ) \
    DEF( StoreI              , StoreMemInstI       , NATIVE|LOW_LEVEL|STORE|NO_DCE|NO_HOIST|NO_CSE|WRITE_BARRIER|NO_DST ) \
    DEF( ResolveObjectField  , ResolveObjectFieldInst, CAN_THROW|NO_DCE|REQUIRE_STATE|RUNTIME_CALL ) \
    DEF( LoadResolvedObjectField, LoadResolvedObjectFieldInst, LOAD|NO_HOIST|NO_CSE|ACC_WRITE|READ_BARRIER ) \
    DEF( StoreObject         , StoreObjectInst     , STORE|NO_DCE|NO_HOIST|NO_CSE|ACC_READ|WRITE_BARRIER|NO_DST ) \
    DEF( StoreObjectDynamic  , StoreObjectDynamicInst, STORE|NO_DCE|NO_HOIST|NO_CSE|ACC_READ|BARRIER ) \
    DEF( StoreResolvedObjectField, StoreResolvedObjectFieldInst, STORE|NO_DCE|NO_HOIST|NO_CSE|ACC_READ|REQUIRE_TMP|WRITE_BARRIER|BARRIER|NO_DST ) \
    DEF( LoadStatic          , LoadStaticInst      , LOAD|NO_HOIST|NO_CSE|ACC_WRITE|READ_BARRIER ) \
    DEF( ResolveObjectFieldStatic, ResolveObjectFieldStaticInst, CAN_THROW|NO_DCE|REQUIRE_STATE|RUNTIME_CALL ) \
    DEF( LoadResolvedObjectFieldStatic, LoadResolvedObjectFieldStaticInst, LOAD|NO_HOIST|NO_CSE|ACC_WRITE|READ_BARRIER ) \
    DEF( StoreStatic         , StoreStaticInst     , STORE|NO_DCE|NO_HOIST|NO_CSE|ACC_READ|WRITE_BARRIER|NO_DST ) \
    DEF( UnresolvedStoreStatic, UnresolvedStoreStaticInst, STORE|CAN_THROW|NO_DCE|NO_HOIST|NO_CSE|BARRIER|REQUIRE_STATE|RUNTIME_CALL|IMPLICIT_RUNTIME_CALL|REQUIRE_TMP|WRITE_BARRIER|NO_DST ) \
    DEF( StoreResolvedObjectFieldStatic, StoreResolvedObjectFieldStaticInst, STORE|NO_DCE|NO_HOIST|NO_CSE|WRITE_BARRIER|BARRIER|NO_DST ) \
    DEF( LenArray            , LengthMethodInst    , ACC_WRITE ) \
    DEF( LoadString          , LoadFromPool        , LOAD|CAN_THROW|NO_HOIST|NO_CSE|REQUIRE_STATE|RUNTIME_CALL|ACC_WRITE|FLAT_STRING ) \
    DEF( LoadFromConstantPool, LoadFromPoolDynamic , LOAD|ACC_WRITE ) \
    DEF( LoadConstArray      , LoadConstArrayInst  , LOAD|CAN_THROW|NO_HOIST|NO_DCE|NO_CSE|REQUIRE_STATE|BARRIER|RUNTIME_CALL ) \
    DEF( LoadConstantPool    , FixedInputsInst<1>  , LOAD ) \
    DEF( LoadLexicalEnv      , FixedInputsInst<1>  , LOAD ) \
    DEF( FillConstArray      , FillConstArrayInst  , STORE|NO_HOIST|NO_DCE|NO_CSE|NO_DST|REQUIRE_STATE|BARRIER|RUNTIME_CALL|REQUIRE_TMP|NO_DST ) \
    DEF( LoadType            , LoadFromPool        , LOAD|CAN_THROW|NO_HOIST|NO_CSE|REQUIRE_STATE|RUNTIME_CALL|ACC_WRITE ) \
    DEF( UnresolvedLoadType  , LoadFromPool        , LOAD|CAN_THROW|NO_DCE|NO_HOIST|BARRIER|NO_CSE|REQUIRE_STATE|RUNTIME_CALL ) \
    DEF( CheckCast           , CheckCastInst       , CAN_THROW|NO_DCE|NO_HOIST|NO_CSE|REQUIRE_STATE|RUNTIME_CALL|ACC_READ|NO_DST ) \
    DEF( IsInstance          , IsInstanceInst      , REQUIRE_STATE|RUNTIME_CALL|ACC_READ|ACC_WRITE ) \
    DEF( InitClass           , ClassInst           , CAN_THROW|NO_HOIST|BARRIER|NO_DCE|REQUIRE_STATE|RUNTIME_CALL|NO_DST ) \
    DEF( LoadClass           , ClassInst           , CAN_THROW|NO_HOIST|BARRIER|NO_DCE|REQUIRE_STATE|RUNTIME_CALL ) \
    DEF( LoadAndInitClass    , ClassInst           , CAN_THROW|NO_DCE|NO_HOIST|BARRIER|REQUIRE_STATE|RUNTIME_CALL ) \
    DEF( UnresolvedLoadAndInitClass, ClassInst           , CAN_THROW|NO_DCE|NO_CSE|NO_HOIST|BARRIER|REQUIRE_STATE|RUNTIME_CALL ) \
    DEF( LoadRuntimeClass    , RuntimeClassInst    , REF_SPECIAL ) \
    DEF( GetInstanceClass    , FixedInputsInst<1>  , REF_SPECIAL ) \
    DEF( LoadImmediate       , LoadImmediateInst   , IFCVT ) \
    DEF( FunctionImmediate   , FunctionImmediateInst, LOAD|IFCVT ) \
    DEF( LoadObjFromConst    , LoadObjFromConstInst, LOAD|IFCVT ) \
    DEF( GetGlobalVarAddress , GlobalVarInst       , CAN_THROW|NO_HOIST|BARRIER|NO_DCE|REQUIRE_STATE|RUNTIME_CALL ) \
    DEF( NullCheck           , NullCheckInst       , CAN_THROW|IS_CHECK|NO_DCE|NO_HOIST|NO_CSE|REQUIRE_STATE|PSEUDO_DST ) \
    DEF( BoundsCheck         , BoundsCheckInst     , CAN_THROW|IS_CHECK|NO_DCE|NO_CSE|NO_HOIST|REQUIRE_STATE|ACC_READ|PSEUDO_DST ) \
    DEF( RefTypeCheck        , FixedInputsInst<3>  , CAN_THROW|NO_DCE|IS_CHECK|NO_HOIST|NO_CSE|REQUIRE_STATE|RUNTIME_CALL|PSEUDO_DST ) \
    DEF( ZeroCheck           , FixedInputsInst<2>  , CAN_THROW|IS_CHECK|NO_DCE|NO_CSE|NO_HOIST|REQUIRE_STATE|PSEUDO_DST ) \
    DEF( NegativeCheck       , FixedInputsInst<2>  , CAN_THROW|IS_CHECK|NO_DCE|NO_CSE|NO_HOIST|REQUIRE_STATE|PSEUDO_DST ) \
    DEF( NotPositiveCheck    , FixedInputsInst<2>  , CAN_THROW|IS_CHECK|NO_DCE|NO_CSE|NO_HOIST|REQUIRE_STATE|PSEUDO_DST ) \
    DEF( ObjByIndexCheck     , FixedInputsInst<2>  , CAN_THROW|IS_CHECK|NO_DCE|NO_CSE|NO_HOIST|REQUIRE_STATE|CAN_DEOPTIMIZE|PSEUDO_DST ) \
    DEF( AnyTypeCheck        , AnyTypeCheckInst    , CAN_THROW|NO_DCE|NO_CSE|IS_CHECK|NO_HOIST|REQUIRE_STATE|RUNTIME_CALL|CAN_DEOPTIMIZE|PSEUDO_DST ) \
    DEF( HclassCheck         , HclassCheckInst     , CAN_THROW|NO_DCE|NO_CSE|IS_CHECK|NO_HOIST|REQUIRE_STATE|RUNTIME_CALL|CAN_DEOPTIMIZE|NO_DST ) \
    DEF( StringFlatCheck     , FixedInputsInst<2>  , CAN_THROW|NO_HOIST|NO_CSE|REQUIRE_STATE|RUNTIME_CALL|FLAT_STRING ) \
    DEF( Deoptimize          , DeoptimizeInst      , CF|CAN_THROW|NO_DCE|NO_CSE|NO_HOIST|REQUIRE_STATE|BARRIER|CAN_DEOPTIMIZE|TERMINATOR|NO_DST ) \
    DEF( DeoptimizeIf        , DeoptimizeIfInst    , CAN_THROW|NO_DCE|NO_CSE|NO_HOIST|REQUIRE_STATE|ACC_READ|BARRIER|CAN_DEOPTIMIZE|NO_DST ) \
    DEF( DeoptimizeCompare   , DeoptimizeCompareInst, CAN_THROW|NO_DCE|NO_CSE|NO_HOIST|REQUIRE_STATE|ACC_READ|BARRIER|CAN_DEOPTIMIZE|LOW_LEVEL|NO_DST ) \
    DEF( DeoptimizeCompareImm, DeoptimizeCompareImmInst, CAN_THROW|NO_DCE|NO_CSE|NO_HOIST|REQUIRE_STATE|ACC_READ|BARRIER|CAN_DEOPTIMIZE|LOW_LEVEL|NO_DST ) \
    DEF( IsMustDeoptimize    , Inst                , NO_CSE|NO_HOIST ) \
    DEF( ReturnVoid          , FixedInputsInst<0>  , CF|NO_DCE|NO_HOIST|NO_CSE|BARRIER|TERMINATOR|NO_DST ) \
    DEF( Return              , FixedInputsInst<1>  , CF|NO_DCE|NO_HOIST|NO_CSE|BARRIER|ACC_READ|TERMINATOR|NO_DST ) \
    DEF( ReturnInlined       , ReturnInlinedInst   , NO_DCE|NO_HOIST|NO_CSE|BARRIER|REQUIRE_STATE|ACC_READ|NO_DST ) \
    DEF( Throw               , ThrowInst           , CF|CAN_THROW|NO_DCE|NO_HOIST|NO_CSE|BARRIER|REQUIRE_STATE|TERMINATOR|NO_DST ) \
    DEF( CallStatic          , CallInst            , CAN_THROW|NO_DCE|NO_HOIST|NO_CSE|BARRIER|REQUIRE_STATE|RUNTIME_CALL|CALL|ACC_WRITE|ACC_READ ) \
    DEF( ResolveStatic       , ResolveStaticInst   , CAN_THROW|BARRIER|REQUIRE_STATE|RUNTIME_CALL ) \
    DEF( CallResolvedStatic  , CallInst            , CAN_THROW|NO_DCE|NO_HOIST|NO_CSE|BARRIER|REQUIRE_STATE|CALL|ACC_WRITE|ACC_READ ) \
    DEF( CallVirtual         , CallInst            , CAN_THROW|NO_DCE|NO_HOIST|NO_CSE|BARRIER|REQUIRE_STATE|RUNTIME_CALL|CALL|ACC_WRITE|ACC_READ ) \
    DEF( ResolveVirtual      , ResolveVirtualInst  , CAN_THROW|BARRIER|REQUIRE_STATE|RUNTIME_CALL ) \
    DEF( CallResolvedVirtual , CallInst            , CAN_THROW|NO_DCE|NO_HOIST|NO_CSE|BARRIER|REQUIRE_STATE|CALL|ACC_WRITE|ACC_READ ) \
    DEF( CallDynamic         , CallInst            , CAN_THROW|NO_DCE|NO_HOIST|NO_CSE|BARRIER|REQUIRE_STATE|RUNTIME_CALL|CALL ) \
    DEF( CallIndirect        , CallIndirectInst    , CAN_THROW|NO_DCE|NO_HOIST|NO_CSE|BARRIER|CALL|LOW_LEVEL ) \
    DEF( Call                , CallInst            , CAN_THROW|NO_DCE|NO_HOIST|NO_CSE|BARRIER|CALL|LOW_LEVEL ) \
    DEF( MultiArray          , CallInst            , CAN_THROW|NO_DCE|NO_HOIST|NO_CSE|ALLOC|BARRIER|REQUIRE_STATE|RUNTIME_CALL|MEM_BARRIER ) \
    DEF( Monitor             , MonitorInst         , CAN_THROW|NO_DCE|NO_HOIST|NO_CSE|BARRIER|REQUIRE_STATE|RUNTIME_CALL|ACC_READ|NO_DST ) \
    DEF( Intrinsic           , IntrinsicInst       , CAN_THROW|HEAP_INV|NO_DCE|NO_HOIST|NO_CSE|BARRIER|REQUIRE_STATE|RUNTIME_CALL|CALL|ACC_WRITE|ACC_READ ) \
    DEF( CallNative          , CallInst            , HEAP_INV|NO_DCE|NO_HOIST|NO_CSE|BARRIER|REQUIRE_STATE|RUNTIME_CALL|CALL ) \
    DEF( WrapObjectNative    , WrapObjectNativeInst, NO_CSE ) \
    DEF( Builtin             , IntrinsicInst       , NONE ) \
    DEF( ResolveByName       , ResolveVirtualInst  , CAN_THROW|BARRIER|REQUIRE_STATE|RUNTIME_CALL ) \
    DEF( AddI                , BinaryImmOperation  , LOW_LEVEL|ACC_WRITE|ACC_READ|IFCVT ) \
    DEF( SubI                , BinaryImmOperation  , LOW_LEVEL|ACC_WRITE|ACC_READ|IFCVT ) \
    DEF( MulI                , BinaryImmOperation  , LOW_LEVEL|ACC_WRITE|ACC_READ|IFCVT ) \
    DEF( DivI                , BinaryImmOperation  , LOW_LEVEL|ACC_WRITE|ACC_READ|IFCVT ) \
    DEF( ModI                , BinaryImmOperation  , LOW_LEVEL|ACC_WRITE|ACC_READ|IFCVT ) \
    DEF( ShlI                , BinaryImmOperation  , LOW_LEVEL|ACC_WRITE|ACC_READ|IFCVT ) \
    DEF( ShrI                , BinaryImmOperation  , LOW_LEVEL|ACC_WRITE|ACC_READ|IFCVT ) \
    DEF( AShrI               , BinaryImmOperation  , LOW_LEVEL|ACC_WRITE|ACC_READ|IFCVT ) \
    DEF( AndI                , BinaryImmOperation  , LOW_LEVEL|ACC_WRITE|ACC_READ|IFCVT ) \
    DEF( OrI                 , BinaryImmOperation  , LOW_LEVEL|ACC_WRITE|ACC_READ|IFCVT ) \
    DEF( XorI                , BinaryImmOperation  , LOW_LEVEL|ACC_WRITE|ACC_READ|IFCVT ) \
    DEF( MAdd                , FixedInputsInst<3>  , LOW_LEVEL|IFCVT ) \
    DEF( MSub                , FixedInputsInst<3>  , LOW_LEVEL|IFCVT ) \
    DEF( MNeg                , BinaryOperation     , LOW_LEVEL|IFCVT ) \
    DEF( OrNot               , BinaryOperation     , LOW_LEVEL|IFCVT ) \
    DEF( AndNot              , BinaryOperation     , LOW_LEVEL|IFCVT ) \
    DEF( XorNot              , BinaryOperation     , LOW_LEVEL|IFCVT ) \
    DEF( AndSR               , BinaryShiftedRegisterOperation, LOW_LEVEL|IFCVT ) \
    DEF( OrSR                , BinaryShiftedRegisterOperation, LOW_LEVEL|IFCVT ) \
    DEF( XorSR               , BinaryShiftedRegisterOperation, LOW_LEVEL|IFCVT ) \
    DEF( AndNotSR            , BinaryShiftedRegisterOperation, LOW_LEVEL|IFCVT ) \
    DEF( OrNotSR             , BinaryShiftedRegisterOperation, LOW_LEVEL|IFCVT ) \
    DEF( XorNotSR            , BinaryShiftedRegisterOperation, LOW_LEVEL|IFCVT ) \
    DEF( AddSR               , BinaryShiftedRegisterOperation, LOW_LEVEL|IFCVT ) \
    DEF( SubSR               , BinaryShiftedRegisterOperation, LOW_LEVEL|IFCVT ) \
    DEF( NegSR               , UnaryShiftedRegisterOperation, LOW_LEVEL|IFCVT ) \
    DEF( BoundsCheckI        , BoundsCheckInstI    , CAN_THROW|IS_CHECK|NO_DCE|NO_HOIST|NO_CSE|REQUIRE_STATE|LOW_LEVEL|PSEUDO_DST ) \
    DEF( LoadArrayI          , LoadInstI           , LOAD|NO_HOIST|NO_CSE|LOW_LEVEL|ACC_READ|ACC_WRITE|READ_BARRIER ) \
    DEF( LoadCompressedStringCharI, LoadCompressedStringCharInstI, LOAD|NO_CSE|LOW_LEVEL|ACC_READ|ACC_WRITE ) \
    DEF( StoreArrayI         , StoreInstI          , STORE|NO_DCE|NO_HOIST|NO_CSE|LOW_LEVEL|ACC_READ|WRITE_BARRIER|NO_DST ) \
    DEF( LoadArrayPair       , LoadArrayPairInst   , LOAD|NO_HOIST|NO_CSE|LOW_LEVEL|ACC_WRITE|READ_BARRIER ) \
    DEF( LoadArrayPairI      , LoadArrayPairInstI  , LOAD|NO_HOIST|NO_CSE|LOW_LEVEL|ACC_WRITE|READ_BARRIER ) \
    DEF( LoadPairPart        , LoadPairPartInst    , LOAD|LOW_LEVEL|ACC_WRITE|NO_HOIST|NO_CSE|PSEUDO_DST ) \
    DEF( LoadObjectPair      , LoadObjectPairInst  , LOAD|NO_HOIST|NO_CSE|LOW_LEVEL|READ_BARRIER ) \
    DEF( StoreArrayPair      , StoreArrayPairInst  , STORE|NO_DCE|NO_HOIST|NO_CSE|LOW_LEVEL|ACC_READ|REQUIRE_TMP|WRITE_BARRIER|NO_DST ) \
    DEF( StoreArrayPairI     , StoreArrayPairInstI , STORE|NO_DCE|NO_HOIST|NO_CSE|LOW_LEVEL|ACC_READ|WRITE_BARRIER|NO_DST ) \
    DEF( StoreObjectPair     , StoreObjectPairInst , STORE|NO_DCE|NO_HOIST|NO_CSE|LOW_LEVEL|REQUIRE_TMP|WRITE_BARRIER|NO_DST ) \
    DEF( ReturnI             , ReturnInstI         , CF|NO_DCE|NO_HOIST|NO_CSE|BARRIER|LOW_LEVEL|ACC_READ|TERMINATOR|NO_DST ) \
    DEF( Phi                 , PhiInst             , NO_CSE|NO_HOIST ) \
    DEF( SpillFill           , SpillFillInst       , NO_CSE|NO_DCE|NO_DST ) \
    DEF( SaveState           , SaveStateInst       , NO_HOIST|NO_CSE|PSEUDO_DST ) \
    DEF( SafePoint           , SaveStateInst       , NO_DCE|NO_HOIST|NO_CSE|BARRIER|RUNTIME_CALL|NO_DST ) \
    DEF( SaveStateDeoptimize , SaveStateInst       , NO_DCE|NO_HOIST|NO_CSE|BARRIER|PSEUDO_DST ) \
    DEF( SaveStateOsr        , SaveStateInst       , NO_DCE|NO_HOIST|NO_CSE|BARRIER|PSEUDO_DST ) \
    DEF( SaveStateSuspend    , SaveStateInst       , NO_DCE|NO_HOIST|NO_CSE|BARRIER|HEAP_INV|PSEUDO_DST ) \
    DEF( Select              , SelectInst          , LOW_LEVEL|IFCVT ) \
    DEF( SelectTransform     , SelectTransformInst , LOW_LEVEL|IFCVT ) \
    DEF( SelectImm           , SelectImmInst       , LOW_LEVEL|IFCVT ) \
    DEF( SelectImmTransform  , SelectImmTransformInst, LOW_LEVEL|IFCVT ) \
    DEF( AddOverflow         , BinaryOverflowInst  , CF|NO_DCE|NO_HOIST|NO_CSE|BARRIER|ACC_READ ) \
    DEF( SubOverflow         , BinaryOverflowInst  , CF|NO_DCE|NO_HOIST|NO_CSE|BARRIER|ACC_READ ) \
    DEF( AddOverflowCheck    , FixedInputsInst<3>  , NO_DCE|NO_HOIST|NO_CSE|BARRIER|ACC_READ|REQUIRE_STATE|CAN_DEOPTIMIZE ) \
    DEF( SubOverflowCheck    , FixedInputsInst<3>  , NO_DCE|NO_HOIST|NO_CSE|BARRIER|ACC_READ|REQUIRE_STATE|CAN_DEOPTIMIZE ) \
    DEF( NegOverflowAndZeroCheck, FixedInputsInst<2>  , NO_DCE|NO_HOIST|NO_CSE|BARRIER|ACC_READ|REQUIRE_STATE|CAN_DEOPTIMIZE ) \
    DEF( If                  , IfInst              , CF|NO_DCE|NO_HOIST|NO_CSE|BARRIER|LOW_LEVEL|ACC_READ|NO_DST ) \
    DEF( IfImm               , IfImmInst           , CF|NO_DCE|NO_HOIST|NO_CSE|BARRIER|ACC_READ|NO_DST ) \
    DEF( NOP                 , FixedInputsInst<0>  , NO_DST|IFCVT|NO_HOIST|NO_DST ) \
    DEF( Try                 , TryInst             , NO_DCE|NO_HOIST|NO_CSE|BARRIER|NO_DST ) \
    DEF( CatchPhi            , CatchPhiInst        , NO_HOIST|NO_CSE ) \
    DEF( LiveIn              , Inst                , NO_DCE|NO_HOIST|NO_CSE|LOW_LEVEL ) \
    DEF( LiveOut             , FixedInputsInst<1>  , NO_DCE|NO_HOIST|NO_CSE|LOW_LEVEL ) \

namespace ark::compiler {
class UnaryOperation;
class BinaryOperation;
class ExtractBitfieldInst;
class CompareInst;
class CmpInst;
class CompareAnyTypeInst;
class GetAnyTypeNameInst;
class CastAnyTypeValueInst;
class CastValueToAnyTypeInst;
class CastInst;
class ConstantInst;
class ParameterInst;
class NewArrayInst;
class NewObjectInst;
class CallInst;
class InitStringInst;
class LoadInst;
class LoadCompressedStringCharInst;
class StoreInst;
class LoadObjectInst;
class LoadObjectDynamicInst;
class LoadMemInst;
class LoadMemInstI;
class StoreMemInst;
class StoreMemInstI;
class ResolveObjectFieldInst;
class LoadResolvedObjectFieldInst;
class StoreObjectInst;
class StoreObjectDynamicInst;
class StoreResolvedObjectFieldInst;
class LoadStaticInst;
class ResolveObjectFieldStaticInst;
class LoadResolvedObjectFieldStaticInst;
class StoreStaticInst;
class UnresolvedStoreStaticInst;
class StoreResolvedObjectFieldStaticInst;
class LengthMethodInst;
class LoadFromPool;
class LoadFromPoolDynamic;
class LoadConstArrayInst;
class FillConstArrayInst;
class CheckCastInst;
class IsInstanceInst;
class ClassInst;
class RuntimeClassInst;
class LoadImmediateInst;
class FunctionImmediateInst;
class LoadObjFromConstInst;
class GlobalVarInst;
class NullCheckInst;
class BoundsCheckInst;
class AnyTypeCheckInst;
class HclassCheckInst;
class DeoptimizeInst;
class DeoptimizeIfInst;
class DeoptimizeCompareInst;
class DeoptimizeCompareImmInst;
class Inst;
class ReturnInlinedInst;
class ThrowInst;
class ResolveStaticInst;
class ResolveVirtualInst;
class CallIndirectInst;
class MonitorInst;
class IntrinsicInst;
class WrapObjectNativeInst;
class BinaryImmOperation;
class BinaryShiftedRegisterOperation;
class UnaryShiftedRegisterOperation;
class BoundsCheckInstI;
class LoadInstI;
class LoadCompressedStringCharInstI;
class StoreInstI;
class LoadArrayPairInst;
class LoadArrayPairInstI;
class LoadPairPartInst;
class LoadObjectPairInst;
class StoreArrayPairInst;
class StoreArrayPairInstI;
class StoreObjectPairInst;
class ReturnInstI;
class PhiInst;
class SpillFillInst;
class SaveStateInst;
class SelectInst;
class SelectTransformInst;
class SelectImmInst;
class SelectImmTransformInst;
class BinaryOverflowInst;
class IfInst;
class IfImmInst;
class TryInst;
class CatchPhiInst;
}  // namespace ark::compiler

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define FLAGS_LIST(DEF) \
    DEF(CF) \
    DEF(TERMINATOR) \
    DEF(LOAD) \
    DEF(STORE) \
    DEF(READ_BARRIER) \
    DEF(WRITE_BARRIER) \
    DEF(CAN_THROW) \
    DEF(CALL) \
    DEF(IS_CHECK) \
    DEF(NO_DCE) \
    DEF(NO_CSE) \
    DEF(NO_DST) \
    DEF(NO_NULLPTR) \
    DEF(PSEUDO_DST) \
    DEF(IMPLICIT_RUNTIME_CALL) \
    DEF(LOW_LEVEL) \
    DEF(NO_HOIST) \
    DEF(BARRIER) \
    DEF(REF_SPECIAL) \
    DEF(IFCVT) \
    DEF(REQUIRE_STATE) \
    DEF(RUNTIME_CALL) \
    DEF(COMMUTATIVE) \
    DEF(ALLOC) \
    DEF(ACC_READ) \
    DEF(ACC_WRITE) \
    DEF(HEAP_INV) \
    DEF(MEM_BARRIER) \
    DEF(NATIVE) \
    DEF(CAN_DEOPTIMIZE) \
    DEF(CATCH_INPUT) \
    DEF(REQUIRE_TMP) \
    DEF(FLAT_STRING) \

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define INST_CAST_TO_DECL() \
          UnaryOperation       *CastToNeg                 (); \
    const UnaryOperation       *CastToNeg                 () const; \
          UnaryOperation       *CastToAbs                 (); \
    const UnaryOperation       *CastToAbs                 () const; \
          UnaryOperation       *CastToSqrt                (); \
    const UnaryOperation       *CastToSqrt                () const; \
          UnaryOperation       *CastToNot                 (); \
    const UnaryOperation       *CastToNot                 () const; \
          BinaryOperation      *CastToAdd                 (); \
    const BinaryOperation      *CastToAdd                 () const; \
          BinaryOperation      *CastToSub                 (); \
    const BinaryOperation      *CastToSub                 () const; \
          BinaryOperation      *CastToMul                 (); \
    const BinaryOperation      *CastToMul                 () const; \
          FixedInputsInst<3>   *CastToMulOverflowCheck    (); \
    const FixedInputsInst<3>   *CastToMulOverflowCheck    () const; \
          BinaryOperation      *CastToDiv                 (); \
    const BinaryOperation      *CastToDiv                 () const; \
          BinaryOperation      *CastToMod                 (); \
    const BinaryOperation      *CastToMod                 () const; \
          BinaryOperation      *CastToMin                 (); \
    const BinaryOperation      *CastToMin                 () const; \
          BinaryOperation      *CastToMax                 (); \
    const BinaryOperation      *CastToMax                 () const; \
          BinaryOperation      *CastToShl                 (); \
    const BinaryOperation      *CastToShl                 () const; \
          BinaryOperation      *CastToShr                 (); \
    const BinaryOperation      *CastToShr                 () const; \
          BinaryOperation      *CastToAShr                (); \
    const BinaryOperation      *CastToAShr                () const; \
          BinaryOperation      *CastToAnd                 (); \
    const BinaryOperation      *CastToAnd                 () const; \
          BinaryOperation      *CastToOr                  (); \
    const BinaryOperation      *CastToOr                  () const; \
          BinaryOperation      *CastToXor                 (); \
    const BinaryOperation      *CastToXor                 () const; \
          ExtractBitfieldInst  *CastToExtractBitfield     (); \
    const ExtractBitfieldInst  *CastToExtractBitfield     () const; \
          CompareInst          *CastToCompare             (); \
    const CompareInst          *CastToCompare             () const; \
          CmpInst              *CastToCmp                 (); \
    const CmpInst              *CastToCmp                 () const; \
          CompareAnyTypeInst   *CastToCompareAnyType      (); \
    const CompareAnyTypeInst   *CastToCompareAnyType      () const; \
          GetAnyTypeNameInst   *CastToGetAnyTypeName      (); \
    const GetAnyTypeNameInst   *CastToGetAnyTypeName      () const; \
          CastAnyTypeValueInst *CastToCastAnyTypeValue    (); \
    const CastAnyTypeValueInst *CastToCastAnyTypeValue    () const; \
          CastValueToAnyTypeInst *CastToCastValueToAnyType  (); \
    const CastValueToAnyTypeInst *CastToCastValueToAnyType  () const; \
          CastInst             *CastToCast                (); \
    const CastInst             *CastToCast                () const; \
          CastInst             *CastToBitcast             (); \
    const CastInst             *CastToBitcast             () const; \
          ConstantInst         *CastToConstant            (); \
    const ConstantInst         *CastToConstant            () const; \
          ParameterInst        *CastToParameter           (); \
    const ParameterInst        *CastToParameter           () const; \
          FixedInputsInst<0>   *CastToNullPtr             (); \
    const FixedInputsInst<0>   *CastToNullPtr             () const; \
          FixedInputsInst<0>   *CastToLoadUniqueObject    (); \
    const FixedInputsInst<0>   *CastToLoadUniqueObject    () const; \
          NewArrayInst         *CastToNewArray            (); \
    const NewArrayInst         *CastToNewArray            () const; \
          NewObjectInst        *CastToNewObject           (); \
    const NewObjectInst        *CastToNewObject           () const; \
          CallInst             *CastToInitObject          (); \
    const CallInst             *CastToInitObject          () const; \
          FixedInputsInst<1>   *CastToInitEmptyString     (); \
    const FixedInputsInst<1>   *CastToInitEmptyString     () const; \
          InitStringInst       *CastToInitString          (); \
    const InitStringInst       *CastToInitString          () const; \
          LoadInst             *CastToLoadArray           (); \
    const LoadInst             *CastToLoadArray           () const; \
          LoadCompressedStringCharInst *CastToLoadCompressedStringChar(); \
    const LoadCompressedStringCharInst *CastToLoadCompressedStringChar() const; \
          StoreInst            *CastToStoreArray          (); \
    const StoreInst            *CastToStoreArray          () const; \
          LoadObjectInst       *CastToLoadObject          (); \
    const LoadObjectInst       *CastToLoadObject          () const; \
          LoadObjectDynamicInst *CastToLoadObjectDynamic   (); \
    const LoadObjectDynamicInst *CastToLoadObjectDynamic   () const; \
          LoadMemInst          *CastToLoad                (); \
    const LoadMemInst          *CastToLoad                () const; \
          LoadMemInst          *CastToLoadNative          (); \
    const LoadMemInst          *CastToLoadNative          () const; \
          LoadMemInstI         *CastToLoadI               (); \
    const LoadMemInstI         *CastToLoadI               () const; \
          StoreMemInst         *CastToStore               (); \
    const StoreMemInst         *CastToStore               () const; \
          StoreMemInst         *CastToStoreNative         (); \
    const StoreMemInst         *CastToStoreNative         () const; \
          StoreMemInstI        *CastToStoreI              (); \
    const StoreMemInstI        *CastToStoreI              () const; \
          ResolveObjectFieldInst *CastToResolveObjectField  (); \
    const ResolveObjectFieldInst *CastToResolveObjectField  () const; \
          LoadResolvedObjectFieldInst *CastToLoadResolvedObjectField(); \
    const LoadResolvedObjectFieldInst *CastToLoadResolvedObjectField() const; \
          StoreObjectInst      *CastToStoreObject         (); \
    const StoreObjectInst      *CastToStoreObject         () const; \
          StoreObjectDynamicInst *CastToStoreObjectDynamic  (); \
    const StoreObjectDynamicInst *CastToStoreObjectDynamic  () const; \
          StoreResolvedObjectFieldInst *CastToStoreResolvedObjectField(); \
    const StoreResolvedObjectFieldInst *CastToStoreResolvedObjectField() const; \
          LoadStaticInst       *CastToLoadStatic          (); \
    const LoadStaticInst       *CastToLoadStatic          () const; \
          ResolveObjectFieldStaticInst *CastToResolveObjectFieldStatic(); \
    const ResolveObjectFieldStaticInst *CastToResolveObjectFieldStatic() const; \
          LoadResolvedObjectFieldStaticInst *CastToLoadResolvedObjectFieldStatic(); \
    const LoadResolvedObjectFieldStaticInst *CastToLoadResolvedObjectFieldStatic() const; \
          StoreStaticInst      *CastToStoreStatic         (); \
    const StoreStaticInst      *CastToStoreStatic         () const; \
          UnresolvedStoreStaticInst *CastToUnresolvedStoreStatic(); \
    const UnresolvedStoreStaticInst *CastToUnresolvedStoreStatic() const; \
          StoreResolvedObjectFieldStaticInst *CastToStoreResolvedObjectFieldStatic(); \
    const StoreResolvedObjectFieldStaticInst *CastToStoreResolvedObjectFieldStatic() const; \
          LengthMethodInst     *CastToLenArray            (); \
    const LengthMethodInst     *CastToLenArray            () const; \
          LoadFromPool         *CastToLoadString          (); \
    const LoadFromPool         *CastToLoadString          () const; \
          LoadFromPoolDynamic  *CastToLoadFromConstantPool(); \
    const LoadFromPoolDynamic  *CastToLoadFromConstantPool() const; \
          LoadConstArrayInst   *CastToLoadConstArray      (); \
    const LoadConstArrayInst   *CastToLoadConstArray      () const; \
          FixedInputsInst<1>   *CastToLoadConstantPool    (); \
    const FixedInputsInst<1>   *CastToLoadConstantPool    () const; \
          FixedInputsInst<1>   *CastToLoadLexicalEnv      (); \
    const FixedInputsInst<1>   *CastToLoadLexicalEnv      () const; \
          FillConstArrayInst   *CastToFillConstArray      (); \
    const FillConstArrayInst   *CastToFillConstArray      () const; \
          LoadFromPool         *CastToLoadType            (); \
    const LoadFromPool         *CastToLoadType            () const; \
          LoadFromPool         *CastToUnresolvedLoadType  (); \
    const LoadFromPool         *CastToUnresolvedLoadType  () const; \
          CheckCastInst        *CastToCheckCast           (); \
    const CheckCastInst        *CastToCheckCast           () const; \
          IsInstanceInst       *CastToIsInstance          (); \
    const IsInstanceInst       *CastToIsInstance          () const; \
          ClassInst            *CastToInitClass           (); \
    const ClassInst            *CastToInitClass           () const; \
          ClassInst            *CastToLoadClass           (); \
    const ClassInst            *CastToLoadClass           () const; \
          ClassInst            *CastToLoadAndInitClass    (); \
    const ClassInst            *CastToLoadAndInitClass    () const; \
          ClassInst            *CastToUnresolvedLoadAndInitClass(); \
    const ClassInst            *CastToUnresolvedLoadAndInitClass() const; \
          RuntimeClassInst     *CastToLoadRuntimeClass    (); \
    const RuntimeClassInst     *CastToLoadRuntimeClass    () const; \
          FixedInputsInst<1>   *CastToGetInstanceClass    (); \
    const FixedInputsInst<1>   *CastToGetInstanceClass    () const; \
          LoadImmediateInst    *CastToLoadImmediate       (); \
    const LoadImmediateInst    *CastToLoadImmediate       () const; \
          FunctionImmediateInst *CastToFunctionImmediate   (); \
    const FunctionImmediateInst *CastToFunctionImmediate   () const; \
          LoadObjFromConstInst *CastToLoadObjFromConst    (); \
    const LoadObjFromConstInst *CastToLoadObjFromConst    () const; \
          GlobalVarInst        *CastToGetGlobalVarAddress (); \
    const GlobalVarInst        *CastToGetGlobalVarAddress () const; \
          NullCheckInst        *CastToNullCheck           (); \
    const NullCheckInst        *CastToNullCheck           () const; \
          BoundsCheckInst      *CastToBoundsCheck         (); \
    const BoundsCheckInst      *CastToBoundsCheck         () const; \
          FixedInputsInst<3>   *CastToRefTypeCheck        (); \
    const FixedInputsInst<3>   *CastToRefTypeCheck        () const; \
          FixedInputsInst<2>   *CastToZeroCheck           (); \
    const FixedInputsInst<2>   *CastToZeroCheck           () const; \
          FixedInputsInst<2>   *CastToNegativeCheck       (); \
    const FixedInputsInst<2>   *CastToNegativeCheck       () const; \
          FixedInputsInst<2>   *CastToNotPositiveCheck    (); \
    const FixedInputsInst<2>   *CastToNotPositiveCheck    () const; \
          FixedInputsInst<2>   *CastToObjByIndexCheck     (); \
    const FixedInputsInst<2>   *CastToObjByIndexCheck     () const; \
          AnyTypeCheckInst     *CastToAnyTypeCheck        (); \
    const AnyTypeCheckInst     *CastToAnyTypeCheck        () const; \
          HclassCheckInst      *CastToHclassCheck         (); \
    const HclassCheckInst      *CastToHclassCheck         () const; \
          FixedInputsInst<2>   *CastToStringFlatCheck     (); \
    const FixedInputsInst<2>   *CastToStringFlatCheck     () const; \
          DeoptimizeInst       *CastToDeoptimize          (); \
    const DeoptimizeInst       *CastToDeoptimize          () const; \
          DeoptimizeIfInst     *CastToDeoptimizeIf        (); \
    const DeoptimizeIfInst     *CastToDeoptimizeIf        () const; \
          DeoptimizeCompareInst *CastToDeoptimizeCompare   (); \
    const DeoptimizeCompareInst *CastToDeoptimizeCompare   () const; \
          DeoptimizeCompareImmInst *CastToDeoptimizeCompareImm(); \
    const DeoptimizeCompareImmInst *CastToDeoptimizeCompareImm() const; \
          Inst                 *CastToIsMustDeoptimize    (); \
    const Inst                 *CastToIsMustDeoptimize    () const; \
          FixedInputsInst<0>   *CastToReturnVoid          (); \
    const FixedInputsInst<0>   *CastToReturnVoid          () const; \
          FixedInputsInst<1>   *CastToReturn              (); \
    const FixedInputsInst<1>   *CastToReturn              () const; \
          ReturnInlinedInst    *CastToReturnInlined       (); \
    const ReturnInlinedInst    *CastToReturnInlined       () const; \
          ThrowInst            *CastToThrow               (); \
    const ThrowInst            *CastToThrow               () const; \
          CallInst             *CastToCallStatic          (); \
    const CallInst             *CastToCallStatic          () const; \
          ResolveStaticInst    *CastToResolveStatic       (); \
    const ResolveStaticInst    *CastToResolveStatic       () const; \
          CallInst             *CastToCallResolvedStatic  (); \
    const CallInst             *CastToCallResolvedStatic  () const; \
          CallInst             *CastToCallVirtual         (); \
    const CallInst             *CastToCallVirtual         () const; \
          ResolveVirtualInst   *CastToResolveVirtual      (); \
    const ResolveVirtualInst   *CastToResolveVirtual      () const; \
          CallInst             *CastToCallResolvedVirtual (); \
    const CallInst             *CastToCallResolvedVirtual () const; \
          CallInst             *CastToCallDynamic         (); \
    const CallInst             *CastToCallDynamic         () const; \
          CallIndirectInst     *CastToCallIndirect        (); \
    const CallIndirectInst     *CastToCallIndirect        () const; \
          CallInst             *CastToCall                (); \
    const CallInst             *CastToCall                () const; \
          CallInst             *CastToMultiArray          (); \
    const CallInst             *CastToMultiArray          () const; \
          MonitorInst          *CastToMonitor             (); \
    const MonitorInst          *CastToMonitor             () const; \
          IntrinsicInst        *CastToIntrinsic           (); \
    const IntrinsicInst        *CastToIntrinsic           () const; \
          CallInst             *CastToCallNative          (); \
    const CallInst             *CastToCallNative          () const; \
          WrapObjectNativeInst *CastToWrapObjectNative    (); \
    const WrapObjectNativeInst *CastToWrapObjectNative    () const; \
          IntrinsicInst        *CastToBuiltin             (); \
    const IntrinsicInst        *CastToBuiltin             () const; \
          ResolveVirtualInst   *CastToResolveByName       (); \
    const ResolveVirtualInst   *CastToResolveByName       () const; \
          BinaryImmOperation   *CastToAddI                (); \
    const BinaryImmOperation   *CastToAddI                () const; \
          BinaryImmOperation   *CastToSubI                (); \
    const BinaryImmOperation   *CastToSubI                () const; \
          BinaryImmOperation   *CastToMulI                (); \
    const BinaryImmOperation   *CastToMulI                () const; \
          BinaryImmOperation   *CastToDivI                (); \
    const BinaryImmOperation   *CastToDivI                () const; \
          BinaryImmOperation   *CastToModI                (); \
    const BinaryImmOperation   *CastToModI                () const; \
          BinaryImmOperation   *CastToShlI                (); \
    const BinaryImmOperation   *CastToShlI                () const; \
          BinaryImmOperation   *CastToShrI                (); \
    const BinaryImmOperation   *CastToShrI                () const; \
          BinaryImmOperation   *CastToAShrI               (); \
    const BinaryImmOperation   *CastToAShrI               () const; \
          BinaryImmOperation   *CastToAndI                (); \
    const BinaryImmOperation   *CastToAndI                () const; \
          BinaryImmOperation   *CastToOrI                 (); \
    const BinaryImmOperation   *CastToOrI                 () const; \
          BinaryImmOperation   *CastToXorI                (); \
    const BinaryImmOperation   *CastToXorI                () const; \
          FixedInputsInst<3>   *CastToMAdd                (); \
    const FixedInputsInst<3>   *CastToMAdd                () const; \
          FixedInputsInst<3>   *CastToMSub                (); \
    const FixedInputsInst<3>   *CastToMSub                () const; \
          BinaryOperation      *CastToMNeg                (); \
    const BinaryOperation      *CastToMNeg                () const; \
          BinaryOperation      *CastToOrNot               (); \
    const BinaryOperation      *CastToOrNot               () const; \
          BinaryOperation      *CastToAndNot              (); \
    const BinaryOperation      *CastToAndNot              () const; \
          BinaryOperation      *CastToXorNot              (); \
    const BinaryOperation      *CastToXorNot              () const; \
          BinaryShiftedRegisterOperation *CastToAndSR               (); \
    const BinaryShiftedRegisterOperation *CastToAndSR               () const; \
          BinaryShiftedRegisterOperation *CastToOrSR                (); \
    const BinaryShiftedRegisterOperation *CastToOrSR                () const; \
          BinaryShiftedRegisterOperation *CastToXorSR               (); \
    const BinaryShiftedRegisterOperation *CastToXorSR               () const; \
          BinaryShiftedRegisterOperation *CastToAndNotSR            (); \
    const BinaryShiftedRegisterOperation *CastToAndNotSR            () const; \
          BinaryShiftedRegisterOperation *CastToOrNotSR             (); \
    const BinaryShiftedRegisterOperation *CastToOrNotSR             () const; \
          BinaryShiftedRegisterOperation *CastToXorNotSR            (); \
    const BinaryShiftedRegisterOperation *CastToXorNotSR            () const; \
          BinaryShiftedRegisterOperation *CastToAddSR               (); \
    const BinaryShiftedRegisterOperation *CastToAddSR               () const; \
          BinaryShiftedRegisterOperation *CastToSubSR               (); \
    const BinaryShiftedRegisterOperation *CastToSubSR               () const; \
          UnaryShiftedRegisterOperation *CastToNegSR               (); \
    const UnaryShiftedRegisterOperation *CastToNegSR               () const; \
          BoundsCheckInstI     *CastToBoundsCheckI        (); \
    const BoundsCheckInstI     *CastToBoundsCheckI        () const; \
          LoadInstI            *CastToLoadArrayI          (); \
    const LoadInstI            *CastToLoadArrayI          () const; \
          LoadCompressedStringCharInstI *CastToLoadCompressedStringCharI(); \
    const LoadCompressedStringCharInstI *CastToLoadCompressedStringCharI() const; \
          StoreInstI           *CastToStoreArrayI         (); \
    const StoreInstI           *CastToStoreArrayI         () const; \
          LoadArrayPairInst    *CastToLoadArrayPair       (); \
    const LoadArrayPairInst    *CastToLoadArrayPair       () const; \
          LoadArrayPairInstI   *CastToLoadArrayPairI      (); \
    const LoadArrayPairInstI   *CastToLoadArrayPairI      () const; \
          LoadPairPartInst     *CastToLoadPairPart        (); \
    const LoadPairPartInst     *CastToLoadPairPart        () const; \
          LoadObjectPairInst   *CastToLoadObjectPair      (); \
    const LoadObjectPairInst   *CastToLoadObjectPair      () const; \
          StoreArrayPairInst   *CastToStoreArrayPair      (); \
    const StoreArrayPairInst   *CastToStoreArrayPair      () const; \
          StoreArrayPairInstI  *CastToStoreArrayPairI     (); \
    const StoreArrayPairInstI  *CastToStoreArrayPairI     () const; \
          StoreObjectPairInst  *CastToStoreObjectPair     (); \
    const StoreObjectPairInst  *CastToStoreObjectPair     () const; \
          ReturnInstI          *CastToReturnI             (); \
    const ReturnInstI          *CastToReturnI             () const; \
          PhiInst              *CastToPhi                 (); \
    const PhiInst              *CastToPhi                 () const; \
          SpillFillInst        *CastToSpillFill           (); \
    const SpillFillInst        *CastToSpillFill           () const; \
          SaveStateInst        *CastToSaveState           (); \
    const SaveStateInst        *CastToSaveState           () const; \
          SaveStateInst        *CastToSafePoint           (); \
    const SaveStateInst        *CastToSafePoint           () const; \
          SaveStateInst        *CastToSaveStateDeoptimize (); \
    const SaveStateInst        *CastToSaveStateDeoptimize () const; \
          SaveStateInst        *CastToSaveStateOsr        (); \
    const SaveStateInst        *CastToSaveStateOsr        () const; \
          SaveStateInst        *CastToSaveStateSuspend    (); \
    const SaveStateInst        *CastToSaveStateSuspend    () const; \
          SelectInst           *CastToSelect              (); \
    const SelectInst           *CastToSelect              () const; \
          SelectTransformInst  *CastToSelectTransform     (); \
    const SelectTransformInst  *CastToSelectTransform     () const; \
          SelectImmInst        *CastToSelectImm           (); \
    const SelectImmInst        *CastToSelectImm           () const; \
          SelectImmTransformInst *CastToSelectImmTransform  (); \
    const SelectImmTransformInst *CastToSelectImmTransform  () const; \
          BinaryOverflowInst   *CastToAddOverflow         (); \
    const BinaryOverflowInst   *CastToAddOverflow         () const; \
          BinaryOverflowInst   *CastToSubOverflow         (); \
    const BinaryOverflowInst   *CastToSubOverflow         () const; \
          FixedInputsInst<3>   *CastToAddOverflowCheck    (); \
    const FixedInputsInst<3>   *CastToAddOverflowCheck    () const; \
          FixedInputsInst<3>   *CastToSubOverflowCheck    (); \
    const FixedInputsInst<3>   *CastToSubOverflowCheck    () const; \
          FixedInputsInst<2>   *CastToNegOverflowAndZeroCheck(); \
    const FixedInputsInst<2>   *CastToNegOverflowAndZeroCheck() const; \
          IfInst               *CastToIf                  (); \
    const IfInst               *CastToIf                  () const; \
          IfImmInst            *CastToIfImm               (); \
    const IfImmInst            *CastToIfImm               () const; \
          FixedInputsInst<0>   *CastToNOP                 (); \
    const FixedInputsInst<0>   *CastToNOP                 () const; \
          TryInst              *CastToTry                 (); \
    const TryInst              *CastToTry                 () const; \
          CatchPhiInst         *CastToCatchPhi            (); \
    const CatchPhiInst         *CastToCatchPhi            () const; \
          Inst                 *CastToLiveIn              (); \
    const Inst                 *CastToLiveIn              () const; \
          FixedInputsInst<1>   *CastToLiveOut             (); \
    const FixedInputsInst<1>   *CastToLiveOut             () const; \

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define INST_CAST_TO_DEF() \
inline       UnaryOperation       *Inst::CastToNeg                 ()       { ASSERT(GetOpcode() == Opcode::Neg                 ); return static_cast<      UnaryOperation *>(this); } \
inline const UnaryOperation       *Inst::CastToNeg                 () const { ASSERT(GetOpcode() == Opcode::Neg                 ); return static_cast<const UnaryOperation *>(this); } \
inline       UnaryOperation       *Inst::CastToAbs                 ()       { ASSERT(GetOpcode() == Opcode::Abs                 ); return static_cast<      UnaryOperation *>(this); } \
inline const UnaryOperation       *Inst::CastToAbs                 () const { ASSERT(GetOpcode() == Opcode::Abs                 ); return static_cast<const UnaryOperation *>(this); } \
inline       UnaryOperation       *Inst::CastToSqrt                ()       { ASSERT(GetOpcode() == Opcode::Sqrt                ); return static_cast<      UnaryOperation *>(this); } \
inline const UnaryOperation       *Inst::CastToSqrt                () const { ASSERT(GetOpcode() == Opcode::Sqrt                ); return static_cast<const UnaryOperation *>(this); } \
inline       UnaryOperation       *Inst::CastToNot                 ()       { ASSERT(GetOpcode() == Opcode::Not                 ); return static_cast<      UnaryOperation *>(this); } \
inline const UnaryOperation       *Inst::CastToNot                 () const { ASSERT(GetOpcode() == Opcode::Not                 ); return static_cast<const UnaryOperation *>(this); } \
inline       BinaryOperation      *Inst::CastToAdd                 ()       { ASSERT(GetOpcode() == Opcode::Add                 ); return static_cast<      BinaryOperation *>(this); } \
inline const BinaryOperation      *Inst::CastToAdd                 () const { ASSERT(GetOpcode() == Opcode::Add                 ); return static_cast<const BinaryOperation *>(this); } \
inline       BinaryOperation      *Inst::CastToSub                 ()       { ASSERT(GetOpcode() == Opcode::Sub                 ); return static_cast<      BinaryOperation *>(this); } \
inline const BinaryOperation      *Inst::CastToSub                 () const { ASSERT(GetOpcode() == Opcode::Sub                 ); return static_cast<const BinaryOperation *>(this); } \
inline       BinaryOperation      *Inst::CastToMul                 ()       { ASSERT(GetOpcode() == Opcode::Mul                 ); return static_cast<      BinaryOperation *>(this); } \
inline const BinaryOperation      *Inst::CastToMul                 () const { ASSERT(GetOpcode() == Opcode::Mul                 ); return static_cast<const BinaryOperation *>(this); } \
inline       FixedInputsInst<3>   *Inst::CastToMulOverflowCheck    ()       { ASSERT(GetOpcode() == Opcode::MulOverflowCheck    ); return static_cast<      FixedInputsInst<3> *>(this); } \
inline const FixedInputsInst<3>   *Inst::CastToMulOverflowCheck    () const { ASSERT(GetOpcode() == Opcode::MulOverflowCheck    ); return static_cast<const FixedInputsInst<3> *>(this); } \
inline       BinaryOperation      *Inst::CastToDiv                 ()       { ASSERT(GetOpcode() == Opcode::Div                 ); return static_cast<      BinaryOperation *>(this); } \
inline const BinaryOperation      *Inst::CastToDiv                 () const { ASSERT(GetOpcode() == Opcode::Div                 ); return static_cast<const BinaryOperation *>(this); } \
inline       BinaryOperation      *Inst::CastToMod                 ()       { ASSERT(GetOpcode() == Opcode::Mod                 ); return static_cast<      BinaryOperation *>(this); } \
inline const BinaryOperation      *Inst::CastToMod                 () const { ASSERT(GetOpcode() == Opcode::Mod                 ); return static_cast<const BinaryOperation *>(this); } \
inline       BinaryOperation      *Inst::CastToMin                 ()       { ASSERT(GetOpcode() == Opcode::Min                 ); return static_cast<      BinaryOperation *>(this); } \
inline const BinaryOperation      *Inst::CastToMin                 () const { ASSERT(GetOpcode() == Opcode::Min                 ); return static_cast<const BinaryOperation *>(this); } \
inline       BinaryOperation      *Inst::CastToMax                 ()       { ASSERT(GetOpcode() == Opcode::Max                 ); return static_cast<      BinaryOperation *>(this); } \
inline const BinaryOperation      *Inst::CastToMax                 () const { ASSERT(GetOpcode() == Opcode::Max                 ); return static_cast<const BinaryOperation *>(this); } \
inline       BinaryOperation      *Inst::CastToShl                 ()       { ASSERT(GetOpcode() == Opcode::Shl                 ); return static_cast<      BinaryOperation *>(this); } \
inline const BinaryOperation      *Inst::CastToShl                 () const { ASSERT(GetOpcode() == Opcode::Shl                 ); return static_cast<const BinaryOperation *>(this); } \
inline       BinaryOperation      *Inst::CastToShr                 ()       { ASSERT(GetOpcode() == Opcode::Shr                 ); return static_cast<      BinaryOperation *>(this); } \
inline const BinaryOperation      *Inst::CastToShr                 () const { ASSERT(GetOpcode() == Opcode::Shr                 ); return static_cast<const BinaryOperation *>(this); } \
inline       BinaryOperation      *Inst::CastToAShr                ()       { ASSERT(GetOpcode() == Opcode::AShr                ); return static_cast<      BinaryOperation *>(this); } \
inline const BinaryOperation      *Inst::CastToAShr                () const { ASSERT(GetOpcode() == Opcode::AShr                ); return static_cast<const BinaryOperation *>(this); } \
inline       BinaryOperation      *Inst::CastToAnd                 ()       { ASSERT(GetOpcode() == Opcode::And                 ); return static_cast<      BinaryOperation *>(this); } \
inline const BinaryOperation      *Inst::CastToAnd                 () const { ASSERT(GetOpcode() == Opcode::And                 ); return static_cast<const BinaryOperation *>(this); } \
inline       BinaryOperation      *Inst::CastToOr                  ()       { ASSERT(GetOpcode() == Opcode::Or                  ); return static_cast<      BinaryOperation *>(this); } \
inline const BinaryOperation      *Inst::CastToOr                  () const { ASSERT(GetOpcode() == Opcode::Or                  ); return static_cast<const BinaryOperation *>(this); } \
inline       BinaryOperation      *Inst::CastToXor                 ()       { ASSERT(GetOpcode() == Opcode::Xor                 ); return static_cast<      BinaryOperation *>(this); } \
inline const BinaryOperation      *Inst::CastToXor                 () const { ASSERT(GetOpcode() == Opcode::Xor                 ); return static_cast<const BinaryOperation *>(this); } \
inline       ExtractBitfieldInst  *Inst::CastToExtractBitfield     ()       { ASSERT(GetOpcode() == Opcode::ExtractBitfield     ); return static_cast<      ExtractBitfieldInst *>(this); } \
inline const ExtractBitfieldInst  *Inst::CastToExtractBitfield     () const { ASSERT(GetOpcode() == Opcode::ExtractBitfield     ); return static_cast<const ExtractBitfieldInst *>(this); } \
inline       CompareInst          *Inst::CastToCompare             ()       { ASSERT(GetOpcode() == Opcode::Compare             ); return static_cast<      CompareInst *>(this); } \
inline const CompareInst          *Inst::CastToCompare             () const { ASSERT(GetOpcode() == Opcode::Compare             ); return static_cast<const CompareInst *>(this); } \
inline       CmpInst              *Inst::CastToCmp                 ()       { ASSERT(GetOpcode() == Opcode::Cmp                 ); return static_cast<      CmpInst *>(this); } \
inline const CmpInst              *Inst::CastToCmp                 () const { ASSERT(GetOpcode() == Opcode::Cmp                 ); return static_cast<const CmpInst *>(this); } \
inline       CompareAnyTypeInst   *Inst::CastToCompareAnyType      ()       { ASSERT(GetOpcode() == Opcode::CompareAnyType      ); return static_cast<      CompareAnyTypeInst *>(this); } \
inline const CompareAnyTypeInst   *Inst::CastToCompareAnyType      () const { ASSERT(GetOpcode() == Opcode::CompareAnyType      ); return static_cast<const CompareAnyTypeInst *>(this); } \
inline       GetAnyTypeNameInst   *Inst::CastToGetAnyTypeName      ()       { ASSERT(GetOpcode() == Opcode::GetAnyTypeName      ); return static_cast<      GetAnyTypeNameInst *>(this); } \
inline const GetAnyTypeNameInst   *Inst::CastToGetAnyTypeName      () const { ASSERT(GetOpcode() == Opcode::GetAnyTypeName      ); return static_cast<const GetAnyTypeNameInst *>(this); } \
inline       CastAnyTypeValueInst *Inst::CastToCastAnyTypeValue    ()       { ASSERT(GetOpcode() == Opcode::CastAnyTypeValue    ); return static_cast<      CastAnyTypeValueInst *>(this); } \
inline const CastAnyTypeValueInst *Inst::CastToCastAnyTypeValue    () const { ASSERT(GetOpcode() == Opcode::CastAnyTypeValue    ); return static_cast<const CastAnyTypeValueInst *>(this); } \
inline       CastValueToAnyTypeInst *Inst::CastToCastValueToAnyType  ()       { ASSERT(GetOpcode() == Opcode::CastValueToAnyType  ); return static_cast<      CastValueToAnyTypeInst *>(this); } \
inline const CastValueToAnyTypeInst *Inst::CastToCastValueToAnyType  () const { ASSERT(GetOpcode() == Opcode::CastValueToAnyType  ); return static_cast<const CastValueToAnyTypeInst *>(this); } \
inline       CastInst             *Inst::CastToCast                ()       { ASSERT(GetOpcode() == Opcode::Cast                ); return static_cast<      CastInst *>(this); } \
inline const CastInst             *Inst::CastToCast                () const { ASSERT(GetOpcode() == Opcode::Cast                ); return static_cast<const CastInst *>(this); } \
inline       CastInst             *Inst::CastToBitcast             ()       { ASSERT(GetOpcode() == Opcode::Bitcast             ); return static_cast<      CastInst *>(this); } \
inline const CastInst             *Inst::CastToBitcast             () const { ASSERT(GetOpcode() == Opcode::Bitcast             ); return static_cast<const CastInst *>(this); } \
inline       ConstantInst         *Inst::CastToConstant            ()       { ASSERT(GetOpcode() == Opcode::Constant            ); return static_cast<      ConstantInst *>(this); } \
inline const ConstantInst         *Inst::CastToConstant            () const { ASSERT(GetOpcode() == Opcode::Constant            ); return static_cast<const ConstantInst *>(this); } \
inline       ParameterInst        *Inst::CastToParameter           ()       { ASSERT(GetOpcode() == Opcode::Parameter           ); return static_cast<      ParameterInst *>(this); } \
inline const ParameterInst        *Inst::CastToParameter           () const { ASSERT(GetOpcode() == Opcode::Parameter           ); return static_cast<const ParameterInst *>(this); } \
inline       FixedInputsInst<0>   *Inst::CastToNullPtr             ()       { ASSERT(GetOpcode() == Opcode::NullPtr             ); return static_cast<      FixedInputsInst<0> *>(this); } \
inline const FixedInputsInst<0>   *Inst::CastToNullPtr             () const { ASSERT(GetOpcode() == Opcode::NullPtr             ); return static_cast<const FixedInputsInst<0> *>(this); } \
inline       FixedInputsInst<0>   *Inst::CastToLoadUniqueObject    ()       { ASSERT(GetOpcode() == Opcode::LoadUniqueObject    ); return static_cast<      FixedInputsInst<0> *>(this); } \
inline const FixedInputsInst<0>   *Inst::CastToLoadUniqueObject    () const { ASSERT(GetOpcode() == Opcode::LoadUniqueObject    ); return static_cast<const FixedInputsInst<0> *>(this); } \
inline       NewArrayInst         *Inst::CastToNewArray            ()       { ASSERT(GetOpcode() == Opcode::NewArray            ); return static_cast<      NewArrayInst *>(this); } \
inline const NewArrayInst         *Inst::CastToNewArray            () const { ASSERT(GetOpcode() == Opcode::NewArray            ); return static_cast<const NewArrayInst *>(this); } \
inline       NewObjectInst        *Inst::CastToNewObject           ()       { ASSERT(GetOpcode() == Opcode::NewObject           ); return static_cast<      NewObjectInst *>(this); } \
inline const NewObjectInst        *Inst::CastToNewObject           () const { ASSERT(GetOpcode() == Opcode::NewObject           ); return static_cast<const NewObjectInst *>(this); } \
inline       CallInst             *Inst::CastToInitObject          ()       { ASSERT(GetOpcode() == Opcode::InitObject          ); return static_cast<      CallInst *>(this); } \
inline const CallInst             *Inst::CastToInitObject          () const { ASSERT(GetOpcode() == Opcode::InitObject          ); return static_cast<const CallInst *>(this); } \
inline       FixedInputsInst<1>   *Inst::CastToInitEmptyString     ()       { ASSERT(GetOpcode() == Opcode::InitEmptyString     ); return static_cast<      FixedInputsInst<1> *>(this); } \
inline const FixedInputsInst<1>   *Inst::CastToInitEmptyString     () const { ASSERT(GetOpcode() == Opcode::InitEmptyString     ); return static_cast<const FixedInputsInst<1> *>(this); } \
inline       InitStringInst       *Inst::CastToInitString          ()       { ASSERT(GetOpcode() == Opcode::InitString          ); return static_cast<      InitStringInst *>(this); } \
inline const InitStringInst       *Inst::CastToInitString          () const { ASSERT(GetOpcode() == Opcode::InitString          ); return static_cast<const InitStringInst *>(this); } \
inline       LoadInst             *Inst::CastToLoadArray           ()       { ASSERT(GetOpcode() == Opcode::LoadArray           ); return static_cast<      LoadInst *>(this); } \
inline const LoadInst             *Inst::CastToLoadArray           () const { ASSERT(GetOpcode() == Opcode::LoadArray           ); return static_cast<const LoadInst *>(this); } \
inline       LoadCompressedStringCharInst *Inst::CastToLoadCompressedStringChar()       { ASSERT(GetOpcode() == Opcode::LoadCompressedStringChar); return static_cast<      LoadCompressedStringCharInst *>(this); } \
inline const LoadCompressedStringCharInst *Inst::CastToLoadCompressedStringChar() const { ASSERT(GetOpcode() == Opcode::LoadCompressedStringChar); return static_cast<const LoadCompressedStringCharInst *>(this); } \
inline       StoreInst            *Inst::CastToStoreArray          ()       { ASSERT(GetOpcode() == Opcode::StoreArray          ); return static_cast<      StoreInst *>(this); } \
inline const StoreInst            *Inst::CastToStoreArray          () const { ASSERT(GetOpcode() == Opcode::StoreArray          ); return static_cast<const StoreInst *>(this); } \
inline       LoadObjectInst       *Inst::CastToLoadObject          ()       { ASSERT(GetOpcode() == Opcode::LoadObject          ); return static_cast<      LoadObjectInst *>(this); } \
inline const LoadObjectInst       *Inst::CastToLoadObject          () const { ASSERT(GetOpcode() == Opcode::LoadObject          ); return static_cast<const LoadObjectInst *>(this); } \
inline       LoadObjectDynamicInst *Inst::CastToLoadObjectDynamic   ()       { ASSERT(GetOpcode() == Opcode::LoadObjectDynamic   ); return static_cast<      LoadObjectDynamicInst *>(this); } \
inline const LoadObjectDynamicInst *Inst::CastToLoadObjectDynamic   () const { ASSERT(GetOpcode() == Opcode::LoadObjectDynamic   ); return static_cast<const LoadObjectDynamicInst *>(this); } \
inline       LoadMemInst          *Inst::CastToLoad                ()       { ASSERT(GetOpcode() == Opcode::Load                ); return static_cast<      LoadMemInst *>(this); } \
inline const LoadMemInst          *Inst::CastToLoad                () const { ASSERT(GetOpcode() == Opcode::Load                ); return static_cast<const LoadMemInst *>(this); } \
inline       LoadMemInst          *Inst::CastToLoadNative          ()       { ASSERT(GetOpcode() == Opcode::LoadNative          ); return static_cast<      LoadMemInst *>(this); } \
inline const LoadMemInst          *Inst::CastToLoadNative          () const { ASSERT(GetOpcode() == Opcode::LoadNative          ); return static_cast<const LoadMemInst *>(this); } \
inline       LoadMemInstI         *Inst::CastToLoadI               ()       { ASSERT(GetOpcode() == Opcode::LoadI               ); return static_cast<      LoadMemInstI *>(this); } \
inline const LoadMemInstI         *Inst::CastToLoadI               () const { ASSERT(GetOpcode() == Opcode::LoadI               ); return static_cast<const LoadMemInstI *>(this); } \
inline       StoreMemInst         *Inst::CastToStore               ()       { ASSERT(GetOpcode() == Opcode::Store               ); return static_cast<      StoreMemInst *>(this); } \
inline const StoreMemInst         *Inst::CastToStore               () const { ASSERT(GetOpcode() == Opcode::Store               ); return static_cast<const StoreMemInst *>(this); } \
inline       StoreMemInst         *Inst::CastToStoreNative         ()       { ASSERT(GetOpcode() == Opcode::StoreNative         ); return static_cast<      StoreMemInst *>(this); } \
inline const StoreMemInst         *Inst::CastToStoreNative         () const { ASSERT(GetOpcode() == Opcode::StoreNative         ); return static_cast<const StoreMemInst *>(this); } \
inline       StoreMemInstI        *Inst::CastToStoreI              ()       { ASSERT(GetOpcode() == Opcode::StoreI              ); return static_cast<      StoreMemInstI *>(this); } \
inline const StoreMemInstI        *Inst::CastToStoreI              () const { ASSERT(GetOpcode() == Opcode::StoreI              ); return static_cast<const StoreMemInstI *>(this); } \
inline       ResolveObjectFieldInst *Inst::CastToResolveObjectField  ()       { ASSERT(GetOpcode() == Opcode::ResolveObjectField  ); return static_cast<      ResolveObjectFieldInst *>(this); } \
inline const ResolveObjectFieldInst *Inst::CastToResolveObjectField  () const { ASSERT(GetOpcode() == Opcode::ResolveObjectField  ); return static_cast<const ResolveObjectFieldInst *>(this); } \
inline       LoadResolvedObjectFieldInst *Inst::CastToLoadResolvedObjectField()       { ASSERT(GetOpcode() == Opcode::LoadResolvedObjectField); return static_cast<      LoadResolvedObjectFieldInst *>(this); } \
inline const LoadResolvedObjectFieldInst *Inst::CastToLoadResolvedObjectField() const { ASSERT(GetOpcode() == Opcode::LoadResolvedObjectField); return static_cast<const LoadResolvedObjectFieldInst *>(this); } \
inline       StoreObjectInst      *Inst::CastToStoreObject         ()       { ASSERT(GetOpcode() == Opcode::StoreObject         ); return static_cast<      StoreObjectInst *>(this); } \
inline const StoreObjectInst      *Inst::CastToStoreObject         () const { ASSERT(GetOpcode() == Opcode::StoreObject         ); return static_cast<const StoreObjectInst *>(this); } \
inline       StoreObjectDynamicInst *Inst::CastToStoreObjectDynamic  ()       { ASSERT(GetOpcode() == Opcode::StoreObjectDynamic  ); return static_cast<      StoreObjectDynamicInst *>(this); } \
inline const StoreObjectDynamicInst *Inst::CastToStoreObjectDynamic  () const { ASSERT(GetOpcode() == Opcode::StoreObjectDynamic  ); return static_cast<const StoreObjectDynamicInst *>(this); } \
inline       StoreResolvedObjectFieldInst *Inst::CastToStoreResolvedObjectField()       { ASSERT(GetOpcode() == Opcode::StoreResolvedObjectField); return static_cast<      StoreResolvedObjectFieldInst *>(this); } \
inline const StoreResolvedObjectFieldInst *Inst::CastToStoreResolvedObjectField() const { ASSERT(GetOpcode() == Opcode::StoreResolvedObjectField); return static_cast<const StoreResolvedObjectFieldInst *>(this); } \
inline       LoadStaticInst       *Inst::CastToLoadStatic          ()       { ASSERT(GetOpcode() == Opcode::LoadStatic          ); return static_cast<      LoadStaticInst *>(this); } \
inline const LoadStaticInst       *Inst::CastToLoadStatic          () const { ASSERT(GetOpcode() == Opcode::LoadStatic          ); return static_cast<const LoadStaticInst *>(this); } \
inline       ResolveObjectFieldStaticInst *Inst::CastToResolveObjectFieldStatic()       { ASSERT(GetOpcode() == Opcode::ResolveObjectFieldStatic); return static_cast<      ResolveObjectFieldStaticInst *>(this); } \
inline const ResolveObjectFieldStaticInst *Inst::CastToResolveObjectFieldStatic() const { ASSERT(GetOpcode() == Opcode::ResolveObjectFieldStatic); return static_cast<const ResolveObjectFieldStaticInst *>(this); } \
inline       LoadResolvedObjectFieldStaticInst *Inst::CastToLoadResolvedObjectFieldStatic()       { ASSERT(GetOpcode() == Opcode::LoadResolvedObjectFieldStatic); return static_cast<      LoadResolvedObjectFieldStaticInst *>(this); } \
inline const LoadResolvedObjectFieldStaticInst *Inst::CastToLoadResolvedObjectFieldStatic() const { ASSERT(GetOpcode() == Opcode::LoadResolvedObjectFieldStatic); return static_cast<const LoadResolvedObjectFieldStaticInst *>(this); } \
inline       StoreStaticInst      *Inst::CastToStoreStatic         ()       { ASSERT(GetOpcode() == Opcode::StoreStatic         ); return static_cast<      StoreStaticInst *>(this); } \
inline const StoreStaticInst      *Inst::CastToStoreStatic         () const { ASSERT(GetOpcode() == Opcode::StoreStatic         ); return static_cast<const StoreStaticInst *>(this); } \
inline       UnresolvedStoreStaticInst *Inst::CastToUnresolvedStoreStatic()       { ASSERT(GetOpcode() == Opcode::UnresolvedStoreStatic); return static_cast<      UnresolvedStoreStaticInst *>(this); } \
inline const UnresolvedStoreStaticInst *Inst::CastToUnresolvedStoreStatic() const { ASSERT(GetOpcode() == Opcode::UnresolvedStoreStatic); return static_cast<const UnresolvedStoreStaticInst *>(this); } \
inline       StoreResolvedObjectFieldStaticInst *Inst::CastToStoreResolvedObjectFieldStatic()       { ASSERT(GetOpcode() == Opcode::StoreResolvedObjectFieldStatic); return static_cast<      StoreResolvedObjectFieldStaticInst *>(this); } \
inline const StoreResolvedObjectFieldStaticInst *Inst::CastToStoreResolvedObjectFieldStatic() const { ASSERT(GetOpcode() == Opcode::StoreResolvedObjectFieldStatic); return static_cast<const StoreResolvedObjectFieldStaticInst *>(this); } \
inline       LengthMethodInst     *Inst::CastToLenArray            ()       { ASSERT(GetOpcode() == Opcode::LenArray            ); return static_cast<      LengthMethodInst *>(this); } \
inline const LengthMethodInst     *Inst::CastToLenArray            () const { ASSERT(GetOpcode() == Opcode::LenArray            ); return static_cast<const LengthMethodInst *>(this); } \
inline       LoadFromPool         *Inst::CastToLoadString          ()       { ASSERT(GetOpcode() == Opcode::LoadString          ); return static_cast<      LoadFromPool *>(this); } \
inline const LoadFromPool         *Inst::CastToLoadString          () const { ASSERT(GetOpcode() == Opcode::LoadString          ); return static_cast<const LoadFromPool *>(this); } \
inline       LoadFromPoolDynamic  *Inst::CastToLoadFromConstantPool()       { ASSERT(GetOpcode() == Opcode::LoadFromConstantPool); return static_cast<      LoadFromPoolDynamic *>(this); } \
inline const LoadFromPoolDynamic  *Inst::CastToLoadFromConstantPool() const { ASSERT(GetOpcode() == Opcode::LoadFromConstantPool); return static_cast<const LoadFromPoolDynamic *>(this); } \
inline       LoadConstArrayInst   *Inst::CastToLoadConstArray      ()       { ASSERT(GetOpcode() == Opcode::LoadConstArray      ); return static_cast<      LoadConstArrayInst *>(this); } \
inline const LoadConstArrayInst   *Inst::CastToLoadConstArray      () const { ASSERT(GetOpcode() == Opcode::LoadConstArray      ); return static_cast<const LoadConstArrayInst *>(this); } \
inline       FixedInputsInst<1>   *Inst::CastToLoadConstantPool    ()       { ASSERT(GetOpcode() == Opcode::LoadConstantPool    ); return static_cast<      FixedInputsInst<1> *>(this); } \
inline const FixedInputsInst<1>   *Inst::CastToLoadConstantPool    () const { ASSERT(GetOpcode() == Opcode::LoadConstantPool    ); return static_cast<const FixedInputsInst<1> *>(this); } \
inline       FixedInputsInst<1>   *Inst::CastToLoadLexicalEnv      ()       { ASSERT(GetOpcode() == Opcode::LoadLexicalEnv      ); return static_cast<      FixedInputsInst<1> *>(this); } \
inline const FixedInputsInst<1>   *Inst::CastToLoadLexicalEnv      () const { ASSERT(GetOpcode() == Opcode::LoadLexicalEnv      ); return static_cast<const FixedInputsInst<1> *>(this); } \
inline       FillConstArrayInst   *Inst::CastToFillConstArray      ()       { ASSERT(GetOpcode() == Opcode::FillConstArray      ); return static_cast<      FillConstArrayInst *>(this); } \
inline const FillConstArrayInst   *Inst::CastToFillConstArray      () const { ASSERT(GetOpcode() == Opcode::FillConstArray      ); return static_cast<const FillConstArrayInst *>(this); } \
inline       LoadFromPool         *Inst::CastToLoadType            ()       { ASSERT(GetOpcode() == Opcode::LoadType            ); return static_cast<      LoadFromPool *>(this); } \
inline const LoadFromPool         *Inst::CastToLoadType            () const { ASSERT(GetOpcode() == Opcode::LoadType            ); return static_cast<const LoadFromPool *>(this); } \
inline       LoadFromPool         *Inst::CastToUnresolvedLoadType  ()       { ASSERT(GetOpcode() == Opcode::UnresolvedLoadType  ); return static_cast<      LoadFromPool *>(this); } \
inline const LoadFromPool         *Inst::CastToUnresolvedLoadType  () const { ASSERT(GetOpcode() == Opcode::UnresolvedLoadType  ); return static_cast<const LoadFromPool *>(this); } \
inline       CheckCastInst        *Inst::CastToCheckCast           ()       { ASSERT(GetOpcode() == Opcode::CheckCast           ); return static_cast<      CheckCastInst *>(this); } \
inline const CheckCastInst        *Inst::CastToCheckCast           () const { ASSERT(GetOpcode() == Opcode::CheckCast           ); return static_cast<const CheckCastInst *>(this); } \
inline       IsInstanceInst       *Inst::CastToIsInstance          ()       { ASSERT(GetOpcode() == Opcode::IsInstance          ); return static_cast<      IsInstanceInst *>(this); } \
inline const IsInstanceInst       *Inst::CastToIsInstance          () const { ASSERT(GetOpcode() == Opcode::IsInstance          ); return static_cast<const IsInstanceInst *>(this); } \
inline       ClassInst            *Inst::CastToInitClass           ()       { ASSERT(GetOpcode() == Opcode::InitClass           ); return static_cast<      ClassInst *>(this); } \
inline const ClassInst            *Inst::CastToInitClass           () const { ASSERT(GetOpcode() == Opcode::InitClass           ); return static_cast<const ClassInst *>(this); } \
inline       ClassInst            *Inst::CastToLoadClass           ()       { ASSERT(GetOpcode() == Opcode::LoadClass           ); return static_cast<      ClassInst *>(this); } \
inline const ClassInst            *Inst::CastToLoadClass           () const { ASSERT(GetOpcode() == Opcode::LoadClass           ); return static_cast<const ClassInst *>(this); } \
inline       ClassInst            *Inst::CastToLoadAndInitClass    ()       { ASSERT(GetOpcode() == Opcode::LoadAndInitClass    ); return static_cast<      ClassInst *>(this); } \
inline const ClassInst            *Inst::CastToLoadAndInitClass    () const { ASSERT(GetOpcode() == Opcode::LoadAndInitClass    ); return static_cast<const ClassInst *>(this); } \
inline       ClassInst            *Inst::CastToUnresolvedLoadAndInitClass()       { ASSERT(GetOpcode() == Opcode::UnresolvedLoadAndInitClass); return static_cast<      ClassInst *>(this); } \
inline const ClassInst            *Inst::CastToUnresolvedLoadAndInitClass() const { ASSERT(GetOpcode() == Opcode::UnresolvedLoadAndInitClass); return static_cast<const ClassInst *>(this); } \
inline       RuntimeClassInst     *Inst::CastToLoadRuntimeClass    ()       { ASSERT(GetOpcode() == Opcode::LoadRuntimeClass    ); return static_cast<      RuntimeClassInst *>(this); } \
inline const RuntimeClassInst     *Inst::CastToLoadRuntimeClass    () const { ASSERT(GetOpcode() == Opcode::LoadRuntimeClass    ); return static_cast<const RuntimeClassInst *>(this); } \
inline       FixedInputsInst<1>   *Inst::CastToGetInstanceClass    ()       { ASSERT(GetOpcode() == Opcode::GetInstanceClass    ); return static_cast<      FixedInputsInst<1> *>(this); } \
inline const FixedInputsInst<1>   *Inst::CastToGetInstanceClass    () const { ASSERT(GetOpcode() == Opcode::GetInstanceClass    ); return static_cast<const FixedInputsInst<1> *>(this); } \
inline       LoadImmediateInst    *Inst::CastToLoadImmediate       ()       { ASSERT(GetOpcode() == Opcode::LoadImmediate       ); return static_cast<      LoadImmediateInst *>(this); } \
inline const LoadImmediateInst    *Inst::CastToLoadImmediate       () const { ASSERT(GetOpcode() == Opcode::LoadImmediate       ); return static_cast<const LoadImmediateInst *>(this); } \
inline       FunctionImmediateInst *Inst::CastToFunctionImmediate   ()       { ASSERT(GetOpcode() == Opcode::FunctionImmediate   ); return static_cast<      FunctionImmediateInst *>(this); } \
inline const FunctionImmediateInst *Inst::CastToFunctionImmediate   () const { ASSERT(GetOpcode() == Opcode::FunctionImmediate   ); return static_cast<const FunctionImmediateInst *>(this); } \
inline       LoadObjFromConstInst *Inst::CastToLoadObjFromConst    ()       { ASSERT(GetOpcode() == Opcode::LoadObjFromConst    ); return static_cast<      LoadObjFromConstInst *>(this); } \
inline const LoadObjFromConstInst *Inst::CastToLoadObjFromConst    () const { ASSERT(GetOpcode() == Opcode::LoadObjFromConst    ); return static_cast<const LoadObjFromConstInst *>(this); } \
inline       GlobalVarInst        *Inst::CastToGetGlobalVarAddress ()       { ASSERT(GetOpcode() == Opcode::GetGlobalVarAddress ); return static_cast<      GlobalVarInst *>(this); } \
inline const GlobalVarInst        *Inst::CastToGetGlobalVarAddress () const { ASSERT(GetOpcode() == Opcode::GetGlobalVarAddress ); return static_cast<const GlobalVarInst *>(this); } \
inline       NullCheckInst        *Inst::CastToNullCheck           ()       { ASSERT(GetOpcode() == Opcode::NullCheck           ); return static_cast<      NullCheckInst *>(this); } \
inline const NullCheckInst        *Inst::CastToNullCheck           () const { ASSERT(GetOpcode() == Opcode::NullCheck           ); return static_cast<const NullCheckInst *>(this); } \
inline       BoundsCheckInst      *Inst::CastToBoundsCheck         ()       { ASSERT(GetOpcode() == Opcode::BoundsCheck         ); return static_cast<      BoundsCheckInst *>(this); } \
inline const BoundsCheckInst      *Inst::CastToBoundsCheck         () const { ASSERT(GetOpcode() == Opcode::BoundsCheck         ); return static_cast<const BoundsCheckInst *>(this); } \
inline       FixedInputsInst<3>   *Inst::CastToRefTypeCheck        ()       { ASSERT(GetOpcode() == Opcode::RefTypeCheck        ); return static_cast<      FixedInputsInst<3> *>(this); } \
inline const FixedInputsInst<3>   *Inst::CastToRefTypeCheck        () const { ASSERT(GetOpcode() == Opcode::RefTypeCheck        ); return static_cast<const FixedInputsInst<3> *>(this); } \
inline       FixedInputsInst<2>   *Inst::CastToZeroCheck           ()       { ASSERT(GetOpcode() == Opcode::ZeroCheck           ); return static_cast<      FixedInputsInst<2> *>(this); } \
inline const FixedInputsInst<2>   *Inst::CastToZeroCheck           () const { ASSERT(GetOpcode() == Opcode::ZeroCheck           ); return static_cast<const FixedInputsInst<2> *>(this); } \
inline       FixedInputsInst<2>   *Inst::CastToNegativeCheck       ()       { ASSERT(GetOpcode() == Opcode::NegativeCheck       ); return static_cast<      FixedInputsInst<2> *>(this); } \
inline const FixedInputsInst<2>   *Inst::CastToNegativeCheck       () const { ASSERT(GetOpcode() == Opcode::NegativeCheck       ); return static_cast<const FixedInputsInst<2> *>(this); } \
inline       FixedInputsInst<2>   *Inst::CastToNotPositiveCheck    ()       { ASSERT(GetOpcode() == Opcode::NotPositiveCheck    ); return static_cast<      FixedInputsInst<2> *>(this); } \
inline const FixedInputsInst<2>   *Inst::CastToNotPositiveCheck    () const { ASSERT(GetOpcode() == Opcode::NotPositiveCheck    ); return static_cast<const FixedInputsInst<2> *>(this); } \
inline       FixedInputsInst<2>   *Inst::CastToObjByIndexCheck     ()       { ASSERT(GetOpcode() == Opcode::ObjByIndexCheck     ); return static_cast<      FixedInputsInst<2> *>(this); } \
inline const FixedInputsInst<2>   *Inst::CastToObjByIndexCheck     () const { ASSERT(GetOpcode() == Opcode::ObjByIndexCheck     ); return static_cast<const FixedInputsInst<2> *>(this); } \
inline       AnyTypeCheckInst     *Inst::CastToAnyTypeCheck        ()       { ASSERT(GetOpcode() == Opcode::AnyTypeCheck        ); return static_cast<      AnyTypeCheckInst *>(this); } \
inline const AnyTypeCheckInst     *Inst::CastToAnyTypeCheck        () const { ASSERT(GetOpcode() == Opcode::AnyTypeCheck        ); return static_cast<const AnyTypeCheckInst *>(this); } \
inline       HclassCheckInst      *Inst::CastToHclassCheck         ()       { ASSERT(GetOpcode() == Opcode::HclassCheck         ); return static_cast<      HclassCheckInst *>(this); } \
inline const HclassCheckInst      *Inst::CastToHclassCheck         () const { ASSERT(GetOpcode() == Opcode::HclassCheck         ); return static_cast<const HclassCheckInst *>(this); } \
inline       FixedInputsInst<2>   *Inst::CastToStringFlatCheck     ()       { ASSERT(GetOpcode() == Opcode::StringFlatCheck     ); return static_cast<      FixedInputsInst<2> *>(this); } \
inline const FixedInputsInst<2>   *Inst::CastToStringFlatCheck     () const { ASSERT(GetOpcode() == Opcode::StringFlatCheck     ); return static_cast<const FixedInputsInst<2> *>(this); } \
inline       DeoptimizeInst       *Inst::CastToDeoptimize          ()       { ASSERT(GetOpcode() == Opcode::Deoptimize          ); return static_cast<      DeoptimizeInst *>(this); } \
inline const DeoptimizeInst       *Inst::CastToDeoptimize          () const { ASSERT(GetOpcode() == Opcode::Deoptimize          ); return static_cast<const DeoptimizeInst *>(this); } \
inline       DeoptimizeIfInst     *Inst::CastToDeoptimizeIf        ()       { ASSERT(GetOpcode() == Opcode::DeoptimizeIf        ); return static_cast<      DeoptimizeIfInst *>(this); } \
inline const DeoptimizeIfInst     *Inst::CastToDeoptimizeIf        () const { ASSERT(GetOpcode() == Opcode::DeoptimizeIf        ); return static_cast<const DeoptimizeIfInst *>(this); } \
inline       DeoptimizeCompareInst *Inst::CastToDeoptimizeCompare   ()       { ASSERT(GetOpcode() == Opcode::DeoptimizeCompare   ); return static_cast<      DeoptimizeCompareInst *>(this); } \
inline const DeoptimizeCompareInst *Inst::CastToDeoptimizeCompare   () const { ASSERT(GetOpcode() == Opcode::DeoptimizeCompare   ); return static_cast<const DeoptimizeCompareInst *>(this); } \
inline       DeoptimizeCompareImmInst *Inst::CastToDeoptimizeCompareImm()       { ASSERT(GetOpcode() == Opcode::DeoptimizeCompareImm); return static_cast<      DeoptimizeCompareImmInst *>(this); } \
inline const DeoptimizeCompareImmInst *Inst::CastToDeoptimizeCompareImm() const { ASSERT(GetOpcode() == Opcode::DeoptimizeCompareImm); return static_cast<const DeoptimizeCompareImmInst *>(this); } \
inline       Inst                 *Inst::CastToIsMustDeoptimize    ()       { ASSERT(GetOpcode() == Opcode::IsMustDeoptimize    ); return static_cast<      Inst *>(this); } \
inline const Inst                 *Inst::CastToIsMustDeoptimize    () const { ASSERT(GetOpcode() == Opcode::IsMustDeoptimize    ); return static_cast<const Inst *>(this); } \
inline       FixedInputsInst<0>   *Inst::CastToReturnVoid          ()       { ASSERT(GetOpcode() == Opcode::ReturnVoid          ); return static_cast<      FixedInputsInst<0> *>(this); } \
inline const FixedInputsInst<0>   *Inst::CastToReturnVoid          () const { ASSERT(GetOpcode() == Opcode::ReturnVoid          ); return static_cast<const FixedInputsInst<0> *>(this); } \
inline       FixedInputsInst<1>   *Inst::CastToReturn              ()       { ASSERT(GetOpcode() == Opcode::Return              ); return static_cast<      FixedInputsInst<1> *>(this); } \
inline const FixedInputsInst<1>   *Inst::CastToReturn              () const { ASSERT(GetOpcode() == Opcode::Return              ); return static_cast<const FixedInputsInst<1> *>(this); } \
inline       ReturnInlinedInst    *Inst::CastToReturnInlined       ()       { ASSERT(GetOpcode() == Opcode::ReturnInlined       ); return static_cast<      ReturnInlinedInst *>(this); } \
inline const ReturnInlinedInst    *Inst::CastToReturnInlined       () const { ASSERT(GetOpcode() == Opcode::ReturnInlined       ); return static_cast<const ReturnInlinedInst *>(this); } \
inline       ThrowInst            *Inst::CastToThrow               ()       { ASSERT(GetOpcode() == Opcode::Throw               ); return static_cast<      ThrowInst *>(this); } \
inline const ThrowInst            *Inst::CastToThrow               () const { ASSERT(GetOpcode() == Opcode::Throw               ); return static_cast<const ThrowInst *>(this); } \
inline       CallInst             *Inst::CastToCallStatic          ()       { ASSERT(GetOpcode() == Opcode::CallStatic          ); return static_cast<      CallInst *>(this); } \
inline const CallInst             *Inst::CastToCallStatic          () const { ASSERT(GetOpcode() == Opcode::CallStatic          ); return static_cast<const CallInst *>(this); } \
inline       ResolveStaticInst    *Inst::CastToResolveStatic       ()       { ASSERT(GetOpcode() == Opcode::ResolveStatic       ); return static_cast<      ResolveStaticInst *>(this); } \
inline const ResolveStaticInst    *Inst::CastToResolveStatic       () const { ASSERT(GetOpcode() == Opcode::ResolveStatic       ); return static_cast<const ResolveStaticInst *>(this); } \
inline       CallInst             *Inst::CastToCallResolvedStatic  ()       { ASSERT(GetOpcode() == Opcode::CallResolvedStatic  ); return static_cast<      CallInst *>(this); } \
inline const CallInst             *Inst::CastToCallResolvedStatic  () const { ASSERT(GetOpcode() == Opcode::CallResolvedStatic  ); return static_cast<const CallInst *>(this); } \
inline       CallInst             *Inst::CastToCallVirtual         ()       { ASSERT(GetOpcode() == Opcode::CallVirtual         ); return static_cast<      CallInst *>(this); } \
inline const CallInst             *Inst::CastToCallVirtual         () const { ASSERT(GetOpcode() == Opcode::CallVirtual         ); return static_cast<const CallInst *>(this); } \
inline       ResolveVirtualInst   *Inst::CastToResolveVirtual      ()       { ASSERT(GetOpcode() == Opcode::ResolveVirtual      ); return static_cast<      ResolveVirtualInst *>(this); } \
inline const ResolveVirtualInst   *Inst::CastToResolveVirtual      () const { ASSERT(GetOpcode() == Opcode::ResolveVirtual      ); return static_cast<const ResolveVirtualInst *>(this); } \
inline       CallInst             *Inst::CastToCallResolvedVirtual ()       { ASSERT(GetOpcode() == Opcode::CallResolvedVirtual ); return static_cast<      CallInst *>(this); } \
inline const CallInst             *Inst::CastToCallResolvedVirtual () const { ASSERT(GetOpcode() == Opcode::CallResolvedVirtual ); return static_cast<const CallInst *>(this); } \
inline       CallInst             *Inst::CastToCallDynamic         ()       { ASSERT(GetOpcode() == Opcode::CallDynamic         ); return static_cast<      CallInst *>(this); } \
inline const CallInst             *Inst::CastToCallDynamic         () const { ASSERT(GetOpcode() == Opcode::CallDynamic         ); return static_cast<const CallInst *>(this); } \
inline       CallIndirectInst     *Inst::CastToCallIndirect        ()       { ASSERT(GetOpcode() == Opcode::CallIndirect        ); return static_cast<      CallIndirectInst *>(this); } \
inline const CallIndirectInst     *Inst::CastToCallIndirect        () const { ASSERT(GetOpcode() == Opcode::CallIndirect        ); return static_cast<const CallIndirectInst *>(this); } \
inline       CallInst             *Inst::CastToCall                ()       { ASSERT(GetOpcode() == Opcode::Call                ); return static_cast<      CallInst *>(this); } \
inline const CallInst             *Inst::CastToCall                () const { ASSERT(GetOpcode() == Opcode::Call                ); return static_cast<const CallInst *>(this); } \
inline       CallInst             *Inst::CastToMultiArray          ()       { ASSERT(GetOpcode() == Opcode::MultiArray          ); return static_cast<      CallInst *>(this); } \
inline const CallInst             *Inst::CastToMultiArray          () const { ASSERT(GetOpcode() == Opcode::MultiArray          ); return static_cast<const CallInst *>(this); } \
inline       MonitorInst          *Inst::CastToMonitor             ()       { ASSERT(GetOpcode() == Opcode::Monitor             ); return static_cast<      MonitorInst *>(this); } \
inline const MonitorInst          *Inst::CastToMonitor             () const { ASSERT(GetOpcode() == Opcode::Monitor             ); return static_cast<const MonitorInst *>(this); } \
inline       IntrinsicInst        *Inst::CastToIntrinsic           ()       { ASSERT(GetOpcode() == Opcode::Intrinsic           ); return static_cast<      IntrinsicInst *>(this); } \
inline const IntrinsicInst        *Inst::CastToIntrinsic           () const { ASSERT(GetOpcode() == Opcode::Intrinsic           ); return static_cast<const IntrinsicInst *>(this); } \
inline       CallInst             *Inst::CastToCallNative          ()       { ASSERT(GetOpcode() == Opcode::CallNative          ); return static_cast<      CallInst *>(this); } \
inline const CallInst             *Inst::CastToCallNative          () const { ASSERT(GetOpcode() == Opcode::CallNative          ); return static_cast<const CallInst *>(this); } \
inline       WrapObjectNativeInst *Inst::CastToWrapObjectNative    ()       { ASSERT(GetOpcode() == Opcode::WrapObjectNative    ); return static_cast<      WrapObjectNativeInst *>(this); } \
inline const WrapObjectNativeInst *Inst::CastToWrapObjectNative    () const { ASSERT(GetOpcode() == Opcode::WrapObjectNative    ); return static_cast<const WrapObjectNativeInst *>(this); } \
inline       IntrinsicInst        *Inst::CastToBuiltin             ()       { ASSERT(GetOpcode() == Opcode::Builtin             ); return static_cast<      IntrinsicInst *>(this); } \
inline const IntrinsicInst        *Inst::CastToBuiltin             () const { ASSERT(GetOpcode() == Opcode::Builtin             ); return static_cast<const IntrinsicInst *>(this); } \
inline       ResolveVirtualInst   *Inst::CastToResolveByName       ()       { ASSERT(GetOpcode() == Opcode::ResolveByName       ); return static_cast<      ResolveVirtualInst *>(this); } \
inline const ResolveVirtualInst   *Inst::CastToResolveByName       () const { ASSERT(GetOpcode() == Opcode::ResolveByName       ); return static_cast<const ResolveVirtualInst *>(this); } \
inline       BinaryImmOperation   *Inst::CastToAddI                ()       { ASSERT(GetOpcode() == Opcode::AddI                ); return static_cast<      BinaryImmOperation *>(this); } \
inline const BinaryImmOperation   *Inst::CastToAddI                () const { ASSERT(GetOpcode() == Opcode::AddI                ); return static_cast<const BinaryImmOperation *>(this); } \
inline       BinaryImmOperation   *Inst::CastToSubI                ()       { ASSERT(GetOpcode() == Opcode::SubI                ); return static_cast<      BinaryImmOperation *>(this); } \
inline const BinaryImmOperation   *Inst::CastToSubI                () const { ASSERT(GetOpcode() == Opcode::SubI                ); return static_cast<const BinaryImmOperation *>(this); } \
inline       BinaryImmOperation   *Inst::CastToMulI                ()       { ASSERT(GetOpcode() == Opcode::MulI                ); return static_cast<      BinaryImmOperation *>(this); } \
inline const BinaryImmOperation   *Inst::CastToMulI                () const { ASSERT(GetOpcode() == Opcode::MulI                ); return static_cast<const BinaryImmOperation *>(this); } \
inline       BinaryImmOperation   *Inst::CastToDivI                ()       { ASSERT(GetOpcode() == Opcode::DivI                ); return static_cast<      BinaryImmOperation *>(this); } \
inline const BinaryImmOperation   *Inst::CastToDivI                () const { ASSERT(GetOpcode() == Opcode::DivI                ); return static_cast<const BinaryImmOperation *>(this); } \
inline       BinaryImmOperation   *Inst::CastToModI                ()       { ASSERT(GetOpcode() == Opcode::ModI                ); return static_cast<      BinaryImmOperation *>(this); } \
inline const BinaryImmOperation   *Inst::CastToModI                () const { ASSERT(GetOpcode() == Opcode::ModI                ); return static_cast<const BinaryImmOperation *>(this); } \
inline       BinaryImmOperation   *Inst::CastToShlI                ()       { ASSERT(GetOpcode() == Opcode::ShlI                ); return static_cast<      BinaryImmOperation *>(this); } \
inline const BinaryImmOperation   *Inst::CastToShlI                () const { ASSERT(GetOpcode() == Opcode::ShlI                ); return static_cast<const BinaryImmOperation *>(this); } \
inline       BinaryImmOperation   *Inst::CastToShrI                ()       { ASSERT(GetOpcode() == Opcode::ShrI                ); return static_cast<      BinaryImmOperation *>(this); } \
inline const BinaryImmOperation   *Inst::CastToShrI                () const { ASSERT(GetOpcode() == Opcode::ShrI                ); return static_cast<const BinaryImmOperation *>(this); } \
inline       BinaryImmOperation   *Inst::CastToAShrI               ()       { ASSERT(GetOpcode() == Opcode::AShrI               ); return static_cast<      BinaryImmOperation *>(this); } \
inline const BinaryImmOperation   *Inst::CastToAShrI               () const { ASSERT(GetOpcode() == Opcode::AShrI               ); return static_cast<const BinaryImmOperation *>(this); } \
inline       BinaryImmOperation   *Inst::CastToAndI                ()       { ASSERT(GetOpcode() == Opcode::AndI                ); return static_cast<      BinaryImmOperation *>(this); } \
inline const BinaryImmOperation   *Inst::CastToAndI                () const { ASSERT(GetOpcode() == Opcode::AndI                ); return static_cast<const BinaryImmOperation *>(this); } \
inline       BinaryImmOperation   *Inst::CastToOrI                 ()       { ASSERT(GetOpcode() == Opcode::OrI                 ); return static_cast<      BinaryImmOperation *>(this); } \
inline const BinaryImmOperation   *Inst::CastToOrI                 () const { ASSERT(GetOpcode() == Opcode::OrI                 ); return static_cast<const BinaryImmOperation *>(this); } \
inline       BinaryImmOperation   *Inst::CastToXorI                ()       { ASSERT(GetOpcode() == Opcode::XorI                ); return static_cast<      BinaryImmOperation *>(this); } \
inline const BinaryImmOperation   *Inst::CastToXorI                () const { ASSERT(GetOpcode() == Opcode::XorI                ); return static_cast<const BinaryImmOperation *>(this); } \
inline       FixedInputsInst<3>   *Inst::CastToMAdd                ()       { ASSERT(GetOpcode() == Opcode::MAdd                ); return static_cast<      FixedInputsInst<3> *>(this); } \
inline const FixedInputsInst<3>   *Inst::CastToMAdd                () const { ASSERT(GetOpcode() == Opcode::MAdd                ); return static_cast<const FixedInputsInst<3> *>(this); } \
inline       FixedInputsInst<3>   *Inst::CastToMSub                ()       { ASSERT(GetOpcode() == Opcode::MSub                ); return static_cast<      FixedInputsInst<3> *>(this); } \
inline const FixedInputsInst<3>   *Inst::CastToMSub                () const { ASSERT(GetOpcode() == Opcode::MSub                ); return static_cast<const FixedInputsInst<3> *>(this); } \
inline       BinaryOperation      *Inst::CastToMNeg                ()       { ASSERT(GetOpcode() == Opcode::MNeg                ); return static_cast<      BinaryOperation *>(this); } \
inline const BinaryOperation      *Inst::CastToMNeg                () const { ASSERT(GetOpcode() == Opcode::MNeg                ); return static_cast<const BinaryOperation *>(this); } \
inline       BinaryOperation      *Inst::CastToOrNot               ()       { ASSERT(GetOpcode() == Opcode::OrNot               ); return static_cast<      BinaryOperation *>(this); } \
inline const BinaryOperation      *Inst::CastToOrNot               () const { ASSERT(GetOpcode() == Opcode::OrNot               ); return static_cast<const BinaryOperation *>(this); } \
inline       BinaryOperation      *Inst::CastToAndNot              ()       { ASSERT(GetOpcode() == Opcode::AndNot              ); return static_cast<      BinaryOperation *>(this); } \
inline const BinaryOperation      *Inst::CastToAndNot              () const { ASSERT(GetOpcode() == Opcode::AndNot              ); return static_cast<const BinaryOperation *>(this); } \
inline       BinaryOperation      *Inst::CastToXorNot              ()       { ASSERT(GetOpcode() == Opcode::XorNot              ); return static_cast<      BinaryOperation *>(this); } \
inline const BinaryOperation      *Inst::CastToXorNot              () const { ASSERT(GetOpcode() == Opcode::XorNot              ); return static_cast<const BinaryOperation *>(this); } \
inline       BinaryShiftedRegisterOperation *Inst::CastToAndSR               ()       { ASSERT(GetOpcode() == Opcode::AndSR               ); return static_cast<      BinaryShiftedRegisterOperation *>(this); } \
inline const BinaryShiftedRegisterOperation *Inst::CastToAndSR               () const { ASSERT(GetOpcode() == Opcode::AndSR               ); return static_cast<const BinaryShiftedRegisterOperation *>(this); } \
inline       BinaryShiftedRegisterOperation *Inst::CastToOrSR                ()       { ASSERT(GetOpcode() == Opcode::OrSR                ); return static_cast<      BinaryShiftedRegisterOperation *>(this); } \
inline const BinaryShiftedRegisterOperation *Inst::CastToOrSR                () const { ASSERT(GetOpcode() == Opcode::OrSR                ); return static_cast<const BinaryShiftedRegisterOperation *>(this); } \
inline       BinaryShiftedRegisterOperation *Inst::CastToXorSR               ()       { ASSERT(GetOpcode() == Opcode::XorSR               ); return static_cast<      BinaryShiftedRegisterOperation *>(this); } \
inline const BinaryShiftedRegisterOperation *Inst::CastToXorSR               () const { ASSERT(GetOpcode() == Opcode::XorSR               ); return static_cast<const BinaryShiftedRegisterOperation *>(this); } \
inline       BinaryShiftedRegisterOperation *Inst::CastToAndNotSR            ()       { ASSERT(GetOpcode() == Opcode::AndNotSR            ); return static_cast<      BinaryShiftedRegisterOperation *>(this); } \
inline const BinaryShiftedRegisterOperation *Inst::CastToAndNotSR            () const { ASSERT(GetOpcode() == Opcode::AndNotSR            ); return static_cast<const BinaryShiftedRegisterOperation *>(this); } \
inline       BinaryShiftedRegisterOperation *Inst::CastToOrNotSR             ()       { ASSERT(GetOpcode() == Opcode::OrNotSR             ); return static_cast<      BinaryShiftedRegisterOperation *>(this); } \
inline const BinaryShiftedRegisterOperation *Inst::CastToOrNotSR             () const { ASSERT(GetOpcode() == Opcode::OrNotSR             ); return static_cast<const BinaryShiftedRegisterOperation *>(this); } \
inline       BinaryShiftedRegisterOperation *Inst::CastToXorNotSR            ()       { ASSERT(GetOpcode() == Opcode::XorNotSR            ); return static_cast<      BinaryShiftedRegisterOperation *>(this); } \
inline const BinaryShiftedRegisterOperation *Inst::CastToXorNotSR            () const { ASSERT(GetOpcode() == Opcode::XorNotSR            ); return static_cast<const BinaryShiftedRegisterOperation *>(this); } \
inline       BinaryShiftedRegisterOperation *Inst::CastToAddSR               ()       { ASSERT(GetOpcode() == Opcode::AddSR               ); return static_cast<      BinaryShiftedRegisterOperation *>(this); } \
inline const BinaryShiftedRegisterOperation *Inst::CastToAddSR               () const { ASSERT(GetOpcode() == Opcode::AddSR               ); return static_cast<const BinaryShiftedRegisterOperation *>(this); } \
inline       BinaryShiftedRegisterOperation *Inst::CastToSubSR               ()       { ASSERT(GetOpcode() == Opcode::SubSR               ); return static_cast<      BinaryShiftedRegisterOperation *>(this); } \
inline const BinaryShiftedRegisterOperation *Inst::CastToSubSR               () const { ASSERT(GetOpcode() == Opcode::SubSR               ); return static_cast<const BinaryShiftedRegisterOperation *>(this); } \
inline       UnaryShiftedRegisterOperation *Inst::CastToNegSR               ()       { ASSERT(GetOpcode() == Opcode::NegSR               ); return static_cast<      UnaryShiftedRegisterOperation *>(this); } \
inline const UnaryShiftedRegisterOperation *Inst::CastToNegSR               () const { ASSERT(GetOpcode() == Opcode::NegSR               ); return static_cast<const UnaryShiftedRegisterOperation *>(this); } \
inline       BoundsCheckInstI     *Inst::CastToBoundsCheckI        ()       { ASSERT(GetOpcode() == Opcode::BoundsCheckI        ); return static_cast<      BoundsCheckInstI *>(this); } \
inline const BoundsCheckInstI     *Inst::CastToBoundsCheckI        () const { ASSERT(GetOpcode() == Opcode::BoundsCheckI        ); return static_cast<const BoundsCheckInstI *>(this); } \
inline       LoadInstI            *Inst::CastToLoadArrayI          ()       { ASSERT(GetOpcode() == Opcode::LoadArrayI          ); return static_cast<      LoadInstI *>(this); } \
inline const LoadInstI            *Inst::CastToLoadArrayI          () const { ASSERT(GetOpcode() == Opcode::LoadArrayI          ); return static_cast<const LoadInstI *>(this); } \
inline       LoadCompressedStringCharInstI *Inst::CastToLoadCompressedStringCharI()       { ASSERT(GetOpcode() == Opcode::LoadCompressedStringCharI); return static_cast<      LoadCompressedStringCharInstI *>(this); } \
inline const LoadCompressedStringCharInstI *Inst::CastToLoadCompressedStringCharI() const { ASSERT(GetOpcode() == Opcode::LoadCompressedStringCharI); return static_cast<const LoadCompressedStringCharInstI *>(this); } \
inline       StoreInstI           *Inst::CastToStoreArrayI         ()       { ASSERT(GetOpcode() == Opcode::StoreArrayI         ); return static_cast<      StoreInstI *>(this); } \
inline const StoreInstI           *Inst::CastToStoreArrayI         () const { ASSERT(GetOpcode() == Opcode::StoreArrayI         ); return static_cast<const StoreInstI *>(this); } \
inline       LoadArrayPairInst    *Inst::CastToLoadArrayPair       ()       { ASSERT(GetOpcode() == Opcode::LoadArrayPair       ); return static_cast<      LoadArrayPairInst *>(this); } \
inline const LoadArrayPairInst    *Inst::CastToLoadArrayPair       () const { ASSERT(GetOpcode() == Opcode::LoadArrayPair       ); return static_cast<const LoadArrayPairInst *>(this); } \
inline       LoadArrayPairInstI   *Inst::CastToLoadArrayPairI      ()       { ASSERT(GetOpcode() == Opcode::LoadArrayPairI      ); return static_cast<      LoadArrayPairInstI *>(this); } \
inline const LoadArrayPairInstI   *Inst::CastToLoadArrayPairI      () const { ASSERT(GetOpcode() == Opcode::LoadArrayPairI      ); return static_cast<const LoadArrayPairInstI *>(this); } \
inline       LoadPairPartInst     *Inst::CastToLoadPairPart        ()       { ASSERT(GetOpcode() == Opcode::LoadPairPart        ); return static_cast<      LoadPairPartInst *>(this); } \
inline const LoadPairPartInst     *Inst::CastToLoadPairPart        () const { ASSERT(GetOpcode() == Opcode::LoadPairPart        ); return static_cast<const LoadPairPartInst *>(this); } \
inline       LoadObjectPairInst   *Inst::CastToLoadObjectPair      ()       { ASSERT(GetOpcode() == Opcode::LoadObjectPair      ); return static_cast<      LoadObjectPairInst *>(this); } \
inline const LoadObjectPairInst   *Inst::CastToLoadObjectPair      () const { ASSERT(GetOpcode() == Opcode::LoadObjectPair      ); return static_cast<const LoadObjectPairInst *>(this); } \
inline       StoreArrayPairInst   *Inst::CastToStoreArrayPair      ()       { ASSERT(GetOpcode() == Opcode::StoreArrayPair      ); return static_cast<      StoreArrayPairInst *>(this); } \
inline const StoreArrayPairInst   *Inst::CastToStoreArrayPair      () const { ASSERT(GetOpcode() == Opcode::StoreArrayPair      ); return static_cast<const StoreArrayPairInst *>(this); } \
inline       StoreArrayPairInstI  *Inst::CastToStoreArrayPairI     ()       { ASSERT(GetOpcode() == Opcode::StoreArrayPairI     ); return static_cast<      StoreArrayPairInstI *>(this); } \
inline const StoreArrayPairInstI  *Inst::CastToStoreArrayPairI     () const { ASSERT(GetOpcode() == Opcode::StoreArrayPairI     ); return static_cast<const StoreArrayPairInstI *>(this); } \
inline       StoreObjectPairInst  *Inst::CastToStoreObjectPair     ()       { ASSERT(GetOpcode() == Opcode::StoreObjectPair     ); return static_cast<      StoreObjectPairInst *>(this); } \
inline const StoreObjectPairInst  *Inst::CastToStoreObjectPair     () const { ASSERT(GetOpcode() == Opcode::StoreObjectPair     ); return static_cast<const StoreObjectPairInst *>(this); } \
inline       ReturnInstI          *Inst::CastToReturnI             ()       { ASSERT(GetOpcode() == Opcode::ReturnI             ); return static_cast<      ReturnInstI *>(this); } \
inline const ReturnInstI          *Inst::CastToReturnI             () const { ASSERT(GetOpcode() == Opcode::ReturnI             ); return static_cast<const ReturnInstI *>(this); } \
inline       PhiInst              *Inst::CastToPhi                 ()       { ASSERT(GetOpcode() == Opcode::Phi                 ); return static_cast<      PhiInst *>(this); } \
inline const PhiInst              *Inst::CastToPhi                 () const { ASSERT(GetOpcode() == Opcode::Phi                 ); return static_cast<const PhiInst *>(this); } \
inline       SpillFillInst        *Inst::CastToSpillFill           ()       { ASSERT(GetOpcode() == Opcode::SpillFill           ); return static_cast<      SpillFillInst *>(this); } \
inline const SpillFillInst        *Inst::CastToSpillFill           () const { ASSERT(GetOpcode() == Opcode::SpillFill           ); return static_cast<const SpillFillInst *>(this); } \
inline       SaveStateInst        *Inst::CastToSaveState           ()       { ASSERT(GetOpcode() == Opcode::SaveState           ); return static_cast<      SaveStateInst *>(this); } \
inline const SaveStateInst        *Inst::CastToSaveState           () const { ASSERT(GetOpcode() == Opcode::SaveState           ); return static_cast<const SaveStateInst *>(this); } \
inline       SaveStateInst        *Inst::CastToSafePoint           ()       { ASSERT(GetOpcode() == Opcode::SafePoint           ); return static_cast<      SaveStateInst *>(this); } \
inline const SaveStateInst        *Inst::CastToSafePoint           () const { ASSERT(GetOpcode() == Opcode::SafePoint           ); return static_cast<const SaveStateInst *>(this); } \
inline       SaveStateInst        *Inst::CastToSaveStateDeoptimize ()       { ASSERT(GetOpcode() == Opcode::SaveStateDeoptimize ); return static_cast<      SaveStateInst *>(this); } \
inline const SaveStateInst        *Inst::CastToSaveStateDeoptimize () const { ASSERT(GetOpcode() == Opcode::SaveStateDeoptimize ); return static_cast<const SaveStateInst *>(this); } \
inline       SaveStateInst        *Inst::CastToSaveStateOsr        ()       { ASSERT(GetOpcode() == Opcode::SaveStateOsr        ); return static_cast<      SaveStateInst *>(this); } \
inline const SaveStateInst        *Inst::CastToSaveStateOsr        () const { ASSERT(GetOpcode() == Opcode::SaveStateOsr        ); return static_cast<const SaveStateInst *>(this); } \
inline       SaveStateInst        *Inst::CastToSaveStateSuspend    ()       { ASSERT(GetOpcode() == Opcode::SaveStateSuspend    ); return static_cast<      SaveStateInst *>(this); } \
inline const SaveStateInst        *Inst::CastToSaveStateSuspend    () const { ASSERT(GetOpcode() == Opcode::SaveStateSuspend    ); return static_cast<const SaveStateInst *>(this); } \
inline       SelectInst           *Inst::CastToSelect              ()       { ASSERT(GetOpcode() == Opcode::Select              ); return static_cast<      SelectInst *>(this); } \
inline const SelectInst           *Inst::CastToSelect              () const { ASSERT(GetOpcode() == Opcode::Select              ); return static_cast<const SelectInst *>(this); } \
inline       SelectTransformInst  *Inst::CastToSelectTransform     ()       { ASSERT(GetOpcode() == Opcode::SelectTransform     ); return static_cast<      SelectTransformInst *>(this); } \
inline const SelectTransformInst  *Inst::CastToSelectTransform     () const { ASSERT(GetOpcode() == Opcode::SelectTransform     ); return static_cast<const SelectTransformInst *>(this); } \
inline       SelectImmInst        *Inst::CastToSelectImm           ()       { ASSERT(GetOpcode() == Opcode::SelectImm           ); return static_cast<      SelectImmInst *>(this); } \
inline const SelectImmInst        *Inst::CastToSelectImm           () const { ASSERT(GetOpcode() == Opcode::SelectImm           ); return static_cast<const SelectImmInst *>(this); } \
inline       SelectImmTransformInst *Inst::CastToSelectImmTransform  ()       { ASSERT(GetOpcode() == Opcode::SelectImmTransform  ); return static_cast<      SelectImmTransformInst *>(this); } \
inline const SelectImmTransformInst *Inst::CastToSelectImmTransform  () const { ASSERT(GetOpcode() == Opcode::SelectImmTransform  ); return static_cast<const SelectImmTransformInst *>(this); } \
inline       BinaryOverflowInst   *Inst::CastToAddOverflow         ()       { ASSERT(GetOpcode() == Opcode::AddOverflow         ); return static_cast<      BinaryOverflowInst *>(this); } \
inline const BinaryOverflowInst   *Inst::CastToAddOverflow         () const { ASSERT(GetOpcode() == Opcode::AddOverflow         ); return static_cast<const BinaryOverflowInst *>(this); } \
inline       BinaryOverflowInst   *Inst::CastToSubOverflow         ()       { ASSERT(GetOpcode() == Opcode::SubOverflow         ); return static_cast<      BinaryOverflowInst *>(this); } \
inline const BinaryOverflowInst   *Inst::CastToSubOverflow         () const { ASSERT(GetOpcode() == Opcode::SubOverflow         ); return static_cast<const BinaryOverflowInst *>(this); } \
inline       FixedInputsInst<3>   *Inst::CastToAddOverflowCheck    ()       { ASSERT(GetOpcode() == Opcode::AddOverflowCheck    ); return static_cast<      FixedInputsInst<3> *>(this); } \
inline const FixedInputsInst<3>   *Inst::CastToAddOverflowCheck    () const { ASSERT(GetOpcode() == Opcode::AddOverflowCheck    ); return static_cast<const FixedInputsInst<3> *>(this); } \
inline       FixedInputsInst<3>   *Inst::CastToSubOverflowCheck    ()       { ASSERT(GetOpcode() == Opcode::SubOverflowCheck    ); return static_cast<      FixedInputsInst<3> *>(this); } \
inline const FixedInputsInst<3>   *Inst::CastToSubOverflowCheck    () const { ASSERT(GetOpcode() == Opcode::SubOverflowCheck    ); return static_cast<const FixedInputsInst<3> *>(this); } \
inline       FixedInputsInst<2>   *Inst::CastToNegOverflowAndZeroCheck()       { ASSERT(GetOpcode() == Opcode::NegOverflowAndZeroCheck); return static_cast<      FixedInputsInst<2> *>(this); } \
inline const FixedInputsInst<2>   *Inst::CastToNegOverflowAndZeroCheck() const { ASSERT(GetOpcode() == Opcode::NegOverflowAndZeroCheck); return static_cast<const FixedInputsInst<2> *>(this); } \
inline       IfInst               *Inst::CastToIf                  ()       { ASSERT(GetOpcode() == Opcode::If                  ); return static_cast<      IfInst *>(this); } \
inline const IfInst               *Inst::CastToIf                  () const { ASSERT(GetOpcode() == Opcode::If                  ); return static_cast<const IfInst *>(this); } \
inline       IfImmInst            *Inst::CastToIfImm               ()       { ASSERT(GetOpcode() == Opcode::IfImm               ); return static_cast<      IfImmInst *>(this); } \
inline const IfImmInst            *Inst::CastToIfImm               () const { ASSERT(GetOpcode() == Opcode::IfImm               ); return static_cast<const IfImmInst *>(this); } \
inline       FixedInputsInst<0>   *Inst::CastToNOP                 ()       { ASSERT(GetOpcode() == Opcode::NOP                 ); return static_cast<      FixedInputsInst<0> *>(this); } \
inline const FixedInputsInst<0>   *Inst::CastToNOP                 () const { ASSERT(GetOpcode() == Opcode::NOP                 ); return static_cast<const FixedInputsInst<0> *>(this); } \
inline       TryInst              *Inst::CastToTry                 ()       { ASSERT(GetOpcode() == Opcode::Try                 ); return static_cast<      TryInst *>(this); } \
inline const TryInst              *Inst::CastToTry                 () const { ASSERT(GetOpcode() == Opcode::Try                 ); return static_cast<const TryInst *>(this); } \
inline       CatchPhiInst         *Inst::CastToCatchPhi            ()       { ASSERT(GetOpcode() == Opcode::CatchPhi            ); return static_cast<      CatchPhiInst *>(this); } \
inline const CatchPhiInst         *Inst::CastToCatchPhi            () const { ASSERT(GetOpcode() == Opcode::CatchPhi            ); return static_cast<const CatchPhiInst *>(this); } \
inline       Inst                 *Inst::CastToLiveIn              ()       { ASSERT(GetOpcode() == Opcode::LiveIn              ); return static_cast<      Inst *>(this); } \
inline const Inst                 *Inst::CastToLiveIn              () const { ASSERT(GetOpcode() == Opcode::LiveIn              ); return static_cast<const Inst *>(this); } \
inline       FixedInputsInst<1>   *Inst::CastToLiveOut             ()       { ASSERT(GetOpcode() == Opcode::LiveOut             ); return static_cast<      FixedInputsInst<1> *>(this); } \
inline const FixedInputsInst<1>   *Inst::CastToLiveOut             () const { ASSERT(GetOpcode() == Opcode::LiveOut             ); return static_cast<const FixedInputsInst<1> *>(this); } \


#ifndef NDEBUG
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define INST_MODES_LIST \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    IRTOC, \
    JIT_AOT, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT, \
    JIT_AOT, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT, \
    JIT_AOT|BYTECODE_OPT, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT, \
    JIT_AOT, \
    JIT_AOT, \
    JIT_AOT, \
    JIT_AOT, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT, \
    JIT_AOT|BYTECODE_OPT, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|BYTECODE_OPT, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT, \
    JIT_AOT, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    BYTECODE_OPT, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT, \
    JIT_AOT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT, \
    JIT_AOT, \
    JIT_AOT, \
    JIT_AOT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT|IRTOC, \
    JIT_AOT, \
    JIT_AOT, \
    JIT_AOT, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT|IRTOC, \
    JIT_AOT|BYTECODE_OPT, \
    JIT_AOT|BYTECODE_OPT, \
    IRTOC, \
    IRTOC, \

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define MODES_LIST(DEF) \
    DEF(JIT_AOT) \
    DEF(BYTECODE_OPT) \
    DEF(IRTOC) \

#endif
