e1b45844cb42e69e568a3d084c36faebdf378898
[profile/ivi/qtdeclarative.git] / src / declarative / qml / v4 / qv4ir_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
6 **
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #ifndef QV4IR_P_H
43 #define QV4IR_P_H
44
45 //
46 //  W A R N I N G
47 //  -------------
48 //
49 // This file is not part of the Qt API.  It exists purely as an
50 // implementation detail.  This header file may change from version to
51 // version without notice, or even be removed.
52 //
53 // We mean it.
54 //
55
56 #include <private/qdeclarativejsast_p.h>
57 #include <private/qdeclarativejsengine_p.h>
58 #include <private/qdeclarativescript_p.h>
59 #include <private/qdeclarativeimport_p.h>
60 #include <private/qdeclarativeengine_p.h>
61 #include <private/qv4compiler_p.h>
62
63 #include <private/qdeclarativepool_p.h>
64 #include <QtCore/qvarlengtharray.h>
65
66 // #define DEBUG_IR_STRUCTURE
67
68 QT_BEGIN_HEADER
69
70 QT_BEGIN_NAMESPACE
71
72 class QTextStream;
73 class QDeclarativeType;
74
75 namespace QDeclarativeJS {
76
77 namespace IR {
78
79 struct BasicBlock;
80 struct Function;
81
82 struct Stmt;
83 struct Expr;
84
85 // expressions
86 struct Const;
87 struct String;
88 struct Name;
89 struct Temp;
90 struct Unop;
91 struct Binop;
92 struct Call;
93
94 // statements
95 struct Exp;
96 struct Move;
97 struct Jump;
98 struct CJump;
99 struct Ret;
100
101 enum AluOp {
102     OpInvalid = 0,
103
104     OpIfTrue,
105     OpNot,
106     OpUMinus,
107     OpUPlus,
108     OpCompl,
109
110     OpBitAnd,
111     OpBitOr,
112     OpBitXor,
113
114     OpAdd,
115     OpSub,
116     OpMul,
117     OpDiv,
118     OpMod,
119
120     OpLShift,
121     OpRShift,
122     OpURShift,
123
124     OpGt,
125     OpLt,
126     OpGe,
127     OpLe,
128     OpEqual,
129     OpNotEqual,
130     OpStrictEqual,
131     OpStrictNotEqual,
132
133     OpAnd,
134     OpOr
135 };
136 AluOp binaryOperator(int op);
137
138 enum Type {
139     InvalidType,
140     UndefinedType,
141     NullType,
142     VoidType,
143     StringType,
144     UrlType,
145     AnchorLineType,
146     SGAnchorLineType,
147     AttachType,
148     ObjectType,
149
150     FirstNumberType,
151     BoolType = FirstNumberType,
152     IntType,
153     RealType,
154     RealNaNType
155 };
156 Type maxType(IR::Type left, IR::Type right);
157
158 struct ExprVisitor {
159     virtual ~ExprVisitor() {}
160     virtual void visitConst(Const *) {}
161     virtual void visitString(String *) {}
162     virtual void visitName(Name *) {}
163     virtual void visitTemp(Temp *) {}
164     virtual void visitUnop(Unop *) {}
165     virtual void visitBinop(Binop *) {}
166     virtual void visitCall(Call *) {}
167 };
168
169 struct StmtVisitor {
170     virtual ~StmtVisitor() {}
171     virtual void visitExp(Exp *) {}
172     virtual void visitMove(Move *) {}
173     virtual void visitJump(Jump *) {}
174     virtual void visitCJump(CJump *) {}
175     virtual void visitRet(Ret *) {}
176 };
177
178 struct Expr: QDeclarativePool::POD {
179     Type type;
180
181     Expr(): type(InvalidType) {}
182     virtual ~Expr() {}
183     virtual void accept(ExprVisitor *) = 0;
184     virtual Const *asConst() { return 0; }
185     virtual String *asString() { return 0; }
186     virtual Name *asName() { return 0; }
187     virtual Temp *asTemp() { return 0; }
188     virtual Unop *asUnop() { return 0; }
189     virtual Binop *asBinop() { return 0; }
190     virtual Call *asCall() { return 0; }
191     virtual void dump(QTextStream &out) = 0;
192 };
193
194 struct ExprList: QDeclarativePool::POD {
195     Expr *expr;
196     ExprList *next;
197
198     void init(Expr *expr, ExprList *next = 0)
199     {
200         this->expr = expr;
201         this->next = next;
202     }
203 };
204
205 struct Const: Expr {
206     double value;
207
208     void init(Type type, double value)
209     {
210         this->type = type;
211         this->value = value;
212     }
213
214     virtual void accept(ExprVisitor *v) { v->visitConst(this); }
215     virtual Const *asConst() { return this; }
216
217     virtual void dump(QTextStream &out);
218 };
219
220 struct String: Expr {
221     QStringRef value;
222
223     void init(const QStringRef &value)
224     {
225         this->type = StringType;
226         this->value = value;
227     }
228
229     virtual void accept(ExprVisitor *v) { v->visitString(this); }
230     virtual String *asString() { return this; }
231
232     virtual void dump(QTextStream &out);
233     static QString escape(const QStringRef &s);
234 };
235
236 enum BuiltinSymbol {
237     NoBuiltinSymbol,
238     MathSinBultinFunction,
239     MathCosBultinFunction,
240     MathRoundBultinFunction,
241     MathFloorBultinFunction,
242
243     MathPIBuiltinConstant
244 };
245
246 struct Name: Expr {
247     enum Symbol {
248         Unbound,
249         IdObject,      // This is a load of a id object.  Storage will always be IdStorage
250         AttachType,    // This is a load of an attached object 
251         Object,        // XXX what is this for?
252         Property,      // This is a load of a regular property
253         Slot           // XXX what is this for?
254     };
255
256     enum Storage {
257         MemberStorage, // This is a property of a previously fetched object
258         IdStorage,     // This is a load of a id object.  Symbol will always be IdObject
259         RootStorage,   // This is a property of the root object
260         ScopeStorage   // This is a property of the scope object
261     };
262
263     Name *base;
264     const QString *id;
265     Symbol symbol;
266     union {
267         void *ptr;
268         const QMetaObject *meta;
269         const QDeclarativeType *declarativeType;
270         const QDeclarativeScript::Object *idObject;
271     };
272     QDeclarativePropertyData *property;
273     Storage storage;
274     BuiltinSymbol builtin;
275     quint32 line;
276     quint32 column;
277
278     void init(Name *base, Type type, const QString *id, Symbol symbol, quint32 line, quint32 column);
279
280     inline bool is(Symbol s) const { return s == symbol; }
281     inline bool isNot(Symbol s) const { return s != symbol; }
282
283     virtual void accept(ExprVisitor *v) { v->visitName(this); }
284     virtual Name *asName() { return this; }
285
286     virtual void dump(QTextStream &out);
287 };
288
289 struct Temp: Expr {
290     int index;
291
292     void init(Type type, int index)
293     {
294         this->type = type;
295         this->index = index;
296     }
297
298     virtual void accept(ExprVisitor *v) { v->visitTemp(this); }
299     virtual Temp *asTemp() { return this; }
300
301     virtual void dump(QTextStream &out);
302 };
303
304 struct Unop: Expr {
305     AluOp op;
306     Expr *expr;
307
308     void init(AluOp op, Expr *expr)
309     {
310         this->typeForOp(op, expr);
311         this->op = op;
312         this->expr = expr;
313     }
314
315     virtual void accept(ExprVisitor *v) { v->visitUnop(this); }
316     virtual Unop *asUnop() { return this; }
317
318     virtual void dump(QTextStream &out);
319
320 private:
321     static Type typeForOp(AluOp op, Expr *expr);
322 };
323
324 struct Binop: Expr {
325     AluOp op;
326     Expr *left;
327     Expr *right;
328
329     void init(AluOp op, Expr *left, Expr *right)
330     {
331         this->type = typeForOp(op, left, right);
332         this->op = op;
333         this->left = left;
334         this->right = right;
335     }
336
337     virtual void accept(ExprVisitor *v) { v->visitBinop(this); }
338     virtual Binop *asBinop() { return this; }
339
340     virtual void dump(QTextStream &out);
341
342 private:
343     static Type typeForOp(AluOp op, Expr *left, Expr *right);
344 };
345
346 struct Call: Expr {
347     Expr *base;
348     ExprList *args;
349
350     void init(Expr *base, ExprList *args)
351     {
352         this->type = typeForFunction(base);
353         this->base = base;
354         this->args = args;
355     }
356
357     Expr *onlyArgument() const {
358         if (args && ! args->next)
359             return args->expr;
360         return 0;
361     }
362
363     virtual void accept(ExprVisitor *v) { v->visitCall(this); }
364     virtual Call *asCall() { return this; }
365
366     virtual void dump(QTextStream &out);
367
368 private:
369     static Type typeForFunction(Expr *base);
370 };
371
372 struct Stmt: QDeclarativePool::POD {
373     enum Mode {
374         HIR,
375         MIR
376     };
377
378     virtual ~Stmt() {}
379     virtual Stmt *asTerminator() { return 0; }
380
381     virtual void accept(StmtVisitor *) = 0;
382     virtual Exp *asExp() { return 0; }
383     virtual Move *asMove() { return 0; }
384     virtual Jump *asJump() { return 0; }
385     virtual CJump *asCJump() { return 0; }
386     virtual Ret *asRet() { return 0; }
387     virtual void dump(QTextStream &out, Mode mode = HIR) = 0;
388 };
389
390 struct Exp: Stmt {
391     Expr *expr;
392
393     void init(Expr *expr)
394     {
395         this->expr = expr;
396     }
397
398     virtual void accept(StmtVisitor *v) { v->visitExp(this); }
399     virtual Exp *asExp() { return this; }
400
401     virtual void dump(QTextStream &out, Mode);
402 };
403
404 struct Move: Stmt {
405     Expr *target;
406     Expr *source;
407     bool isMoveForReturn;
408
409     void init(Expr *target, Expr *source, bool isMoveForReturn)
410     {
411         this->target = target;
412         this->source = source;
413         this->isMoveForReturn = isMoveForReturn;
414     }
415
416     virtual void accept(StmtVisitor *v) { v->visitMove(this); }
417     virtual Move *asMove() { return this; }
418
419     virtual void dump(QTextStream &out, Mode);
420 };
421
422 struct Jump: Stmt {
423     BasicBlock *target;
424
425     void init(BasicBlock *target)
426     {
427         this->target = target;
428     }
429
430     virtual Stmt *asTerminator() { return this; }
431
432     virtual void accept(StmtVisitor *v) { v->visitJump(this); }
433     virtual Jump *asJump() { return this; }
434
435     virtual void dump(QTextStream &out, Mode mode);
436 };
437
438 struct CJump: Stmt {
439     Expr *cond;
440     BasicBlock *iftrue;
441     BasicBlock *iffalse;
442
443     void init(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse)
444     {
445         this->cond = cond;
446         this->iftrue = iftrue;
447         this->iffalse = iffalse;
448     }
449
450     virtual Stmt *asTerminator() { return this; }
451
452     virtual void accept(StmtVisitor *v) { v->visitCJump(this); }
453     virtual CJump *asCJump() { return this; }
454
455     virtual void dump(QTextStream &out, Mode mode);
456 };
457
458 struct Ret: Stmt {
459     Expr *expr;
460     Type type;
461     quint32 line;
462     quint32 column;
463
464     void init(Expr *expr, Type type, quint32 line, quint32 column)
465     {
466         this->expr = expr;
467         this->type = type;
468         this->line = line;
469         this->column = column;
470     }
471
472     virtual Stmt *asTerminator() { return this; }
473
474     virtual void accept(StmtVisitor *v) { v->visitRet(this); }
475     virtual Ret *asRet() { return this; }
476
477     virtual void dump(QTextStream &out, Mode);
478 };
479
480 struct Function {
481     QDeclarativePool *pool;
482     QVarLengthArray<BasicBlock *, 8> basicBlocks;
483     int tempCount;
484
485     Function(QDeclarativePool *pool)
486       : pool(pool), tempCount(0) {}
487
488     ~Function();
489
490     BasicBlock *newBasicBlock();
491     QString *newString(const QString &text);
492
493     inline BasicBlock *i(BasicBlock *block) { basicBlocks.append(block); return block; }
494
495     virtual void dump(QTextStream &out);
496 };
497
498 struct BasicBlock {
499     Function *function;
500     int index;
501     int offset;
502     QVarLengthArray<Stmt *, 32> statements;
503
504     BasicBlock(Function *function, int index): function(function), index(index), offset(-1) {}
505     ~BasicBlock() {}
506
507     template <typename Instr> inline Instr i(Instr i) { statements.append(i); return i; }
508
509     inline bool isEmpty() const {
510         return statements.isEmpty();
511     }
512
513     inline Stmt *terminator() const {
514         if (! statements.isEmpty() && statements.at(statements.size() - 1)->asTerminator() != 0)
515             return statements.at(statements.size() - 1);
516         return 0;
517     }
518
519     inline bool isTerminated() const {
520         if (terminator() != 0)
521             return true;
522         return false;
523     }
524
525     Temp *TEMP(Type type, int index);
526     Temp *TEMP(Type type);
527
528     Expr *CONST(double value);
529     Expr *CONST(Type type, double value);
530     Expr *STRING(const QStringRef &value);
531
532     Name *NAME(const QString &id, quint32 line, quint32 column);
533     Name *NAME(Name *base, const QString &id, quint32 line, quint32 column);
534     Name *SYMBOL(Type type, const QString &id, const QMetaObject *meta, QDeclarativePropertyData *property, Name::Storage storage, quint32 line, quint32 column);
535     Name *SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, QDeclarativePropertyData *property, quint32 line, quint32 column);
536     Name *SYMBOL(Name *base, Type type, const QString &id, const QMetaObject *meta, QDeclarativePropertyData *property, Name::Storage storage, quint32 line, quint32 column);
537     Name *ID_OBJECT(const QString &id, const QDeclarativeScript::Object *object, quint32 line, quint32 column);
538     Name *ATTACH_TYPE(const QString &id, const QDeclarativeType *attachType, Name::Storage storage, quint32 line, quint32 column);
539
540     Expr *UNOP(AluOp op, Expr *expr);
541     Expr *BINOP(AluOp op, Expr *left, Expr *right);
542     Expr *CALL(Expr *base, ExprList *args);
543
544     Stmt *EXP(Expr *expr);
545     Stmt *MOVE(Expr *target, Expr *source, bool = false);
546
547     Stmt *JUMP(BasicBlock *target);
548     Stmt *CJUMP(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse);
549     Stmt *RET(Expr *expr, Type type, quint32 line, quint32 column);
550
551     virtual void dump(QTextStream &out);
552 };
553
554 #ifdef DEBUG_IR_STRUCTURE
555 struct IRDump : public ExprVisitor,
556                 public StmtVisitor 
557 {
558 public:
559     IRDump();
560
561     void expression(QDeclarativeJS::IR::Expr *);
562     void basicblock(QDeclarativeJS::IR::BasicBlock *);
563     void statement(QDeclarativeJS::IR::Stmt *);
564     void function(QDeclarativeJS::IR::Function *);
565 protected:
566
567     const char *indent();
568
569     //
570     // expressions
571     //
572     virtual void visitConst(QDeclarativeJS::IR::Const *e);
573     virtual void visitString(QDeclarativeJS::IR::String *e);
574     virtual void visitName(QDeclarativeJS::IR::Name *e);
575     virtual void visitTemp(QDeclarativeJS::IR::Temp *e);
576     virtual void visitUnop(QDeclarativeJS::IR::Unop *e);
577     virtual void visitBinop(QDeclarativeJS::IR::Binop *e);
578     virtual void visitCall(QDeclarativeJS::IR::Call *e);
579
580     //
581     // statements
582     //
583     virtual void visitExp(QDeclarativeJS::IR::Exp *s);
584     virtual void visitMove(QDeclarativeJS::IR::Move *s);
585     virtual void visitJump(QDeclarativeJS::IR::Jump *s);
586     virtual void visitCJump(QDeclarativeJS::IR::CJump *s);
587     virtual void visitRet(QDeclarativeJS::IR::Ret *s);
588
589 private:
590     int indentSize;
591     QByteArray indentData;
592     void inc();
593     void dec();
594 };
595 #endif
596
597 } // end of namespace IR
598
599 } // end of namespace QDeclarativeJS
600
601 QT_END_NAMESPACE
602
603 QT_END_HEADER
604
605 #endif // QV4IR_P_H