| 1 | // Copyright (C) 2016 The Qt Company Ltd. |
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
| 3 | |
| 4 | #ifndef QV4INSTR_MOTH_P_H |
| 5 | #define QV4INSTR_MOTH_P_H |
| 6 | |
| 7 | // |
| 8 | // W A R N I N G |
| 9 | // ------------- |
| 10 | // |
| 11 | // This file is not part of the Qt API. It exists purely as an |
| 12 | // implementation detail. This header file may change from version to |
| 13 | // version without notice, or even be removed. |
| 14 | // |
| 15 | // We mean it. |
| 16 | // |
| 17 | |
| 18 | #include <private/qv4staticvalue_p.h> |
| 19 | #include <private/qv4compileddata_p.h> // for CompiledData::CodeOffsetToLine used by the dumper |
| 20 | #include <qendian.h> |
| 21 | |
| 22 | QT_BEGIN_NAMESPACE |
| 23 | |
| 24 | #define INSTRUCTION(op, name, nargs, ...) \ |
| 25 | op##_INSTRUCTION(name, nargs, __VA_ARGS__) |
| 26 | |
| 27 | /* for all jump instructions, the offset has to come last, to simplify the job of the bytecode generator */ |
| 28 | #define INSTR_Nop(op) INSTRUCTION(op, Nop, 0) |
| 29 | #define INSTR_Ret(op) INSTRUCTION(op, Ret, 0) |
| 30 | #define INSTR_Debug(op) INSTRUCTION(op, Debug, 0) |
| 31 | #define INSTR_LoadConst(op) INSTRUCTION(op, LoadConst, 1, index) |
| 32 | #define INSTR_LoadZero(op) INSTRUCTION(op, LoadZero, 0) |
| 33 | #define INSTR_LoadTrue(op) INSTRUCTION(op, LoadTrue, 0) |
| 34 | #define INSTR_LoadFalse(op) INSTRUCTION(op, LoadFalse, 0) |
| 35 | #define INSTR_LoadNull(op) INSTRUCTION(op, LoadNull, 0) |
| 36 | #define INSTR_LoadUndefined(op) INSTRUCTION(op, LoadUndefined, 0) |
| 37 | #define INSTR_LoadInt(op) INSTRUCTION(op, LoadInt, 1, value) |
| 38 | #define INSTR_MoveConst(op) INSTRUCTION(op, MoveConst, 2, constIndex, destTemp) |
| 39 | #define INSTR_LoadReg(op) INSTRUCTION(op, LoadReg, 1, reg) |
| 40 | #define INSTR_StoreReg(op) INSTRUCTION(op, StoreReg, 1, reg) |
| 41 | #define INSTR_MoveReg(op) INSTRUCTION(op, MoveReg, 2, srcReg, destReg) |
| 42 | #define INSTR_LoadImport(op) INSTRUCTION(op, LoadImport, 1, index) |
| 43 | #define INSTR_LoadLocal(op) INSTRUCTION(op, LoadLocal, 1, index) |
| 44 | #define INSTR_StoreLocal(op) INSTRUCTION(op, StoreLocal, 1, index) |
| 45 | #define INSTR_LoadScopedLocal(op) INSTRUCTION(op, LoadScopedLocal, 2, scope, index) |
| 46 | #define INSTR_StoreScopedLocal(op) INSTRUCTION(op, StoreScopedLocal, 2, scope, index) |
| 47 | #define INSTR_LoadRuntimeString(op) INSTRUCTION(op, LoadRuntimeString, 1, stringId) |
| 48 | #define INSTR_MoveRegExp(op) INSTRUCTION(op, MoveRegExp, 2, regExpId, destReg) |
| 49 | #define INSTR_LoadClosure(op) INSTRUCTION(op, LoadClosure, 1, value) |
| 50 | #define INSTR_LoadName(op) INSTRUCTION(op, LoadName, 1, name) |
| 51 | #define INSTR_LoadGlobalLookup(op) INSTRUCTION(op, LoadGlobalLookup, 1, index) |
| 52 | #define INSTR_LoadQmlContextPropertyLookup(op) INSTRUCTION(op, LoadQmlContextPropertyLookup, 1, index) |
| 53 | #define INSTR_StoreNameSloppy(op) INSTRUCTION(op, StoreNameSloppy, 1, name) |
| 54 | #define INSTR_StoreNameStrict(op) INSTRUCTION(op, StoreNameStrict, 1, name) |
| 55 | #define INSTR_LoadProperty(op) INSTRUCTION(op, LoadProperty, 1, name) |
| 56 | #define INSTR_LoadOptionalProperty(op) INSTRUCTION(op, LoadOptionalProperty, 2, name, offset) |
| 57 | #define INSTR_GetLookup(op) INSTRUCTION(op, GetLookup, 1, index) |
| 58 | #define INSTR_GetOptionalLookup(op) INSTRUCTION(op, GetOptionalLookup, 2, index, offset) |
| 59 | #define INSTR_LoadIdObject(op) INSTRUCTION(op, LoadIdObject, 2, index, base) |
| 60 | #define INSTR_Yield(op) INSTRUCTION(op, Yield, 0) |
| 61 | #define INSTR_YieldStar(op) INSTRUCTION(op, YieldStar, 0) |
| 62 | #define INSTR_Resume(op) INSTRUCTION(op, Resume, 1, offset) |
| 63 | #define INSTR_IteratorNextForYieldStar(op) INSTRUCTION(op, IteratorNextForYieldStar, 3, iterator, object, offset) |
| 64 | #define INSTR_StoreProperty(op) INSTRUCTION(op, StoreProperty, 2, name, base) |
| 65 | #define INSTR_SetLookup(op) INSTRUCTION(op, SetLookup, 2, index, base) |
| 66 | #define INSTR_LoadSuperProperty(op) INSTRUCTION(op, LoadSuperProperty, 1, property) |
| 67 | #define INSTR_StoreSuperProperty(op) INSTRUCTION(op, StoreSuperProperty, 1, property) |
| 68 | #define INSTR_LoadElement(op) INSTRUCTION(op, LoadElement, 1, base) |
| 69 | #define INSTR_StoreElement(op) INSTRUCTION(op, StoreElement, 2, base, index) |
| 70 | #define INSTR_CallValue(op) INSTRUCTION(op, CallValue, 3, name, argc, argv) |
| 71 | #define INSTR_CallWithReceiver(op) INSTRUCTION(op, CallWithReceiver, 4, name, thisObject, argc, argv) |
| 72 | #define INSTR_CallProperty(op) INSTRUCTION(op, CallProperty, 4, name, base, argc, argv) |
| 73 | #define INSTR_CallPropertyLookup(op) INSTRUCTION(op, CallPropertyLookup, 4, lookupIndex, base, argc, argv) |
| 74 | #define INSTR_CallName(op) INSTRUCTION(op, CallName, 3, name, argc, argv) |
| 75 | #define INSTR_CallPossiblyDirectEval(op) INSTRUCTION(op, CallPossiblyDirectEval, 2, argc, argv) |
| 76 | #define INSTR_CallGlobalLookup(op) INSTRUCTION(op, CallGlobalLookup, 3, index, argc, argv) |
| 77 | #define INSTR_CallQmlContextPropertyLookup(op) INSTRUCTION(op, CallQmlContextPropertyLookup, 3, index, argc, argv) |
| 78 | #define INSTR_CallWithSpread(op) INSTRUCTION(op, CallWithSpread, 4, func, thisObject, argc, argv) |
| 79 | #define INSTR_Construct(op) INSTRUCTION(op, Construct, 3, func, argc, argv) |
| 80 | #define INSTR_ConstructWithSpread(op) INSTRUCTION(op, ConstructWithSpread, 3, func, argc, argv) |
| 81 | #define INSTR_SetUnwindHandler(op) INSTRUCTION(op, SetUnwindHandler, 1, offset) |
| 82 | #define INSTR_UnwindDispatch(op) INSTRUCTION(op, UnwindDispatch, 0) |
| 83 | #define INSTR_UnwindToLabel(op) INSTRUCTION(op, UnwindToLabel, 2, level, offset) |
| 84 | #define INSTR_DeadTemporalZoneCheck(op) INSTRUCTION(op, DeadTemporalZoneCheck, 1, name) |
| 85 | #define INSTR_ThrowException(op) INSTRUCTION(op, ThrowException, 0) |
| 86 | #define INSTR_GetException(op) INSTRUCTION(op, GetException, 0) |
| 87 | #define INSTR_SetException(op) INSTRUCTION(op, SetException, 0) |
| 88 | #define INSTR_CreateCallContext(op) INSTRUCTION(op, CreateCallContext, 0) |
| 89 | #define INSTR_PushCatchContext(op) INSTRUCTION(op, PushCatchContext, 2, index, name) |
| 90 | #define INSTR_PushWithContext(op) INSTRUCTION(op, PushWithContext, 0) |
| 91 | #define INSTR_PushBlockContext(op) INSTRUCTION(op, PushBlockContext, 1, index) |
| 92 | #define INSTR_CloneBlockContext(op) INSTRUCTION(op, CloneBlockContext, 0) |
| 93 | #define INSTR_PushScriptContext(op) INSTRUCTION(op, PushScriptContext, 1, index) |
| 94 | #define INSTR_PopScriptContext(op) INSTRUCTION(op, PopScriptContext, 0) |
| 95 | #define INSTR_PopContext(op) INSTRUCTION(op, PopContext, 0) |
| 96 | #define INSTR_GetIterator(op) INSTRUCTION(op, GetIterator, 1, iterator) |
| 97 | #define INSTR_IteratorNext(op) INSTRUCTION(op, IteratorNext, 2, value, offset) |
| 98 | #define INSTR_IteratorClose(op) INSTRUCTION(op, IteratorClose, 0) |
| 99 | #define INSTR_DestructureRestElement(op) INSTRUCTION(op, DestructureRestElement, 0) |
| 100 | #define INSTR_DeleteProperty(op) INSTRUCTION(op, DeleteProperty, 2, base, index) |
| 101 | #define INSTR_DeleteName(op) INSTRUCTION(op, DeleteName, 1, name) |
| 102 | #define INSTR_TypeofName(op) INSTRUCTION(op, TypeofName, 1, name) |
| 103 | #define INSTR_TypeofValue(op) INSTRUCTION(op, TypeofValue, 0) |
| 104 | #define INSTR_DeclareVar(op) INSTRUCTION(op, DeclareVar, 2, varName, isDeletable) |
| 105 | #define INSTR_DefineArray(op) INSTRUCTION(op, DefineArray, 2, argc, args) |
| 106 | #define INSTR_DefineObjectLiteral(op) INSTRUCTION(op, DefineObjectLiteral, 3, internalClassId, argc, args) |
| 107 | #define INSTR_CreateClass(op) INSTRUCTION(op, CreateClass, 3, classIndex, heritage, computedNames) |
| 108 | #define INSTR_CreateMappedArgumentsObject(op) INSTRUCTION(op, CreateMappedArgumentsObject, 0) |
| 109 | #define INSTR_CreateUnmappedArgumentsObject(op) INSTRUCTION(op, CreateUnmappedArgumentsObject, 0) |
| 110 | #define INSTR_CreateRestParameter(op) INSTRUCTION(op, CreateRestParameter, 1, argIndex) |
| 111 | #define INSTR_ConvertThisToObject(op) INSTRUCTION(op, ConvertThisToObject, 0) |
| 112 | #define INSTR_LoadSuperConstructor(op) INSTRUCTION(op, LoadSuperConstructor, 0) |
| 113 | #define INSTR_ToObject(op) INSTRUCTION(op, ToObject, 0) |
| 114 | #define INSTR_Jump(op) INSTRUCTION(op, Jump, 1, offset) |
| 115 | #define INSTR_JumpTrue(op) INSTRUCTION(op, JumpTrue, 1, offset) |
| 116 | #define INSTR_JumpFalse(op) INSTRUCTION(op, JumpFalse, 1, offset) |
| 117 | #define INSTR_JumpNotUndefined(op) INSTRUCTION(op, JumpNotUndefined, 1, offset) |
| 118 | #define INSTR_JumpNoException(op) INSTRUCTION(op, JumpNoException, 1, offset) |
| 119 | #define INSTR_CheckException(op) INSTRUCTION(op, CheckException, 0) |
| 120 | #define INSTR_CmpEqNull(op) INSTRUCTION(op, CmpEqNull, 0) |
| 121 | #define INSTR_CmpNeNull(op) INSTRUCTION(op, CmpNeNull, 0) |
| 122 | #define INSTR_CmpEqInt(op) INSTRUCTION(op, CmpEqInt, 1, lhs) |
| 123 | #define INSTR_CmpNeInt(op) INSTRUCTION(op, CmpNeInt, 1, lhs) |
| 124 | #define INSTR_CmpEq(op) INSTRUCTION(op, CmpEq, 1, lhs) |
| 125 | #define INSTR_CmpNe(op) INSTRUCTION(op, CmpNe, 1, lhs) |
| 126 | #define INSTR_CmpGt(op) INSTRUCTION(op, CmpGt, 1, lhs) |
| 127 | #define INSTR_CmpGe(op) INSTRUCTION(op, CmpGe, 1, lhs) |
| 128 | #define INSTR_CmpLt(op) INSTRUCTION(op, CmpLt, 1, lhs) |
| 129 | #define INSTR_CmpLe(op) INSTRUCTION(op, CmpLe, 1, lhs) |
| 130 | #define INSTR_CmpStrictEqual(op) INSTRUCTION(op, CmpStrictEqual, 1, lhs) |
| 131 | #define INSTR_CmpStrictNotEqual(op) INSTRUCTION(op, CmpStrictNotEqual, 1, lhs) |
| 132 | #define INSTR_CmpIn(op) INSTRUCTION(op, CmpIn, 1, lhs) |
| 133 | #define INSTR_CmpInstanceOf(op) INSTRUCTION(op, CmpInstanceOf, 1, lhs) |
| 134 | #define INSTR_UNot(op) INSTRUCTION(op, UNot, 0) |
| 135 | #define INSTR_UPlus(op) INSTRUCTION(op, UPlus, 0) |
| 136 | #define INSTR_UMinus(op) INSTRUCTION(op, UMinus, 0) |
| 137 | #define INSTR_UCompl(op) INSTRUCTION(op, UCompl, 0) |
| 138 | #define INSTR_Increment(op) INSTRUCTION(op, Increment, 0) |
| 139 | #define INSTR_Decrement(op) INSTRUCTION(op, Decrement, 0) |
| 140 | #define INSTR_Add(op) INSTRUCTION(op, Add, 1, lhs) |
| 141 | #define INSTR_BitAnd(op) INSTRUCTION(op, BitAnd, 1, lhs) |
| 142 | #define INSTR_BitOr(op) INSTRUCTION(op, BitOr, 1, lhs) |
| 143 | #define INSTR_BitXor(op) INSTRUCTION(op, BitXor, 1, lhs) |
| 144 | #define INSTR_UShr(op) INSTRUCTION(op, UShr, 1, lhs) |
| 145 | #define INSTR_Shr(op) INSTRUCTION(op, Shr, 1, lhs) |
| 146 | #define INSTR_Shl(op) INSTRUCTION(op, Shl, 1, lhs) |
| 147 | #define INSTR_BitAndConst(op) INSTRUCTION(op, BitAndConst, 1, rhs) |
| 148 | #define INSTR_BitOrConst(op) INSTRUCTION(op, BitOrConst, 1, rhs) |
| 149 | #define INSTR_BitXorConst(op) INSTRUCTION(op, BitXorConst, 1, rhs) |
| 150 | #define INSTR_UShrConst(op) INSTRUCTION(op, UShrConst, 1, rhs) |
| 151 | #define INSTR_ShrConst(op) INSTRUCTION(op, ShrConst, 1, rhs) |
| 152 | #define INSTR_ShlConst(op) INSTRUCTION(op, ShlConst, 1, rhs) |
| 153 | #define INSTR_Exp(op) INSTRUCTION(op, Exp, 1, lhs) |
| 154 | #define INSTR_Mul(op) INSTRUCTION(op, Mul, 1, lhs) |
| 155 | #define INSTR_Div(op) INSTRUCTION(op, Div, 1, lhs) |
| 156 | #define INSTR_Mod(op) INSTRUCTION(op, Mod, 1, lhs) |
| 157 | #define INSTR_Sub(op) INSTRUCTION(op, Sub, 1, lhs) |
| 158 | #define INSTR_As(op) INSTRUCTION(op, As, 1, lhs) |
| 159 | #define INSTR_LoadQmlImportedScripts(op) INSTRUCTION(op, LoadQmlImportedScripts, 1, result) |
| 160 | #define INSTR_InitializeBlockDeadTemporalZone(op) INSTRUCTION(op, InitializeBlockDeadTemporalZone, 2, firstReg, count) |
| 161 | #define INSTR_ThrowOnNullOrUndefined(op) INSTRUCTION(op, ThrowOnNullOrUndefined, 0) |
| 162 | #define INSTR_GetTemplateObject(op) INSTRUCTION(op, GetTemplateObject, 1, index) |
| 163 | #define INSTR_TailCall(op) INSTRUCTION(op, TailCall, 4, func, thisObject, argc, argv) |
| 164 | |
| 165 | #define FOR_EACH_MOTH_INSTR_ALL(F) \ |
| 166 | F(Nop) \ |
| 167 | FOR_EACH_MOTH_INSTR(F) |
| 168 | |
| 169 | #define FOR_EACH_MOTH_INSTR(F) \ |
| 170 | F(Ret) \ |
| 171 | F(LoadConst) \ |
| 172 | F(LoadZero) \ |
| 173 | F(LoadTrue) \ |
| 174 | F(LoadFalse) \ |
| 175 | F(LoadNull) \ |
| 176 | F(LoadUndefined) \ |
| 177 | F(LoadInt) \ |
| 178 | F(LoadRuntimeString) \ |
| 179 | F(MoveConst) \ |
| 180 | F(LoadReg) \ |
| 181 | F(StoreReg) \ |
| 182 | F(MoveReg) \ |
| 183 | F(LoadImport) \ |
| 184 | F(LoadLocal) \ |
| 185 | F(StoreLocal) \ |
| 186 | F(LoadScopedLocal) \ |
| 187 | F(StoreScopedLocal) \ |
| 188 | F(MoveRegExp) \ |
| 189 | F(LoadClosure) \ |
| 190 | F(LoadName) \ |
| 191 | F(LoadGlobalLookup) \ |
| 192 | F(LoadQmlContextPropertyLookup) \ |
| 193 | F(StoreNameSloppy) \ |
| 194 | F(StoreNameStrict) \ |
| 195 | F(LoadElement) \ |
| 196 | F(StoreElement) \ |
| 197 | F(LoadProperty) \ |
| 198 | F(LoadOptionalProperty) \ |
| 199 | F(GetLookup) \ |
| 200 | F(GetOptionalLookup) \ |
| 201 | F(StoreProperty) \ |
| 202 | F(SetLookup) \ |
| 203 | F(LoadSuperProperty) \ |
| 204 | F(StoreSuperProperty) \ |
| 205 | F(ConvertThisToObject) \ |
| 206 | F(ToObject) \ |
| 207 | F(Jump) \ |
| 208 | F(JumpTrue) \ |
| 209 | F(JumpFalse) \ |
| 210 | F(JumpNoException) \ |
| 211 | F(JumpNotUndefined) \ |
| 212 | F(CheckException) \ |
| 213 | F(CmpEqNull) \ |
| 214 | F(CmpNeNull) \ |
| 215 | F(CmpEqInt) \ |
| 216 | F(CmpNeInt) \ |
| 217 | F(CmpEq) \ |
| 218 | F(CmpNe) \ |
| 219 | F(CmpGt) \ |
| 220 | F(CmpGe) \ |
| 221 | F(CmpLt) \ |
| 222 | F(CmpLe) \ |
| 223 | F(CmpStrictEqual) \ |
| 224 | F(CmpStrictNotEqual) \ |
| 225 | F(CmpIn) \ |
| 226 | F(CmpInstanceOf) \ |
| 227 | F(UNot) \ |
| 228 | F(UPlus) \ |
| 229 | F(UMinus) \ |
| 230 | F(UCompl) \ |
| 231 | F(Increment) \ |
| 232 | F(Decrement) \ |
| 233 | F(Add) \ |
| 234 | F(BitAnd) \ |
| 235 | F(BitOr) \ |
| 236 | F(BitXor) \ |
| 237 | F(UShr) \ |
| 238 | F(Shr) \ |
| 239 | F(Shl) \ |
| 240 | F(BitAndConst) \ |
| 241 | F(BitOrConst) \ |
| 242 | F(BitXorConst) \ |
| 243 | F(UShrConst) \ |
| 244 | F(ShrConst) \ |
| 245 | F(ShlConst) \ |
| 246 | F(Exp) \ |
| 247 | F(Mul) \ |
| 248 | F(Div) \ |
| 249 | F(Mod) \ |
| 250 | F(Sub) \ |
| 251 | F(As) \ |
| 252 | F(CallValue) \ |
| 253 | F(CallWithReceiver) \ |
| 254 | F(CallProperty) \ |
| 255 | F(CallPropertyLookup) \ |
| 256 | F(CallName) \ |
| 257 | F(CallPossiblyDirectEval) \ |
| 258 | F(CallGlobalLookup) \ |
| 259 | F(CallQmlContextPropertyLookup) \ |
| 260 | F(CallWithSpread) \ |
| 261 | F(Construct) \ |
| 262 | F(ConstructWithSpread) \ |
| 263 | F(SetUnwindHandler) \ |
| 264 | F(UnwindDispatch) \ |
| 265 | F(UnwindToLabel) \ |
| 266 | F(DeadTemporalZoneCheck) \ |
| 267 | F(ThrowException) \ |
| 268 | F(GetException) \ |
| 269 | F(SetException) \ |
| 270 | F(CreateCallContext) \ |
| 271 | F(PushCatchContext) \ |
| 272 | F(PushWithContext) \ |
| 273 | F(PushBlockContext) \ |
| 274 | F(CloneBlockContext) \ |
| 275 | F(PopContext) \ |
| 276 | F(GetIterator) \ |
| 277 | F(IteratorNext) \ |
| 278 | F(IteratorClose) \ |
| 279 | F(DestructureRestElement) \ |
| 280 | F(DeleteProperty) \ |
| 281 | F(DeleteName) \ |
| 282 | F(TypeofName) \ |
| 283 | F(TypeofValue) \ |
| 284 | F(DeclareVar) \ |
| 285 | F(DefineArray) \ |
| 286 | F(DefineObjectLiteral) \ |
| 287 | F(CreateMappedArgumentsObject) \ |
| 288 | F(CreateUnmappedArgumentsObject) \ |
| 289 | F(CreateRestParameter) \ |
| 290 | F(Yield) \ |
| 291 | F(YieldStar) \ |
| 292 | F(Resume) \ |
| 293 | F(IteratorNextForYieldStar) \ |
| 294 | F(CreateClass) \ |
| 295 | F(LoadSuperConstructor) \ |
| 296 | F(PushScriptContext) \ |
| 297 | F(PopScriptContext) \ |
| 298 | F(InitializeBlockDeadTemporalZone) \ |
| 299 | F(ThrowOnNullOrUndefined) \ |
| 300 | F(GetTemplateObject) \ |
| 301 | F(TailCall) \ |
| 302 | F(Debug) \ |
| 303 | |
| 304 | #define MOTH_NUM_INSTRUCTIONS() (static_cast<int>(Moth::Instr::Type::Debug_Wide) + 1) |
| 305 | |
| 306 | #if defined(Q_CC_GNU) |
| 307 | #if defined(Q_OS_WASM) && !defined(__asmjs) |
| 308 | // Upstream llvm does not support computed goto for the wasm target, unlike the 'fastcomp' llvm fork |
| 309 | // shipped with the emscripten SDK. Disable computed goto usage for non-fastcomp llvm on Wasm. |
| 310 | #else |
| 311 | # define MOTH_COMPUTED_GOTO |
| 312 | #endif |
| 313 | #endif |
| 314 | |
| 315 | #define MOTH_INSTR_ALIGN_MASK (alignof(QV4::Moth::Instr) - 1) |
| 316 | |
| 317 | #define MOTH_INSTR_ENUM(I) I, I##_Wide, |
| 318 | #define MOTH_INSTR_SIZE(I) (sizeof(QV4::Moth::Instr::instr_##I)) |
| 319 | |
| 320 | #define MOTH_EXPAND_FOR_MSVC(x) x |
| 321 | #define MOTH_DEFINE_ARGS(nargs, ...) \ |
| 322 | MOTH_EXPAND_FOR_MSVC(MOTH_DEFINE_ARGS##nargs(__VA_ARGS__)) |
| 323 | |
| 324 | #define MOTH_DEFINE_ARGS0() |
| 325 | #define MOTH_DEFINE_ARGS1(arg) \ |
| 326 | int arg; |
| 327 | #define MOTH_DEFINE_ARGS2(arg1, arg2) \ |
| 328 | int arg1; \ |
| 329 | int arg2; |
| 330 | #define MOTH_DEFINE_ARGS3(arg1, arg2, arg3) \ |
| 331 | int arg1; \ |
| 332 | int arg2; \ |
| 333 | int arg3; |
| 334 | #define MOTH_DEFINE_ARGS4(arg1, arg2, arg3, arg4) \ |
| 335 | int arg1; \ |
| 336 | int arg2; \ |
| 337 | int arg3; \ |
| 338 | int arg4; |
| 339 | #define MOTH_DEFINE_ARGS5(arg1, arg2, arg3, arg4, arg5) \ |
| 340 | int arg1; \ |
| 341 | int arg2; \ |
| 342 | int arg3; \ |
| 343 | int arg4; \ |
| 344 | int arg5; |
| 345 | |
| 346 | #define MOTH_COLLECT_ENUMS(instr) \ |
| 347 | INSTR_##instr(MOTH_GET_ENUM) |
| 348 | #define MOTH_GET_ENUM_INSTRUCTION(name, ...) \ |
| 349 | name, |
| 350 | |
| 351 | #define MOTH_EMIT_STRUCTS(instr) \ |
| 352 | INSTR_##instr(MOTH_EMIT_STRUCT) |
| 353 | #define MOTH_EMIT_STRUCT_INSTRUCTION(name, nargs, ...) \ |
| 354 | struct instr_##name { \ |
| 355 | MOTH_DEFINE_ARGS(nargs, __VA_ARGS__) \ |
| 356 | }; |
| 357 | |
| 358 | #define MOTH_EMIT_INSTR_MEMBERS(instr) \ |
| 359 | INSTR_##instr(MOTH_EMIT_INSTR_MEMBER) |
| 360 | #define MOTH_EMIT_INSTR_MEMBER_INSTRUCTION(name, nargs, ...) \ |
| 361 | instr_##name name; |
| 362 | |
| 363 | #define MOTH_COLLECT_NARGS(instr) \ |
| 364 | INSTR_##instr(MOTH_COLLECT_ARG_COUNT) |
| 365 | #define MOTH_COLLECT_ARG_COUNT_INSTRUCTION(name, nargs, ...) \ |
| 366 | nargs, nargs, |
| 367 | |
| 368 | #define MOTH_DECODE_ARG(arg, type, nargs, offset) \ |
| 369 | arg = qFromLittleEndian<type>(qFromUnaligned<type>(reinterpret_cast<const type *>(code) - nargs + offset)); |
| 370 | #define MOTH_ADJUST_CODE(type, nargs) \ |
| 371 | code += static_cast<quintptr>(nargs*sizeof(type) + 1) |
| 372 | |
| 373 | #define MOTH_DECODE_INSTRUCTION(name, nargs, ...) \ |
| 374 | MOTH_DEFINE_ARGS(nargs, __VA_ARGS__) \ |
| 375 | op_int_##name: \ |
| 376 | MOTH_ADJUST_CODE(int, nargs); \ |
| 377 | MOTH_DECODE_ARGS(name, int, nargs, __VA_ARGS__) \ |
| 378 | goto op_main_##name; \ |
| 379 | op_byte_##name: \ |
| 380 | MOTH_ADJUST_CODE(qint8, nargs); \ |
| 381 | MOTH_DECODE_ARGS(name, qint8, nargs, __VA_ARGS__) \ |
| 382 | op_main_##name: \ |
| 383 | ; \ |
| 384 | |
| 385 | #define MOTH_DECODE_WITH_BASE_INSTRUCTION(name, nargs, ...) \ |
| 386 | MOTH_DEFINE_ARGS(nargs, __VA_ARGS__) \ |
| 387 | const char *base_ptr; \ |
| 388 | op_int_##name: \ |
| 389 | base_ptr = code; \ |
| 390 | MOTH_ADJUST_CODE(int, nargs); \ |
| 391 | MOTH_DECODE_ARGS(name, int, nargs, __VA_ARGS__) \ |
| 392 | goto op_main_##name; \ |
| 393 | op_byte_##name: \ |
| 394 | base_ptr = code; \ |
| 395 | MOTH_ADJUST_CODE(qint8, nargs); \ |
| 396 | MOTH_DECODE_ARGS(name, qint8, nargs, __VA_ARGS__) \ |
| 397 | op_main_##name: \ |
| 398 | ; \ |
| 399 | |
| 400 | #define MOTH_DECODE_ARGS(name, type, nargs, ...) \ |
| 401 | MOTH_EXPAND_FOR_MSVC(MOTH_DECODE_ARGS##nargs(name, type, nargs, __VA_ARGS__)) |
| 402 | |
| 403 | #define MOTH_DECODE_ARGS0(name, type, nargs, dummy) |
| 404 | #define MOTH_DECODE_ARGS1(name, type, nargs, arg) \ |
| 405 | MOTH_DECODE_ARG(arg, type, nargs, 0); |
| 406 | #define MOTH_DECODE_ARGS2(name, type, nargs, arg1, arg2) \ |
| 407 | MOTH_DECODE_ARGS1(name, type, nargs, arg1); \ |
| 408 | MOTH_DECODE_ARG(arg2, type, nargs, 1); |
| 409 | #define MOTH_DECODE_ARGS3(name, type, nargs, arg1, arg2, arg3) \ |
| 410 | MOTH_DECODE_ARGS2(name, type, nargs, arg1, arg2); \ |
| 411 | MOTH_DECODE_ARG(arg3, type, nargs, 2); |
| 412 | #define MOTH_DECODE_ARGS4(name, type, nargs, arg1, arg2, arg3, arg4) \ |
| 413 | MOTH_DECODE_ARGS3(name, type, nargs, arg1, arg2, arg3); \ |
| 414 | MOTH_DECODE_ARG(arg4, type, nargs, 3); |
| 415 | #define MOTH_DECODE_ARGS5(name, type, nargs, arg1, arg2, arg3, arg4, arg5) \ |
| 416 | MOTH_DECODE_ARGS4(name, type, nargs, arg1, arg2, arg3, arg4); \ |
| 417 | MOTH_DECODE_ARG(arg5, type, nargs, 4); |
| 418 | |
| 419 | #ifdef MOTH_COMPUTED_GOTO |
| 420 | /* collect jump labels */ |
| 421 | #define COLLECT_LABELS(instr) \ |
| 422 | INSTR_##instr(GET_LABEL) \ |
| 423 | INSTR_##instr(GET_LABEL_WIDE) |
| 424 | #define GET_LABEL_INSTRUCTION(name, ...) \ |
| 425 | &&op_byte_##name, |
| 426 | #define GET_LABEL_WIDE_INSTRUCTION(name, ...) \ |
| 427 | &&op_int_##name, |
| 428 | |
| 429 | #define MOTH_JUMP_TABLE \ |
| 430 | static const void *jumpTable[] = { \ |
| 431 | FOR_EACH_MOTH_INSTR_ALL(COLLECT_LABELS) \ |
| 432 | }; |
| 433 | |
| 434 | #define MOTH_DISPATCH_SINGLE() \ |
| 435 | goto *jumpTable[*reinterpret_cast<const uchar *>(code)]; |
| 436 | |
| 437 | #define MOTH_DISPATCH() \ |
| 438 | MOTH_DISPATCH_SINGLE() \ |
| 439 | op_byte_Nop: \ |
| 440 | ++code; \ |
| 441 | MOTH_DISPATCH_SINGLE() \ |
| 442 | op_int_Nop: /* wide prefix */ \ |
| 443 | ++code; \ |
| 444 | goto *jumpTable[0x100 | *reinterpret_cast<const uchar *>(code)]; |
| 445 | #else |
| 446 | #define MOTH_JUMP_TABLE |
| 447 | |
| 448 | #define MOTH_INSTR_CASE_AND_JUMP(instr) \ |
| 449 | INSTR_##instr(GET_CASE_AND_JUMP) \ |
| 450 | INSTR_##instr(GET_CASE_AND_JUMP_WIDE) |
| 451 | #define GET_CASE_AND_JUMP_INSTRUCTION(name, ...) \ |
| 452 | case Instr::Type::name: goto op_byte_##name; |
| 453 | #define GET_CASE_AND_JUMP_WIDE_INSTRUCTION(name, ...) \ |
| 454 | case Instr::Type::name##_Wide: goto op_int_##name; |
| 455 | |
| 456 | #define MOTH_DISPATCH() \ |
| 457 | Instr::Type type = Instr::Type(static_cast<uchar>(*code)); \ |
| 458 | dispatch: \ |
| 459 | switch (type) { \ |
| 460 | case Instr::Type::Nop: \ |
| 461 | ++code; \ |
| 462 | type = Instr::Type(static_cast<uchar>(*code)); \ |
| 463 | goto dispatch; \ |
| 464 | case Instr::Type::Nop_Wide: /* wide prefix */ \ |
| 465 | ++code; \ |
| 466 | type = Instr::Type(0x100 | static_cast<uchar>(*code)); \ |
| 467 | goto dispatch; \ |
| 468 | FOR_EACH_MOTH_INSTR(MOTH_INSTR_CASE_AND_JUMP) \ |
| 469 | } |
| 470 | #endif |
| 471 | |
| 472 | namespace QV4 { |
| 473 | |
| 474 | namespace CompiledData { |
| 475 | struct CodeOffsetToLineAndStatement; |
| 476 | } |
| 477 | |
| 478 | namespace Moth { |
| 479 | |
| 480 | class StackSlot { |
| 481 | int index; |
| 482 | |
| 483 | public: |
| 484 | static StackSlot createRegister(int index) { |
| 485 | Q_ASSERT(index >= 0); |
| 486 | StackSlot t; |
| 487 | t.index = index; |
| 488 | return t; |
| 489 | } |
| 490 | |
| 491 | int stackSlot() const { return index; } |
| 492 | operator int() const { return index; } |
| 493 | }; |
| 494 | |
| 495 | inline bool operator==(const StackSlot &l, const StackSlot &r) { return l.stackSlot() == r.stackSlot(); } |
| 496 | inline bool operator!=(const StackSlot &l, const StackSlot &r) { return l.stackSlot() != r.stackSlot(); } |
| 497 | |
| 498 | // When making changes to the instructions, make sure to bump QV4_DATA_STRUCTURE_VERSION in qv4compileddata_p.h |
| 499 | |
| 500 | Q_QML_EXPORT |
| 501 | QString dumpBytecode( |
| 502 | const char *bytecode, int len, int nLocals, int nFormals, int beginOffset, int endOffset, |
| 503 | const QVector<CompiledData::CodeOffsetToLineAndStatement> &lineAndStatementNumberMapping = |
| 504 | QVector<CompiledData::CodeOffsetToLineAndStatement>()); |
| 505 | QString dumpBytecode( |
| 506 | const char *bytecode, int len, int nLocals, int nFormals, int startLine = 1, |
| 507 | const QVector<CompiledData::CodeOffsetToLineAndStatement> &lineAndStatementNumberMapping = |
| 508 | QVector<CompiledData::CodeOffsetToLineAndStatement>()); |
| 509 | inline QString dumpBytecode( |
| 510 | const QByteArray &bytecode, int nLocals, int nFormals, int startLine = 1, |
| 511 | const QVector<CompiledData::CodeOffsetToLineAndStatement> &lineAndStatementNumberMapping = |
| 512 | QVector<CompiledData::CodeOffsetToLineAndStatement>()) |
| 513 | { |
| 514 | return dumpBytecode(bytecode: bytecode.constData(), len: bytecode.size(), nLocals, nFormals, startLine, |
| 515 | lineAndStatementNumberMapping); |
| 516 | } |
| 517 | |
| 518 | union Instr |
| 519 | { |
| 520 | enum class Type { |
| 521 | FOR_EACH_MOTH_INSTR_ALL(MOTH_INSTR_ENUM) |
| 522 | }; |
| 523 | |
| 524 | static Type wideInstructionType(Type t) { return Type(int(t) | 1); } |
| 525 | static Type narrowInstructionType(Type t) { return Type(int(t) & ~1); } |
| 526 | static bool isWide(Type t) { return int(t) & 1; } |
| 527 | static bool isNarrow(Type t) { return !(int(t) & 1); } |
| 528 | static int encodedLength(Type t) { return int(t) >= 256 ? 2 : 1; } |
| 529 | |
| 530 | static Type unpack(const uchar *c) { if (c[0] == 0x1) return Type(0x100 + c[1]); return Type(c[0]); } |
| 531 | static uchar *pack(uchar *c, Type t) { |
| 532 | if (uint(t) >= 256) { |
| 533 | c[0] = 0x1; |
| 534 | c[1] = uint(t) &0xff; |
| 535 | return c + 2; |
| 536 | } |
| 537 | c[0] = uchar(uint(t)); |
| 538 | return c + 1; |
| 539 | } |
| 540 | |
| 541 | FOR_EACH_MOTH_INSTR_ALL(MOTH_EMIT_STRUCTS) |
| 542 | |
| 543 | FOR_EACH_MOTH_INSTR_ALL(MOTH_EMIT_INSTR_MEMBERS) |
| 544 | |
| 545 | int argumentsAsInts[4]; |
| 546 | }; |
| 547 | |
| 548 | struct InstrInfo |
| 549 | { |
| 550 | static const int argumentCount[]; |
| 551 | static int size(Instr::Type type); |
| 552 | }; |
| 553 | |
| 554 | template<int N> |
| 555 | struct InstrMeta { |
| 556 | }; |
| 557 | |
| 558 | QT_WARNING_PUSH |
| 559 | QT_WARNING_DISABLE_GCC("-Wuninitialized" ) |
| 560 | QT_WARNING_DISABLE_GCC("-Wmaybe-uninitialized" ) |
| 561 | #define MOTH_INSTR_META_TEMPLATE(I) \ |
| 562 | template<> struct InstrMeta<int(Instr::Type::I)> { \ |
| 563 | enum { Size = MOTH_INSTR_SIZE(I) }; \ |
| 564 | typedef Instr::instr_##I DataType; \ |
| 565 | static const DataType &data(const Instr &instr) { return instr.I; } \ |
| 566 | static void setData(Instr &instr, const DataType &v) \ |
| 567 | { memcpy(reinterpret_cast<char *>(&instr.I), \ |
| 568 | reinterpret_cast<const char *>(&v), \ |
| 569 | Size); } \ |
| 570 | }; |
| 571 | FOR_EACH_MOTH_INSTR_ALL(MOTH_INSTR_META_TEMPLATE); |
| 572 | #undef MOTH_INSTR_META_TEMPLATE |
| 573 | QT_WARNING_POP |
| 574 | |
| 575 | template<int InstrType> |
| 576 | class InstrData : public InstrMeta<InstrType>::DataType |
| 577 | { |
| 578 | }; |
| 579 | |
| 580 | struct Instruction { |
| 581 | #define MOTH_INSTR_DATA_TYPEDEF(I) typedef InstrData<int(Instr::Type::I)> I; |
| 582 | FOR_EACH_MOTH_INSTR_ALL(MOTH_INSTR_DATA_TYPEDEF) |
| 583 | #undef MOTH_INSTR_DATA_TYPEDEF |
| 584 | private: |
| 585 | Instruction(); |
| 586 | }; |
| 587 | |
| 588 | } // namespace Moth |
| 589 | } // namespace QV4 |
| 590 | |
| 591 | QT_END_NAMESPACE |
| 592 | |
| 593 | #endif // QV4INSTR_MOTH_P_H |
| 594 | |