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

source code of qtdeclarative/src/qml/compiler/qv4instr_moth_p.h