1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
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 ****************************************************************************/
42 #include "qv4irbuilder_p.h"
43 #include "qv4compiler_p_p.h"
45 #include <private/qquickanchors_p_p.h> // For AnchorLine
46 #include <private/qdeclarativetypenamecache_p.h>
48 DEFINE_BOOL_CONFIG_OPTION(qmlVerboseCompiler, QML_VERBOSE_COMPILER)
52 using namespace QDeclarativeJS;
54 static IR::Type irTypeFromVariantType(int t, QDeclarativeEnginePrivate *engine, const QMetaObject *meta)
63 case QMetaType::QReal:
66 case QMetaType::QString:
67 return IR::StringType;
73 if (t == qMetaTypeId<QDeclarative1AnchorLine>())
74 return IR::AnchorLineType;
75 else if (t == qMetaTypeId<QQuickAnchorLine>())
76 return IR::SGAnchorLineType;
77 else if (const QMetaObject *m = engine->metaObjectForType(t)) {
79 return IR::ObjectType;
82 return IR::InvalidType;
86 QV4IRBuilder::QV4IRBuilder(const QV4Compiler::Expression *expr,
87 QDeclarativeEnginePrivate *engine)
88 : m_expression(expr), m_engine(engine), _function(0), _block(0), _discard(false)
92 bool QV4IRBuilder::operator()(QDeclarativeJS::IR::Function *function,
93 QDeclarativeJS::AST::Node *ast)
95 bool discarded = false;
97 IR::BasicBlock *block = function->newBasicBlock();
99 qSwap(_discard, discarded);
100 qSwap(_function, function);
101 qSwap(_block, block);
104 AST::SourceLocation location;
105 if (AST::ExpressionNode *asExpr = ast->expressionCast()) {
106 r = expression(asExpr);
107 location = asExpr->firstSourceLocation();
108 } else if (AST::Statement *asStmt = ast->statementCast()) {
109 r = statement(asStmt);
110 location = asStmt->firstSourceLocation();
113 //_block->MOVE(_block->TEMP(IR::InvalidType), r.code);
115 const QMetaObject *m = 0;
116 const IR::Type targetType = irTypeFromVariantType(m_expression->property->type, m_engine, m);
117 if (targetType != r.type()) {
118 IR::Expr *x = _block->TEMP(targetType);
119 _block->MOVE(x, r, true);
122 _block->RET(r.code, targetType, location.startLine, location.startColumn);
125 qSwap(_block, block);
126 qSwap(_function, function);
127 qSwap(_discard, discarded);
132 bool QV4IRBuilder::buildName(QList<QStringRef> &name,
134 QList<AST::ExpressionNode *> *nodes)
136 if (node->kind == AST::Node::Kind_IdentifierExpression) {
137 name << static_cast<AST::IdentifierExpression*>(node)->name;
138 if (nodes) *nodes << static_cast<AST::IdentifierExpression*>(node);
139 } else if (node->kind == AST::Node::Kind_FieldMemberExpression) {
140 AST::FieldMemberExpression *expr =
141 static_cast<AST::FieldMemberExpression *>(node);
143 if (!buildName(name, expr->base, nodes))
147 if (nodes) *nodes << expr;
155 void QV4IRBuilder::discard()
160 QV4IRBuilder::ExprResult
161 QV4IRBuilder::expression(AST::ExpressionNode *ast)
169 if (r.is(IR::InvalidType))
172 Q_ASSERT(r.hint == r.format);
179 void QV4IRBuilder::condition(AST::ExpressionNode *ast, IR::BasicBlock *iftrue, IR::BasicBlock *iffalse)
183 ExprResult r(iftrue, iffalse);
188 if (r.format != ExprResult::cx) {
192 Q_ASSERT(r.hint == ExprResult::cx);
193 Q_ASSERT(r.format == ExprResult::ex);
195 if (r.type() != IR::BoolType) {
196 IR::Temp *t = _block->TEMP(IR::BoolType);
201 _block->CJUMP(_block->UNOP(IR::OpIfTrue, r), iftrue, iffalse);
205 QV4IRBuilder::ExprResult
206 QV4IRBuilder::statement(AST::Statement *ast)
214 if (r.is(IR::InvalidType))
217 Q_ASSERT(r.hint == r.format);
224 void QV4IRBuilder::sourceElement(AST::SourceElement *ast)
229 void QV4IRBuilder::implicitCvt(ExprResult &expr, IR::Type type)
231 if (expr.type() == type)
232 return; // nothing to do
234 IR::Expr *x = _block->TEMP(type);
235 _block->MOVE(x, expr.code);
240 bool QV4IRBuilder::visit(AST::UiProgram *)
242 Q_ASSERT(!"unreachable");
246 bool QV4IRBuilder::visit(AST::UiImportList *)
248 Q_ASSERT(!"unreachable");
252 bool QV4IRBuilder::visit(AST::UiImport *)
254 Q_ASSERT(!"unreachable");
258 bool QV4IRBuilder::visit(AST::UiPublicMember *)
260 Q_ASSERT(!"unreachable");
264 bool QV4IRBuilder::visit(AST::UiSourceElement *)
266 Q_ASSERT(!"unreachable");
270 bool QV4IRBuilder::visit(AST::UiObjectDefinition *)
272 Q_ASSERT(!"unreachable");
276 bool QV4IRBuilder::visit(AST::UiObjectInitializer *)
278 Q_ASSERT(!"unreachable");
282 bool QV4IRBuilder::visit(AST::UiObjectBinding *)
284 Q_ASSERT(!"unreachable");
288 bool QV4IRBuilder::visit(AST::UiScriptBinding *)
290 Q_ASSERT(!"unreachable");
294 bool QV4IRBuilder::visit(AST::UiArrayBinding *)
296 Q_ASSERT(!"unreachable");
300 bool QV4IRBuilder::visit(AST::UiObjectMemberList *)
302 Q_ASSERT(!"unreachable");
306 bool QV4IRBuilder::visit(AST::UiArrayMemberList *)
308 Q_ASSERT(!"unreachable");
312 bool QV4IRBuilder::visit(AST::UiQualifiedId *)
314 Q_ASSERT(!"unreachable");
318 bool QV4IRBuilder::visit(AST::UiSignature *)
320 Q_ASSERT(!"unreachable");
324 bool QV4IRBuilder::visit(AST::UiFormalList *)
326 Q_ASSERT(!"unreachable");
330 bool QV4IRBuilder::visit(AST::UiFormal *)
332 Q_ASSERT(!"unreachable");
338 bool QV4IRBuilder::visit(AST::Program *)
340 Q_ASSERT(!"unreachable");
344 bool QV4IRBuilder::visit(AST::SourceElements *)
346 Q_ASSERT(!"unreachable");
350 bool QV4IRBuilder::visit(AST::FunctionSourceElement *)
352 Q_ASSERT(!"unreachable");
356 bool QV4IRBuilder::visit(AST::StatementSourceElement *)
358 Q_ASSERT(!"unreachable");
363 bool QV4IRBuilder::visit(AST::PropertyNameAndValueList *)
365 Q_ASSERT(!"unreachable");
369 bool QV4IRBuilder::visit(AST::IdentifierPropertyName *)
371 Q_ASSERT(!"unreachable");
375 bool QV4IRBuilder::visit(AST::StringLiteralPropertyName *)
377 Q_ASSERT(!"unreachable");
381 bool QV4IRBuilder::visit(AST::NumericLiteralPropertyName *)
383 Q_ASSERT(!"unreachable");
389 bool QV4IRBuilder::visit(AST::ElementList *)
391 Q_ASSERT(!"unreachable");
395 bool QV4IRBuilder::visit(AST::Elision *)
397 Q_ASSERT(!"unreachable");
403 bool QV4IRBuilder::visit(AST::ArgumentList *)
405 Q_ASSERT(!"unreachable");
410 bool QV4IRBuilder::visit(AST::ObjectLiteral *)
415 bool QV4IRBuilder::visit(AST::ArrayLiteral *)
420 bool QV4IRBuilder::visit(AST::ThisExpression *)
425 bool QV4IRBuilder::visit(AST::IdentifierExpression *ast)
427 const quint32 line = ast->identifierToken.startLine;
428 const quint32 column = ast->identifierToken.startColumn;
430 const QString name = ast->name.toString();
432 if (name.at(0) == QLatin1Char('u') && name.length() == 9 && name == QLatin1String("undefined")) {
433 _expr.code = _block->CONST(IR::UndefinedType, 0); // ### undefined value
434 } else if (m_engine->v8engine()->illegalNames().contains(name) ) {
435 if (qmlVerboseCompiler()) qWarning() << "*** illegal symbol:" << name;
437 } else if (const QDeclarativeScript::Object *obj = m_expression->ids->value(name)) {
438 IR::Name *code = _block->ID_OBJECT(name, obj, line, column);
439 if (obj == m_expression->component)
440 code->storage = IR::Name::RootStorage;
444 QDeclarativeTypeNameCache::Result r = m_expression->importCache->query(name);
447 _expr.code = _block->ATTACH_TYPE(name, r.type, IR::Name::ScopeStorage, line, column);
449 // We don't support anything else
453 if (m_expression->context != m_expression->component) {
454 // RootStorage is more efficient than ScopeStorage, so prefer that if they are the same
455 QDeclarativePropertyCache *cache = m_expression->context->synthCache;
456 const QMetaObject *metaObject = m_expression->context->metaObject();
457 if (!cache) cache = m_engine->cache(metaObject);
459 QDeclarativePropertyData *data = cache->property(name);
461 if (data && data->revision != 0) {
462 if (qmlVerboseCompiler())
463 qWarning() << "*** versioned symbol:" << name;
468 if (data && !data->isFunction()) {
469 IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject);
470 _expr.code = _block->SYMBOL(irType, name, metaObject, data->coreIndex, IR::Name::ScopeStorage, line, column);
476 QDeclarativePropertyCache *cache = m_expression->component->synthCache;
477 const QMetaObject *metaObject = m_expression->component->metaObject();
478 if (!cache) cache = m_engine->cache(metaObject);
480 QDeclarativePropertyData *data = cache->property(name);
482 if (data && data->revision != 0) {
483 if (qmlVerboseCompiler())
484 qWarning() << "*** versioned symbol:" << name;
489 if (data && !data->isFunction()) {
490 IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject);
491 _expr.code = _block->SYMBOL(irType, name, metaObject, data->coreIndex, IR::Name::RootStorage, line, column);
496 if (!found && qmlVerboseCompiler())
497 qWarning() << "*** unknown symbol:" << name;
501 if (_expr.code && _expr.hint == ExprResult::cx) {
502 _expr.format = ExprResult::cx;
504 if (_expr.type() != IR::BoolType) {
505 IR::Temp *t = _block->TEMP(IR::BoolType);
506 _block->MOVE(t, _expr);
510 _block->CJUMP(_expr.code, _expr.iftrue, _expr.iffalse);
517 bool QV4IRBuilder::visit(AST::NullExpression *)
519 // ### TODO: cx format
520 _expr.code = _block->CONST(IR::NullType, 0);
524 bool QV4IRBuilder::visit(AST::TrueLiteral *)
526 // ### TODO: cx format
527 _expr.code = _block->CONST(IR::BoolType, 1);
531 bool QV4IRBuilder::visit(AST::FalseLiteral *)
533 // ### TODO: cx format
534 _expr.code = _block->CONST(IR::BoolType, 0);
538 bool QV4IRBuilder::visit(AST::StringLiteral *ast)
540 // ### TODO: cx format
541 _expr.code = _block->STRING(ast->value);
545 bool QV4IRBuilder::visit(AST::NumericLiteral *ast)
547 if (_expr.hint == ExprResult::cx) {
548 _expr.format = ExprResult::cx;
549 _block->JUMP(ast->value ? _expr.iftrue : _expr.iffalse);
551 _expr.code = _block->CONST(ast->value);
556 bool QV4IRBuilder::visit(AST::RegExpLiteral *)
561 bool QV4IRBuilder::visit(AST::NestedExpression *)
563 return true; // the value of the nested expression
566 bool QV4IRBuilder::visit(AST::ArrayMemberExpression *)
571 bool QV4IRBuilder::visit(AST::FieldMemberExpression *ast)
573 if (IR::Expr *left = expression(ast->base)) {
574 if (IR::Name *baseName = left->asName()) {
575 const quint32 line = ast->identifierToken.startLine;
576 const quint32 column = ast->identifierToken.startColumn;
578 QString name = ast->name.toString();
580 switch(baseName->symbol) {
581 case IR::Name::Unbound:
584 case IR::Name::AttachType:
585 if (name.at(0).isUpper()) {
586 QByteArray utf8Name = name.toUtf8();
587 const char *enumName = utf8Name.constData();
589 const QMetaObject *meta = baseName->declarativeType->metaObject();
591 for (int ii = 0; !found && ii < meta->enumeratorCount(); ++ii) {
592 QMetaEnum e = meta->enumerator(ii);
593 for (int jj = 0; !found && jj < e.keyCount(); ++jj) {
594 if (0 == strcmp(e.key(jj), enumName)) {
596 _expr.code = _block->CONST(IR::IntType, e.value(jj));
601 if (!found && qmlVerboseCompiler())
602 qWarning() << "*** unresolved enum:"
603 << (*baseName->id + QLatin1String(".") + ast->name.toString());
604 } else if(const QMetaObject *attachedMeta = baseName->declarativeType->attachedPropertiesType()) {
605 QDeclarativePropertyCache *cache = m_engine->cache(attachedMeta);
606 QDeclarativePropertyData *data = cache->property(name);
608 if (!data || data->isFunction())
609 return false; // Don't support methods (or non-existing properties ;)
611 if(!data->isFinal()) {
612 if (qmlVerboseCompiler())
613 qWarning() << "*** non-final attached property:"
614 << (*baseName->id + QLatin1String(".") + ast->name.toString());
615 return false; // We don't know enough about this property
618 IR::Type irType = irTypeFromVariantType(data->propType, m_engine, attachedMeta);
619 _expr.code = _block->SYMBOL(baseName, irType, name, attachedMeta, data->coreIndex, line, column);
623 case IR::Name::IdObject: {
624 const QDeclarativeScript::Object *idObject = baseName->idObject;
625 QDeclarativePropertyCache *cache =
626 idObject->synthCache?idObject->synthCache:m_engine->cache(idObject->metaObject());
628 QDeclarativePropertyData *data = cache->property(name);
630 if (!data || data->isFunction())
631 return false; // Don't support methods (or non-existing properties ;)
633 if (data->revision != 0) {
634 if (qmlVerboseCompiler())
635 qWarning() << "*** versioned symbol:" << name;
640 IR::Type irType = irTypeFromVariantType(data->propType, m_engine, idObject->metaObject());
641 _expr.code = _block->SYMBOL(baseName, irType, name,
642 idObject->metaObject(), data->coreIndex, line, column);
646 case IR::Name::Property:
647 if (baseName->type == IR::ObjectType) {
648 const QMetaObject *m =
649 m_engine->metaObjectForType(baseName->meta->property(baseName->index).userType());
650 QDeclarativePropertyCache *cache = m_engine->cache(m);
652 QDeclarativePropertyData *data = cache->property(name);
654 if (!data || data->isFunction())
655 return false; // Don't support methods (or non-existing properties ;)
657 if(!data->isFinal()) {
658 if (qmlVerboseCompiler())
659 qWarning() << "*** non-final property access:"
660 << (*baseName->id + QLatin1String(".") + ast->name.toString());
661 return false; // We don't know enough about this property
664 IR::Type irType = irTypeFromVariantType(data->propType, m_engine, baseName->meta);
665 _expr.code = _block->SYMBOL(baseName, irType, name,
666 baseName->meta, data->coreIndex, line, column);
670 case IR::Name::Object:
680 bool QV4IRBuilder::preVisit(AST::Node *)
685 bool QV4IRBuilder::visit(AST::NewMemberExpression *)
690 bool QV4IRBuilder::visit(AST::NewExpression *)
695 bool QV4IRBuilder::visit(AST::CallExpression *ast)
697 QList<QStringRef> names;
698 QList<AST::ExpressionNode *> nameNodes;
701 nameNodes.reserve(4);
703 if (buildName(names, ast->base, &nameNodes)) {
704 //ExprResult base = expression(ast->base);
706 for (int i = 0; i < names.size(); ++i) {
708 id += QLatin1Char('.');
711 const AST::SourceLocation loc = nameNodes.last()->firstSourceLocation();
712 IR::Expr *base = _block->NAME(id, loc.startLine, loc.startColumn);
714 IR::ExprList *args = 0, **argsInserter = &args;
715 for (AST::ArgumentList *it = ast->arguments; it; it = it->next) {
716 IR::Expr *arg = expression(it->expression);
717 *argsInserter = _function->pool->New<IR::ExprList>();
718 (*argsInserter)->init(arg);
719 argsInserter = &(*argsInserter)->next;
722 IR::Temp *r = _block->TEMP(IR::InvalidType);
723 IR::Expr *call = _block->CALL(base, args);
724 _block->MOVE(r, call);
725 r->type = call->type;
732 bool QV4IRBuilder::visit(AST::PostIncrementExpression *)
737 bool QV4IRBuilder::visit(AST::PostDecrementExpression *)
742 bool QV4IRBuilder::visit(AST::DeleteExpression *)
747 bool QV4IRBuilder::visit(AST::VoidExpression *)
752 bool QV4IRBuilder::visit(AST::TypeOfExpression *)
757 bool QV4IRBuilder::visit(AST::PreIncrementExpression *)
762 bool QV4IRBuilder::visit(AST::PreDecrementExpression *)
767 bool QV4IRBuilder::visit(AST::UnaryPlusExpression *ast)
769 ExprResult expr = expression(ast->expression);
770 if (expr.isNot(IR::InvalidType)) {
771 if (expr.code->asConst() != 0) {
776 IR::Expr *code = _block->UNOP(IR::OpUPlus, expr);
777 _expr.code = _block->TEMP(code->type);
778 _block->MOVE(_expr, code);
784 bool QV4IRBuilder::visit(AST::UnaryMinusExpression *ast)
786 ExprResult expr = expression(ast->expression);
787 if (expr.isNot(IR::InvalidType)) {
788 if (IR::Const *c = expr.code->asConst()) {
790 _expr.code = _block->CONST(-c->value);
794 IR::Expr *code = _block->UNOP(IR::OpUMinus, expr);
795 _expr.code = _block->TEMP(code->type);
796 _block->MOVE(_expr, code);
802 bool QV4IRBuilder::visit(AST::TildeExpression *ast)
804 ExprResult expr = expression(ast->expression);
805 if (expr.isNot(IR::InvalidType)) {
806 if (IR::Const *c = expr.code->asConst()) {
808 _expr.code = _block->CONST(~int(c->value));
811 IR::Expr *code = _block->UNOP(IR::OpCompl, expr);
812 _expr.code = _block->TEMP(code->type);
813 _block->MOVE(_expr, code);
819 bool QV4IRBuilder::visit(AST::NotExpression *ast)
821 ExprResult expr = expression(ast->expression);
823 if (expr.isNot(IR::InvalidType)) {
824 if (IR::Const *c = expr.code->asConst()) {
826 _expr.code = _block->CONST(!c->value);
830 IR::Expr *code = _block->UNOP(IR::OpNot, expr);
831 _expr.code = _block->TEMP(code->type);
832 _block->MOVE(_expr, code);
834 } else if (expr.hint == ExprResult::cx) {
835 expr.format = ExprResult::cx;
836 _block->CJUMP(_block->UNOP(IR::OpNot, expr), _expr.iftrue, _expr.iffalse);
843 void QV4IRBuilder::binop(AST::BinaryExpression *ast, ExprResult left, ExprResult right)
845 if (IR::Type t = maxType(left.type(), right.type())) {
846 implicitCvt(left, t);
847 implicitCvt(right, t);
849 if (_expr.hint == ExprResult::cx) {
850 _expr.format = ExprResult::cx;
851 _block->CJUMP(_block->BINOP(IR::binaryOperator(ast->op), left, right), _expr.iftrue, _expr.iffalse);
853 IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
854 _expr.code = _block->TEMP(code->type);
855 _block->MOVE(_expr.code, code);
860 bool QV4IRBuilder::visit(AST::BinaryExpression *ast)
863 case QSOperator::And: {
864 if (_expr.hint == ExprResult::cx) {
865 _expr.format = ExprResult::cx;
867 Q_ASSERT(_expr.iffalse != 0);
868 Q_ASSERT(_expr.iftrue != 0);
870 IR::BasicBlock *iftrue = _function->newBasicBlock();
871 condition(ast->left, iftrue, _expr.iffalse);
874 condition(ast->right, _expr.iftrue, _expr.iffalse);
876 IR::BasicBlock *iftrue = _function->newBasicBlock();
877 IR::BasicBlock *iffalse = _function->newBasicBlock();
878 IR::BasicBlock *endif = _function->newBasicBlock();
880 condition(ast->left, iftrue, iffalse);
882 IR::Temp *r = _block->TEMP(IR::InvalidType);
885 _block->MOVE(r, _block->CONST(0)); // ### use the right null value
889 ExprResult right = expression(ast->right);
890 _block->MOVE(r, right);
895 r->type = right.type(); // ### not exactly, it can be IR::BoolType.
900 case QSOperator::Or: {
901 IR::BasicBlock *iftrue = _function->newBasicBlock();
902 IR::BasicBlock *endif = _function->newBasicBlock();
904 ExprResult left = expression(ast->left);
905 IR::Temp *r = _block->TEMP(left.type());
906 _block->MOVE(r, left);
909 if (r->type != IR::BoolType) {
910 cond = _block->TEMP(IR::BoolType);
911 _block->MOVE(cond, r);
914 _block->CJUMP(_block->UNOP(IR::OpNot, cond), iftrue, endif);
917 ExprResult right = expression(ast->right);
918 _block->MOVE(r, right);
920 if (left.type() != right.type())
931 case QSOperator::Ge: {
932 ExprResult left = expression(ast->left);
933 ExprResult right = expression(ast->right);
934 if (left.type() == IR::StringType && right.type() == IR::StringType) {
935 binop(ast, left, right);
936 } else if (left.isValid() && right.isValid()) {
937 implicitCvt(left, IR::RealType);
938 implicitCvt(right, IR::RealType);
939 binop(ast, left, right);
943 case QSOperator::NotEqual:
944 case QSOperator::Equal: {
945 ExprResult left = expression(ast->left);
946 ExprResult right = expression(ast->right);
947 if ((left.type() == IR::NullType || left.type() == IR::UndefinedType) &&
948 (right.type() == IR::NullType || right.type() == IR::UndefinedType)) {
949 const bool isEq = ast->op == QSOperator::Equal;
950 if (_expr.hint == ExprResult::cx) {
951 _expr.format = ExprResult::cx;
952 _block->JUMP(isEq ? _expr.iftrue : _expr.iffalse);
954 _expr.code = _block->CONST(IR::BoolType, isEq ? 1 : 0);
956 } else if ((left.type() == IR::StringType && right.type() >= IR::FirstNumberType) ||
957 (left.type() >= IR::FirstNumberType && right.type() == IR::StringType)) {
958 implicitCvt(left, IR::RealType);
959 implicitCvt(right, IR::RealType);
960 binop(ast, left, right);
961 } else if (left.type() == IR::BoolType || right.type() == IR::BoolType) {
962 implicitCvt(left, IR::BoolType);
963 implicitCvt(right, IR::BoolType);
964 } else if (left.isValid() && right.isValid()) {
965 binop(ast, left, right);
969 case QSOperator::StrictEqual:
970 case QSOperator::StrictNotEqual: {
971 ExprResult left = expression(ast->left);
972 ExprResult right = expression(ast->right);
973 if (left.type() == right.type()) {
974 binop(ast, left, right);
975 } else if (left.type() >= IR::BoolType && right.type() >= IR::BoolType) {
976 // left and right have numeric type (int or real)
977 binop(ast, left, right);
978 } else if (left.isValid() && right.isValid()) {
979 const bool isEq = ast->op == QSOperator::StrictEqual;
980 if (_expr.hint == ExprResult::cx) {
981 _expr.format = ExprResult::cx;
982 _block->JUMP(isEq ? _expr.iftrue : _expr.iffalse);
984 _expr.code = _block->CONST(IR::BoolType, isEq ? 1 : 0);
989 case QSOperator::BitAnd:
990 case QSOperator::BitOr:
991 case QSOperator::BitXor:
992 case QSOperator::LShift:
993 case QSOperator::RShift:
994 case QSOperator::URShift: {
995 ExprResult left = expression(ast->left);
996 if (left.is(IR::InvalidType))
999 ExprResult right = expression(ast->right);
1000 if (right.is(IR::InvalidType))
1003 implicitCvt(left, IR::IntType);
1004 implicitCvt(right, IR::IntType);
1006 IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
1007 _expr.code = _block->TEMP(code->type);
1008 _block->MOVE(_expr.code, code);
1012 case QSOperator::Add: {
1013 ExprResult left = expression(ast->left);
1014 if (left.is(IR::InvalidType))
1017 ExprResult right = expression(ast->right);
1018 if (right.is(IR::InvalidType))
1021 if (left.isPrimitive() && right.isPrimitive()) {
1022 if (left.type() == IR::StringType || right.type() == IR::StringType) {
1023 implicitCvt(left, IR::StringType);
1024 implicitCvt(right, IR::StringType);
1026 binop(ast, left, right);
1030 case QSOperator::Div:
1031 case QSOperator::Mod:
1032 case QSOperator::Mul:
1033 case QSOperator::Sub: {
1034 ExprResult left = expression(ast->left);
1035 if (left.is(IR::InvalidType))
1038 ExprResult right = expression(ast->right);
1039 if (right.is(IR::InvalidType))
1042 IR::Type t = maxType(left.type(), right.type());
1043 if (t >= IR::FirstNumberType) {
1044 implicitCvt(left, IR::RealType);
1045 implicitCvt(right, IR::RealType);
1047 IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
1048 _expr.code = _block->TEMP(code->type);
1049 _block->MOVE(_expr.code, code);
1053 case QSOperator::In:
1054 case QSOperator::InstanceOf:
1055 case QSOperator::Assign:
1056 case QSOperator::InplaceAnd:
1057 case QSOperator::InplaceSub:
1058 case QSOperator::InplaceDiv:
1059 case QSOperator::InplaceAdd:
1060 case QSOperator::InplaceLeftShift:
1061 case QSOperator::InplaceMod:
1062 case QSOperator::InplaceMul:
1063 case QSOperator::InplaceOr:
1064 case QSOperator::InplaceRightShift:
1065 case QSOperator::InplaceURightShift:
1066 case QSOperator::InplaceXor:
1067 // yup, we don't do those.
1074 bool QV4IRBuilder::visit(AST::ConditionalExpression *ast)
1076 IR::BasicBlock *iftrue = _function->newBasicBlock();
1077 IR::BasicBlock *iffalse = _function->newBasicBlock();
1078 IR::BasicBlock *endif = _function->newBasicBlock();
1080 condition(ast->expression, iftrue, iffalse);
1082 IR::Temp *r = _block->TEMP(IR::InvalidType);
1084 qSwap(_block, iftrue);
1085 ExprResult ok = expression(ast->ok);
1086 _block->MOVE(r, ok);
1087 _block->JUMP(endif);
1088 qSwap(_block, iftrue);
1090 qSwap(_block, iffalse);
1091 ExprResult ko = expression(ast->ko);
1092 _block->MOVE(r, ko);
1093 _block->JUMP(endif);
1094 qSwap(_block, iffalse);
1096 r->type = maxType(ok.type(), ko.type());
1104 bool QV4IRBuilder::visit(AST::Expression *ast)
1106 _block->EXP(expression(ast->left));
1107 _expr = expression(ast->right);
1114 bool QV4IRBuilder::visit(AST::Block *ast)
1116 if (ast->statements && ! ast->statements->next) {
1117 // we have one and only one statement
1118 accept(ast->statements->statement);
1124 bool QV4IRBuilder::visit(AST::StatementList *)
1129 bool QV4IRBuilder::visit(AST::VariableStatement *)
1134 bool QV4IRBuilder::visit(AST::VariableDeclarationList *)
1139 bool QV4IRBuilder::visit(AST::VariableDeclaration *)
1144 bool QV4IRBuilder::visit(AST::EmptyStatement *)
1149 bool QV4IRBuilder::visit(AST::ExpressionStatement *ast)
1151 if (ast->expression) {
1152 // return the value of this expression
1159 bool QV4IRBuilder::visit(AST::IfStatement *ast)
1162 // This is an if statement without an else branch.
1165 IR::BasicBlock *iftrue = _function->newBasicBlock();
1166 IR::BasicBlock *iffalse = _function->newBasicBlock();
1167 IR::BasicBlock *endif = _function->newBasicBlock();
1169 condition(ast->expression, iftrue, iffalse);
1171 IR::Temp *r = _block->TEMP(IR::InvalidType);
1173 qSwap(_block, iftrue);
1174 ExprResult ok = statement(ast->ok);
1175 _block->MOVE(r, ok);
1176 _block->JUMP(endif);
1177 qSwap(_block, iftrue);
1179 qSwap(_block, iffalse);
1180 ExprResult ko = statement(ast->ko);
1181 _block->MOVE(r, ko);
1182 _block->JUMP(endif);
1183 qSwap(_block, iffalse);
1185 r->type = maxType(ok.type(), ko.type());
1194 bool QV4IRBuilder::visit(AST::DoWhileStatement *)
1199 bool QV4IRBuilder::visit(AST::WhileStatement *)
1204 bool QV4IRBuilder::visit(AST::ForStatement *)
1209 bool QV4IRBuilder::visit(AST::LocalForStatement *)
1214 bool QV4IRBuilder::visit(AST::ForEachStatement *)
1219 bool QV4IRBuilder::visit(AST::LocalForEachStatement *)
1225 bool QV4IRBuilder::visit(AST::ContinueStatement *)
1230 bool QV4IRBuilder::visit(AST::BreakStatement *)
1235 bool QV4IRBuilder::visit(AST::ReturnStatement *ast)
1237 if (ast->expression) {
1238 // return the value of the expression
1245 bool QV4IRBuilder::visit(AST::WithStatement *)
1250 bool QV4IRBuilder::visit(AST::SwitchStatement *)
1255 bool QV4IRBuilder::visit(AST::CaseBlock *)
1260 bool QV4IRBuilder::visit(AST::CaseClauses *)
1265 bool QV4IRBuilder::visit(AST::CaseClause *)
1270 bool QV4IRBuilder::visit(AST::DefaultClause *)
1275 bool QV4IRBuilder::visit(AST::LabelledStatement *)
1280 bool QV4IRBuilder::visit(AST::ThrowStatement *)
1285 bool QV4IRBuilder::visit(AST::TryStatement *)
1290 bool QV4IRBuilder::visit(AST::Catch *)
1295 bool QV4IRBuilder::visit(AST::Finally *)
1300 bool QV4IRBuilder::visit(AST::FunctionDeclaration *)
1305 bool QV4IRBuilder::visit(AST::FunctionExpression *)
1310 bool QV4IRBuilder::visit(AST::FormalParameterList *)
1315 bool QV4IRBuilder::visit(AST::FunctionBody *)
1320 bool QV4IRBuilder::visit(AST::DebuggerStatement *)