1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
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.
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>
63 #include <private/qdeclarativepool_p.h>
64 #include <QtCore/qvarlengtharray.h>
66 // #define DEBUG_IR_STRUCTURE
73 class QDeclarativeType;
75 namespace QDeclarativeJS {
136 AluOp binaryOperator(int op);
151 BoolType = FirstNumberType,
156 Type maxType(IR::Type left, IR::Type right);
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 *) {}
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 *) {}
178 struct Expr: QDeclarativePool::POD {
181 Expr(): type(InvalidType) {}
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;
194 struct ExprList: QDeclarativePool::POD {
198 void init(Expr *expr, ExprList *next = 0)
208 void init(Type type, double value)
214 virtual void accept(ExprVisitor *v) { v->visitConst(this); }
215 virtual Const *asConst() { return this; }
217 virtual void dump(QTextStream &out);
220 struct String: Expr {
223 void init(const QStringRef &value)
225 this->type = StringType;
229 virtual void accept(ExprVisitor *v) { v->visitString(this); }
230 virtual String *asString() { return this; }
232 virtual void dump(QTextStream &out);
233 static QString escape(const QStringRef &s);
238 MathSinBultinFunction,
239 MathCosBultinFunction,
240 MathRoundBultinFunction,
241 MathFloorBultinFunction,
243 MathPIBuiltinConstant
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?
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
268 const QMetaObject *meta;
269 const QDeclarativeType *declarativeType;
270 const QDeclarativeScript::Object *idObject;
272 QDeclarativePropertyData *property;
274 BuiltinSymbol builtin;
278 void init(Name *base, Type type, const QString *id, Symbol symbol, quint32 line, quint32 column);
280 inline bool is(Symbol s) const { return s == symbol; }
281 inline bool isNot(Symbol s) const { return s != symbol; }
283 virtual void accept(ExprVisitor *v) { v->visitName(this); }
284 virtual Name *asName() { return this; }
286 virtual void dump(QTextStream &out);
292 void init(Type type, int index)
298 virtual void accept(ExprVisitor *v) { v->visitTemp(this); }
299 virtual Temp *asTemp() { return this; }
301 virtual void dump(QTextStream &out);
308 void init(AluOp op, Expr *expr)
310 this->typeForOp(op, expr);
315 virtual void accept(ExprVisitor *v) { v->visitUnop(this); }
316 virtual Unop *asUnop() { return this; }
318 virtual void dump(QTextStream &out);
321 static Type typeForOp(AluOp op, Expr *expr);
329 void init(AluOp op, Expr *left, Expr *right)
331 this->type = typeForOp(op, left, right);
337 virtual void accept(ExprVisitor *v) { v->visitBinop(this); }
338 virtual Binop *asBinop() { return this; }
340 virtual void dump(QTextStream &out);
343 static Type typeForOp(AluOp op, Expr *left, Expr *right);
350 void init(Expr *base, ExprList *args)
352 this->type = typeForFunction(base);
357 Expr *onlyArgument() const {
358 if (args && ! args->next)
363 virtual void accept(ExprVisitor *v) { v->visitCall(this); }
364 virtual Call *asCall() { return this; }
366 virtual void dump(QTextStream &out);
369 static Type typeForFunction(Expr *base);
372 struct Stmt: QDeclarativePool::POD {
379 virtual Stmt *asTerminator() { return 0; }
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;
393 void init(Expr *expr)
398 virtual void accept(StmtVisitor *v) { v->visitExp(this); }
399 virtual Exp *asExp() { return this; }
401 virtual void dump(QTextStream &out, Mode);
407 bool isMoveForReturn;
409 void init(Expr *target, Expr *source, bool isMoveForReturn)
411 this->target = target;
412 this->source = source;
413 this->isMoveForReturn = isMoveForReturn;
416 virtual void accept(StmtVisitor *v) { v->visitMove(this); }
417 virtual Move *asMove() { return this; }
419 virtual void dump(QTextStream &out, Mode);
425 void init(BasicBlock *target)
427 this->target = target;
430 virtual Stmt *asTerminator() { return this; }
432 virtual void accept(StmtVisitor *v) { v->visitJump(this); }
433 virtual Jump *asJump() { return this; }
435 virtual void dump(QTextStream &out, Mode mode);
443 void init(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse)
446 this->iftrue = iftrue;
447 this->iffalse = iffalse;
450 virtual Stmt *asTerminator() { return this; }
452 virtual void accept(StmtVisitor *v) { v->visitCJump(this); }
453 virtual CJump *asCJump() { return this; }
455 virtual void dump(QTextStream &out, Mode mode);
464 void init(Expr *expr, Type type, quint32 line, quint32 column)
469 this->column = column;
472 virtual Stmt *asTerminator() { return this; }
474 virtual void accept(StmtVisitor *v) { v->visitRet(this); }
475 virtual Ret *asRet() { return this; }
477 virtual void dump(QTextStream &out, Mode);
481 QDeclarativePool *pool;
482 QVarLengthArray<BasicBlock *, 8> basicBlocks;
485 Function(QDeclarativePool *pool)
486 : pool(pool), tempCount(0) {}
490 BasicBlock *newBasicBlock();
491 QString *newString(const QString &text);
493 inline BasicBlock *i(BasicBlock *block) { basicBlocks.append(block); return block; }
495 virtual void dump(QTextStream &out);
502 QVarLengthArray<Stmt *, 32> statements;
504 BasicBlock(Function *function, int index): function(function), index(index), offset(-1) {}
507 template <typename Instr> inline Instr i(Instr i) { statements.append(i); return i; }
509 inline bool isEmpty() const {
510 return statements.isEmpty();
513 inline Stmt *terminator() const {
514 if (! statements.isEmpty() && statements.at(statements.size() - 1)->asTerminator() != 0)
515 return statements.at(statements.size() - 1);
519 inline bool isTerminated() const {
520 if (terminator() != 0)
525 Temp *TEMP(Type type, int index);
526 Temp *TEMP(Type type);
528 Expr *CONST(double value);
529 Expr *CONST(Type type, double value);
530 Expr *STRING(const QStringRef &value);
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);
540 Expr *UNOP(AluOp op, Expr *expr);
541 Expr *BINOP(AluOp op, Expr *left, Expr *right);
542 Expr *CALL(Expr *base, ExprList *args);
544 Stmt *EXP(Expr *expr);
545 Stmt *MOVE(Expr *target, Expr *source, bool = false);
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);
551 virtual void dump(QTextStream &out);
554 #ifdef DEBUG_IR_STRUCTURE
555 struct IRDump : public ExprVisitor,
561 void expression(QDeclarativeJS::IR::Expr *);
562 void basicblock(QDeclarativeJS::IR::BasicBlock *);
563 void statement(QDeclarativeJS::IR::Stmt *);
564 void function(QDeclarativeJS::IR::Function *);
567 const char *indent();
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);
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);
591 QByteArray indentData;
597 } // end of namespace IR
599 } // end of namespace QDeclarativeJS