Support variable length instructions in QML bytecode
[profile/ivi/qtdeclarative.git] / src / declarative / qml / v4 / qdeclarativev4instruction.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qdeclarativev4instruction_p.h"
43 #include "qdeclarativev4bindings_p.h"
44
45 #include <QtCore/qdebug.h>
46 #include <private/qdeclarativeglobal_p.h>
47
48 // Define this to do a test dump of all the instructions at startup.  This is 
49 // helpful to test that each instruction's Instr::dump() case uses the correct
50 // number of tabs etc and otherwise looks correct.
51 // #define DEBUG_INSTR_DUMP
52
53 QT_BEGIN_NAMESPACE
54
55 DEFINE_BOOL_CONFIG_OPTION(qmlVerboseCompiler, QML_VERBOSE_COMPILER)
56
57 namespace QDeclarativeJS {
58
59 #ifdef DEBUG_INSTR_DUMP
60 static struct DumpInstrAtStartup {
61     DumpInstrAtStartup() {
62 #define DUMP_INSTR_AT_STARTUP(Type, FMT) { Instr i; i.common.type = Instr::Type; i.dump(0); }
63         FOR_EACH_V4_INSTR(DUMP_INSTR_AT_STARTUP);
64     }
65 } dump_instr_at_startup;
66 #endif
67
68 int Instr::size() const
69 {
70 #define V4_RETURN_INSTR_SIZE(I, FMT) case I: return QML_V4_INSTR_SIZE(I, FMT);
71     switch (common.type) {
72     FOR_EACH_V4_INSTR(V4_RETURN_INSTR_SIZE)
73     }
74 #undef V4_RETURN_INSTR_SIZE
75     return 0;
76 }
77
78 void Instr::dump(int address) const
79 {
80     QByteArray leading;
81     if (address != -1) {
82         leading = QByteArray::number(address);
83         leading.prepend(QByteArray(8 - leading.count(), ' '));
84         leading.append("\t");
85     }
86
87 #define INSTR_DUMP qWarning().nospace() << leading.constData() 
88
89     switch (common.type) {
90     case Instr::Noop:
91         INSTR_DUMP << "\t" << "Noop";
92         break;
93     case Instr::BindingId:
94         INSTR_DUMP << id.line << ":" << id.column << ":";
95         break;
96     case Instr::Subscribe:
97         INSTR_DUMP << "\t" << "Subscribe" << "\t\t" << "Object_Reg(" << subscribeop.reg << ") Notify_Signal(" << subscribeop.index << ") -> Subscribe_Slot(" << subscribeop.offset << ")";
98         break;
99     case Instr::SubscribeId:
100         INSTR_DUMP << "\t" << "SubscribeId" << "\t\t" << "Id_Offset(" << subscribeop.index << ") -> Subscribe_Slot(" << subscribeop.offset << ")";
101         break;
102     case Instr::FetchAndSubscribe:
103         INSTR_DUMP << "\t" << "FetchAndSubscribe" << "\t" << "Object_Reg(" << fetchAndSubscribe.reg << ") Fast_Accessor(" << fetchAndSubscribe.function << ") -> Output_Reg(" << fetchAndSubscribe.reg << ") Subscription_Slot(" <<  fetchAndSubscribe.subscription << ")";
104         break;
105     case Instr::LoadId:
106         INSTR_DUMP << "\t" << "LoadId" << "\t\t\t" << "Id_Offset(" << load.index << ") -> Output_Reg(" << load.reg << ")";
107         break;
108     case Instr::LoadScope:
109         INSTR_DUMP << "\t" << "LoadScope" << "\t\t" << "-> Output_Reg(" << load.reg << ")";
110         break;
111     case Instr::LoadRoot:
112         INSTR_DUMP << "\t" << "LoadRoot" << "\t\t" << "-> Output_Reg(" << load.reg << ")";
113         break;
114     case Instr::LoadAttached:
115         INSTR_DUMP << "\t" << "LoadAttached" << "\t\t" << "Object_Reg(" << attached.reg << ") Attached_Index(" << attached.id << ") -> Output_Reg(" << attached.output << ")";
116         break;
117     case Instr::UnaryNot:
118         INSTR_DUMP << "\t" << "UnaryNot" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
119         break;
120     case Instr::UnaryMinusReal:
121         INSTR_DUMP << "\t" << "UnaryMinusReal" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
122         break;
123     case Instr::UnaryMinusInt:
124         INSTR_DUMP << "\t" << "UnaryMinusInt" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
125         break;
126     case Instr::UnaryPlusReal:
127         INSTR_DUMP << "\t" << "UnaryPlusReal" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
128         break;
129     case Instr::UnaryPlusInt:
130         INSTR_DUMP << "\t" << "UnaryPlusInt" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
131         break;
132     case Instr::ConvertBoolToInt:
133         INSTR_DUMP << "\t" << "ConvertBoolToInt" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
134         break;
135     case Instr::ConvertBoolToReal:
136         INSTR_DUMP << "\t" << "ConvertBoolToReal" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
137         break;
138     case Instr::ConvertBoolToString:
139         INSTR_DUMP << "\t" << "ConvertBoolToString" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
140         break;
141     case Instr::ConvertIntToBool:
142         INSTR_DUMP << "\t" << "ConvertIntToBool" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
143         break;
144     case Instr::ConvertIntToReal:
145         INSTR_DUMP << "\t" << "ConvertIntToReal" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
146         break;
147     case Instr::ConvertIntToString:
148         INSTR_DUMP << "\t" << "ConvertIntToString" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
149         break;
150     case Instr::ConvertRealToBool:
151         INSTR_DUMP << "\t" << "ConvertRealToBool" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
152         break;
153     case Instr::ConvertRealToInt:
154         INSTR_DUMP << "\t" << "ConvertRealToInt" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
155         break;
156     case Instr::ConvertRealToString:
157         INSTR_DUMP << "\t" << "ConvertRealToString" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
158         break;
159     case Instr::ConvertStringToBool:
160         INSTR_DUMP << "\t" << "ConvertStringToBool" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
161         break;
162     case Instr::ConvertStringToInt:
163         INSTR_DUMP << "\t" << "ConvertStringToInt" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
164         break;
165     case Instr::ConvertStringToReal:
166         INSTR_DUMP << "\t" << "ConvertStringToReal" << "\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
167         break;
168     case Instr::MathSinReal:
169         INSTR_DUMP << "\t" << "MathSinReal" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
170         break;
171     case Instr::MathCosReal:
172         INSTR_DUMP << "\t" << "MathCosReal" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
173         break;
174     case Instr::MathRoundReal:
175         INSTR_DUMP << "\t" << "MathRoundReal" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
176         break;
177     case Instr::MathFloorReal:
178         INSTR_DUMP << "\t" << "MathFloorReal" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
179         break;
180     case Instr::MathPIReal:
181         INSTR_DUMP << "\t" << "MathPIReal" << "\t\t" << "Input_Reg(" << unaryop.src << ") -> Output_Reg(" << unaryop.output << ")";
182         break;
183     case Instr::Real:
184         INSTR_DUMP << "\t" << "Real" << "\t\t\t" << "Constant(" << real_value.value << ") -> Output_Reg(" << real_value.reg << ")";
185         break;
186     case Instr::Int:
187         INSTR_DUMP << "\t" << "Int" << "\t\t\t" << "Constant(" << int_value.value << ") -> Output_Reg(" << int_value.reg << ")";
188         break;
189     case Instr::Bool:
190         INSTR_DUMP << "\t" << "Bool" << "\t\t\t" << "Constant(" << bool_value.value << ") -> Output_Reg(" << bool_value.reg << ")";
191         break;
192     case Instr::String:
193         INSTR_DUMP << "\t" << "String" << "\t\t\t" << "String_DataIndex(" << string_value.offset << ") String_Length(" << string_value.length << ") -> Output_Register(" << string_value.reg << ")";
194         break;
195     case Instr::EnableV4Test:
196         INSTR_DUMP << "\t" << "EnableV4Test" << "\t\t" << "String_DataIndex(" << string_value.offset << ") String_Length(" << string_value.length << ")";
197         break;
198     case Instr::TestV4Store:
199         INSTR_DUMP << "\t" << "TestV4Store" << "\t\t" << "Input_Reg(" << storetest.reg << ") Reg_Type(" << storetest.regType << ")";
200         break;
201     case Instr::BitAndInt:
202         INSTR_DUMP << "\t" << "BitAndInt" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
203         break;
204     case Instr::BitOrInt:
205         INSTR_DUMP << "\t" << "BitOrInt" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
206         break;
207     case Instr::BitXorInt:
208         INSTR_DUMP << "\t" << "BitXorInt" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
209         break;
210     case Instr::AddReal:
211         INSTR_DUMP << "\t" << "AddReal" << "\t\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
212         break;
213     case Instr::AddString:
214         INSTR_DUMP << "\t" << "AddString" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
215         break;
216     case Instr::SubReal:
217         INSTR_DUMP << "\t" << "SubReal" << "\t\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
218         break;
219     case Instr::MulReal:
220         INSTR_DUMP << "\t" << "MulReal" << "\t\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
221         break;
222     case Instr::DivReal:
223         INSTR_DUMP << "\t" << "DivReal" << "\t\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
224         break;
225     case Instr::ModReal:
226         INSTR_DUMP << "\t" << "ModReal" << "\t\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
227         break;
228     case Instr::LShiftInt:
229         INSTR_DUMP << "\t" << "LShiftInt" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
230         break;
231     case Instr::RShiftInt:
232         INSTR_DUMP << "\t" << "RShiftInt" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
233         break;
234     case Instr::URShiftInt:
235         INSTR_DUMP << "\t" << "URShiftInt" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
236         break;
237     case Instr::GtReal:
238         INSTR_DUMP << "\t" << "GtReal" << "\t\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
239         break;
240     case Instr::LtReal:
241         INSTR_DUMP << "\t" << "LtReal" << "\t\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
242         break;
243     case Instr::GeReal:
244         INSTR_DUMP << "\t" << "GeReal" << "\t\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
245         break;
246     case Instr::LeReal:
247         INSTR_DUMP << "\t" << "LeReal" << "\t\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
248         break;
249     case Instr::EqualReal:
250         INSTR_DUMP << "\t" << "EqualReal" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
251         break;
252     case Instr::NotEqualReal:
253         INSTR_DUMP << "\t" << "NotEqualReal" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
254         break;
255     case Instr::StrictEqualReal:
256         INSTR_DUMP << "\t" << "StrictEqualReal" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
257         break;
258     case Instr::StrictNotEqualReal:
259         INSTR_DUMP << "\t" << "StrictNotEqualReal" << "\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
260         break;
261     case Instr::GtString:
262         INSTR_DUMP << "\t" << "GtString" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
263         break;
264     case Instr::LtString:
265         INSTR_DUMP << "\t" << "LtString" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
266         break;
267     case Instr::GeString:
268         INSTR_DUMP << "\t" << "GeString" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
269         break;
270     case Instr::LeString:
271         INSTR_DUMP << "\t" << "LeString" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
272         break;
273     case Instr::EqualString:
274         INSTR_DUMP << "\t" << "EqualString" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
275         break;
276     case Instr::NotEqualString:
277         INSTR_DUMP << "\t" << "NotEqualString" << "\t\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
278         break;
279     case Instr::StrictEqualString:
280         INSTR_DUMP << "\t" << "StrictEqualString" << "\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
281         break;
282     case Instr::StrictNotEqualString:
283         INSTR_DUMP << "\t" << "StrictNotEqualString" << "\t" << "Input_Reg(" << binaryop.left << ") Input_Reg(" << binaryop.right << ") -> Output_Reg(" << binaryop.output << ")";
284         break;
285     case Instr::NewString:
286         INSTR_DUMP << "\t" << "NewString" << "\t\t" << "Register(" << construct.reg << ")";
287         break;
288     case Instr::NewUrl:
289         INSTR_DUMP << "\t" << "NewUrl" << "\t\t\t" << "Register(" << construct.reg << ")";
290         break;
291     case Instr::CleanupRegister:
292         INSTR_DUMP << "\t" << "CleanupRegister" << "\t\t" << "Register(" << cleanup.reg << ")";
293         break;
294     case Instr::Fetch:
295         INSTR_DUMP << "\t" << "Fetch" << "\t\t\t" << "Object_Reg(" << fetch.reg << ") Property_Index(" << fetch.index << ") -> Output_Reg(" << fetch.reg << ")";
296         break;
297     case Instr::Store:
298         INSTR_DUMP << "\t" << "Store" << "\t\t\t" << "Input_Reg(" << store.reg << ") -> Object_Reg(" << store.output << ") Property_Index(" << store.index << ")";
299         break;
300     case Instr::Copy:
301         INSTR_DUMP << "\t" << "Copy" << "\t\t\t" << "Input_Reg(" << copy.src << ") -> Output_Reg(" << copy.reg << ")";
302         break;
303     case Instr::Jump:
304         if (jump.reg != -1) {
305             INSTR_DUMP << "\t" << "Jump" << "\t\t\t" << "Address(" << (address + size() + jump.count) << ") [if false == Input_Reg(" << jump.reg << ")]";
306         } else {
307             INSTR_DUMP << "\t" << "Jump" << "\t\t\t" << "Address(" << (address + size() + jump.count) << ")";
308         }
309         break;
310     case Instr::BranchFalse:
311         INSTR_DUMP << "\t" << "BranchFalse" << "\t\t" << "Address(" << (address + size() + branchop.offset) << ") [if false == Input_Reg(" << branchop.reg << ")]";
312         break;
313     case Instr::BranchTrue:
314         INSTR_DUMP << "\t" << "BranchTrue" << "\t\t" << "Address(" << (address + size() + branchop.offset) << ") [if true == Input_Reg(" << branchop.reg << ")]";
315         break;
316     case Instr::Branch:
317         INSTR_DUMP << "\t" << "Branch" << "\t\t\t" << "Address(" << (address + size() + branchop.offset) << ")";
318         break;
319     case Instr::InitString:
320         INSTR_DUMP << "\t" << "InitString" << "\t\t" << "String_DataIndex(" << initstring.dataIdx << ") -> String_Slot(" << initstring.offset << ")";
321         break;
322     case Instr::Block:
323         INSTR_DUMP << "\t" << "Block" << "\t\t\t" << "Mask(" << QByteArray::number(blockop.block, 16).constData()  << ")";
324         break;
325     default:
326         INSTR_DUMP << "\t" << "Unknown";
327         break;
328     }
329 }
330
331 void Instr::noop()
332 {
333     common.type = Noop;
334 }
335
336 void Instr::load_root(quint8 reg)
337 {
338     common.type = LoadRoot;
339     load.reg = reg;
340     load.index = 0;
341 }
342
343 void Instr::load_scope(quint8 reg)
344 {
345     common.type = LoadScope;
346     load.reg = reg;
347     load.index = 0;
348 }
349
350 void Instr::load_id(quint8 reg, quint32 idIndex)
351 {
352     common.type = LoadId;
353     load.reg = reg;
354     load.index = idIndex;
355 }
356
357 void Instr::subscribe(qint8 reg, quint16 subscribeSlot, quint32 notifyIndex)
358 {
359     common.type = Instr::Subscribe;
360     subscribeop.reg = reg;
361     subscribeop.offset = subscribeSlot;
362     subscribeop.index = notifyIndex; 
363 }
364
365 void Instr::subscribeId(qint8 reg, quint16 subscribeSlot, quint32 idIndex)
366 {
367     common.type = Instr::SubscribeId;
368     subscribeop.reg = reg;
369     subscribeop.offset = subscribeSlot;
370     subscribeop.index = idIndex;
371 }
372
373 void Instr::move_reg_bool(quint8 reg, bool value)
374 {
375     common.type = Bool;
376     bool_value.reg = reg;
377     bool_value.value = value;
378 }
379
380 void Instr::move_reg_int(quint8 reg, int value)
381 {
382     common.type = Int;
383     int_value.reg = reg;
384     int_value.value = value;
385 }
386
387 void Instr::move_reg_qreal(quint8 reg, qreal value)
388 {
389     common.type = Real;
390     real_value.reg = reg;
391     real_value.value = value;
392 }
393
394 void Instr::move_reg_reg(quint8 reg, quint8 src)
395 {
396     common.type = Copy;
397     copy.reg = reg;
398     copy.src = src;
399 }
400
401 void Instr::unary_not(quint8 dest, quint8 src)
402 {
403     common.type = UnaryNot;
404     unaryop.src = src;
405     unaryop.output = dest;
406 }
407
408 void Instr::uminus_real(quint8 dest, quint8 src)
409 {
410     common.type = UnaryMinusReal;
411     unaryop.src = src;
412     unaryop.output = dest;
413 }
414
415 void Instr::uminus_int(quint8 dest, quint8 src)
416 {
417     common.type = UnaryMinusInt;
418     unaryop.src = src;
419     unaryop.output = dest;
420 }
421
422 void Instr::uplus_real(quint8 dest, quint8 src)
423 {
424     common.type = UnaryPlusReal;
425     unaryop.src = src;
426     unaryop.output = dest;
427 }
428
429 void Instr::uplus_int(quint8 dest, quint8 src)
430 {
431     common.type = UnaryPlusInt;
432     unaryop.src = src;
433     unaryop.output = dest;
434 }
435
436 void Instr::ucompl_real(quint8 dest, quint8 src)
437 {
438     Q_UNUSED(dest);
439     Q_UNUSED(src);
440     if (qmlVerboseCompiler())
441         qWarning() << "TODO" << Q_FUNC_INFO;
442 }
443
444 void Instr::ucompl_int(quint8 dest, quint8 src)
445 {
446     Q_UNUSED(dest);
447     Q_UNUSED(src);
448     if (qmlVerboseCompiler())
449         qWarning() << "TODO" << Q_FUNC_INFO;
450 }
451
452 void Instr::math_sin_real(quint8 reg)
453 {
454     common.type = MathSinReal;
455     unaryop.src = reg;
456     unaryop.output = reg;
457 }
458
459 void Instr::math_cos_real(quint8 reg)
460 {
461     common.type = MathCosReal;
462     unaryop.src = reg;
463     unaryop.output = reg;
464 }
465
466 void Instr::math_round_real(quint8 reg)
467 {
468     common.type = MathRoundReal;
469     unaryop.src = reg;
470     unaryop.output = reg;
471 }
472
473 void Instr::math_floor_real(quint8 reg)
474 {
475     common.type = MathFloorReal;
476     unaryop.src = reg;
477     unaryop.output = reg;
478 }
479
480 void Instr::math_pi_real(quint8 reg)
481 {
482     common.type = MathPIReal;
483     unaryop.src = reg;
484     unaryop.output = reg;
485 }
486
487 void Instr::branch_true(quint8 reg, qint16 offset)
488 {
489     common.type = BranchTrue;
490     branchop.reg = reg;
491     branchop.offset = offset;
492 }
493
494 void Instr::branch_false(quint8 reg, qint16 offset)
495 {
496     common.type = BranchFalse;
497     branchop.reg = reg;
498     branchop.offset = offset;
499 }
500
501 void Instr::branch(qint16 offset)
502 {
503     common.type = Branch;
504     branchop.offset = offset;
505 }
506
507 void Instr::block(quint32 mask)
508 {
509     common.type = Block;
510     blockop.block = mask;
511 }
512
513 Bytecode::Bytecode()
514 {
515 #ifdef QML_THREADED_INTERPRETER
516     decodeInstr = QDeclarativeV4Bindings::getDecodeInstrTable();
517 #endif
518 }
519
520 void Bytecode::append(const Instr &instr)
521 {
522     const char *it;
523 #ifdef QML_THREADED_INTERPRETER
524     Instr i = instr;
525     i.common.code = decodeInstr[i.common.type];
526     it = (const char *) &i;
527 #else
528     it = (const char *) &instr;
529 #endif
530     d.append(it, instr.size());
531 }
532
533 void Bytecode::append(const QVector<Instr> &instrs)
534 {
535     foreach (const Instr &i, instrs)
536         append(i);
537 }
538
539 int Bytecode::remove(int offset)
540 {
541     const Instr *instr = (const Instr *) (d.begin() + offset);
542     const int instrSize = instr->size();
543     d.remove(offset, instrSize);
544     return instrSize;
545 }
546
547 const Instr &Bytecode::operator[](int offset) const
548 {
549     return *((const Instr *) (d.begin() + offset));
550 }
551
552 Instr &Bytecode::operator[](int offset)
553 {
554     return *((Instr *) (d.begin() + offset));
555 }
556
557 }
558
559 QT_END_NAMESPACE