2013-06-24 10:07:48 +00:00
|
|
|
/****************************************************************************
|
|
|
|
**
|
|
|
|
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
|
|
|
** Contact: http://www.qt-project.org/legal
|
|
|
|
**
|
2013-06-24 11:50:51 +00:00
|
|
|
** This file is part of the QtQml module of the Qt Toolkit.
|
2013-06-24 10:07:48 +00:00
|
|
|
**
|
|
|
|
** $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$
|
|
|
|
**
|
|
|
|
****************************************************************************/
|
|
|
|
|
2013-04-15 09:50:16 +00:00
|
|
|
#include "qv4debugging_p.h"
|
|
|
|
#include "qv4engine_p.h"
|
2013-03-05 11:49:35 +00:00
|
|
|
#include "qv4jsir_p.h"
|
2012-11-19 13:59:53 +00:00
|
|
|
#include "qv4isel_p.h"
|
2012-12-11 09:03:40 +00:00
|
|
|
#include "qv4isel_util_p.h"
|
2013-04-15 09:50:16 +00:00
|
|
|
#include "qv4functionobject_p.h"
|
2013-05-08 12:24:30 +00:00
|
|
|
#include "qv4function_p.h"
|
2013-10-24 12:51:02 +00:00
|
|
|
#include <private/qqmlpropertycache_p.h>
|
2012-12-11 09:03:40 +00:00
|
|
|
|
|
|
|
#include <QString>
|
|
|
|
|
|
|
|
#include <cassert>
|
2012-11-19 13:59:53 +00:00
|
|
|
|
2013-01-13 21:17:26 +00:00
|
|
|
namespace {
|
2014-01-29 14:11:14 +00:00
|
|
|
Q_GLOBAL_STATIC_WITH_ARGS(QTextStream, qout, (stderr, QIODevice::WriteOnly));
|
|
|
|
#define qout *qout()
|
2013-01-13 21:17:26 +00:00
|
|
|
} // anonymous namespace
|
|
|
|
|
2014-02-14 12:58:40 +00:00
|
|
|
using namespace QV4;
|
|
|
|
using namespace QV4::IR;
|
2012-11-19 13:59:53 +00:00
|
|
|
|
2013-09-01 11:11:00 +00:00
|
|
|
EvalInstructionSelection::EvalInstructionSelection(QV4::ExecutableAllocator *execAllocator, Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator)
|
|
|
|
: useFastLookups(true)
|
2013-08-17 18:48:56 +00:00
|
|
|
, executableAllocator(execAllocator)
|
2013-09-01 11:11:00 +00:00
|
|
|
, irModule(module)
|
2012-12-11 09:03:40 +00:00
|
|
|
{
|
2013-09-01 11:11:00 +00:00
|
|
|
if (!jsGenerator) {
|
|
|
|
jsGenerator = new QV4::Compiler::JSUnitGenerator(module);
|
|
|
|
ownJSGenerator.reset(jsGenerator);
|
|
|
|
}
|
|
|
|
this->jsGenerator = jsGenerator;
|
2013-08-17 18:48:56 +00:00
|
|
|
assert(execAllocator);
|
2012-12-11 09:03:40 +00:00
|
|
|
assert(module);
|
|
|
|
}
|
|
|
|
|
2012-11-19 13:59:53 +00:00
|
|
|
EvalInstructionSelection::~EvalInstructionSelection()
|
|
|
|
{}
|
|
|
|
|
2012-11-20 12:41:49 +00:00
|
|
|
EvalISelFactory::~EvalISelFactory()
|
2012-11-19 13:59:53 +00:00
|
|
|
{}
|
2012-12-11 09:03:40 +00:00
|
|
|
|
2013-08-06 14:41:28 +00:00
|
|
|
QV4::CompiledData::CompilationUnit *EvalInstructionSelection::compile(bool generateUnitData)
|
2012-12-11 09:03:40 +00:00
|
|
|
{
|
2013-09-11 09:26:32 +00:00
|
|
|
for (int i = 0; i < irModule->functions.size(); ++i)
|
|
|
|
run(i);
|
2012-12-13 11:09:04 +00:00
|
|
|
|
2013-08-06 14:41:28 +00:00
|
|
|
QV4::CompiledData::CompilationUnit *unit = backendCompileStep();
|
2014-03-04 15:15:26 +00:00
|
|
|
if (generateUnitData)
|
2013-08-06 14:41:28 +00:00
|
|
|
unit->data = jsGenerator->generateUnit();
|
|
|
|
return unit;
|
2012-12-13 11:09:04 +00:00
|
|
|
}
|
2013-01-13 21:17:26 +00:00
|
|
|
|
2014-02-14 12:58:40 +00:00
|
|
|
void IRDecoder::visitMove(IR::Move *s)
|
2013-01-13 21:17:26 +00:00
|
|
|
{
|
2014-02-14 12:58:40 +00:00
|
|
|
if (IR::Name *n = s->target->asName()) {
|
2013-09-26 12:49:44 +00:00
|
|
|
if (s->source->asTemp() || s->source->asConst()) {
|
|
|
|
setActivationProperty(s->source, *n->id);
|
|
|
|
return;
|
|
|
|
}
|
2014-02-14 12:58:40 +00:00
|
|
|
} else if (IR::Temp *t = s->target->asTemp()) {
|
|
|
|
if (IR::Name *n = s->source->asName()) {
|
2013-10-24 12:51:02 +00:00
|
|
|
if (n->id && *n->id == QStringLiteral("this")) // TODO: `this' should be a builtin.
|
2013-09-26 12:49:44 +00:00
|
|
|
loadThisObject(t);
|
2014-02-14 12:58:40 +00:00
|
|
|
else if (n->builtin == IR::Name::builtin_qml_id_array)
|
2013-11-02 17:48:18 +00:00
|
|
|
loadQmlIdArray(t);
|
2014-02-14 12:58:40 +00:00
|
|
|
else if (n->builtin == IR::Name::builtin_qml_context_object)
|
2013-10-24 12:51:02 +00:00
|
|
|
loadQmlContextObject(t);
|
2014-02-14 12:58:40 +00:00
|
|
|
else if (n->builtin == IR::Name::builtin_qml_scope_object)
|
2013-10-24 12:51:02 +00:00
|
|
|
loadQmlScopeObject(t);
|
2014-02-14 12:58:40 +00:00
|
|
|
else if (n->builtin == IR::Name::builtin_qml_imported_scripts_object)
|
2013-10-29 10:59:54 +00:00
|
|
|
loadQmlImportedScripts(t);
|
2013-11-02 21:46:25 +00:00
|
|
|
else if (n->qmlSingleton)
|
|
|
|
loadQmlSingleton(*n->id, t);
|
2013-09-26 12:49:44 +00:00
|
|
|
else
|
|
|
|
getActivationProperty(n, t);
|
|
|
|
return;
|
2014-02-14 12:58:40 +00:00
|
|
|
} else if (IR::Const *c = s->source->asConst()) {
|
2013-09-26 12:49:44 +00:00
|
|
|
loadConst(c, t);
|
|
|
|
return;
|
2014-02-14 12:58:40 +00:00
|
|
|
} else if (IR::Temp *t2 = s->source->asTemp()) {
|
2013-09-26 12:49:44 +00:00
|
|
|
if (s->swap)
|
|
|
|
swapValues(t2, t);
|
|
|
|
else
|
|
|
|
copyValue(t2, t);
|
|
|
|
return;
|
2014-02-14 12:58:40 +00:00
|
|
|
} else if (IR::String *str = s->source->asString()) {
|
2013-09-26 12:49:44 +00:00
|
|
|
loadString(*str->value, t);
|
|
|
|
return;
|
2014-02-14 12:58:40 +00:00
|
|
|
} else if (IR::RegExp *re = s->source->asRegExp()) {
|
2013-09-26 12:49:44 +00:00
|
|
|
loadRegexp(re, t);
|
|
|
|
return;
|
2014-02-14 12:58:40 +00:00
|
|
|
} else if (IR::Closure *clos = s->source->asClosure()) {
|
2013-09-26 12:49:44 +00:00
|
|
|
initClosure(clos, t);
|
|
|
|
return;
|
2014-02-14 12:58:40 +00:00
|
|
|
} else if (IR::New *ctor = s->source->asNew()) {
|
2013-09-26 12:49:44 +00:00
|
|
|
if (Name *func = ctor->base->asName()) {
|
|
|
|
constructActivationProperty(func, ctor->args, t);
|
2013-01-13 21:17:26 +00:00
|
|
|
return;
|
2014-02-14 12:58:40 +00:00
|
|
|
} else if (IR::Member *member = ctor->base->asMember()) {
|
2013-09-26 12:49:44 +00:00
|
|
|
constructProperty(member->base->asTemp(), *member->name, ctor->args, t);
|
2013-05-02 13:40:35 +00:00
|
|
|
return;
|
2014-02-14 12:58:40 +00:00
|
|
|
} else if (IR::Temp *value = ctor->base->asTemp()) {
|
2013-09-26 12:49:44 +00:00
|
|
|
constructValue(value, ctor->args, t);
|
2013-06-10 14:32:48 +00:00
|
|
|
return;
|
2013-01-13 21:17:26 +00:00
|
|
|
}
|
2014-02-14 12:58:40 +00:00
|
|
|
} else if (IR::Member *m = s->source->asMember()) {
|
2013-11-02 17:48:18 +00:00
|
|
|
if (m->property) {
|
2013-11-02 19:35:33 +00:00
|
|
|
bool captureRequired = true;
|
2013-12-05 13:53:58 +00:00
|
|
|
|
2014-02-14 12:58:40 +00:00
|
|
|
Q_ASSERT(m->kind != IR::Member::MemberOfEnum);
|
2013-12-05 13:53:58 +00:00
|
|
|
const int attachedPropertiesId = m->attachedPropertiesIdOrEnumValue;
|
|
|
|
|
|
|
|
if (_function && attachedPropertiesId == 0 && !m->property->isConstant()) {
|
2014-02-14 12:58:40 +00:00
|
|
|
if (m->kind == IR::Member::MemberOfQmlContextObject) {
|
2013-12-05 13:53:58 +00:00
|
|
|
_function->contextObjectPropertyDependencies.insert(m->property->coreIndex, m->property->notifyIndex);
|
2013-12-04 15:30:54 +00:00
|
|
|
captureRequired = false;
|
2014-02-14 12:58:40 +00:00
|
|
|
} else if (m->kind == IR::Member::MemberOfQmlScopeObject) {
|
2013-12-05 13:53:58 +00:00
|
|
|
_function->scopeObjectPropertyDependencies.insert(m->property->coreIndex, m->property->notifyIndex);
|
2013-12-04 15:30:54 +00:00
|
|
|
captureRequired = false;
|
|
|
|
}
|
2013-11-02 19:35:33 +00:00
|
|
|
}
|
2013-12-05 13:53:58 +00:00
|
|
|
getQObjectProperty(m->base, m->property->coreIndex, captureRequired, attachedPropertiesId, t);
|
2013-10-24 12:51:02 +00:00
|
|
|
return;
|
2013-10-23 14:24:58 +00:00
|
|
|
} else if (m->base->asTemp() || m->base->asConst()) {
|
2013-09-26 12:49:44 +00:00
|
|
|
getProperty(m->base, *m->name, t);
|
2013-01-13 21:17:26 +00:00
|
|
|
return;
|
|
|
|
}
|
2014-02-14 12:58:40 +00:00
|
|
|
} else if (IR::Subscript *ss = s->source->asSubscript()) {
|
2014-02-21 14:48:39 +00:00
|
|
|
getElement(ss->base, ss->index, t);
|
2013-09-26 12:49:44 +00:00
|
|
|
return;
|
2014-02-14 12:58:40 +00:00
|
|
|
} else if (IR::Unop *u = s->source->asUnop()) {
|
|
|
|
if (IR::Temp *e = u->expr->asTemp()) {
|
2013-09-26 12:49:44 +00:00
|
|
|
unop(u->op, e, t);
|
2013-01-13 21:17:26 +00:00
|
|
|
return;
|
|
|
|
}
|
2014-02-14 12:58:40 +00:00
|
|
|
} else if (IR::Binop *b = s->source->asBinop()) {
|
2013-09-26 12:49:44 +00:00
|
|
|
binop(b->op, b->left, b->right, t);
|
|
|
|
return;
|
2014-02-14 12:58:40 +00:00
|
|
|
} else if (IR::Call *c = s->source->asCall()) {
|
2013-09-26 12:49:44 +00:00
|
|
|
if (c->base->asName()) {
|
|
|
|
callBuiltin(c, t);
|
2013-01-13 21:17:26 +00:00
|
|
|
return;
|
2013-09-26 12:49:44 +00:00
|
|
|
} else if (Member *member = c->base->asMember()) {
|
|
|
|
callProperty(member->base, *member->name, c->args, t);
|
|
|
|
return;
|
|
|
|
} else if (Subscript *ss = c->base->asSubscript()) {
|
|
|
|
callSubscript(ss->base, ss->index, c->args, t);
|
|
|
|
return;
|
2014-02-14 12:58:40 +00:00
|
|
|
} else if (IR::Temp *value = c->base->asTemp()) {
|
2013-09-26 12:49:44 +00:00
|
|
|
callValue(value, c->args, t);
|
2013-01-13 21:17:26 +00:00
|
|
|
return;
|
|
|
|
}
|
2014-02-14 12:58:40 +00:00
|
|
|
} else if (IR::Convert *c = s->source->asConvert()) {
|
2013-09-26 12:49:44 +00:00
|
|
|
Q_ASSERT(c->expr->asTemp());
|
|
|
|
convertType(c->expr->asTemp(), t);
|
|
|
|
return;
|
|
|
|
}
|
2014-02-14 12:58:40 +00:00
|
|
|
} else if (IR::Member *m = s->target->asMember()) {
|
2013-09-26 12:49:44 +00:00
|
|
|
if (m->base->asTemp() || m->base->asConst()) {
|
|
|
|
if (s->source->asTemp() || s->source->asConst()) {
|
2014-02-14 12:58:40 +00:00
|
|
|
Q_ASSERT(m->kind != IR::Member::MemberOfEnum);
|
2013-12-05 13:53:58 +00:00
|
|
|
const int attachedPropertiesId = m->attachedPropertiesIdOrEnumValue;
|
|
|
|
if (m->property && attachedPropertiesId == 0) {
|
2013-10-28 14:18:31 +00:00
|
|
|
setQObjectProperty(s->source, m->base, m->property->coreIndex);
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
setProperty(s->source, m->base, *m->name);
|
|
|
|
return;
|
|
|
|
}
|
2013-01-13 21:17:26 +00:00
|
|
|
}
|
|
|
|
}
|
2014-02-14 12:58:40 +00:00
|
|
|
} else if (IR::Subscript *ss = s->target->asSubscript()) {
|
2013-09-26 12:49:44 +00:00
|
|
|
if (s->source->asTemp() || s->source->asConst()) {
|
|
|
|
setElement(s->source, ss->base, ss->index);
|
|
|
|
return;
|
|
|
|
}
|
2013-01-13 21:17:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// For anything else...:
|
|
|
|
Q_UNIMPLEMENTED();
|
2014-02-14 12:58:40 +00:00
|
|
|
s->dump(qout, IR::Stmt::MIR);
|
2013-01-13 21:17:26 +00:00
|
|
|
qout << endl;
|
|
|
|
assert(!"TODO");
|
|
|
|
}
|
|
|
|
|
2013-06-12 11:30:28 +00:00
|
|
|
IRDecoder::~IRDecoder()
|
2013-01-13 21:17:26 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-02-14 12:58:40 +00:00
|
|
|
void IRDecoder::visitExp(IR::Exp *s)
|
2013-01-13 21:17:26 +00:00
|
|
|
{
|
2014-02-14 12:58:40 +00:00
|
|
|
if (IR::Call *c = s->expr->asCall()) {
|
2013-01-13 21:17:26 +00:00
|
|
|
// These are calls where the result is ignored.
|
|
|
|
if (c->base->asName()) {
|
2013-01-16 14:49:42 +00:00
|
|
|
callBuiltin(c, 0);
|
2013-01-23 09:22:52 +00:00
|
|
|
} else if (Temp *value = c->base->asTemp()) {
|
|
|
|
callValue(value, c->args, 0);
|
|
|
|
} else if (Member *member = c->base->asMember()) {
|
2013-05-02 13:40:35 +00:00
|
|
|
Q_ASSERT(member->base->asTemp());
|
|
|
|
callProperty(member->base->asTemp(), *member->name, c->args, 0);
|
2013-01-27 21:39:01 +00:00
|
|
|
} else if (Subscript *s = c->base->asSubscript()) {
|
2013-12-02 15:33:58 +00:00
|
|
|
callSubscript(s->base, s->index, c->args, 0);
|
2013-01-13 21:17:26 +00:00
|
|
|
} else {
|
2013-01-17 15:49:19 +00:00
|
|
|
Q_UNIMPLEMENTED();
|
2013-01-13 21:17:26 +00:00
|
|
|
}
|
|
|
|
} else {
|
2013-01-17 15:49:19 +00:00
|
|
|
Q_UNIMPLEMENTED();
|
2013-01-13 21:17:26 +00:00
|
|
|
}
|
|
|
|
}
|
2013-01-16 14:49:42 +00:00
|
|
|
|
2014-02-14 12:58:40 +00:00
|
|
|
void IRDecoder::callBuiltin(IR::Call *call, IR::Temp *result)
|
2013-01-16 14:49:42 +00:00
|
|
|
{
|
2014-02-14 12:58:40 +00:00
|
|
|
IR::Name *baseName = call->base->asName();
|
2013-01-16 14:49:42 +00:00
|
|
|
assert(baseName != 0);
|
|
|
|
|
|
|
|
switch (baseName->builtin) {
|
2014-02-14 12:58:40 +00:00
|
|
|
case IR::Name::builtin_invalid:
|
2013-01-16 15:29:28 +00:00
|
|
|
callBuiltinInvalid(baseName, call->args, result);
|
2013-01-16 14:49:42 +00:00
|
|
|
return;
|
|
|
|
|
2014-02-14 12:58:40 +00:00
|
|
|
case IR::Name::builtin_typeof: {
|
|
|
|
if (IR::Member *m = call->args->expr->asMember()) {
|
2013-08-23 12:40:33 +00:00
|
|
|
callBuiltinTypeofMember(m->base, *m->name, result);
|
2013-01-16 14:49:42 +00:00
|
|
|
return;
|
2014-02-14 12:58:40 +00:00
|
|
|
} else if (IR::Subscript *ss = call->args->expr->asSubscript()) {
|
2013-08-23 12:40:33 +00:00
|
|
|
callBuiltinTypeofSubscript(ss->base, ss->index, result);
|
2013-01-16 14:49:42 +00:00
|
|
|
return;
|
2014-02-14 12:58:40 +00:00
|
|
|
} else if (IR::Name *n = call->args->expr->asName()) {
|
2013-01-16 14:49:42 +00:00
|
|
|
callBuiltinTypeofName(*n->id, result);
|
|
|
|
return;
|
2013-08-23 12:40:33 +00:00
|
|
|
} else if (call->args->expr->asTemp() || call->args->expr->asConst()){
|
|
|
|
callBuiltinTypeofValue(call->args->expr, result);
|
2013-01-16 14:49:42 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
2014-02-14 12:58:40 +00:00
|
|
|
case IR::Name::builtin_delete: {
|
|
|
|
if (IR::Member *m = call->args->expr->asMember()) {
|
2013-01-16 14:49:42 +00:00
|
|
|
callBuiltinDeleteMember(m->base->asTemp(), *m->name, result);
|
|
|
|
return;
|
2014-02-14 12:58:40 +00:00
|
|
|
} else if (IR::Subscript *ss = call->args->expr->asSubscript()) {
|
2013-08-23 12:40:33 +00:00
|
|
|
callBuiltinDeleteSubscript(ss->base->asTemp(), ss->index, result);
|
2013-01-16 14:49:42 +00:00
|
|
|
return;
|
2014-02-14 12:58:40 +00:00
|
|
|
} else if (IR::Name *n = call->args->expr->asName()) {
|
2013-01-16 14:49:42 +00:00
|
|
|
callBuiltinDeleteName(*n->id, result);
|
|
|
|
return;
|
|
|
|
} else if (call->args->expr->asTemp()){
|
|
|
|
// TODO: should throw in strict mode
|
|
|
|
callBuiltinDeleteValue(result);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
2014-02-14 12:58:40 +00:00
|
|
|
case IR::Name::builtin_throw: {
|
|
|
|
IR::Expr *arg = call->args->expr;
|
2013-08-23 12:40:33 +00:00
|
|
|
assert(arg->asTemp() || arg->asConst());
|
2013-05-27 12:19:35 +00:00
|
|
|
callBuiltinThrow(arg);
|
2013-01-16 14:49:42 +00:00
|
|
|
} return;
|
|
|
|
|
2014-02-14 12:58:40 +00:00
|
|
|
case IR::Name::builtin_rethrow: {
|
2013-10-18 13:42:17 +00:00
|
|
|
callBuiltinReThrow();
|
|
|
|
} return;
|
|
|
|
|
2014-02-14 12:58:40 +00:00
|
|
|
case IR::Name::builtin_unwind_exception: {
|
2013-10-21 15:07:45 +00:00
|
|
|
callBuiltinUnwindException(result);
|
|
|
|
} return;
|
|
|
|
|
2014-02-14 12:58:40 +00:00
|
|
|
case IR::Name::builtin_push_catch_scope: {
|
|
|
|
IR::String *s = call->args->expr->asString();
|
2013-10-18 13:42:17 +00:00
|
|
|
Q_ASSERT(s);
|
|
|
|
callBuiltinPushCatchScope(*s->value);
|
|
|
|
} return;
|
2013-01-16 14:49:42 +00:00
|
|
|
|
2014-02-14 12:58:40 +00:00
|
|
|
case IR::Name::builtin_foreach_iterator_object: {
|
|
|
|
IR::Temp *arg = call->args->expr->asTemp();
|
2013-01-16 14:49:42 +00:00
|
|
|
assert(arg != 0);
|
|
|
|
callBuiltinForeachIteratorObject(arg, result);
|
|
|
|
} return;
|
|
|
|
|
2014-02-14 12:58:40 +00:00
|
|
|
case IR::Name::builtin_foreach_next_property_name: {
|
|
|
|
IR::Temp *arg = call->args->expr->asTemp();
|
2013-01-16 14:49:42 +00:00
|
|
|
assert(arg != 0);
|
|
|
|
callBuiltinForeachNextPropertyname(arg, result);
|
|
|
|
} return;
|
2014-02-14 12:58:40 +00:00
|
|
|
case IR::Name::builtin_push_with_scope: {
|
|
|
|
IR::Temp *arg = call->args->expr->asTemp();
|
2013-01-16 14:49:42 +00:00
|
|
|
assert(arg != 0);
|
2013-01-24 11:13:47 +00:00
|
|
|
callBuiltinPushWithScope(arg);
|
2013-01-16 14:49:42 +00:00
|
|
|
} return;
|
|
|
|
|
2014-02-14 12:58:40 +00:00
|
|
|
case IR::Name::builtin_pop_scope:
|
2013-01-24 11:13:47 +00:00
|
|
|
callBuiltinPopScope();
|
2013-01-16 14:49:42 +00:00
|
|
|
return;
|
|
|
|
|
2014-02-14 12:58:40 +00:00
|
|
|
case IR::Name::builtin_declare_vars: {
|
2013-01-16 14:49:42 +00:00
|
|
|
if (!call->args)
|
|
|
|
return;
|
2014-02-14 12:58:40 +00:00
|
|
|
IR::Const *deletable = call->args->expr->asConst();
|
|
|
|
assert(deletable->type == IR::BoolType);
|
|
|
|
for (IR::ExprList *it = call->args->next; it; it = it->next) {
|
|
|
|
IR::Name *arg = it->expr->asName();
|
2013-01-16 14:49:42 +00:00
|
|
|
assert(arg != 0);
|
|
|
|
callBuiltinDeclareVar(deletable->value != 0, *arg->id);
|
|
|
|
}
|
|
|
|
} return;
|
|
|
|
|
2014-02-15 01:16:43 +00:00
|
|
|
case IR::Name::builtin_define_array:
|
|
|
|
callBuiltinDefineArray(result, call->args);
|
|
|
|
return;
|
2013-01-16 14:49:42 +00:00
|
|
|
|
2014-02-15 01:16:43 +00:00
|
|
|
case IR::Name::builtin_define_object_literal: {
|
2014-02-14 12:58:40 +00:00
|
|
|
IR::ExprList *args = call->args;
|
2014-02-15 01:16:43 +00:00
|
|
|
const int keyValuePairsCount = args->expr->asConst()->value;
|
2013-01-16 14:49:42 +00:00
|
|
|
args = args->next;
|
|
|
|
|
2014-02-15 01:16:43 +00:00
|
|
|
IR::ExprList *keyValuePairs = args;
|
|
|
|
for (int i = 0; i < keyValuePairsCount; ++i) {
|
|
|
|
args = args->next; // name
|
|
|
|
bool isData = args->expr->asConst()->value;
|
|
|
|
args = args->next; // isData flag
|
|
|
|
args = args->next; // value or getter
|
|
|
|
if (!isData)
|
|
|
|
args = args->next; // setter
|
|
|
|
}
|
2013-01-16 14:49:42 +00:00
|
|
|
|
2014-02-15 01:16:43 +00:00
|
|
|
IR::ExprList *arrayEntries = args;
|
2014-02-15 03:39:33 +00:00
|
|
|
bool needSparseArray = false;
|
|
|
|
for (IR::ExprList *it = arrayEntries; it; it = it->next) {
|
|
|
|
uint index = it->expr->asConst()->value;
|
|
|
|
if (index > 16) {
|
|
|
|
needSparseArray = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
it = it->next;
|
|
|
|
bool isData = it->expr->asConst()->value;
|
|
|
|
it = it->next;
|
|
|
|
if (!isData)
|
|
|
|
it = it->next;
|
|
|
|
}
|
2013-01-24 11:53:47 +00:00
|
|
|
|
2014-02-15 03:39:33 +00:00
|
|
|
callBuiltinDefineObjectLiteral(result, keyValuePairsCount, keyValuePairs, arrayEntries, needSparseArray);
|
2014-02-15 01:16:43 +00:00
|
|
|
} return;
|
2013-04-23 05:31:02 +00:00
|
|
|
|
2014-02-14 12:58:40 +00:00
|
|
|
case IR::Name::builtin_setup_argument_object:
|
2013-08-16 10:54:30 +00:00
|
|
|
callBuiltinSetupArgumentObject(result);
|
|
|
|
return;
|
|
|
|
|
2014-02-14 12:58:40 +00:00
|
|
|
case IR::Name::builtin_convert_this_to_object:
|
2013-11-02 20:10:13 +00:00
|
|
|
callBuiltinConvertThisToObject();
|
|
|
|
return;
|
|
|
|
|
2013-01-16 14:49:42 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
Q_UNIMPLEMENTED();
|
|
|
|
call->dump(qout); qout << endl;
|
|
|
|
assert(!"TODO!");
|
|
|
|
Q_UNREACHABLE();
|
|
|
|
}
|