/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtQml module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef QV4INSTR_MOTH_P_H #define QV4INSTR_MOTH_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an // implementation detail. This header file may change from version to // version without notice, or even be removed. // // We mean it. // #include #include #include #include // for CompiledData::CodeOffsetToLine used by the dumper #include QT_BEGIN_NAMESPACE #define INSTRUCTION(op, name, nargs, ...) \ op##_INSTRUCTION(name, nargs, __VA_ARGS__) /* for all jump instructions, the offset has to come last, to simplify the job of the bytecode generator */ #define INSTR_Nop(op) INSTRUCTION(op, Nop, 0) #define INSTR_Ret(op) INSTRUCTION(op, Ret, 0) #define INSTR_Debug(op) INSTRUCTION(op, Debug, 0) #define INSTR_LoadConst(op) INSTRUCTION(op, LoadConst, 1, index) #define INSTR_LoadZero(op) INSTRUCTION(op, LoadZero, 0) #define INSTR_LoadTrue(op) INSTRUCTION(op, LoadTrue, 0) #define INSTR_LoadFalse(op) INSTRUCTION(op, LoadFalse, 0) #define INSTR_LoadNull(op) INSTRUCTION(op, LoadNull, 0) #define INSTR_LoadUndefined(op) INSTRUCTION(op, LoadUndefined, 0) #define INSTR_LoadInt(op) INSTRUCTION(op, LoadInt, 1, value) #define INSTR_MoveConst(op) INSTRUCTION(op, MoveConst, 2, constIndex, destTemp) #define INSTR_LoadReg(op) INSTRUCTION(op, LoadReg, 1, reg) #define INSTR_StoreReg(op) INSTRUCTION(op, StoreReg, 1, reg) #define INSTR_MoveReg(op) INSTRUCTION(op, MoveReg, 2, srcReg, destReg) #define INSTR_LoadImport(op) INSTRUCTION(op, LoadImport, 1, index) #define INSTR_LoadLocal(op) INSTRUCTION(op, LoadLocal, 1, index) #define INSTR_StoreLocal(op) INSTRUCTION(op, StoreLocal, 1, index) #define INSTR_LoadScopedLocal(op) INSTRUCTION(op, LoadScopedLocal, 2, scope, index) #define INSTR_StoreScopedLocal(op) INSTRUCTION(op, StoreScopedLocal, 2, scope, index) #define INSTR_LoadRuntimeString(op) INSTRUCTION(op, LoadRuntimeString, 1, stringId) #define INSTR_MoveRegExp(op) INSTRUCTION(op, MoveRegExp, 2, regExpId, destReg) #define INSTR_LoadClosure(op) INSTRUCTION(op, LoadClosure, 1, value) #define INSTR_LoadName(op) INSTRUCTION(op, LoadName, 1, name) #define INSTR_LoadGlobalLookup(op) INSTRUCTION(op, LoadGlobalLookup, 1, index) #define INSTR_LoadQmlContextPropertyLookup(op) INSTRUCTION(op, LoadQmlContextPropertyLookup, 1, index) #define INSTR_StoreNameSloppy(op) INSTRUCTION(op, StoreNameSloppy, 1, name) #define INSTR_StoreNameStrict(op) INSTRUCTION(op, StoreNameStrict, 1, name) #define INSTR_LoadProperty(op) INSTRUCTION(op, LoadProperty, 1, name) #define INSTR_GetLookup(op) INSTRUCTION(op, GetLookup, 1, index) #define INSTR_LoadIdObject(op) INSTRUCTION(op, LoadIdObject, 2, index, base) #define INSTR_Yield(op) INSTRUCTION(op, Yield, 0) #define INSTR_YieldStar(op) INSTRUCTION(op, YieldStar, 0) #define INSTR_Resume(op) INSTRUCTION(op, Resume, 1, offset) #define INSTR_IteratorNextForYieldStar(op) INSTRUCTION(op, IteratorNextForYieldStar, 2, iterator, object) #define INSTR_StoreProperty(op) INSTRUCTION(op, StoreProperty, 2, name, base) #define INSTR_SetLookup(op) INSTRUCTION(op, SetLookup, 2, index, base) #define INSTR_LoadSuperProperty(op) INSTRUCTION(op, LoadSuperProperty, 1, property) #define INSTR_StoreSuperProperty(op) INSTRUCTION(op, StoreSuperProperty, 1, property) #define INSTR_LoadElement(op) INSTRUCTION(op, LoadElement, 1, base) #define INSTR_StoreElement(op) INSTRUCTION(op, StoreElement, 2, base, index) #define INSTR_CallValue(op) INSTRUCTION(op, CallValue, 3, name, argc, argv) #define INSTR_CallWithReceiver(op) INSTRUCTION(op, CallWithReceiver, 4, name, thisObject, argc, argv) #define INSTR_CallProperty(op) INSTRUCTION(op, CallProperty, 4, name, base, argc, argv) #define INSTR_CallPropertyLookup(op) INSTRUCTION(op, CallPropertyLookup, 4, lookupIndex, base, argc, argv) #define INSTR_CallElement(op) INSTRUCTION(op, CallElement, 4, base, index, argc, argv) #define INSTR_CallName(op) INSTRUCTION(op, CallName, 3, name, argc, argv) #define INSTR_CallPossiblyDirectEval(op) INSTRUCTION(op, CallPossiblyDirectEval, 2, argc, argv) #define INSTR_CallGlobalLookup(op) INSTRUCTION(op, CallGlobalLookup, 3, index, argc, argv) #define INSTR_CallQmlContextPropertyLookup(op) INSTRUCTION(op, CallQmlContextPropertyLookup, 3, index, argc, argv) #define INSTR_CallWithSpread(op) INSTRUCTION(op, CallWithSpread, 4, func, thisObject, argc, argv) #define INSTR_Construct(op) INSTRUCTION(op, Construct, 3, func, argc, argv) #define INSTR_ConstructWithSpread(op) INSTRUCTION(op, ConstructWithSpread, 3, func, argc, argv) #define INSTR_SetUnwindHandler(op) INSTRUCTION(op, SetUnwindHandler, 1, offset) #define INSTR_UnwindDispatch(op) INSTRUCTION(op, UnwindDispatch, 0) #define INSTR_UnwindToLabel(op) INSTRUCTION(op, UnwindToLabel, 2, level, offset) #define INSTR_DeadTemporalZoneCheck(op) INSTRUCTION(op, DeadTemporalZoneCheck, 1, name) #define INSTR_ThrowException(op) INSTRUCTION(op, ThrowException, 0) #define INSTR_GetException(op) INSTRUCTION(op, GetException, 0) #define INSTR_SetException(op) INSTRUCTION(op, SetException, 0) #define INSTR_CreateCallContext(op) INSTRUCTION(op, CreateCallContext, 0) #define INSTR_PushCatchContext(op) INSTRUCTION(op, PushCatchContext, 2, index, name) #define INSTR_PushWithContext(op) INSTRUCTION(op, PushWithContext, 0) #define INSTR_PushBlockContext(op) INSTRUCTION(op, PushBlockContext, 1, index) #define INSTR_CloneBlockContext(op) INSTRUCTION(op, CloneBlockContext, 0) #define INSTR_PushScriptContext(op) INSTRUCTION(op, PushScriptContext, 1, index) #define INSTR_PopScriptContext(op) INSTRUCTION(op, PopScriptContext, 0) #define INSTR_PopContext(op) INSTRUCTION(op, PopContext, 0) #define INSTR_GetIterator(op) INSTRUCTION(op, GetIterator, 1, iterator) #define INSTR_IteratorNext(op) INSTRUCTION(op, IteratorNext, 2, value, done) #define INSTR_IteratorClose(op) INSTRUCTION(op, IteratorClose, 1, done) #define INSTR_DestructureRestElement(op) INSTRUCTION(op, DestructureRestElement, 0) #define INSTR_DeleteProperty(op) INSTRUCTION(op, DeleteProperty, 2, base, index) #define INSTR_DeleteName(op) INSTRUCTION(op, DeleteName, 1, name) #define INSTR_TypeofName(op) INSTRUCTION(op, TypeofName, 1, name) #define INSTR_TypeofValue(op) INSTRUCTION(op, TypeofValue, 0) #define INSTR_DeclareVar(op) INSTRUCTION(op, DeclareVar, 2, varName, isDeletable) #define INSTR_DefineArray(op) INSTRUCTION(op, DefineArray, 2, argc, args) #define INSTR_DefineObjectLiteral(op) INSTRUCTION(op, DefineObjectLiteral, 3, internalClassId, argc, args) #define INSTR_CreateClass(op) INSTRUCTION(op, CreateClass, 3, classIndex, heritage, computedNames) #define INSTR_CreateMappedArgumentsObject(op) INSTRUCTION(op, CreateMappedArgumentsObject, 0) #define INSTR_CreateUnmappedArgumentsObject(op) INSTRUCTION(op, CreateUnmappedArgumentsObject, 0) #define INSTR_CreateRestParameter(op) INSTRUCTION(op, CreateRestParameter, 1, argIndex) #define INSTR_ConvertThisToObject(op) INSTRUCTION(op, ConvertThisToObject, 0) #define INSTR_LoadSuperConstructor(op) INSTRUCTION(op, LoadSuperConstructor, 0) #define INSTR_ToObject(op) INSTRUCTION(op, ToObject, 0) #define INSTR_Jump(op) INSTRUCTION(op, Jump, 1, offset) #define INSTR_JumpTrue(op) INSTRUCTION(op, JumpTrue, 1, offset) #define INSTR_JumpFalse(op) INSTRUCTION(op, JumpFalse, 1, offset) #define INSTR_JumpNotUndefined(op) INSTRUCTION(op, JumpNotUndefined, 1, offset) #define INSTR_JumpNoException(op) INSTRUCTION(op, JumpNoException, 1, offset) #define INSTR_CheckException(op) INSTRUCTION(op, CheckException, 0) #define INSTR_CmpEqNull(op) INSTRUCTION(op, CmpEqNull, 0) #define INSTR_CmpNeNull(op) INSTRUCTION(op, CmpNeNull, 0) #define INSTR_CmpEqInt(op) INSTRUCTION(op, CmpEqInt, 1, lhs) #define INSTR_CmpNeInt(op) INSTRUCTION(op, CmpNeInt, 1, lhs) #define INSTR_CmpEq(op) INSTRUCTION(op, CmpEq, 1, lhs) #define INSTR_CmpNe(op) INSTRUCTION(op, CmpNe, 1, lhs) #define INSTR_CmpGt(op) INSTRUCTION(op, CmpGt, 1, lhs) #define INSTR_CmpGe(op) INSTRUCTION(op, CmpGe, 1, lhs) #define INSTR_CmpLt(op) INSTRUCTION(op, CmpLt, 1, lhs) #define INSTR_CmpLe(op) INSTRUCTION(op, CmpLe, 1, lhs) #define INSTR_CmpStrictEqual(op) INSTRUCTION(op, CmpStrictEqual, 1, lhs) #define INSTR_CmpStrictNotEqual(op) INSTRUCTION(op, CmpStrictNotEqual, 1, lhs) #define INSTR_CmpIn(op) INSTRUCTION(op, CmpIn, 1, lhs) #define INSTR_CmpInstanceOf(op) INSTRUCTION(op, CmpInstanceOf, 1, lhs) #define INSTR_UNot(op) INSTRUCTION(op, UNot, 0) #define INSTR_UPlus(op) INSTRUCTION(op, UPlus, 0) #define INSTR_UMinus(op) INSTRUCTION(op, UMinus, 0) #define INSTR_UCompl(op) INSTRUCTION(op, UCompl, 0) #define INSTR_Increment(op) INSTRUCTION(op, Increment, 0) #define INSTR_Decrement(op) INSTRUCTION(op, Decrement, 0) #define INSTR_Add(op) INSTRUCTION(op, Add, 1, lhs) #define INSTR_BitAnd(op) INSTRUCTION(op, BitAnd, 1, lhs) #define INSTR_BitOr(op) INSTRUCTION(op, BitOr, 1, lhs) #define INSTR_BitXor(op) INSTRUCTION(op, BitXor, 1, lhs) #define INSTR_UShr(op) INSTRUCTION(op, UShr, 1, lhs) #define INSTR_Shr(op) INSTRUCTION(op, Shr, 1, lhs) #define INSTR_Shl(op) INSTRUCTION(op, Shl, 1, lhs) #define INSTR_BitAndConst(op) INSTRUCTION(op, BitAndConst, 1, rhs) #define INSTR_BitOrConst(op) INSTRUCTION(op, BitOrConst, 1, rhs) #define INSTR_BitXorConst(op) INSTRUCTION(op, BitXorConst, 1, rhs) #define INSTR_UShrConst(op) INSTRUCTION(op, UShrConst, 1, rhs) #define INSTR_ShrConst(op) INSTRUCTION(op, ShrConst, 1, rhs) #define INSTR_ShlConst(op) INSTRUCTION(op, ShlConst, 1, rhs) #define INSTR_Exp(op) INSTRUCTION(op, Exp, 1, lhs) #define INSTR_Mul(op) INSTRUCTION(op, Mul, 1, lhs) #define INSTR_Div(op) INSTRUCTION(op, Div, 1, lhs) #define INSTR_Mod(op) INSTRUCTION(op, Mod, 1, lhs) #define INSTR_Sub(op) INSTRUCTION(op, Sub, 1, lhs) #define INSTR_LoadQmlImportedScripts(op) INSTRUCTION(op, LoadQmlImportedScripts, 1, result) #define INSTR_InitializeBlockDeadTemporalZone(op) INSTRUCTION(op, InitializeBlockDeadTemporalZone, 2, firstReg, count) #define INSTR_ThrowOnNullOrUndefined(op) INSTRUCTION(op, ThrowOnNullOrUndefined, 0) #define INSTR_GetTemplateObject(op) INSTRUCTION(op, GetTemplateObject, 1, index) #define INSTR_TailCall(op) INSTRUCTION(op, TailCall, 4, func, thisObject, argc, argv) #define FOR_EACH_MOTH_INSTR_ALL(F) \ F(Nop) \ FOR_EACH_MOTH_INSTR(F) #define FOR_EACH_MOTH_INSTR(F) \ F(Ret) \ F(LoadConst) \ F(LoadZero) \ F(LoadTrue) \ F(LoadFalse) \ F(LoadNull) \ F(LoadUndefined) \ F(LoadInt) \ F(LoadRuntimeString) \ F(MoveConst) \ F(LoadReg) \ F(StoreReg) \ F(MoveReg) \ F(LoadImport) \ F(LoadLocal) \ F(StoreLocal) \ F(LoadScopedLocal) \ F(StoreScopedLocal) \ F(MoveRegExp) \ F(LoadClosure) \ F(LoadName) \ F(LoadGlobalLookup) \ F(LoadQmlContextPropertyLookup) \ F(StoreNameSloppy) \ F(StoreNameStrict) \ F(LoadElement) \ F(StoreElement) \ F(LoadProperty) \ F(GetLookup) \ F(StoreProperty) \ F(SetLookup) \ F(LoadSuperProperty) \ F(StoreSuperProperty) \ F(ConvertThisToObject) \ F(ToObject) \ F(Jump) \ F(JumpTrue) \ F(JumpFalse) \ F(JumpNoException) \ F(JumpNotUndefined) \ F(CheckException) \ F(CmpEqNull) \ F(CmpNeNull) \ F(CmpEqInt) \ F(CmpNeInt) \ F(CmpEq) \ F(CmpNe) \ F(CmpGt) \ F(CmpGe) \ F(CmpLt) \ F(CmpLe) \ F(CmpStrictEqual) \ F(CmpStrictNotEqual) \ F(CmpIn) \ F(CmpInstanceOf) \ F(UNot) \ F(UPlus) \ F(UMinus) \ F(UCompl) \ F(Increment) \ F(Decrement) \ F(Add) \ F(BitAnd) \ F(BitOr) \ F(BitXor) \ F(UShr) \ F(Shr) \ F(Shl) \ F(BitAndConst) \ F(BitOrConst) \ F(BitXorConst) \ F(UShrConst) \ F(ShrConst) \ F(ShlConst) \ F(Exp) \ F(Mul) \ F(Div) \ F(Mod) \ F(Sub) \ F(CallValue) \ F(CallWithReceiver) \ F(CallProperty) \ F(CallPropertyLookup) \ F(CallElement) \ F(CallName) \ F(CallPossiblyDirectEval) \ F(CallGlobalLookup) \ F(CallQmlContextPropertyLookup) \ F(CallWithSpread) \ F(Construct) \ F(ConstructWithSpread) \ F(SetUnwindHandler) \ F(UnwindDispatch) \ F(UnwindToLabel) \ F(DeadTemporalZoneCheck) \ F(ThrowException) \ F(GetException) \ F(SetException) \ F(CreateCallContext) \ F(PushCatchContext) \ F(PushWithContext) \ F(PushBlockContext) \ F(CloneBlockContext) \ F(PopContext) \ F(GetIterator) \ F(IteratorNext) \ F(IteratorClose) \ F(DestructureRestElement) \ F(DeleteProperty) \ F(DeleteName) \ F(TypeofName) \ F(TypeofValue) \ F(DeclareVar) \ F(DefineArray) \ F(DefineObjectLiteral) \ F(CreateMappedArgumentsObject) \ F(CreateUnmappedArgumentsObject) \ F(CreateRestParameter) \ F(Yield) \ F(YieldStar) \ F(Resume) \ F(IteratorNextForYieldStar) \ F(CreateClass) \ F(LoadSuperConstructor) \ F(PushScriptContext) \ F(PopScriptContext) \ F(InitializeBlockDeadTemporalZone) \ F(ThrowOnNullOrUndefined) \ F(GetTemplateObject) \ F(TailCall) \ F(Debug) \ #define MOTH_NUM_INSTRUCTIONS() (static_cast(Moth::Instr::Type::Debug_Wide) + 1) #if defined(Q_CC_GNU) #if defined(Q_CC_INTEL) // icc before version 1200 doesn't support computed goto, and at least up to version 18.0.0 the // current use results in an internal compiler error. We could enable this if/when it gets fixed // in a later version. # elif defined(Q_OS_WASM) && !defined(__asmjs) // Upstream llvm does not support computed goto for the wasm target, unlike the 'fastcomp' llvm fork // shipped with the emscripten SDK. Disable computed goto usage for non-fastcomp llvm on Wasm. #else # define MOTH_COMPUTED_GOTO #endif #endif #define MOTH_INSTR_ALIGN_MASK (Q_ALIGNOF(QV4::Moth::Instr) - 1) #define MOTH_INSTR_ENUM(I) I, I##_Wide, #define MOTH_INSTR_SIZE(I) (sizeof(QV4::Moth::Instr::instr_##I)) #define MOTH_EXPAND_FOR_MSVC(x) x #define MOTH_DEFINE_ARGS(nargs, ...) \ MOTH_EXPAND_FOR_MSVC(MOTH_DEFINE_ARGS##nargs(__VA_ARGS__)) #define MOTH_DEFINE_ARGS0() #define MOTH_DEFINE_ARGS1(arg) \ int arg; #define MOTH_DEFINE_ARGS2(arg1, arg2) \ int arg1; \ int arg2; #define MOTH_DEFINE_ARGS3(arg1, arg2, arg3) \ int arg1; \ int arg2; \ int arg3; #define MOTH_DEFINE_ARGS4(arg1, arg2, arg3, arg4) \ int arg1; \ int arg2; \ int arg3; \ int arg4; #define MOTH_DEFINE_ARGS5(arg1, arg2, arg3, arg4, arg5) \ int arg1; \ int arg2; \ int arg3; \ int arg4; \ int arg5; #define MOTH_COLLECT_ENUMS(instr) \ INSTR_##instr(MOTH_GET_ENUM) #define MOTH_GET_ENUM_INSTRUCTION(name, ...) \ name, #define MOTH_EMIT_STRUCTS(instr) \ INSTR_##instr(MOTH_EMIT_STRUCT) #define MOTH_EMIT_STRUCT_INSTRUCTION(name, nargs, ...) \ struct instr_##name { \ MOTH_DEFINE_ARGS(nargs, __VA_ARGS__) \ }; #define MOTH_EMIT_INSTR_MEMBERS(instr) \ INSTR_##instr(MOTH_EMIT_INSTR_MEMBER) #define MOTH_EMIT_INSTR_MEMBER_INSTRUCTION(name, nargs, ...) \ instr_##name name; #define MOTH_COLLECT_NARGS(instr) \ INSTR_##instr(MOTH_COLLECT_ARG_COUNT) #define MOTH_COLLECT_ARG_COUNT_INSTRUCTION(name, nargs, ...) \ nargs, nargs, #define MOTH_DECODE_ARG(arg, type, nargs, offset) \ arg = qFromLittleEndian(qFromUnaligned(reinterpret_cast(code) - nargs + offset)); #define MOTH_ADJUST_CODE(type, nargs) \ code += static_cast(nargs*sizeof(type) + 1) #define MOTH_DECODE_INSTRUCTION(name, nargs, ...) \ MOTH_DEFINE_ARGS(nargs, __VA_ARGS__) \ op_int_##name: \ MOTH_ADJUST_CODE(int, nargs); \ MOTH_DECODE_ARGS(name, int, nargs, __VA_ARGS__) \ goto op_main_##name; \ op_byte_##name: \ MOTH_ADJUST_CODE(qint8, nargs); \ MOTH_DECODE_ARGS(name, qint8, nargs, __VA_ARGS__) \ op_main_##name: \ ; \ #define MOTH_DECODE_WITH_BASE_INSTRUCTION(name, nargs, ...) \ MOTH_DEFINE_ARGS(nargs, __VA_ARGS__) \ const char *base_ptr; \ op_int_##name: \ base_ptr = code; \ MOTH_ADJUST_CODE(int, nargs); \ MOTH_DECODE_ARGS(name, int, nargs, __VA_ARGS__) \ goto op_main_##name; \ op_byte_##name: \ base_ptr = code; \ MOTH_ADJUST_CODE(qint8, nargs); \ MOTH_DECODE_ARGS(name, qint8, nargs, __VA_ARGS__) \ op_main_##name: \ ; \ #define MOTH_DECODE_ARGS(name, type, nargs, ...) \ MOTH_EXPAND_FOR_MSVC(MOTH_DECODE_ARGS##nargs(name, type, nargs, __VA_ARGS__)) #define MOTH_DECODE_ARGS0(name, type, nargs, dummy) #define MOTH_DECODE_ARGS1(name, type, nargs, arg) \ MOTH_DECODE_ARG(arg, type, nargs, 0); #define MOTH_DECODE_ARGS2(name, type, nargs, arg1, arg2) \ MOTH_DECODE_ARGS1(name, type, nargs, arg1); \ MOTH_DECODE_ARG(arg2, type, nargs, 1); #define MOTH_DECODE_ARGS3(name, type, nargs, arg1, arg2, arg3) \ MOTH_DECODE_ARGS2(name, type, nargs, arg1, arg2); \ MOTH_DECODE_ARG(arg3, type, nargs, 2); #define MOTH_DECODE_ARGS4(name, type, nargs, arg1, arg2, arg3, arg4) \ MOTH_DECODE_ARGS3(name, type, nargs, arg1, arg2, arg3); \ MOTH_DECODE_ARG(arg4, type, nargs, 3); #define MOTH_DECODE_ARGS5(name, type, nargs, arg1, arg2, arg3, arg4, arg5) \ MOTH_DECODE_ARGS4(name, type, nargs, arg1, arg2, arg3, arg4); \ MOTH_DECODE_ARG(arg5, type, nargs, 4); #ifdef MOTH_COMPUTED_GOTO /* collect jump labels */ #define COLLECT_LABELS(instr) \ INSTR_##instr(GET_LABEL) \ INSTR_##instr(GET_LABEL_WIDE) #define GET_LABEL_INSTRUCTION(name, ...) \ &&op_byte_##name, #define GET_LABEL_WIDE_INSTRUCTION(name, ...) \ &&op_int_##name, #define MOTH_JUMP_TABLE \ static const void *jumpTable[] = { \ FOR_EACH_MOTH_INSTR_ALL(COLLECT_LABELS) \ }; #define MOTH_DISPATCH_SINGLE() \ goto *jumpTable[*reinterpret_cast(code)]; #define MOTH_DISPATCH() \ MOTH_DISPATCH_SINGLE() \ op_byte_Nop: \ ++code; \ MOTH_DISPATCH_SINGLE() \ op_int_Nop: /* wide prefix */ \ ++code; \ goto *jumpTable[0x100 | *reinterpret_cast(code)]; #else #define MOTH_JUMP_TABLE #define MOTH_INSTR_CASE_AND_JUMP(instr) \ INSTR_##instr(GET_CASE_AND_JUMP) \ INSTR_##instr(GET_CASE_AND_JUMP_WIDE) #define GET_CASE_AND_JUMP_INSTRUCTION(name, ...) \ case Instr::Type::name: goto op_byte_##name; #define GET_CASE_AND_JUMP_WIDE_INSTRUCTION(name, ...) \ case Instr::Type::name##_Wide: goto op_int_##name; #define MOTH_DISPATCH() \ Instr::Type type = Instr::Type(static_cast(*code)); \ dispatch: \ switch (type) { \ case Instr::Type::Nop: \ ++code; \ type = Instr::Type(static_cast(*code)); \ goto dispatch; \ case Instr::Type::Nop_Wide: /* wide prefix */ \ ++code; \ type = Instr::Type(0x100 | static_cast(*code)); \ goto dispatch; \ FOR_EACH_MOTH_INSTR(MOTH_INSTR_CASE_AND_JUMP) \ } #endif namespace QV4 { namespace CompiledData { struct CodeOffsetToLine; } namespace Moth { class StackSlot { int index; public: static StackSlot createRegister(int index) { Q_ASSERT(index >= 0); StackSlot t; t.index = index; return t; } int stackSlot() const { return index; } operator int() const { return index; } }; inline bool operator==(const StackSlot &l, const StackSlot &r) { return l.stackSlot() == r.stackSlot(); } inline bool operator!=(const StackSlot &l, const StackSlot &r) { return l.stackSlot() != r.stackSlot(); } // When making changes to the instructions, make sure to bump QV4_DATA_STRUCTURE_VERSION in qv4compileddata_p.h void dumpConstantTable(const Value *constants, uint count); void dumpBytecode(const char *bytecode, int len, int nLocals, int nFormals, int startLine = 1, const QVector &lineNumberMapping = QVector()); inline void dumpBytecode(const QByteArray &bytecode, int nLocals, int nFormals, int startLine = 1, const QVector &lineNumberMapping = QVector()) { dumpBytecode(bytecode.constData(), bytecode.length(), nLocals, nFormals, startLine, lineNumberMapping); } union Instr { enum class Type { FOR_EACH_MOTH_INSTR_ALL(MOTH_INSTR_ENUM) }; static Type wideInstructionType(Type t) { return Type(int(t) | 1); } static Type narrowInstructionType(Type t) { return Type(int(t) & ~1); } static bool isWide(Type t) { return int(t) & 1; } static bool isNarrow(Type t) { return !(int(t) & 1); } static int encodedLength(Type t) { return int(t) >= 256 ? 2 : 1; } static Type unpack(const uchar *c) { if (c[0] == 0x1) return Type(0x100 + c[1]); return Type(c[0]); } static uchar *pack(uchar *c, Type t) { if (uint(t) >= 256) { c[0] = 0x1; c[1] = uint(t) &0xff; return c + 2; } c[0] = uchar(uint(t)); return c + 1; } FOR_EACH_MOTH_INSTR_ALL(MOTH_EMIT_STRUCTS) FOR_EACH_MOTH_INSTR_ALL(MOTH_EMIT_INSTR_MEMBERS) int argumentsAsInts[4]; }; struct InstrInfo { static const int argumentCount[]; static int size(Instr::Type type); }; template struct InstrMeta { }; QT_WARNING_PUSH QT_WARNING_DISABLE_GCC("-Wuninitialized") QT_WARNING_DISABLE_GCC("-Wmaybe-uninitialized") #define MOTH_INSTR_META_TEMPLATE(I) \ template<> struct InstrMeta { \ enum { Size = MOTH_INSTR_SIZE(I) }; \ typedef Instr::instr_##I DataType; \ static const DataType &data(const Instr &instr) { return instr.I; } \ static void setData(Instr &instr, const DataType &v) \ { memcpy(reinterpret_cast(&instr.I), \ reinterpret_cast(&v), \ Size); } \ }; FOR_EACH_MOTH_INSTR_ALL(MOTH_INSTR_META_TEMPLATE); #undef MOTH_INSTR_META_TEMPLATE QT_WARNING_POP template class InstrData : public InstrMeta::DataType { }; struct Instruction { #define MOTH_INSTR_DATA_TYPEDEF(I) typedef InstrData I; FOR_EACH_MOTH_INSTR_ALL(MOTH_INSTR_DATA_TYPEDEF) #undef MOTH_INSTR_DATA_TYPEDEF private: Instruction(); }; } // namespace Moth } // namespace QV4 QT_END_NAMESPACE #endif // QV4INSTR_MOTH_P_H