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 ** 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
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.
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.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include "qdeclarativev4irbuilder_p.h"
44 #include <private/qdeclarativeglobalscriptclass_p.h> // For illegalNames
45 #include <private/qdeclarativeanchors_p_p.h> // For AnchorLine
46 #include <private/qsganchors_p_p.h> // For AnchorLine
47 #include <private/qdeclarativetypenamecache_p.h>
49 DEFINE_BOOL_CONFIG_OPTION(qmlVerboseCompiler, QML_VERBOSE_COMPILER)
53 using namespace QDeclarativeJS;
55 static IR::Type irTypeFromVariantType(int t, QDeclarativeEnginePrivate *engine, const QMetaObject *meta)
64 case QMetaType::QReal:
67 case QMetaType::QString:
68 return IR::StringType;
74 if (t == qMetaTypeId<QDeclarativeAnchorLine>())
75 return IR::AnchorLineType;
76 else if (t == qMetaTypeId<QSGAnchorLine>())
77 return IR::SGAnchorLineType;
78 else if (const QMetaObject *m = engine->metaObjectForType(t)) {
80 return IR::ObjectType;
83 return IR::InvalidType;
87 QDeclarativeV4IRBuilder::QDeclarativeV4IRBuilder(const QDeclarativeV4Compiler::Expression *expr,
88 QDeclarativeEnginePrivate *engine)
89 : m_expression(expr), m_engine(engine), _module(0), _function(0), _block(0), _discard(false)
93 QDeclarativeJS::IR::Function *
94 QDeclarativeV4IRBuilder::operator()(QDeclarativeJS::IR::Module *module,
95 QDeclarativeJS::AST::Node *ast)
97 bool discarded = false;
99 qSwap(_module, module);
101 IR::Function *function = _module->newFunction();
102 IR::BasicBlock *block = function->newBasicBlock();
104 qSwap(_discard, discarded);
105 qSwap(_function, function);
106 qSwap(_block, block);
109 AST::SourceLocation location;
110 if (AST::ExpressionNode *asExpr = ast->expressionCast()) {
111 r = expression(asExpr);
112 location = asExpr->firstSourceLocation();
113 } else if (AST::Statement *asStmt = ast->statementCast()) {
114 r = statement(asStmt);
115 location = asStmt->firstSourceLocation();
118 //_block->MOVE(_block->TEMP(IR::InvalidType), r.code);
120 const QMetaObject *m = 0;
121 const IR::Type targetType = irTypeFromVariantType(m_expression->property->type, m_engine, m);
122 if (targetType != r.type()) {
123 IR::Expr *x = _block->TEMP(targetType);
124 _block->MOVE(x, r, true);
127 _block->RET(r.code, targetType, location.startLine, location.startColumn);
130 qSwap(_block, block);
131 qSwap(_function, function);
132 qSwap(_discard, discarded);
134 qSwap(_module, module);
136 return discarded?0:function;
139 bool QDeclarativeV4IRBuilder::buildName(QStringList &name,
141 QList<AST::ExpressionNode *> *nodes)
143 if (node->kind == AST::Node::Kind_IdentifierExpression) {
144 name << static_cast<AST::IdentifierExpression*>(node)->name->asString();
145 if (nodes) *nodes << static_cast<AST::IdentifierExpression*>(node);
146 } else if (node->kind == AST::Node::Kind_FieldMemberExpression) {
147 AST::FieldMemberExpression *expr =
148 static_cast<AST::FieldMemberExpression *>(node);
150 if (!buildName(name, expr->base, nodes))
153 name << expr->name->asString();
154 if (nodes) *nodes << expr;
162 void QDeclarativeV4IRBuilder::discard()
167 QDeclarativeV4IRBuilder::ExprResult
168 QDeclarativeV4IRBuilder::expression(AST::ExpressionNode *ast)
176 if (r.is(IR::InvalidType))
179 Q_ASSERT(r.hint == r.format);
186 void QDeclarativeV4IRBuilder::condition(AST::ExpressionNode *ast, IR::BasicBlock *iftrue, IR::BasicBlock *iffalse)
190 ExprResult r(iftrue, iffalse);
195 if (r.format != ExprResult::cx) {
199 Q_ASSERT(r.hint == ExprResult::cx);
200 Q_ASSERT(r.format == ExprResult::ex);
202 if (r.type() != IR::BoolType) {
203 IR::Temp *t = _block->TEMP(IR::BoolType);
208 _block->CJUMP(_block->UNOP(IR::OpIfTrue, r), iftrue, iffalse);
212 QDeclarativeV4IRBuilder::ExprResult
213 QDeclarativeV4IRBuilder::statement(AST::Statement *ast)
221 if (r.is(IR::InvalidType))
224 Q_ASSERT(r.hint == r.format);
231 void QDeclarativeV4IRBuilder::sourceElement(AST::SourceElement *ast)
236 void QDeclarativeV4IRBuilder::implicitCvt(ExprResult &expr, IR::Type type)
238 if (expr.type() == type)
239 return; // nothing to do
241 IR::Expr *x = _block->TEMP(type);
242 _block->MOVE(x, expr.code);
247 bool QDeclarativeV4IRBuilder::visit(AST::UiProgram *)
249 Q_ASSERT(!"unreachable");
253 bool QDeclarativeV4IRBuilder::visit(AST::UiImportList *)
255 Q_ASSERT(!"unreachable");
259 bool QDeclarativeV4IRBuilder::visit(AST::UiImport *)
261 Q_ASSERT(!"unreachable");
265 bool QDeclarativeV4IRBuilder::visit(AST::UiPublicMember *)
267 Q_ASSERT(!"unreachable");
271 bool QDeclarativeV4IRBuilder::visit(AST::UiSourceElement *)
273 Q_ASSERT(!"unreachable");
277 bool QDeclarativeV4IRBuilder::visit(AST::UiObjectDefinition *)
279 Q_ASSERT(!"unreachable");
283 bool QDeclarativeV4IRBuilder::visit(AST::UiObjectInitializer *)
285 Q_ASSERT(!"unreachable");
289 bool QDeclarativeV4IRBuilder::visit(AST::UiObjectBinding *)
291 Q_ASSERT(!"unreachable");
295 bool QDeclarativeV4IRBuilder::visit(AST::UiScriptBinding *)
297 Q_ASSERT(!"unreachable");
301 bool QDeclarativeV4IRBuilder::visit(AST::UiArrayBinding *)
303 Q_ASSERT(!"unreachable");
307 bool QDeclarativeV4IRBuilder::visit(AST::UiObjectMemberList *)
309 Q_ASSERT(!"unreachable");
313 bool QDeclarativeV4IRBuilder::visit(AST::UiArrayMemberList *)
315 Q_ASSERT(!"unreachable");
319 bool QDeclarativeV4IRBuilder::visit(AST::UiQualifiedId *)
321 Q_ASSERT(!"unreachable");
325 bool QDeclarativeV4IRBuilder::visit(AST::UiSignature *)
327 Q_ASSERT(!"unreachable");
331 bool QDeclarativeV4IRBuilder::visit(AST::UiFormalList *)
333 Q_ASSERT(!"unreachable");
337 bool QDeclarativeV4IRBuilder::visit(AST::UiFormal *)
339 Q_ASSERT(!"unreachable");
345 bool QDeclarativeV4IRBuilder::visit(AST::Program *ast)
347 _function = _module->newFunction();
348 _block = _function->newBasicBlock();
349 accept(ast->elements);
353 bool QDeclarativeV4IRBuilder::visit(AST::SourceElements *)
358 bool QDeclarativeV4IRBuilder::visit(AST::FunctionSourceElement *)
360 return true; // look inside
363 bool QDeclarativeV4IRBuilder::visit(AST::StatementSourceElement *)
365 return true; // look inside
369 bool QDeclarativeV4IRBuilder::visit(AST::PropertyNameAndValueList *)
371 Q_ASSERT(!"unreachable");
375 bool QDeclarativeV4IRBuilder::visit(AST::IdentifierPropertyName *)
377 Q_ASSERT(!"unreachable");
381 bool QDeclarativeV4IRBuilder::visit(AST::StringLiteralPropertyName *)
383 Q_ASSERT(!"unreachable");
387 bool QDeclarativeV4IRBuilder::visit(AST::NumericLiteralPropertyName *)
389 Q_ASSERT(!"unreachable");
395 bool QDeclarativeV4IRBuilder::visit(AST::ElementList *)
397 Q_ASSERT(!"unreachable");
401 bool QDeclarativeV4IRBuilder::visit(AST::Elision *)
403 Q_ASSERT(!"unreachable");
409 bool QDeclarativeV4IRBuilder::visit(AST::ArgumentList *)
411 Q_ASSERT(!"unreachable");
416 bool QDeclarativeV4IRBuilder::visit(AST::ObjectLiteral *)
421 bool QDeclarativeV4IRBuilder::visit(AST::ArrayLiteral *)
426 bool QDeclarativeV4IRBuilder::visit(AST::ThisExpression *)
431 bool QDeclarativeV4IRBuilder::visit(AST::IdentifierExpression *ast)
433 const quint32 line = ast->identifierToken.startLine;
434 const quint32 column = ast->identifierToken.startColumn;
436 const QString name = ast->name->asString();
438 if (name.at(0) == QLatin1Char('u') && name.length() == 9 && name == QLatin1String("undefined")) {
439 _expr.code = _block->CONST(IR::UndefinedType, 0); // ### undefined value
440 } else if(m_engine->globalClass->illegalNames().contains(name) ) {
441 if (qmlVerboseCompiler()) qWarning() << "*** illegal symbol:" << name;
443 } else if (const QDeclarativeParser::Object *obj = m_expression->ids.value(name)) {
444 IR::Name *code = _block->ID_OBJECT(name, obj, line, column);
445 if (obj == m_expression->component)
446 code->storage = IR::Name::RootStorage;
448 } else if (QDeclarativeTypeNameCache::Data *typeNameData = m_expression->importCache->data(name)) {
449 if (typeNameData->importedScriptIndex != -1) {
450 // We don't support invoking imported scripts
451 } else if (typeNameData->type) {
452 _expr.code = _block->ATTACH_TYPE(name, typeNameData->type, IR::Name::ScopeStorage, line, column);
453 } else if (typeNameData->typeNamespace) {
454 // We don't support namespaces
456 Q_ASSERT(!"Unreachable");
461 if (m_expression->context != m_expression->component) {
462 // RootStorage is more efficient than ScopeStorage, so prefer that if they are the same
463 QDeclarativePropertyCache *cache = m_expression->context->synthCache;
464 const QMetaObject *metaObject = m_expression->context->metaObject();
465 if (!cache) cache = m_engine->cache(metaObject);
467 QDeclarativePropertyCache::Data *data = cache->property(name);
469 if (data && data->revision != 0) {
470 if (qmlVerboseCompiler())
471 qWarning() << "*** versioned symbol:" << name;
476 if (data && !(data->flags & QDeclarativePropertyCache::Data::IsFunction)) {
477 IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject);
478 _expr.code = _block->SYMBOL(irType, name, metaObject, data->coreIndex, IR::Name::ScopeStorage, line, column);
484 QDeclarativePropertyCache *cache = m_expression->component->synthCache;
485 const QMetaObject *metaObject = m_expression->component->metaObject();
486 if (!cache) cache = m_engine->cache(metaObject);
488 QDeclarativePropertyCache::Data *data = cache->property(name);
490 if (data && data->revision != 0) {
491 if (qmlVerboseCompiler())
492 qWarning() << "*** versioned symbol:" << name;
497 if (data && !(data->flags & QDeclarativePropertyCache::Data::IsFunction)) {
498 IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject);
499 _expr.code = _block->SYMBOL(irType, name, metaObject, data->coreIndex, IR::Name::RootStorage, line, column);
504 if (!found && qmlVerboseCompiler())
505 qWarning() << "*** unknown symbol:" << name;
508 if (_expr.code && _expr.hint == ExprResult::cx) {
509 _expr.format = ExprResult::cx;
511 if (_expr.type() != IR::BoolType) {
512 IR::Temp *t = _block->TEMP(IR::BoolType);
513 _block->MOVE(t, _expr);
517 _block->CJUMP(_expr.code, _expr.iftrue, _expr.iffalse);
524 bool QDeclarativeV4IRBuilder::visit(AST::NullExpression *)
526 // ### TODO: cx format
527 _expr.code = _block->CONST(IR::NullType, 0);
531 bool QDeclarativeV4IRBuilder::visit(AST::TrueLiteral *)
533 // ### TODO: cx format
534 _expr.code = _block->CONST(IR::BoolType, 1);
538 bool QDeclarativeV4IRBuilder::visit(AST::FalseLiteral *)
540 // ### TODO: cx format
541 _expr.code = _block->CONST(IR::BoolType, 0);
545 bool QDeclarativeV4IRBuilder::visit(AST::StringLiteral *ast)
547 // ### TODO: cx format
548 _expr.code = _block->STRING(ast->value->asString());
552 bool QDeclarativeV4IRBuilder::visit(AST::NumericLiteral *ast)
554 if (_expr.hint == ExprResult::cx) {
555 _expr.format = ExprResult::cx;
556 _block->JUMP(ast->value ? _expr.iftrue : _expr.iffalse);
558 _expr.code = _block->CONST(ast->value);
563 bool QDeclarativeV4IRBuilder::visit(AST::RegExpLiteral *)
568 bool QDeclarativeV4IRBuilder::visit(AST::NestedExpression *)
570 return true; // the value of the nested expression
573 bool QDeclarativeV4IRBuilder::visit(AST::ArrayMemberExpression *)
578 bool QDeclarativeV4IRBuilder::visit(AST::FieldMemberExpression *ast)
580 if (IR::Expr *left = expression(ast->base)) {
581 if (IR::Name *baseName = left->asName()) {
582 const quint32 line = ast->identifierToken.startLine;
583 const quint32 column = ast->identifierToken.startColumn;
585 QString name = ast->name->asString();
587 switch(baseName->symbol) {
588 case IR::Name::Unbound:
591 case IR::Name::AttachType:
592 if (name.at(0).isUpper()) {
593 QByteArray utf8Name = name.toUtf8();
594 const char *enumName = utf8Name.constData();
596 const QMetaObject *meta = baseName->declarativeType->metaObject();
598 for (int ii = 0; !found && ii < meta->enumeratorCount(); ++ii) {
599 QMetaEnum e = meta->enumerator(ii);
600 for (int jj = 0; !found && jj < e.keyCount(); ++jj) {
601 if (0 == strcmp(e.key(jj), enumName)) {
603 _expr.code = _block->CONST(IR::IntType, e.value(jj));
608 if (!found && qmlVerboseCompiler())
609 qWarning() << "*** unresolved enum:"
610 << (baseName->id + QLatin1String(".") + ast->name->asString());
611 } else if(const QMetaObject *attachedMeta = baseName->declarativeType->attachedPropertiesType()) {
612 QDeclarativePropertyCache *cache = m_engine->cache(attachedMeta);
613 QDeclarativePropertyCache::Data *data = cache->property(name);
615 if (!data || data->flags & QDeclarativePropertyCache::Data::IsFunction)
616 return false; // Don't support methods (or non-existing properties ;)
618 if(!(data->flags & QDeclarativePropertyCache::Data::IsFinal)) {
619 if (qmlVerboseCompiler())
620 qWarning() << "*** non-final attached property:"
621 << (baseName->id + QLatin1String(".") + ast->name->asString());
622 return false; // We don't know enough about this property
625 IR::Type irType = irTypeFromVariantType(data->propType, m_engine, attachedMeta);
626 _expr.code = _block->SYMBOL(baseName, irType, name, attachedMeta, data->coreIndex, line, column);
630 case IR::Name::IdObject: {
631 const QDeclarativeParser::Object *idObject = baseName->idObject;
632 QDeclarativePropertyCache *cache =
633 idObject->synthCache?idObject->synthCache:m_engine->cache(idObject->metaObject());
635 QDeclarativePropertyCache::Data *data = cache->property(name);
637 if (!data || data->flags & QDeclarativePropertyCache::Data::IsFunction)
638 return false; // Don't support methods (or non-existing properties ;)
640 if (data->revision != 0) {
641 if (qmlVerboseCompiler())
642 qWarning() << "*** versioned symbol:" << name;
647 IR::Type irType = irTypeFromVariantType(data->propType, m_engine, idObject->metaObject());
648 _expr.code = _block->SYMBOL(baseName, irType, name,
649 idObject->metaObject(), data->coreIndex, line, column);
653 case IR::Name::Property:
654 if (baseName->type == IR::ObjectType) {
655 const QMetaObject *m =
656 m_engine->metaObjectForType(baseName->meta->property(baseName->index).userType());
657 QDeclarativePropertyCache *cache = m_engine->cache(m);
659 QDeclarativePropertyCache::Data *data = cache->property(name);
661 if (!data || data->flags & QDeclarativePropertyCache::Data::IsFunction)
662 return false; // Don't support methods (or non-existing properties ;)
664 if(!(data->flags & QDeclarativePropertyCache::Data::IsFinal)) {
665 if (qmlVerboseCompiler())
666 qWarning() << "*** non-final property access:"
667 << (baseName->id + QLatin1String(".") + ast->name->asString());
668 return false; // We don't know enough about this property
671 IR::Type irType = irTypeFromVariantType(data->propType, m_engine, baseName->meta);
672 _expr.code = _block->SYMBOL(baseName, irType, name,
673 baseName->meta, data->coreIndex, line, column);
677 case IR::Name::Object:
687 bool QDeclarativeV4IRBuilder::visit(AST::NewMemberExpression *)
692 bool QDeclarativeV4IRBuilder::visit(AST::NewExpression *)
697 bool QDeclarativeV4IRBuilder::visit(AST::CallExpression *ast)
700 QList<AST::ExpressionNode *> nameNodes;
701 if (buildName(names, ast->base, &nameNodes)) {
702 //ExprResult base = expression(ast->base);
703 const QString id = names.join(QLatin1String("."));
704 const quint32 line = nameNodes.last()->firstSourceLocation().startLine;
705 const quint32 column = nameNodes.last()->firstSourceLocation().startColumn;
706 IR::Expr *base = _block->NAME(id, line, column);
708 QVector<IR::Expr *> args;
709 for (AST::ArgumentList *it = ast->arguments; it; it = it->next)
710 args.append(expression(it->expression));
712 IR::Temp *r = _block->TEMP(IR::InvalidType);
713 IR::Expr *call = _block->CALL(base, args);
714 _block->MOVE(r, call);
715 r->type = call->type;
722 bool QDeclarativeV4IRBuilder::visit(AST::PostIncrementExpression *)
727 bool QDeclarativeV4IRBuilder::visit(AST::PostDecrementExpression *)
732 bool QDeclarativeV4IRBuilder::visit(AST::DeleteExpression *)
737 bool QDeclarativeV4IRBuilder::visit(AST::VoidExpression *)
742 bool QDeclarativeV4IRBuilder::visit(AST::TypeOfExpression *)
747 bool QDeclarativeV4IRBuilder::visit(AST::PreIncrementExpression *)
752 bool QDeclarativeV4IRBuilder::visit(AST::PreDecrementExpression *)
757 bool QDeclarativeV4IRBuilder::visit(AST::UnaryPlusExpression *ast)
759 ExprResult expr = expression(ast->expression);
760 if (expr.isNot(IR::InvalidType)) {
761 if (expr.code->asConst() != 0) {
766 IR::Expr *code = _block->UNOP(IR::OpUPlus, expr);
767 _expr.code = _block->TEMP(code->type);
768 _block->MOVE(_expr, code);
774 bool QDeclarativeV4IRBuilder::visit(AST::UnaryMinusExpression *ast)
776 ExprResult expr = expression(ast->expression);
777 if (expr.isNot(IR::InvalidType)) {
778 if (IR::Const *c = expr.code->asConst()) {
780 _expr.code = _block->CONST(-c->value);
784 IR::Expr *code = _block->UNOP(IR::OpUMinus, expr);
785 _expr.code = _block->TEMP(code->type);
786 _block->MOVE(_expr, code);
792 bool QDeclarativeV4IRBuilder::visit(AST::TildeExpression *ast)
794 ExprResult expr = expression(ast->expression);
795 if (expr.isNot(IR::InvalidType)) {
796 if (IR::Const *c = expr.code->asConst()) {
798 _expr.code = _block->CONST(~int(c->value));
801 IR::Expr *code = _block->UNOP(IR::OpCompl, expr);
802 _expr.code = _block->TEMP(code->type);
803 _block->MOVE(_expr, code);
809 bool QDeclarativeV4IRBuilder::visit(AST::NotExpression *ast)
811 ExprResult expr = expression(ast->expression);
813 if (expr.isNot(IR::InvalidType)) {
814 if (IR::Const *c = expr.code->asConst()) {
816 _expr.code = _block->CONST(!c->value);
820 IR::Expr *code = _block->UNOP(IR::OpNot, expr);
821 _expr.code = _block->TEMP(code->type);
822 _block->MOVE(_expr, code);
824 } else if (expr.hint == ExprResult::cx) {
825 expr.format = ExprResult::cx;
826 _block->CJUMP(_block->UNOP(IR::OpNot, expr), _expr.iftrue, _expr.iffalse);
833 void QDeclarativeV4IRBuilder::binop(AST::BinaryExpression *ast, ExprResult left, ExprResult right)
835 if (IR::Type t = maxType(left.type(), right.type())) {
836 implicitCvt(left, t);
837 implicitCvt(right, t);
839 if (_expr.hint == ExprResult::cx) {
840 _expr.format = ExprResult::cx;
841 _block->CJUMP(_block->BINOP(IR::binaryOperator(ast->op), left, right), _expr.iftrue, _expr.iffalse);
843 IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
844 _expr.code = _block->TEMP(code->type);
845 _block->MOVE(_expr.code, code);
850 bool QDeclarativeV4IRBuilder::visit(AST::BinaryExpression *ast)
853 case QSOperator::And: {
854 if (_expr.hint == ExprResult::cx) {
855 _expr.format = ExprResult::cx;
857 Q_ASSERT(_expr.iffalse != 0);
858 Q_ASSERT(_expr.iftrue != 0);
860 IR::BasicBlock *iftrue = _function->newBasicBlock();
861 condition(ast->left, iftrue, _expr.iffalse);
864 condition(ast->right, _expr.iftrue, _expr.iffalse);
866 IR::BasicBlock *iftrue = _function->newBasicBlock();
867 IR::BasicBlock *iffalse = _function->newBasicBlock();
868 IR::BasicBlock *endif = _function->newBasicBlock();
870 condition(ast->left, iftrue, iffalse);
872 IR::Temp *r = _block->TEMP(IR::InvalidType);
875 _block->MOVE(r, _block->CONST(0)); // ### use the right null value
879 ExprResult right = expression(ast->right);
880 _block->MOVE(r, right);
885 r->type = right.type(); // ### not exactly, it can be IR::BoolType.
890 case QSOperator::Or: {
891 IR::BasicBlock *iftrue = _function->newBasicBlock();
892 IR::BasicBlock *endif = _function->newBasicBlock();
894 ExprResult left = expression(ast->left);
895 IR::Temp *r = _block->TEMP(left.type());
896 _block->MOVE(r, left);
899 if (r->type != IR::BoolType) {
900 cond = _block->TEMP(IR::BoolType);
901 _block->MOVE(cond, r);
904 _block->CJUMP(_block->UNOP(IR::OpNot, cond), iftrue, endif);
907 ExprResult right = expression(ast->right);
908 _block->MOVE(r, right);
910 if (left.type() != right.type())
921 case QSOperator::Ge: {
922 ExprResult left = expression(ast->left);
923 ExprResult right = expression(ast->right);
924 if (left.type() == IR::StringType && right.type() == IR::StringType) {
925 binop(ast, left, right);
926 } else if (left.isValid() && right.isValid()) {
927 implicitCvt(left, IR::RealType);
928 implicitCvt(right, IR::RealType);
929 binop(ast, left, right);
933 case QSOperator::NotEqual:
934 case QSOperator::Equal: {
935 ExprResult left = expression(ast->left);
936 ExprResult right = expression(ast->right);
937 if ((left.type() == IR::NullType || left.type() == IR::UndefinedType) &&
938 (right.type() == IR::NullType || right.type() == IR::UndefinedType)) {
939 const bool isEq = ast->op == QSOperator::Equal;
940 if (_expr.hint == ExprResult::cx) {
941 _expr.format = ExprResult::cx;
942 _block->JUMP(isEq ? _expr.iftrue : _expr.iffalse);
944 _expr.code = _block->CONST(IR::BoolType, isEq ? 1 : 0);
946 } else if ((left.type() == IR::StringType && right.type() >= IR::FirstNumberType) ||
947 (left.type() >= IR::FirstNumberType && right.type() == IR::StringType)) {
948 implicitCvt(left, IR::RealType);
949 implicitCvt(right, IR::RealType);
950 binop(ast, left, right);
951 } else if (left.type() == IR::BoolType || right.type() == IR::BoolType) {
952 implicitCvt(left, IR::BoolType);
953 implicitCvt(right, IR::BoolType);
954 } else if (left.isValid() && right.isValid()) {
955 binop(ast, left, right);
959 case QSOperator::StrictEqual:
960 case QSOperator::StrictNotEqual: {
961 ExprResult left = expression(ast->left);
962 ExprResult right = expression(ast->right);
963 if (left.type() == right.type()) {
964 binop(ast, left, right);
965 } else if (left.type() >= IR::BoolType && right.type() >= IR::BoolType) {
966 // left and right have numeric type (int or real)
967 binop(ast, left, right);
968 } else if (left.isValid() && right.isValid()) {
969 const bool isEq = ast->op == QSOperator::StrictEqual;
970 if (_expr.hint == ExprResult::cx) {
971 _expr.format = ExprResult::cx;
972 _block->JUMP(isEq ? _expr.iftrue : _expr.iffalse);
974 _expr.code = _block->CONST(IR::BoolType, isEq ? 1 : 0);
979 case QSOperator::BitAnd:
980 case QSOperator::BitOr:
981 case QSOperator::BitXor:
982 case QSOperator::LShift:
983 case QSOperator::RShift:
984 case QSOperator::URShift: {
985 ExprResult left = expression(ast->left);
986 if (left.is(IR::InvalidType))
989 ExprResult right = expression(ast->right);
990 if (right.is(IR::InvalidType))
993 implicitCvt(left, IR::IntType);
994 implicitCvt(right, IR::IntType);
996 IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
997 _expr.code = _block->TEMP(code->type);
998 _block->MOVE(_expr.code, code);
1002 case QSOperator::Add: {
1003 ExprResult left = expression(ast->left);
1004 if (left.is(IR::InvalidType))
1007 ExprResult right = expression(ast->right);
1008 if (right.is(IR::InvalidType))
1011 if (left.isPrimitive() && right.isPrimitive()) {
1012 if (left.type() == IR::StringType || right.type() == IR::StringType) {
1013 implicitCvt(left, IR::StringType);
1014 implicitCvt(right, IR::StringType);
1016 binop(ast, left, right);
1020 case QSOperator::Div:
1021 case QSOperator::Mod:
1022 case QSOperator::Mul:
1023 case QSOperator::Sub: {
1024 ExprResult left = expression(ast->left);
1025 if (left.is(IR::InvalidType))
1028 ExprResult right = expression(ast->right);
1029 if (right.is(IR::InvalidType))
1032 IR::Type t = maxType(left.type(), right.type());
1033 if (t >= IR::FirstNumberType) {
1034 implicitCvt(left, IR::RealType);
1035 implicitCvt(right, IR::RealType);
1037 IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
1038 _expr.code = _block->TEMP(code->type);
1039 _block->MOVE(_expr.code, code);
1043 case QSOperator::In:
1044 case QSOperator::InstanceOf:
1045 case QSOperator::Assign:
1046 case QSOperator::InplaceAnd:
1047 case QSOperator::InplaceSub:
1048 case QSOperator::InplaceDiv:
1049 case QSOperator::InplaceAdd:
1050 case QSOperator::InplaceLeftShift:
1051 case QSOperator::InplaceMod:
1052 case QSOperator::InplaceMul:
1053 case QSOperator::InplaceOr:
1054 case QSOperator::InplaceRightShift:
1055 case QSOperator::InplaceURightShift:
1056 case QSOperator::InplaceXor:
1057 // yup, we don't do those.
1064 bool QDeclarativeV4IRBuilder::visit(AST::ConditionalExpression *ast)
1066 IR::BasicBlock *iftrue = _function->newBasicBlock();
1067 IR::BasicBlock *iffalse = _function->newBasicBlock();
1068 IR::BasicBlock *endif = _function->newBasicBlock();
1070 condition(ast->expression, iftrue, iffalse);
1072 IR::Temp *r = _block->TEMP(IR::InvalidType);
1074 qSwap(_block, iftrue);
1075 ExprResult ok = expression(ast->ok);
1076 _block->MOVE(r, ok);
1077 _block->JUMP(endif);
1078 qSwap(_block, iftrue);
1080 qSwap(_block, iffalse);
1081 ExprResult ko = expression(ast->ko);
1082 _block->MOVE(r, ko);
1083 _block->JUMP(endif);
1084 qSwap(_block, iffalse);
1086 r->type = maxType(ok.type(), ko.type());
1094 bool QDeclarativeV4IRBuilder::visit(AST::Expression *ast)
1096 _block->EXP(expression(ast->left));
1097 _expr = expression(ast->right);
1104 bool QDeclarativeV4IRBuilder::visit(AST::Block *ast)
1106 if (ast->statements && ! ast->statements->next) {
1107 // we have one and only one statement
1108 accept(ast->statements->statement);
1114 bool QDeclarativeV4IRBuilder::visit(AST::StatementList *)
1119 bool QDeclarativeV4IRBuilder::visit(AST::VariableStatement *)
1124 bool QDeclarativeV4IRBuilder::visit(AST::VariableDeclarationList *)
1129 bool QDeclarativeV4IRBuilder::visit(AST::VariableDeclaration *)
1134 bool QDeclarativeV4IRBuilder::visit(AST::EmptyStatement *)
1139 bool QDeclarativeV4IRBuilder::visit(AST::ExpressionStatement *ast)
1141 if (ast->expression) {
1142 // return the value of this expression
1149 bool QDeclarativeV4IRBuilder::visit(AST::IfStatement *ast)
1152 // This is an if statement without an else branch.
1155 IR::BasicBlock *iftrue = _function->newBasicBlock();
1156 IR::BasicBlock *iffalse = _function->newBasicBlock();
1157 IR::BasicBlock *endif = _function->newBasicBlock();
1159 condition(ast->expression, iftrue, iffalse);
1161 IR::Temp *r = _block->TEMP(IR::InvalidType);
1163 qSwap(_block, iftrue);
1164 ExprResult ok = statement(ast->ok);
1165 _block->MOVE(r, ok);
1166 _block->JUMP(endif);
1167 qSwap(_block, iftrue);
1169 qSwap(_block, iffalse);
1170 ExprResult ko = statement(ast->ko);
1171 _block->MOVE(r, ko);
1172 _block->JUMP(endif);
1173 qSwap(_block, iffalse);
1175 r->type = maxType(ok.type(), ko.type());
1184 bool QDeclarativeV4IRBuilder::visit(AST::DoWhileStatement *)
1189 bool QDeclarativeV4IRBuilder::visit(AST::WhileStatement *)
1194 bool QDeclarativeV4IRBuilder::visit(AST::ForStatement *)
1199 bool QDeclarativeV4IRBuilder::visit(AST::LocalForStatement *)
1204 bool QDeclarativeV4IRBuilder::visit(AST::ForEachStatement *)
1209 bool QDeclarativeV4IRBuilder::visit(AST::LocalForEachStatement *)
1215 bool QDeclarativeV4IRBuilder::visit(AST::ContinueStatement *)
1220 bool QDeclarativeV4IRBuilder::visit(AST::BreakStatement *)
1225 bool QDeclarativeV4IRBuilder::visit(AST::ReturnStatement *ast)
1227 if (ast->expression) {
1228 // return the value of the expression
1235 bool QDeclarativeV4IRBuilder::visit(AST::WithStatement *)
1240 bool QDeclarativeV4IRBuilder::visit(AST::SwitchStatement *)
1245 bool QDeclarativeV4IRBuilder::visit(AST::CaseBlock *)
1250 bool QDeclarativeV4IRBuilder::visit(AST::CaseClauses *)
1255 bool QDeclarativeV4IRBuilder::visit(AST::CaseClause *)
1260 bool QDeclarativeV4IRBuilder::visit(AST::DefaultClause *)
1265 bool QDeclarativeV4IRBuilder::visit(AST::LabelledStatement *)
1270 bool QDeclarativeV4IRBuilder::visit(AST::ThrowStatement *)
1275 bool QDeclarativeV4IRBuilder::visit(AST::TryStatement *)
1280 bool QDeclarativeV4IRBuilder::visit(AST::Catch *)
1285 bool QDeclarativeV4IRBuilder::visit(AST::Finally *)
1290 bool QDeclarativeV4IRBuilder::visit(AST::FunctionDeclaration *)
1295 bool QDeclarativeV4IRBuilder::visit(AST::FunctionExpression *)
1300 bool QDeclarativeV4IRBuilder::visit(AST::FormalParameterList *)
1305 bool QDeclarativeV4IRBuilder::visit(AST::FunctionBody *)
1310 bool QDeclarativeV4IRBuilder::visit(AST::DebuggerStatement *)