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)) {
78 return IR::ObjectType;
81 return IR::InvalidType;
85 QV4IRBuilder::QV4IRBuilder(const QV4Compiler::Expression *expr,
86 QDeclarativeEnginePrivate *engine)
87 : m_expression(expr), m_engine(engine), _function(0), _block(0), _discard(false)
91 bool QV4IRBuilder::operator()(QDeclarativeJS::IR::Function *function,
92 QDeclarativeJS::AST::Node *ast)
94 bool discarded = false;
96 IR::BasicBlock *block = function->newBasicBlock();
98 qSwap(_discard, discarded);
99 qSwap(_function, function);
100 qSwap(_block, block);
103 AST::SourceLocation location;
104 if (AST::ExpressionNode *asExpr = ast->expressionCast()) {
105 r = expression(asExpr);
106 location = asExpr->firstSourceLocation();
107 } else if (AST::Statement *asStmt = ast->statementCast()) {
108 r = statement(asStmt);
109 location = asStmt->firstSourceLocation();
112 //_block->MOVE(_block->TEMP(IR::InvalidType), r.code);
114 const QMetaObject *m = 0;
115 const IR::Type targetType = irTypeFromVariantType(m_expression->property->type, m_engine, m);
116 if (targetType != r.type()) {
117 IR::Expr *x = _block->TEMP(targetType);
118 _block->MOVE(x, r, true);
121 _block->RET(r.code, targetType, location.startLine, location.startColumn);
124 qSwap(_block, block);
125 qSwap(_function, function);
126 qSwap(_discard, discarded);
131 bool QV4IRBuilder::buildName(QList<QStringRef> &name,
133 QList<AST::ExpressionNode *> *nodes)
135 if (node->kind == AST::Node::Kind_IdentifierExpression) {
136 name << static_cast<AST::IdentifierExpression*>(node)->name;
137 if (nodes) *nodes << static_cast<AST::IdentifierExpression*>(node);
138 } else if (node->kind == AST::Node::Kind_FieldMemberExpression) {
139 AST::FieldMemberExpression *expr =
140 static_cast<AST::FieldMemberExpression *>(node);
142 if (!buildName(name, expr->base, nodes))
146 if (nodes) *nodes << expr;
154 void QV4IRBuilder::discard()
159 QV4IRBuilder::ExprResult
160 QV4IRBuilder::expression(AST::ExpressionNode *ast)
168 if (r.is(IR::InvalidType))
171 Q_ASSERT(r.hint == r.format);
178 void QV4IRBuilder::condition(AST::ExpressionNode *ast, IR::BasicBlock *iftrue, IR::BasicBlock *iffalse)
182 ExprResult r(iftrue, iffalse);
187 if (r.format != ExprResult::cx) {
191 Q_ASSERT(r.hint == ExprResult::cx);
192 Q_ASSERT(r.format == ExprResult::ex);
194 if (r.type() != IR::BoolType) {
195 IR::Temp *t = _block->TEMP(IR::BoolType);
200 _block->CJUMP(_block->UNOP(IR::OpIfTrue, r), iftrue, iffalse);
204 QV4IRBuilder::ExprResult
205 QV4IRBuilder::statement(AST::Statement *ast)
213 if (r.is(IR::InvalidType))
216 Q_ASSERT(r.hint == r.format);
223 void QV4IRBuilder::sourceElement(AST::SourceElement *ast)
228 void QV4IRBuilder::implicitCvt(ExprResult &expr, IR::Type type)
230 if (expr.type() == type)
231 return; // nothing to do
233 IR::Expr *x = _block->TEMP(type);
234 _block->MOVE(x, expr.code);
239 bool QV4IRBuilder::visit(AST::UiProgram *)
241 Q_ASSERT(!"unreachable");
245 bool QV4IRBuilder::visit(AST::UiImportList *)
247 Q_ASSERT(!"unreachable");
251 bool QV4IRBuilder::visit(AST::UiImport *)
253 Q_ASSERT(!"unreachable");
257 bool QV4IRBuilder::visit(AST::UiPublicMember *)
259 Q_ASSERT(!"unreachable");
263 bool QV4IRBuilder::visit(AST::UiSourceElement *)
265 Q_ASSERT(!"unreachable");
269 bool QV4IRBuilder::visit(AST::UiObjectDefinition *)
271 Q_ASSERT(!"unreachable");
275 bool QV4IRBuilder::visit(AST::UiObjectInitializer *)
277 Q_ASSERT(!"unreachable");
281 bool QV4IRBuilder::visit(AST::UiObjectBinding *)
283 Q_ASSERT(!"unreachable");
287 bool QV4IRBuilder::visit(AST::UiScriptBinding *)
289 Q_ASSERT(!"unreachable");
293 bool QV4IRBuilder::visit(AST::UiArrayBinding *)
295 Q_ASSERT(!"unreachable");
299 bool QV4IRBuilder::visit(AST::UiObjectMemberList *)
301 Q_ASSERT(!"unreachable");
305 bool QV4IRBuilder::visit(AST::UiArrayMemberList *)
307 Q_ASSERT(!"unreachable");
311 bool QV4IRBuilder::visit(AST::UiQualifiedId *)
313 Q_ASSERT(!"unreachable");
317 bool QV4IRBuilder::visit(AST::UiSignature *)
319 Q_ASSERT(!"unreachable");
323 bool QV4IRBuilder::visit(AST::UiFormalList *)
325 Q_ASSERT(!"unreachable");
329 bool QV4IRBuilder::visit(AST::UiFormal *)
331 Q_ASSERT(!"unreachable");
337 bool QV4IRBuilder::visit(AST::Program *)
339 Q_ASSERT(!"unreachable");
343 bool QV4IRBuilder::visit(AST::SourceElements *)
345 Q_ASSERT(!"unreachable");
349 bool QV4IRBuilder::visit(AST::FunctionSourceElement *)
351 Q_ASSERT(!"unreachable");
355 bool QV4IRBuilder::visit(AST::StatementSourceElement *)
357 Q_ASSERT(!"unreachable");
362 bool QV4IRBuilder::visit(AST::PropertyNameAndValueList *)
364 Q_ASSERT(!"unreachable");
368 bool QV4IRBuilder::visit(AST::IdentifierPropertyName *)
370 Q_ASSERT(!"unreachable");
374 bool QV4IRBuilder::visit(AST::StringLiteralPropertyName *)
376 Q_ASSERT(!"unreachable");
380 bool QV4IRBuilder::visit(AST::NumericLiteralPropertyName *)
382 Q_ASSERT(!"unreachable");
388 bool QV4IRBuilder::visit(AST::ElementList *)
390 Q_ASSERT(!"unreachable");
394 bool QV4IRBuilder::visit(AST::Elision *)
396 Q_ASSERT(!"unreachable");
402 bool QV4IRBuilder::visit(AST::ArgumentList *)
404 Q_ASSERT(!"unreachable");
409 bool QV4IRBuilder::visit(AST::ObjectLiteral *)
414 bool QV4IRBuilder::visit(AST::ArrayLiteral *)
419 bool QV4IRBuilder::visit(AST::ThisExpression *)
424 bool QV4IRBuilder::visit(AST::IdentifierExpression *ast)
426 const quint32 line = ast->identifierToken.startLine;
427 const quint32 column = ast->identifierToken.startColumn;
429 const QString name = ast->name.toString();
431 if (name.at(0) == QLatin1Char('u') && name.length() == 9 && name == QLatin1String("undefined")) {
432 _expr.code = _block->CONST(IR::UndefinedType, 0); // ### undefined value
433 } else if (m_engine->v8engine()->illegalNames().contains(name) ) {
434 if (qmlVerboseCompiler()) qWarning() << "*** illegal symbol:" << name;
436 } else if (const QDeclarativeScript::Object *obj = m_expression->ids->value(name)) {
437 IR::Name *code = _block->ID_OBJECT(name, obj, line, column);
438 if (obj == m_expression->component)
439 code->storage = IR::Name::RootStorage;
443 QDeclarativeTypeNameCache::Result r = m_expression->importCache->query(name);
446 _expr.code = _block->ATTACH_TYPE(name, r.type, IR::Name::ScopeStorage, line, column);
448 // We don't support anything else
452 if (m_expression->context != m_expression->component) {
453 // RootStorage is more efficient than ScopeStorage, so prefer that if they are the same
454 QDeclarativePropertyCache *cache = m_expression->context->synthCache;
455 const QMetaObject *metaObject = m_expression->context->metaObject();
456 if (!cache) cache = m_engine->cache(metaObject);
458 QDeclarativePropertyData *data = cache->property(name);
460 if (data && data->revision != 0) {
461 if (qmlVerboseCompiler())
462 qWarning() << "*** versioned symbol:" << name;
467 if (data && !data->isFunction()) {
468 IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject);
469 _expr.code = _block->SYMBOL(irType, name, metaObject, data->coreIndex, IR::Name::ScopeStorage, line, column);
475 QDeclarativePropertyCache *cache = m_expression->component->synthCache;
476 const QMetaObject *metaObject = m_expression->component->metaObject();
477 if (!cache) cache = m_engine->cache(metaObject);
479 QDeclarativePropertyData *data = cache->property(name);
481 if (data && data->revision != 0) {
482 if (qmlVerboseCompiler())
483 qWarning() << "*** versioned symbol:" << name;
488 if (data && !data->isFunction()) {
489 IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject);
490 _expr.code = _block->SYMBOL(irType, name, metaObject, data->coreIndex, IR::Name::RootStorage, line, column);
495 if (!found && qmlVerboseCompiler())
496 qWarning() << "*** unknown symbol:" << name;
500 if (_expr.code && _expr.hint == ExprResult::cx) {
501 _expr.format = ExprResult::cx;
503 if (_expr.type() != IR::BoolType) {
504 IR::Temp *t = _block->TEMP(IR::BoolType);
505 _block->MOVE(t, _expr);
509 _block->CJUMP(_expr.code, _expr.iftrue, _expr.iffalse);
516 bool QV4IRBuilder::visit(AST::NullExpression *)
518 // ### TODO: cx format
519 _expr.code = _block->CONST(IR::NullType, 0);
523 bool QV4IRBuilder::visit(AST::TrueLiteral *)
525 // ### TODO: cx format
526 _expr.code = _block->CONST(IR::BoolType, 1);
530 bool QV4IRBuilder::visit(AST::FalseLiteral *)
532 // ### TODO: cx format
533 _expr.code = _block->CONST(IR::BoolType, 0);
537 bool QV4IRBuilder::visit(AST::StringLiteral *ast)
539 // ### TODO: cx format
540 _expr.code = _block->STRING(ast->value);
544 bool QV4IRBuilder::visit(AST::NumericLiteral *ast)
546 if (_expr.hint == ExprResult::cx) {
547 _expr.format = ExprResult::cx;
548 _block->JUMP(ast->value ? _expr.iftrue : _expr.iffalse);
550 _expr.code = _block->CONST(ast->value);
555 bool QV4IRBuilder::visit(AST::RegExpLiteral *)
560 bool QV4IRBuilder::visit(AST::NestedExpression *)
562 return true; // the value of the nested expression
565 bool QV4IRBuilder::visit(AST::ArrayMemberExpression *)
570 bool QV4IRBuilder::visit(AST::FieldMemberExpression *ast)
572 if (IR::Expr *left = expression(ast->base)) {
573 if (IR::Name *baseName = left->asName()) {
574 const quint32 line = ast->identifierToken.startLine;
575 const quint32 column = ast->identifierToken.startColumn;
577 QString name = ast->name.toString();
579 switch(baseName->symbol) {
580 case IR::Name::Unbound:
583 case IR::Name::AttachType:
584 if (name.at(0).isUpper()) {
585 QByteArray utf8Name = name.toUtf8();
586 const char *enumName = utf8Name.constData();
588 const QMetaObject *meta = baseName->declarativeType->metaObject();
590 for (int ii = 0; !found && ii < meta->enumeratorCount(); ++ii) {
591 QMetaEnum e = meta->enumerator(ii);
592 for (int jj = 0; !found && jj < e.keyCount(); ++jj) {
593 if (0 == strcmp(e.key(jj), enumName)) {
595 _expr.code = _block->CONST(IR::IntType, e.value(jj));
600 if (!found && qmlVerboseCompiler())
601 qWarning() << "*** unresolved enum:"
602 << (*baseName->id + QLatin1String(".") + ast->name.toString());
603 } else if(const QMetaObject *attachedMeta = baseName->declarativeType->attachedPropertiesType()) {
604 QDeclarativePropertyCache *cache = m_engine->cache(attachedMeta);
605 QDeclarativePropertyData *data = cache->property(name);
607 if (!data || data->isFunction())
608 return false; // Don't support methods (or non-existing properties ;)
610 if(!data->isFinal()) {
611 if (qmlVerboseCompiler())
612 qWarning() << "*** non-final attached property:"
613 << (*baseName->id + QLatin1String(".") + ast->name.toString());
614 return false; // We don't know enough about this property
617 IR::Type irType = irTypeFromVariantType(data->propType, m_engine, attachedMeta);
618 _expr.code = _block->SYMBOL(baseName, irType, name, attachedMeta, data->coreIndex, line, column);
622 case IR::Name::IdObject: {
623 const QDeclarativeScript::Object *idObject = baseName->idObject;
624 QDeclarativePropertyCache *cache =
625 idObject->synthCache?idObject->synthCache:m_engine->cache(idObject->metaObject());
627 QDeclarativePropertyData *data = cache->property(name);
629 if (!data || data->isFunction())
630 return false; // Don't support methods (or non-existing properties ;)
632 if (data->revision != 0) {
633 if (qmlVerboseCompiler())
634 qWarning() << "*** versioned symbol:" << name;
639 IR::Type irType = irTypeFromVariantType(data->propType, m_engine, idObject->metaObject());
640 _expr.code = _block->SYMBOL(baseName, irType, name,
641 idObject->metaObject(), data->coreIndex, line, column);
645 case IR::Name::Property:
646 if (baseName->type == IR::ObjectType) {
647 const QMetaObject *m =
648 m_engine->metaObjectForType(baseName->meta->property(baseName->index).userType());
649 QDeclarativePropertyCache *cache = m_engine->cache(m);
651 QDeclarativePropertyData *data = cache->property(name);
653 if (!data || data->isFunction())
654 return false; // Don't support methods (or non-existing properties ;)
656 if(!data->isFinal()) {
657 if (qmlVerboseCompiler())
658 qWarning() << "*** non-final property access:"
659 << (*baseName->id + QLatin1String(".") + ast->name.toString());
660 return false; // We don't know enough about this property
663 IR::Type irType = irTypeFromVariantType(data->propType, m_engine, baseName->meta);
664 _expr.code = _block->SYMBOL(baseName, irType, name,
665 baseName->meta, data->coreIndex, line, column);
669 case IR::Name::Object:
679 bool QV4IRBuilder::preVisit(AST::Node *)
684 bool QV4IRBuilder::visit(AST::NewMemberExpression *)
689 bool QV4IRBuilder::visit(AST::NewExpression *)
694 bool QV4IRBuilder::visit(AST::CallExpression *ast)
696 QList<QStringRef> names;
697 QList<AST::ExpressionNode *> nameNodes;
700 nameNodes.reserve(4);
702 if (buildName(names, ast->base, &nameNodes)) {
703 //ExprResult base = expression(ast->base);
705 for (int i = 0; i < names.size(); ++i) {
707 id += QLatin1Char('.');
710 const AST::SourceLocation loc = nameNodes.last()->firstSourceLocation();
711 IR::Expr *base = _block->NAME(id, loc.startLine, loc.startColumn);
713 IR::ExprList *args = 0, **argsInserter = &args;
714 for (AST::ArgumentList *it = ast->arguments; it; it = it->next) {
715 IR::Expr *arg = expression(it->expression);
716 *argsInserter = _function->pool->New<IR::ExprList>();
717 (*argsInserter)->init(arg);
718 argsInserter = &(*argsInserter)->next;
721 IR::Temp *r = _block->TEMP(IR::InvalidType);
722 IR::Expr *call = _block->CALL(base, args);
723 _block->MOVE(r, call);
724 r->type = call->type;
731 bool QV4IRBuilder::visit(AST::PostIncrementExpression *)
736 bool QV4IRBuilder::visit(AST::PostDecrementExpression *)
741 bool QV4IRBuilder::visit(AST::DeleteExpression *)
746 bool QV4IRBuilder::visit(AST::VoidExpression *)
751 bool QV4IRBuilder::visit(AST::TypeOfExpression *)
756 bool QV4IRBuilder::visit(AST::PreIncrementExpression *)
761 bool QV4IRBuilder::visit(AST::PreDecrementExpression *)
766 bool QV4IRBuilder::visit(AST::UnaryPlusExpression *ast)
768 ExprResult expr = expression(ast->expression);
769 if (expr.isNot(IR::InvalidType)) {
770 if (expr.code->asConst() != 0) {
775 IR::Expr *code = _block->UNOP(IR::OpUPlus, expr);
776 _expr.code = _block->TEMP(code->type);
777 _block->MOVE(_expr, code);
783 bool QV4IRBuilder::visit(AST::UnaryMinusExpression *ast)
785 ExprResult expr = expression(ast->expression);
786 if (expr.isNot(IR::InvalidType)) {
787 if (IR::Const *c = expr.code->asConst()) {
789 _expr.code = _block->CONST(-c->value);
793 IR::Expr *code = _block->UNOP(IR::OpUMinus, expr);
794 _expr.code = _block->TEMP(code->type);
795 _block->MOVE(_expr, code);
801 bool QV4IRBuilder::visit(AST::TildeExpression *ast)
803 ExprResult expr = expression(ast->expression);
804 if (expr.isNot(IR::InvalidType)) {
805 if (IR::Const *c = expr.code->asConst()) {
807 _expr.code = _block->CONST(~int(c->value));
810 IR::Expr *code = _block->UNOP(IR::OpCompl, expr);
811 _expr.code = _block->TEMP(code->type);
812 _block->MOVE(_expr, code);
818 bool QV4IRBuilder::visit(AST::NotExpression *ast)
820 ExprResult expr = expression(ast->expression);
822 if (expr.isNot(IR::InvalidType)) {
823 if (IR::Const *c = expr.code->asConst()) {
825 _expr.code = _block->CONST(!c->value);
829 IR::Expr *code = _block->UNOP(IR::OpNot, expr);
830 _expr.code = _block->TEMP(code->type);
831 _block->MOVE(_expr, code);
833 } else if (expr.hint == ExprResult::cx) {
834 expr.format = ExprResult::cx;
835 _block->CJUMP(_block->UNOP(IR::OpNot, expr), _expr.iftrue, _expr.iffalse);
842 void QV4IRBuilder::binop(AST::BinaryExpression *ast, ExprResult left, ExprResult right)
844 if (IR::Type t = maxType(left.type(), right.type())) {
845 implicitCvt(left, t);
846 implicitCvt(right, t);
848 if (_expr.hint == ExprResult::cx) {
849 _expr.format = ExprResult::cx;
850 _block->CJUMP(_block->BINOP(IR::binaryOperator(ast->op), left, right), _expr.iftrue, _expr.iffalse);
852 IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
853 _expr.code = _block->TEMP(code->type);
854 _block->MOVE(_expr.code, code);
859 bool QV4IRBuilder::visit(AST::BinaryExpression *ast)
862 case QSOperator::And: {
863 if (_expr.hint == ExprResult::cx) {
864 _expr.format = ExprResult::cx;
866 Q_ASSERT(_expr.iffalse != 0);
867 Q_ASSERT(_expr.iftrue != 0);
869 IR::BasicBlock *iftrue = _function->newBasicBlock();
870 condition(ast->left, iftrue, _expr.iffalse);
873 condition(ast->right, _expr.iftrue, _expr.iffalse);
875 IR::BasicBlock *iftrue = _function->newBasicBlock();
876 IR::BasicBlock *iffalse = _function->newBasicBlock();
877 IR::BasicBlock *endif = _function->newBasicBlock();
879 condition(ast->left, iftrue, iffalse);
881 IR::Temp *r = _block->TEMP(IR::InvalidType);
884 _block->MOVE(r, _block->CONST(0)); // ### use the right null value
888 ExprResult right = expression(ast->right);
889 _block->MOVE(r, right);
894 r->type = right.type(); // ### not exactly, it can be IR::BoolType.
899 case QSOperator::Or: {
900 IR::BasicBlock *iftrue = _function->newBasicBlock();
901 IR::BasicBlock *endif = _function->newBasicBlock();
903 ExprResult left = expression(ast->left);
904 IR::Temp *r = _block->TEMP(left.type());
905 _block->MOVE(r, left);
908 if (r->type != IR::BoolType) {
909 cond = _block->TEMP(IR::BoolType);
910 _block->MOVE(cond, r);
913 _block->CJUMP(_block->UNOP(IR::OpNot, cond), iftrue, endif);
916 ExprResult right = expression(ast->right);
917 _block->MOVE(r, right);
919 if (left.type() != right.type())
930 case QSOperator::Ge: {
931 ExprResult left = expression(ast->left);
932 ExprResult right = expression(ast->right);
933 if (left.type() == IR::StringType && right.type() == IR::StringType) {
934 binop(ast, left, right);
935 } else if (left.isValid() && right.isValid()) {
936 implicitCvt(left, IR::RealType);
937 implicitCvt(right, IR::RealType);
938 binop(ast, left, right);
942 case QSOperator::NotEqual:
943 case QSOperator::Equal: {
944 ExprResult left = expression(ast->left);
945 ExprResult right = expression(ast->right);
946 if ((left.type() == IR::NullType || left.type() == IR::UndefinedType) &&
947 (right.type() == IR::NullType || right.type() == IR::UndefinedType)) {
948 const bool isEq = ast->op == QSOperator::Equal;
949 if (_expr.hint == ExprResult::cx) {
950 _expr.format = ExprResult::cx;
951 _block->JUMP(isEq ? _expr.iftrue : _expr.iffalse);
953 _expr.code = _block->CONST(IR::BoolType, isEq ? 1 : 0);
955 } else if ((left.type() == IR::StringType && right.type() >= IR::FirstNumberType) ||
956 (left.type() >= IR::FirstNumberType && right.type() == IR::StringType)) {
957 implicitCvt(left, IR::RealType);
958 implicitCvt(right, IR::RealType);
959 binop(ast, left, right);
960 } else if (left.type() == IR::BoolType || right.type() == IR::BoolType) {
961 implicitCvt(left, IR::BoolType);
962 implicitCvt(right, IR::BoolType);
963 } else if (left.isValid() && right.isValid()) {
964 binop(ast, left, right);
968 case QSOperator::StrictEqual:
969 case QSOperator::StrictNotEqual: {
970 ExprResult left = expression(ast->left);
971 ExprResult right = expression(ast->right);
972 if (left.type() == right.type()) {
973 binop(ast, left, right);
974 } else if (left.type() >= IR::BoolType && right.type() >= IR::BoolType) {
975 // left and right have numeric type (int or real)
976 binop(ast, left, right);
977 } else if (left.isValid() && right.isValid()) {
978 const bool isEq = ast->op == QSOperator::StrictEqual;
979 if (_expr.hint == ExprResult::cx) {
980 _expr.format = ExprResult::cx;
981 _block->JUMP(isEq ? _expr.iftrue : _expr.iffalse);
983 _expr.code = _block->CONST(IR::BoolType, isEq ? 1 : 0);
988 case QSOperator::BitAnd:
989 case QSOperator::BitOr:
990 case QSOperator::BitXor:
991 case QSOperator::LShift:
992 case QSOperator::RShift:
993 case QSOperator::URShift: {
994 ExprResult left = expression(ast->left);
995 if (left.is(IR::InvalidType))
998 ExprResult right = expression(ast->right);
999 if (right.is(IR::InvalidType))
1002 implicitCvt(left, IR::IntType);
1003 implicitCvt(right, IR::IntType);
1005 IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
1006 _expr.code = _block->TEMP(code->type);
1007 _block->MOVE(_expr.code, code);
1011 case QSOperator::Add: {
1012 ExprResult left = expression(ast->left);
1013 if (left.is(IR::InvalidType))
1016 ExprResult right = expression(ast->right);
1017 if (right.is(IR::InvalidType))
1020 if (left.isPrimitive() && right.isPrimitive()) {
1021 if (left.type() == IR::StringType || right.type() == IR::StringType) {
1022 implicitCvt(left, IR::StringType);
1023 implicitCvt(right, IR::StringType);
1025 binop(ast, left, right);
1029 case QSOperator::Div:
1030 case QSOperator::Mod:
1031 case QSOperator::Mul:
1032 case QSOperator::Sub: {
1033 ExprResult left = expression(ast->left);
1034 if (left.is(IR::InvalidType))
1037 ExprResult right = expression(ast->right);
1038 if (right.is(IR::InvalidType))
1041 IR::Type t = maxType(left.type(), right.type());
1042 if (t >= IR::FirstNumberType) {
1043 implicitCvt(left, IR::RealType);
1044 implicitCvt(right, IR::RealType);
1046 IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
1047 _expr.code = _block->TEMP(code->type);
1048 _block->MOVE(_expr.code, code);
1052 case QSOperator::In:
1053 case QSOperator::InstanceOf:
1054 case QSOperator::Assign:
1055 case QSOperator::InplaceAnd:
1056 case QSOperator::InplaceSub:
1057 case QSOperator::InplaceDiv:
1058 case QSOperator::InplaceAdd:
1059 case QSOperator::InplaceLeftShift:
1060 case QSOperator::InplaceMod:
1061 case QSOperator::InplaceMul:
1062 case QSOperator::InplaceOr:
1063 case QSOperator::InplaceRightShift:
1064 case QSOperator::InplaceURightShift:
1065 case QSOperator::InplaceXor:
1066 // yup, we don't do those.
1073 bool QV4IRBuilder::visit(AST::ConditionalExpression *ast)
1075 IR::BasicBlock *iftrue = _function->newBasicBlock();
1076 IR::BasicBlock *iffalse = _function->newBasicBlock();
1077 IR::BasicBlock *endif = _function->newBasicBlock();
1079 condition(ast->expression, iftrue, iffalse);
1081 IR::Temp *r = _block->TEMP(IR::InvalidType);
1083 qSwap(_block, iftrue);
1084 ExprResult ok = expression(ast->ok);
1085 _block->MOVE(r, ok);
1086 _block->JUMP(endif);
1087 qSwap(_block, iftrue);
1089 qSwap(_block, iffalse);
1090 ExprResult ko = expression(ast->ko);
1091 _block->MOVE(r, ko);
1092 _block->JUMP(endif);
1093 qSwap(_block, iffalse);
1095 r->type = maxType(ok.type(), ko.type());
1103 bool QV4IRBuilder::visit(AST::Expression *ast)
1105 _block->EXP(expression(ast->left));
1106 _expr = expression(ast->right);
1113 bool QV4IRBuilder::visit(AST::Block *ast)
1115 if (ast->statements && ! ast->statements->next) {
1116 // we have one and only one statement
1117 accept(ast->statements->statement);
1123 bool QV4IRBuilder::visit(AST::StatementList *)
1128 bool QV4IRBuilder::visit(AST::VariableStatement *)
1133 bool QV4IRBuilder::visit(AST::VariableDeclarationList *)
1138 bool QV4IRBuilder::visit(AST::VariableDeclaration *)
1143 bool QV4IRBuilder::visit(AST::EmptyStatement *)
1148 bool QV4IRBuilder::visit(AST::ExpressionStatement *ast)
1150 if (ast->expression) {
1151 // return the value of this expression
1158 bool QV4IRBuilder::visit(AST::IfStatement *ast)
1161 // This is an if statement without an else branch.
1164 IR::BasicBlock *iftrue = _function->newBasicBlock();
1165 IR::BasicBlock *iffalse = _function->newBasicBlock();
1166 IR::BasicBlock *endif = _function->newBasicBlock();
1168 condition(ast->expression, iftrue, iffalse);
1170 IR::Temp *r = _block->TEMP(IR::InvalidType);
1172 qSwap(_block, iftrue);
1173 ExprResult ok = statement(ast->ok);
1174 _block->MOVE(r, ok);
1175 _block->JUMP(endif);
1176 qSwap(_block, iftrue);
1178 qSwap(_block, iffalse);
1179 ExprResult ko = statement(ast->ko);
1180 _block->MOVE(r, ko);
1181 _block->JUMP(endif);
1182 qSwap(_block, iffalse);
1184 r->type = maxType(ok.type(), ko.type());
1193 bool QV4IRBuilder::visit(AST::DoWhileStatement *)
1198 bool QV4IRBuilder::visit(AST::WhileStatement *)
1203 bool QV4IRBuilder::visit(AST::ForStatement *)
1208 bool QV4IRBuilder::visit(AST::LocalForStatement *)
1213 bool QV4IRBuilder::visit(AST::ForEachStatement *)
1218 bool QV4IRBuilder::visit(AST::LocalForEachStatement *)
1224 bool QV4IRBuilder::visit(AST::ContinueStatement *)
1229 bool QV4IRBuilder::visit(AST::BreakStatement *)
1234 bool QV4IRBuilder::visit(AST::ReturnStatement *ast)
1236 if (ast->expression) {
1237 // return the value of the expression
1244 bool QV4IRBuilder::visit(AST::WithStatement *)
1249 bool QV4IRBuilder::visit(AST::SwitchStatement *)
1254 bool QV4IRBuilder::visit(AST::CaseBlock *)
1259 bool QV4IRBuilder::visit(AST::CaseClauses *)
1264 bool QV4IRBuilder::visit(AST::CaseClause *)
1269 bool QV4IRBuilder::visit(AST::DefaultClause *)
1274 bool QV4IRBuilder::visit(AST::LabelledStatement *)
1279 bool QV4IRBuilder::visit(AST::ThrowStatement *)
1284 bool QV4IRBuilder::visit(AST::TryStatement *)
1289 bool QV4IRBuilder::visit(AST::Catch *)
1294 bool QV4IRBuilder::visit(AST::Finally *)
1299 bool QV4IRBuilder::visit(AST::FunctionDeclaration *)
1304 bool QV4IRBuilder::visit(AST::FunctionExpression *)
1309 bool QV4IRBuilder::visit(AST::FormalParameterList *)
1314 bool QV4IRBuilder::visit(AST::FunctionBody *)
1319 bool QV4IRBuilder::visit(AST::DebuggerStatement *)