aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/v4/qv4irbuilder.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2013-04-27 21:26:19 +0200
committerLars Knoll <lars.knoll@digia.com>2013-04-29 14:47:35 +0200
commit382509a7f8753e2a11315eeb2086b27b6bc50a61 (patch)
tree1eb3853a9670a92c9ae6b2349ccf35ff296ead9a /src/qml/qml/v4/qv4irbuilder.cpp
parent7b8af027e5d4188311429dc8df1de67f44e5252d (diff)
Remove the old v4 and rename v4vm to v4
For archeologists v4 can still be found in the history. Otherwise it is confusing to have both engines in the tree. Change-Id: Ice05afb7013f0fe536aab6bb19114f696c58fc94 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/qml/qml/v4/qv4irbuilder.cpp')
-rw-r--r--src/qml/qml/v4/qv4irbuilder.cpp1387
1 files changed, 0 insertions, 1387 deletions
diff --git a/src/qml/qml/v4/qv4irbuilder.cpp b/src/qml/qml/v4/qv4irbuilder.cpp
deleted file mode 100644
index 4aa257d54a..0000000000
--- a/src/qml/qml/v4/qv4irbuilder.cpp
+++ /dev/null
@@ -1,1387 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qv4irbuilder_p.h"
-#include "qv4compiler_p_p.h"
-
-#include <private/qqmlglobal_p.h>
-#include <private/qqmlmetatype_p.h>
-#include <private/qqmltypenamecache_p.h>
-
-DEFINE_BOOL_CONFIG_OPTION(qmlVerboseCompiler, QML_VERBOSE_COMPILER)
-
-QT_BEGIN_NAMESPACE
-
-using namespace QQmlJS;
-
-static IR::Type irTypeFromVariantType(int t, QQmlEnginePrivate *engine)
-{
- switch (t) {
- case QMetaType::Bool:
- return IR::BoolType;
-
- case QMetaType::Int:
- return IR::IntType;
-
- case QMetaType::Float:
- return IR::FloatType;
-
- case QMetaType::Double:
- return IR::NumberType;
-
- case QMetaType::QString:
- return IR::StringType;
-
- case QMetaType::QUrl:
- return IR::UrlType;
-
- case QMetaType::QColor:
- return IR::ColorType;
-
- default:
- if (t == QQmlMetaType::QQuickAnchorLineMetaTypeId()) {
- return IR::SGAnchorLineType;
- } else if (!engine->metaObjectForType(t).isNull()) {
- return IR::ObjectType;
- } else if (t == qMetaTypeId<QJSValue>()) {
- return IR::JSValueType;
- }
-
- return IR::InvalidType;
- }
-}
-
-QV4IRBuilder::QV4IRBuilder(const QV4Compiler::Expression *expr,
- QQmlEnginePrivate *engine)
-: m_expression(expr), m_engine(engine), _function(0), _block(0), _discard(false),
- _invalidatable(false)
-{
-}
-
-bool QV4IRBuilder::operator()(QQmlJS::IR::Function *function,
- QQmlJS::AST::Node *ast, bool *invalidatable)
-{
- bool discarded = false;
-
- IR::BasicBlock *block = function->newBasicBlock();
-
- qSwap(_discard, discarded);
- qSwap(_function, function);
- qSwap(_block, block);
-
- ExprResult r;
- AST::SourceLocation location;
- if (AST::ExpressionNode *asExpr = ast->expressionCast()) {
- r = expression(asExpr);
- location = asExpr->firstSourceLocation();
- } else if (AST::Statement *asStmt = ast->statementCast()) {
- r = statement(asStmt);
- location = asStmt->firstSourceLocation();
- }
-
- //_block->MOVE(_block->TEMP(IR::InvalidType), r.code);
- if (r.code) {
- IR::Type targetType = IR::InvalidType;
-
- // This is the only operation where variant is supported:
- QQmlPropertyData *data = &m_expression->property->core;
- if (data->propType == QMetaType::QVariant) {
- targetType = (data->isVarProperty() ? IR::VarType : IR::VariantType);
- } else {
- targetType = irTypeFromVariantType(data->propType, m_engine);
- }
-
- if (targetType != r.type()) {
- IR::Expr *x = _block->TEMP(targetType);
- _block->MOVE(x, r, true);
- r.code = x;
- }
- _block->RET(r.code, targetType, location.startLine, location.startColumn);
- }
-
- qSwap(_block, block);
- qSwap(_function, function);
- qSwap(_discard, discarded);
-
- *invalidatable = _invalidatable;
- return !discarded;
-}
-
-bool QV4IRBuilder::buildName(QList<QStringRef> &name,
- AST::Node *node,
- QList<AST::ExpressionNode *> *nodes)
-{
- if (node->kind == AST::Node::Kind_IdentifierExpression) {
- name << static_cast<AST::IdentifierExpression*>(node)->name;
- if (nodes) *nodes << static_cast<AST::IdentifierExpression*>(node);
- } else if (node->kind == AST::Node::Kind_FieldMemberExpression) {
- AST::FieldMemberExpression *expr =
- static_cast<AST::FieldMemberExpression *>(node);
-
- if (!buildName(name, expr->base, nodes))
- return false;
-
- name << expr->name;
- if (nodes) *nodes << expr;
- } else {
- return false;
- }
-
- return true;
-}
-
-void QV4IRBuilder::discard()
-{
- _discard = true;
-}
-
-QV4IRBuilder::ExprResult
-QV4IRBuilder::expression(AST::ExpressionNode *ast)
-{
- ExprResult r;
- if (ast) {
- qSwap(_expr, r);
- accept(ast);
- qSwap(_expr, r);
-
- if (r.is(IR::InvalidType))
- discard();
- else {
- Q_ASSERT(r.hint == r.format);
- }
- }
-
- return r;
-}
-
-void QV4IRBuilder::condition(AST::ExpressionNode *ast, IR::BasicBlock *iftrue, IR::BasicBlock *iffalse)
-{
- if (! ast)
- return;
- ExprResult r(iftrue, iffalse);
- qSwap(_expr, r);
- accept(ast);
- qSwap(_expr, r);
-
- if (r.format != ExprResult::cx) {
- if (! r.code)
- discard();
-
- Q_ASSERT(r.hint == ExprResult::cx);
- Q_ASSERT(r.format == ExprResult::ex);
-
- if (r.type() != IR::BoolType) {
- IR::Temp *t = _block->TEMP(IR::BoolType);
- _block->MOVE(t, r);
- r = t;
- }
-
- _block->CJUMP(_block->UNOP(IR::OpIfTrue, r), iftrue, iffalse);
- }
-}
-
-QV4IRBuilder::ExprResult
-QV4IRBuilder::statement(AST::Statement *ast)
-{
- ExprResult r;
- if (ast) {
- qSwap(_expr, r);
- accept(ast);
- qSwap(_expr, r);
-
- if (r.is(IR::InvalidType))
- discard();
- else {
- Q_ASSERT(r.hint == r.format);
- }
- }
-
- return r;
-}
-
-void QV4IRBuilder::sourceElement(AST::SourceElement *ast)
-{
- accept(ast);
-}
-
-void QV4IRBuilder::implicitCvt(ExprResult &expr, IR::Type type)
-{
- if (expr.type() == type)
- return; // nothing to do
-
- IR::Expr *x = _block->TEMP(type);
- _block->MOVE(x, expr.code);
- expr.code = x;
-}
-
-// QML
-bool QV4IRBuilder::visit(AST::UiProgram *)
-{
- Q_ASSERT(!"unreachable");
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::UiImportList *)
-{
- Q_ASSERT(!"unreachable");
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::UiImport *)
-{
- Q_ASSERT(!"unreachable");
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::UiPublicMember *)
-{
- Q_ASSERT(!"unreachable");
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::UiSourceElement *)
-{
- Q_ASSERT(!"unreachable");
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::UiObjectDefinition *)
-{
- Q_ASSERT(!"unreachable");
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::UiObjectInitializer *)
-{
- Q_ASSERT(!"unreachable");
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::UiObjectBinding *)
-{
- Q_ASSERT(!"unreachable");
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::UiScriptBinding *)
-{
- Q_ASSERT(!"unreachable");
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::UiArrayBinding *)
-{
- Q_ASSERT(!"unreachable");
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::UiObjectMemberList *)
-{
- Q_ASSERT(!"unreachable");
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::UiArrayMemberList *)
-{
- Q_ASSERT(!"unreachable");
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::UiQualifiedId *)
-{
- Q_ASSERT(!"unreachable");
- return false;
-}
-
-
-// JS
-bool QV4IRBuilder::visit(AST::Program *)
-{
- Q_ASSERT(!"unreachable");
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::SourceElements *)
-{
- Q_ASSERT(!"unreachable");
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::FunctionSourceElement *)
-{
- Q_ASSERT(!"unreachable");
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::StatementSourceElement *)
-{
- Q_ASSERT(!"unreachable");
- return false;
-}
-
-// object literals
-bool QV4IRBuilder::visit(AST::PropertyAssignmentList *)
-{
- Q_ASSERT(!"unreachable");
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::PropertyNameAndValue *)
-{
- Q_ASSERT(!"unreachable");
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::PropertyGetterSetter *)
-{
- Q_ASSERT(!"unreachable");
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::IdentifierPropertyName *)
-{
- Q_ASSERT(!"unreachable");
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::StringLiteralPropertyName *)
-{
- Q_ASSERT(!"unreachable");
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::NumericLiteralPropertyName *)
-{
- Q_ASSERT(!"unreachable");
- return false;
-}
-
-
-// array literals
-bool QV4IRBuilder::visit(AST::ElementList *)
-{
- Q_ASSERT(!"unreachable");
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::Elision *)
-{
- Q_ASSERT(!"unreachable");
- return false;
-}
-
-
-// function calls
-bool QV4IRBuilder::visit(AST::ArgumentList *)
-{
- Q_ASSERT(!"unreachable");
- return false;
-}
-
-// expressions
-bool QV4IRBuilder::visit(AST::ObjectLiteral *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::ArrayLiteral *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::ThisExpression *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::IdentifierExpression *ast)
-{
- const quint16 line = ast->identifierToken.startLine;
- const quint16 column = ast->identifierToken.startColumn;
-
- const QString name = ast->name.toString();
-
- if (name.at(0) == QLatin1Char('u') && name.length() == 9 && name == QLatin1String("undefined")) {
- _expr.code = _block->CONST(IR::UndefinedType, 0); // ### undefined value
- } else if (m_engine->v8engine()->illegalNames().contains(name) ) {
- if (qmlVerboseCompiler()) qWarning() << "*** illegal symbol:" << name;
- return false;
- } else if (const QQmlScript::Object *obj = m_expression->ids->value(name)) {
- IR::Name *code = _block->ID_OBJECT(name, obj, line, column);
- if (obj == m_expression->component)
- code->storage = IR::Name::RootStorage;
- _expr.code = code;
- } else {
-
- QQmlTypeNameCache::Result r = m_expression->importCache->query(name);
- if (r.isValid()) {
- if (r.type) {
- if (r.type->isSingleton()) {
- // Note: we don't need to check singletonType->qobjectCallback here, since
- // we did that check in registerSingletonType() in qqmlmetatype.cpp.
- // We cannot create the QObject Singleton Type Instance here,
- // as we might be running in a loader thread.
- // Thus, V4 can only handle bindings which use Singleton Types which
- // were registered with the templated registration function.
- _expr.code = _block->SINGLETON_OBJECT(name, r.type->singletonInstanceInfo()->instanceMetaObject, IR::Name::MemberStorage, line, column);
- } else {
- _expr.code = _block->ATTACH_TYPE(name, r.type, IR::Name::ScopeStorage, line, column);
- }
- }
- } else {
- bool found = false;
-
- if (m_expression->context != m_expression->component) {
- // RootStorage is more efficient than ScopeStorage, so prefer that if they are the same
- QQmlPropertyCache *cache = m_expression->context->synthCache;
- if (!cache) cache = m_expression->context->metatype;
-
- QQmlPropertyData *data = cache->property(name, 0, 0);
-
- if (data && data->hasRevision()) {
- if (qmlVerboseCompiler())
- qWarning() << "*** versioned symbol:" << name;
- discard();
- return false;
- }
-
- if (data && !data->isFunction()) {
- IR::Type irType = irTypeFromVariantType(data->propType, m_engine);
- _expr.code = _block->SYMBOL(irType, name, QQmlMetaObject(cache), data, IR::Name::ScopeStorage, line, column);
- found = true;
- }
- }
-
- if (!found) {
- QQmlPropertyCache *cache = m_expression->component->synthCache;
- if (!cache) cache = m_expression->component->metatype;
-
- QQmlPropertyData *data = cache->property(name, 0, 0);
-
- if (data && data->hasRevision()) {
- if (qmlVerboseCompiler())
- qWarning() << "*** versioned symbol:" << name;
- discard();
- return false;
- }
-
- if (data && !data->isFunction()) {
- IR::Type irType = irTypeFromVariantType(data->propType, m_engine);
- _expr.code = _block->SYMBOL(irType, name, QQmlMetaObject(cache), data, IR::Name::RootStorage, line, column);
- found = true;
- }
- }
-
- if (!found && qmlVerboseCompiler())
- qWarning() << "*** unknown symbol:" << name;
- }
- }
-
- if (_expr.code && _expr.hint == ExprResult::cx) {
- _expr.format = ExprResult::cx;
-
- if (_expr.type() != IR::BoolType) {
- IR::Temp *t = _block->TEMP(IR::BoolType);
- _block->MOVE(t, _expr);
- _expr.code = t;
- }
-
- _block->CJUMP(_expr.code, _expr.iftrue, _expr.iffalse);
- _expr.code = 0;
- }
-
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::NullExpression *)
-{
- // ### TODO: cx format
- _expr.code = _block->CONST(IR::NullType, 0);
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::TrueLiteral *)
-{
- // ### TODO: cx format
- _expr.code = _block->CONST(IR::BoolType, 1);
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::FalseLiteral *)
-{
- // ### TODO: cx format
- _expr.code = _block->CONST(IR::BoolType, 0);
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::StringLiteral *ast)
-{
- // ### TODO: cx format
- _expr.code = _block->STRING(ast->value);
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::NumericLiteral *ast)
-{
- if (_expr.hint == ExprResult::cx) {
- _expr.format = ExprResult::cx;
- _block->JUMP(ast->value ? _expr.iftrue : _expr.iffalse);
- } else {
- _expr.code = _block->CONST(IR::NumberType, ast->value);
- }
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::RegExpLiteral *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::NestedExpression *)
-{
- return true; // the value of the nested expression
-}
-
-bool QV4IRBuilder::visit(AST::ArrayMemberExpression *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::FieldMemberExpression *ast)
-{
- if (IR::Expr *left = expression(ast->base)) {
- if (IR::Name *baseName = left->asName()) {
- const quint32 line = ast->identifierToken.startLine;
- const quint32 column = ast->identifierToken.startColumn;
-
- QString name = ast->name.toString();
-
- switch(baseName->symbol) {
- case IR::Name::Unbound:
- break;
-
- case IR::Name::AttachType:
- if (name.at(0).isUpper()) {
- QByteArray utf8Name = name.toUtf8();
- const char *enumName = utf8Name.constData();
-
- const QMetaObject *meta = baseName->declarativeType->metaObject();
- bool found = false;
- for (int ii = 0; !found && ii < meta->enumeratorCount(); ++ii) {
- QMetaEnum e = meta->enumerator(ii);
- for (int jj = 0; !found && jj < e.keyCount(); ++jj) {
- if (0 == strcmp(e.key(jj), enumName)) {
- found = true;
- _expr.code = _block->CONST(IR::IntType, e.value(jj));
- }
- }
- }
-
- if (!found && qmlVerboseCompiler())
- qWarning() << "*** unresolved enum:"
- << (*baseName->id + QLatin1Char('.') + ast->name.toString());
- } else if(const QMetaObject *attachedMeta = baseName->declarativeType->attachedPropertiesType()) {
- QQmlPropertyCache *cache = m_engine->cache(attachedMeta);
- QQmlPropertyData *data = cache->property(name, 0, 0);
-
- if (!data || data->isFunction())
- return false; // Don't support methods (or non-existing properties ;)
-
- if (!data->isFinal())
- _invalidatable = true;
-
- IR::Type irType = irTypeFromVariantType(data->propType, m_engine);
- _expr.code = _block->SYMBOL(baseName, irType, name, attachedMeta, data, line, column);
- }
- break;
-
- case IR::Name::SingletonObject: {
- if (name.at(0).isUpper()) {
- QByteArray utf8Name = name.toUtf8();
- const char *enumName = utf8Name.constData();
-
- const QMetaObject *meta = baseName->meta.propertyCache(m_engine)->firstCppMetaObject();
- bool found = false;
- for (int ii = 0; !found && ii < meta->enumeratorCount(); ++ii) {
- QMetaEnum e = meta->enumerator(ii);
- for (int jj = 0; !found && jj < e.keyCount(); ++jj) {
- if (0 == strcmp(e.key(jj), enumName)) {
- found = true;
- _expr.code = _block->CONST(IR::IntType, e.value(jj));
- }
- }
- }
- if (!found && qmlVerboseCompiler())
- qWarning() << "*** unresolved enum:"
- << (*baseName->id + QLatin1Char('.') + ast->name.toString());
- } else {
- QQmlPropertyCache *cache = baseName->meta.propertyCache(m_engine);
- if (!cache) return false;
- QQmlPropertyData *data = cache->property(name, 0, 0);
-
- if (!data || data->isFunction())
- return false; // Don't support methods (or non-existing properties ;)
-
- if (!data->isFinal())
- _invalidatable = true;
-
- IR::Type irType = irTypeFromVariantType(data->propType, m_engine);
- _expr.code = _block->SYMBOL(baseName, irType, name, baseName->meta, data, line, column);
- }
- }
- break;
-
- case IR::Name::IdObject: {
- const QQmlScript::Object *idObject = baseName->idObject;
- QQmlPropertyCache *cache =
- idObject->synthCache?idObject->synthCache:idObject->metatype;
-
- QQmlPropertyData *data = cache->property(name, 0, 0);
-
- if (!data || data->isFunction())
- return false; // Don't support methods (or non-existing properties ;)
-
- if (data->hasRevision()) {
- if (qmlVerboseCompiler())
- qWarning() << "*** versioned symbol:" << name;
- discard();
- return false;
- }
-
- IR::Type irType = irTypeFromVariantType(data->propType, m_engine);
- _expr.code = _block->SYMBOL(baseName, irType, name, QQmlMetaObject(cache), data, line, column);
- }
- break;
-
- case IR::Name::Property:
- if (baseName->type == IR::ObjectType && !baseName->meta.isNull()) {
- QQmlMetaObject meta = m_engine->metaObjectForType(baseName->property->propType);
- QQmlPropertyCache *cache = meta.propertyCache(m_engine);
- if (!cache)
- return false;
-
- if (QQmlPropertyData *data = cache->property(name, 0, 0)) {
- if (!baseName->property->isFinal() || !data->isFinal())
- _invalidatable = true;
-
- IR::Type irType = irTypeFromVariantType(data->propType, m_engine);
- _expr.code = _block->SYMBOL(baseName, irType, name,
- meta, data, line, column);
- }
- }
- break;
-
- case IR::Name::Object:
- case IR::Name::Slot:
- break;
- }
- }
- }
-
- return false;
-}
-
-bool QV4IRBuilder::preVisit(AST::Node *)
-{
- return ! _discard;
-}
-
-bool QV4IRBuilder::visit(AST::NewMemberExpression *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::NewExpression *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::CallExpression *ast)
-{
- QList<QStringRef> names;
- QList<AST::ExpressionNode *> nameNodes;
-
- names.reserve(4);
- nameNodes.reserve(4);
-
- if (buildName(names, ast->base, &nameNodes)) {
- //ExprResult base = expression(ast->base);
- QString id;
- for (int i = 0; i < names.size(); ++i) {
- if (i)
- id += QLatin1Char('.');
- id += names.at(i);
- }
- const AST::SourceLocation loc = nameNodes.last()->firstSourceLocation();
- IR::Expr *base = _block->NAME(id, loc.startLine, loc.startColumn);
-
- IR::ExprList *args = 0, **argsInserter = &args;
- for (AST::ArgumentList *it = ast->arguments; it; it = it->next) {
- IR::Expr *arg = expression(it->expression);
- *argsInserter = _function->pool->New<IR::ExprList>();
- (*argsInserter)->init(arg);
- argsInserter = &(*argsInserter)->next;
- }
-
- IR::Temp *r = _block->TEMP(IR::InvalidType);
- IR::Expr *call = _block->CALL(base, args);
- _block->MOVE(r, call);
- r->type = call->type;
- _expr.code = r;
- }
-
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::PostIncrementExpression *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::PostDecrementExpression *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::DeleteExpression *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::VoidExpression *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::TypeOfExpression *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::PreIncrementExpression *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::PreDecrementExpression *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::UnaryPlusExpression *ast)
-{
- ExprResult expr = expression(ast->expression);
- if (expr.isNot(IR::InvalidType)) {
- if (expr.code->asConst() != 0) {
- _expr = expr;
- return false;
- }
-
- IR::Expr *code = _block->UNOP(IR::OpUPlus, expr);
- _expr.code = _block->TEMP(code->type);
- _block->MOVE(_expr, code);
- }
-
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::UnaryMinusExpression *ast)
-{
- ExprResult expr = expression(ast->expression);
- if (expr.isNot(IR::InvalidType)) {
- if (IR::Const *c = expr.code->asConst()) {
- _expr = expr;
- _expr.code = _block->CONST(expr->type, -c->value);
- return false;
- }
-
- IR::Expr *code = _block->UNOP(IR::OpUMinus, expr);
- _expr.code = _block->TEMP(code->type);
- _block->MOVE(_expr, code);
- }
-
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::TildeExpression *ast)
-{
- ExprResult expr = expression(ast->expression);
- if (expr.isNot(IR::InvalidType)) {
- if (IR::Const *c = expr.code->asConst()) {
- _expr = expr;
- _expr.code = _block->CONST(expr->type, ~int(c->value));
- return false;
- }
- IR::Expr *code = _block->UNOP(IR::OpCompl, expr);
- _expr.code = _block->TEMP(code->type);
- _block->MOVE(_expr, code);
- }
-
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::NotExpression *ast)
-{
- ExprResult expr = expression(ast->expression);
-
- if (expr.isNot(IR::InvalidType)) {
- if (IR::Const *c = expr.code->asConst()) {
- _expr = expr;
- _expr.code = _block->CONST(IR::BoolType, !c->value);
- return false;
- }
-
- IR::Expr *code = _block->UNOP(IR::OpNot, expr);
- _expr.code = _block->TEMP(code->type);
- _block->MOVE(_expr, code);
-
- } else if (expr.hint == ExprResult::cx) {
- expr.format = ExprResult::cx;
- _block->CJUMP(_block->UNOP(IR::OpNot, expr), _expr.iftrue, _expr.iffalse);
- return false;
- }
-
- return false;
-}
-
-void QV4IRBuilder::binop(AST::BinaryExpression *ast, ExprResult left, ExprResult right)
-{
- if (IR::Type t = maxType(left.type(), right.type())) {
- if (!left->asConst() && !right->asConst()) {
- // the implicit conversions are needed only
- // when compiling non-constant expressions.
- implicitCvt(left, t);
- implicitCvt(right, t);
- }
- } else if ((left.type() != IR::ObjectType && left.type() != IR::NullType) ||
- (right.type() != IR::ObjectType && right.type() != IR::NullType))
- return;
-
- if (_expr.hint == ExprResult::cx) {
- _expr.format = ExprResult::cx;
- _block->CJUMP(_block->BINOP(IR::binaryOperator(ast->op), left, right), _expr.iftrue, _expr.iffalse);
- } else {
- IR::Expr *e = _block->BINOP(IR::binaryOperator(ast->op), left, right);
- if (e->asConst() != 0 || e->asString() != 0)
- _expr.code = e;
- else {
- IR::Temp *t = _block->TEMP(e->type);
- _block->MOVE(t, e);
- _expr.code = t;
- }
- }
-}
-
-bool QV4IRBuilder::visit(AST::BinaryExpression *ast)
-{
- switch (ast->op) {
- case QSOperator::And: {
- if (_expr.hint == ExprResult::cx) {
- _expr.format = ExprResult::cx;
-
- Q_ASSERT(_expr.iffalse != 0);
- Q_ASSERT(_expr.iftrue != 0);
-
- IR::BasicBlock *iftrue = _function->newBasicBlock();
- condition(ast->left, iftrue, _expr.iffalse);
-
- _block = iftrue;
- condition(ast->right, _expr.iftrue, _expr.iffalse);
- } else {
- IR::BasicBlock *iftrue = _function->newBasicBlock();
- IR::BasicBlock *iffalse = _function->newBasicBlock();
- IR::BasicBlock *endif = _function->newBasicBlock();
-
- ExprResult left = expression(ast->left);
- IR::Temp *cond = _block->TEMP(IR::BoolType);
- _block->MOVE(cond, left);
- _block->CJUMP(cond, iftrue, iffalse);
-
- IR::Temp *r = _block->TEMP(IR::InvalidType);
-
- _block = iffalse;
- _block->MOVE(r, cond);
- _block->JUMP(endif);
-
- _block = iftrue;
- ExprResult right = expression(ast->right);
- _block->MOVE(r, right);
- _block->JUMP(endif);
-
- if (left.type() != right.type())
- discard();
-
- _block = endif;
-
- r->type = right.type();
- _expr.code = r;
- }
- } break;
-
- case QSOperator::Or: {
- IR::BasicBlock *iftrue = _function->newBasicBlock();
- IR::BasicBlock *endif = _function->newBasicBlock();
-
- ExprResult left = expression(ast->left);
- IR::Temp *r = _block->TEMP(left.type());
- _block->MOVE(r, left);
-
- IR::Expr *cond = r;
- if (r->type != IR::BoolType) {
- cond = _block->TEMP(IR::BoolType);
- _block->MOVE(cond, r);
- }
-
- _block->CJUMP(_block->UNOP(IR::OpNot, cond), iftrue, endif);
-
- _block = iftrue;
- ExprResult right = expression(ast->right);
- _block->MOVE(r, right);
- _block->JUMP(endif);
-
- if (left.type() != right.type())
- discard();
-
- _expr.code = r;
-
- _block = endif;
- } break;
-
- case QSOperator::Lt:
- case QSOperator::Gt:
- case QSOperator::Le:
- case QSOperator::Ge: {
- ExprResult left = expression(ast->left);
- ExprResult right = expression(ast->right);
- if (left.type() == IR::StringType && right.type() == IR::StringType) {
- binop(ast, left, right);
- } else if (left.isValid() && right.isValid()) {
- implicitCvt(left, IR::NumberType);
- implicitCvt(right, IR::NumberType);
- binop(ast, left, right);
- }
- } break;
-
- case QSOperator::NotEqual:
- case QSOperator::Equal: {
- ExprResult left = expression(ast->left);
- ExprResult right = expression(ast->right);
- if ((left.type() == IR::NullType || left.type() == IR::UndefinedType) &&
- (right.type() == IR::NullType || right.type() == IR::UndefinedType)) {
- const bool isEq = ast->op == QSOperator::Equal;
- if (_expr.hint == ExprResult::cx) {
- _expr.format = ExprResult::cx;
- _block->JUMP(isEq ? _expr.iftrue : _expr.iffalse);
- } else {
- _expr.code = _block->CONST(IR::BoolType, isEq ? 1 : 0);
- }
- } else if ((left.type() == IR::StringType && right.type() >= IR::FirstNumberType) ||
- (left.type() >= IR::FirstNumberType && right.type() == IR::StringType)) {
- implicitCvt(left, IR::NumberType);
- implicitCvt(right, IR::NumberType);
- binop(ast, left, right);
- } else if (left.isValid() && right.isValid()) {
- binop(ast, left, right);
- }
- } break;
-
- case QSOperator::StrictEqual:
- case QSOperator::StrictNotEqual: {
- ExprResult left = expression(ast->left);
- ExprResult right = expression(ast->right);
- if (left.type() == right.type()) {
- binop(ast, left, right);
- } else if (left.type() > IR::BoolType && right.type() > IR::BoolType) {
- // left and right have numeric type (int or real)
- binop(ast, left, right);
- } else if ((left.type() == IR::ObjectType && right.type() == IR::NullType) ||
- (right.type() == IR::ObjectType && left.type() == IR::NullType)) {
- // comparing a qobject with null
- binop(ast, left, right);
- } else if (left.isValid() && right.isValid()) {
- // left and right have different types
- const bool isEq = ast->op == QSOperator::StrictEqual;
- if (_expr.hint == ExprResult::cx) {
- _expr.format = ExprResult::cx;
- _block->JUMP(isEq ? _expr.iffalse : _expr.iftrue);
- } else {
- _expr.code = _block->CONST(IR::BoolType, isEq ? 0 : 1);
- }
- }
- } break;
-
- case QSOperator::BitAnd:
- case QSOperator::BitOr:
- case QSOperator::BitXor:
- case QSOperator::LShift:
- case QSOperator::RShift:
- case QSOperator::URShift: {
- ExprResult left = expression(ast->left);
- if (left.is(IR::InvalidType))
- return false;
-
- ExprResult right = expression(ast->right);
- if (right.is(IR::InvalidType))
- return false;
-
- implicitCvt(left, IR::IntType);
- implicitCvt(right, IR::IntType);
-
- IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
- _expr.code = _block->TEMP(code->type);
- _block->MOVE(_expr.code, code);
-
- } break;
-
- case QSOperator::Add: {
- ExprResult left = expression(ast->left);
- if (left.is(IR::InvalidType))
- return false;
-
- ExprResult right = expression(ast->right);
- if (right.is(IR::InvalidType))
- return false;
-
- if (left.isPrimitive() && right.isPrimitive()) {
- if (left.type() == IR::StringType || right.type() == IR::StringType) {
- implicitCvt(left, IR::StringType);
- implicitCvt(right, IR::StringType);
- }
- binop(ast, left, right);
- }
- } break;
-
- case QSOperator::Div:
- case QSOperator::Mod:
- case QSOperator::Mul:
- case QSOperator::Sub: {
- ExprResult left = expression(ast->left);
- if (left.is(IR::InvalidType))
- return false;
-
- ExprResult right = expression(ast->right);
- if (right.is(IR::InvalidType))
- return false;
-
- IR::Type t = maxType(left.type(), right.type());
- if (t >= IR::FirstNumberType) {
- implicitCvt(left, IR::NumberType);
- implicitCvt(right, IR::NumberType);
-
- IR::Expr *code = _block->BINOP(IR::binaryOperator(ast->op), left, right);
- _expr.code = _block->TEMP(code->type);
- _block->MOVE(_expr.code, code);
- }
- } break;
-
- case QSOperator::In:
- case QSOperator::InstanceOf:
- case QSOperator::Assign:
- case QSOperator::InplaceAnd:
- case QSOperator::InplaceSub:
- case QSOperator::InplaceDiv:
- case QSOperator::InplaceAdd:
- case QSOperator::InplaceLeftShift:
- case QSOperator::InplaceMod:
- case QSOperator::InplaceMul:
- case QSOperator::InplaceOr:
- case QSOperator::InplaceRightShift:
- case QSOperator::InplaceURightShift:
- case QSOperator::InplaceXor:
- // yup, we don't do those.
- break;
- } // switch
-
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::ConditionalExpression *ast)
-{
- IR::BasicBlock *iftrue = _function->newBasicBlock();
- IR::BasicBlock *iffalse = _function->newBasicBlock();
- IR::BasicBlock *endif = _function->newBasicBlock();
-
- condition(ast->expression, iftrue, iffalse);
-
- IR::Temp *r = _block->TEMP(IR::InvalidType);
-
- qSwap(_block, iftrue);
- ExprResult ok = expression(ast->ok);
- _block->MOVE(r, ok);
- _block->JUMP(endif);
- qSwap(_block, iftrue);
-
- qSwap(_block, iffalse);
- ExprResult ko = expression(ast->ko);
- _block->MOVE(r, ko);
- _block->JUMP(endif);
- qSwap(_block, iffalse);
-
- r->type = maxType(ok.type(), ko.type());
- _expr.code = r;
-
- _block = endif;
-
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::Expression *ast)
-{
- _block->EXP(expression(ast->left));
- _expr = expression(ast->right);
-
- return false;
-}
-
-
-// statements
-bool QV4IRBuilder::visit(AST::Block *ast)
-{
- if (ast->statements && ! ast->statements->next) {
- // we have one and only one statement
- accept(ast->statements->statement);
- }
-
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::StatementList *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::VariableStatement *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::VariableDeclarationList *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::VariableDeclaration *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::EmptyStatement *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::ExpressionStatement *ast)
-{
- if (ast->expression) {
- // return the value of this expression
- return true;
- }
-
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::IfStatement *ast)
-{
- if (! ast->ko) {
- // This is an if statement without an else branch.
- discard();
- } else {
- IR::BasicBlock *iftrue = _function->newBasicBlock();
- IR::BasicBlock *iffalse = _function->newBasicBlock();
- IR::BasicBlock *endif = _function->newBasicBlock();
-
- condition(ast->expression, iftrue, iffalse);
-
- IR::Temp *r = _block->TEMP(IR::InvalidType);
-
- qSwap(_block, iftrue);
- ExprResult ok = statement(ast->ok);
- _block->MOVE(r, ok);
- _block->JUMP(endif);
- qSwap(_block, iftrue);
-
- qSwap(_block, iffalse);
- ExprResult ko = statement(ast->ko);
- _block->MOVE(r, ko);
- _block->JUMP(endif);
- qSwap(_block, iffalse);
-
- r->type = maxType(ok.type(), ko.type());
- _expr.code = r;
-
- _block = endif;
- }
-
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::DoWhileStatement *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::WhileStatement *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::ForStatement *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::LocalForStatement *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::ForEachStatement *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::LocalForEachStatement *)
-{
- discard();
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::ContinueStatement *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::BreakStatement *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::ReturnStatement *ast)
-{
- if (ast->expression) {
- // return the value of the expression
- return true;
- }
-
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::WithStatement *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::SwitchStatement *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::CaseBlock *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::CaseClauses *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::CaseClause *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::DefaultClause *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::LabelledStatement *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::ThrowStatement *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::TryStatement *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::Catch *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::Finally *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::FunctionDeclaration *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::FunctionExpression *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::FormalParameterList *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::FunctionBody *)
-{
- return false;
-}
-
-bool QV4IRBuilder::visit(AST::DebuggerStatement *)
-{
- return false;
-}
-
-QT_END_NAMESPACE