aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler/qv4jsir.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/compiler/qv4jsir.cpp')
-rw-r--r--src/qml/compiler/qv4jsir.cpp994
1 files changed, 0 insertions, 994 deletions
diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp
deleted file mode 100644
index 464eb008e7..0000000000
--- a/src/qml/compiler/qv4jsir.cpp
+++ /dev/null
@@ -1,994 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** 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 The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qv4jsir_p.h"
-#include <private/qqmljsast_p.h>
-
-#ifndef V4_BOOTSTRAP
-#include <private/qqmlpropertycache_p.h>
-#endif
-
-#include <QtCore/QBuffer>
-#include <QtCore/qtextstream.h>
-#include <QtCore/qdebug.h>
-#include <QtCore/qset.h>
-#include <cmath>
-
-#include <vector>
-
-#ifdef CONST
-#undef CONST
-#endif
-
-QT_BEGIN_NAMESPACE
-
-namespace QV4 {
-namespace IR {
-
-QString typeName(Type t)
-{
- switch (t) {
- case UnknownType: return QStringLiteral("");
- case MissingType: return QStringLiteral("missing");
- case UndefinedType: return QStringLiteral("undefined");
- case NullType: return QStringLiteral("null");
- case BoolType: return QStringLiteral("bool");
- case UInt32Type: return QStringLiteral("uint32");
- case SInt32Type: return QStringLiteral("int32");
- case DoubleType: return QStringLiteral("double");
- case NumberType: return QStringLiteral("number");
- case StringType: return QStringLiteral("string");
- case VarType: return QStringLiteral("var");
- case QObjectType: return QStringLiteral("qobject");
- default: return QStringLiteral("multiple");
- }
-}
-
-const char *opname(AluOp op)
-{
- switch (op) {
- case OpInvalid: return "?";
-
- case OpIfTrue: return "(bool)";
- case OpNot: return "not";
- case OpUMinus: return "neg";
- case OpUPlus: return "plus";
- case OpCompl: return "invert";
- case OpPreIncrement: return "pre-incr";
- case OpPreDecrement: return "pre-decr";
- case OpPostIncrement: return "post-incr";
- case OpPostDecrement: return "post-decr";
-
- case OpBitAnd: return "bitand";
- case OpBitOr: return "bitor";
- case OpBitXor: return "bitxor";
-
- case OpAdd: return "add";
- case OpSub: return "sub";
- case OpMul: return "mul";
- case OpDiv: return "div";
- case OpMod: return "mod";
-
- case OpLShift: return "shl";
- case OpRShift: return "shr";
- case OpURShift: return "asr";
-
- case OpGt: return "gt";
- case OpLt: return "lt";
- case OpGe: return "ge";
- case OpLe: return "le";
- case OpEqual: return "eq";
- case OpNotEqual: return "ne";
- case OpStrictEqual: return "se";
- case OpStrictNotEqual: return "sne";
-
- case OpInstanceof: return "instanceof";
- case OpIn: return "in";
-
- case OpAnd: return "and";
- case OpOr: return "or";
-
- default: return "?";
-
- } // switch
-}
-
-AluOp binaryOperator(int op)
-{
- switch (static_cast<QSOperator::Op>(op)) {
- case QSOperator::Add: return OpAdd;
- case QSOperator::And: return OpAnd;
- case QSOperator::BitAnd: return OpBitAnd;
- case QSOperator::BitOr: return OpBitOr;
- case QSOperator::BitXor: return OpBitXor;
- case QSOperator::Div: return OpDiv;
- case QSOperator::Equal: return OpEqual;
- case QSOperator::Ge: return OpGe;
- case QSOperator::Gt: return OpGt;
- case QSOperator::Le: return OpLe;
- case QSOperator::LShift: return OpLShift;
- case QSOperator::Lt: return OpLt;
- case QSOperator::Mod: return OpMod;
- case QSOperator::Mul: return OpMul;
- case QSOperator::NotEqual: return OpNotEqual;
- case QSOperator::Or: return OpOr;
- case QSOperator::RShift: return OpRShift;
- case QSOperator::StrictEqual: return OpStrictEqual;
- case QSOperator::StrictNotEqual: return OpStrictNotEqual;
- case QSOperator::Sub: return OpSub;
- case QSOperator::URShift: return OpURShift;
- case QSOperator::InstanceOf: return OpInstanceof;
- case QSOperator::In: return OpIn;
- default: return OpInvalid;
- }
-}
-
-class RemoveSharedExpressions
-{
- CloneExpr clone;
- std::vector<Expr *> subexpressions; // contains all the non-cloned subexpressions in the given function. sorted using std::lower_bound.
- Expr *uniqueExpr;
-
-public:
- RemoveSharedExpressions(): uniqueExpr(0) {}
-
- void operator()(IR::Function *function)
- {
- subexpressions.clear();
- subexpressions.reserve(function->basicBlockCount() * 8);
-
- for (BasicBlock *block : function->basicBlocks()) {
- if (block->isRemoved())
- continue;
- clone.setBasicBlock(block);
-
- for (Stmt *s : block->statements()) {
- visit(s);
- }
- }
- }
-
-private:
- template <typename Expr_>
- Expr_ *cleanup(Expr_ *expr)
- {
- std::vector<Expr *>::iterator it = std::lower_bound(subexpressions.begin(), subexpressions.end(), expr);
- if (it == subexpressions.end() || *it != expr) {
- subexpressions.insert(it, expr);
- IR::Expr *e = expr;
- qSwap(uniqueExpr, e);
- visit(expr);
- qSwap(uniqueExpr, e);
- return static_cast<Expr_ *>(e);
- }
-
- // the cloned expression is unique by definition
- // so we don't need to add it to `subexpressions'.
- return clone(expr);
- }
-
- void visit(Stmt *s)
- {
- if (auto e = s->asExp()) {
- e->expr = cleanup(e->expr);
- } else if (auto m = s->asMove()) {
- m->target = cleanup(m->target);
- m->source = cleanup(m->source);
- } else if (auto c = s->asCJump()) {
- c->cond = cleanup(c->cond);
- } else if (auto r = s->asRet()) {
- r->expr = cleanup(r->expr);
- }
- }
-
- void visit(Expr *e)
- {
- if (auto c = e->asConvert()) {
- c->expr = cleanup(c->expr);
- } else if (auto u = e->asUnop()) {
- u->expr = cleanup(u->expr);
- } else if (auto b = e->asBinop()) {
- b->left = cleanup(b->left);
- b->right = cleanup(b->right);
- } else if (auto c = e->asCall()) {
- c->base = cleanup(c->base);
- for (IR::ExprList *it = c->args; it; it = it->next) {
- it->expr = cleanup(it->expr);
- }
- } else if (auto n = e->asNew()) {
- n->base = cleanup(n->base);
- for (IR::ExprList *it = n->args; it; it = it->next) {
- it->expr = cleanup(it->expr);
- }
- } else if (auto s = e->asSubscript()) {
- s->base = cleanup(s->base);
- s->index = cleanup(s->index);
- } else if (auto m = e->asMember()) {
- m->base = cleanup(m->base);
- }
- }
-};
-
-void Name::initGlobal(const QString *id, quint32 line, quint32 column)
-{
- this->id = id;
- this->builtin = builtin_invalid;
- this->global = true;
- this->qmlSingleton = false;
- this->freeOfSideEffects = false;
- this->line = line;
- this->column = column;
-}
-
-void Name::init(const QString *id, quint32 line, quint32 column)
-{
- this->id = id;
- this->builtin = builtin_invalid;
- this->global = false;
- this->qmlSingleton = false;
- this->freeOfSideEffects = false;
- this->line = line;
- this->column = column;
-}
-
-void Name::init(Builtin builtin, quint32 line, quint32 column)
-{
- this->id = 0;
- this->builtin = builtin;
- this->global = false;
- this->qmlSingleton = false;
- this->freeOfSideEffects = false;
- this->line = line;
- this->column = column;
-}
-
-const char *builtin_to_string(Name::Builtin b)
-{
- switch (b) {
- case Name::builtin_invalid:
- return "builtin_invalid";
- case Name::builtin_typeof:
- return "builtin_typeof";
- case Name::builtin_delete:
- return "builtin_delete";
- case Name::builtin_throw:
- return "builtin_throw";
- case Name::builtin_rethrow:
- return "builtin_rethrow";
- case Name::builtin_unwind_exception:
- return "builtin_unwind_exception";
- case Name::builtin_push_catch_scope:
- return "builtin_push_catch_scope";
- case IR::Name::builtin_foreach_iterator_object:
- return "builtin_foreach_iterator_object";
- case IR::Name::builtin_foreach_next_property_name:
- return "builtin_foreach_next_property_name";
- case IR::Name::builtin_push_with_scope:
- return "builtin_push_with_scope";
- case IR::Name::builtin_pop_scope:
- return "builtin_pop_scope";
- case IR::Name::builtin_declare_vars:
- return "builtin_declare_vars";
- case IR::Name::builtin_define_array:
- return "builtin_define_array";
- case IR::Name::builtin_define_object_literal:
- return "builtin_define_object_literal";
- case IR::Name::builtin_setup_argument_object:
- return "builtin_setup_argument_object";
- case IR::Name::builtin_convert_this_to_object:
- return "builtin_convert_this_to_object";
- case IR::Name::builtin_qml_context:
- return "builtin_qml_context";
- case IR::Name::builtin_qml_imported_scripts_object:
- return "builtin_qml_imported_scripts_object";
- }
- return "builtin_(###FIXME)";
-};
-
-bool operator<(const Temp &t1, const Temp &t2) Q_DECL_NOTHROW
-{
- if (t1.kind < t2.kind) return true;
- if (t1.kind > t2.kind) return false;
- return t1.index < t2.index;
-}
-
-Function *Module::newFunction(const QString &name, Function *outer)
-{
- Function *f = new Function(this, outer, name);
- functions.append(f);
- if (!outer) {
- if (!isQmlModule) {
- Q_ASSERT(!rootFunction);
- rootFunction = f;
- }
- } else {
- outer->nestedFunctions.append(f);
- }
- return f;
-}
-
-Module::~Module()
-{
- qDeleteAll(functions);
-}
-
-void Module::setFileName(const QString &name)
-{
- fileName = name;
-}
-
-Function::Function(Module *module, Function *outer, const QString &name)
- : module(module)
- , pool(&module->pool)
- , tempCount(0)
- , maxNumberOfArguments(0)
- , outer(outer)
- , insideWithOrCatch(0)
- , hasDirectEval(false)
- , usesArgumentsObject(false)
- , isStrict(false)
- , isNamedExpression(false)
- , hasTry(false)
- , hasWith(false)
- , isQmlBinding(false)
- , unused(0)
- , line(0)
- , column(0)
- , _allBasicBlocks(0)
- , _statementCount(0)
-{
- this->name = newString(name);
- _basicBlocks.reserve(8);
-}
-
-Function::~Function()
-{
- if (_allBasicBlocks) {
- qDeleteAll(*_allBasicBlocks);
- delete _allBasicBlocks;
- } else {
- qDeleteAll(_basicBlocks);
- }
-
- pool = 0;
- module = 0;
-}
-
-
-const QString *Function::newString(const QString &text)
-{
- return &*strings.insert(text);
-}
-
-BasicBlock *Function::newBasicBlock(BasicBlock *catchBlock, BasicBlockInsertMode mode)
-{
- BasicBlock *block = new BasicBlock(this, catchBlock);
- return mode == InsertBlock ? addBasicBlock(block) : block;
-}
-
-BasicBlock *Function::addBasicBlock(BasicBlock *block)
-{
- Q_ASSERT(block->index() < 0);
- block->setIndex(_basicBlocks.size());
- _basicBlocks.append(block);
- return block;
-}
-
-void Function::removeBasicBlock(BasicBlock *block)
-{
- block->markAsRemoved();
- block->in.clear();
- block->out.clear();
-}
-
-int Function::liveBasicBlocksCount() const
-{
- int count = 0;
- for (BasicBlock *bb : basicBlocks())
- if (!bb->isRemoved())
- ++count;
- return count;
-}
-
-void Function::removeSharedExpressions()
-{
- RemoveSharedExpressions removeSharedExpressions;
- removeSharedExpressions(this);
-}
-
-int Function::indexOfArgument(const QStringRef &string) const
-{
- for (int i = formals.size() - 1; i >= 0; --i) {
- if (*formals.at(i) == string)
- return i;
- }
- return -1;
-}
-
-void Function::setScheduledBlocks(const QVector<BasicBlock *> &scheduled)
-{
- Q_ASSERT(!_allBasicBlocks);
- _allBasicBlocks = new QVector<BasicBlock *>(basicBlocks());
- _basicBlocks = scheduled;
- for (int i = 0, ei = basicBlockCount(); i != ei; ++i)
- basicBlock(i)->changeIndex(i);
-}
-
-BasicBlock *Function::getOrCreateBasicBlock(int index)
-{
- if (_basicBlocks.size() <= index) {
- const int oldSize = _basicBlocks.size();
- _basicBlocks.resize(index + 1);
- for (int i = oldSize; i <= index; ++i) {
- BasicBlock *block = new BasicBlock(this, 0);
- block->setIndex(i);
- _basicBlocks[i] = block;
- }
- }
-
- return _basicBlocks.at(index);
-}
-
-void Function::setStatementCount(int cnt)
-{
- _statementCount = cnt;
-}
-
-void BasicBlock::setStatements(const QVector<Stmt *> &newStatements)
-{
- Q_ASSERT(!isRemoved());
- Q_ASSERT(newStatements.size() >= _statements.size());
- for (Stmt *s : qAsConst(_statements)) {
- if (Phi *p = s->asPhi()) {
- if (!newStatements.contains(p)) {
- // phi-node was not copied over, so:
- p->destroyData();
- }
- } else {
- break;
- }
- }
- _statements = newStatements;
-}
-
-CloneExpr::CloneExpr(BasicBlock *block)
- : block(block), cloned(0)
-{
-}
-
-void CloneExpr::setBasicBlock(BasicBlock *block)
-{
- this->block = block;
-}
-
-ExprList *CloneExpr::clone(ExprList *list)
-{
- if (! list)
- return 0;
-
- ExprList *clonedList = block->function->New<IR::ExprList>();
- clonedList->init(clone(list->expr), clone(list->next));
- return clonedList;
-}
-
-void CloneExpr::visit(Expr *e)
-{
- if (auto c = e->asConst()) {
- cloned = cloneConst(c, block->function);
- } else if (auto s = e->asString()) {
- cloned = block->STRING(s->value);
- } else if (auto r = e->asRegExp()) {
- cloned = block->REGEXP(r->value, r->flags);
- } else if (auto n = e->asName()) {
- cloned = cloneName(n, block->function);
- } else if (auto t = e->asTemp()) {
- cloned = cloneTemp(t, block->function);
- } else if (auto a = e->asArgLocal()) {
- cloned = cloneArgLocal(a, block->function);
- } else if (auto c = e->asClosure()) {
- cloned = block->CLOSURE(c->value);
- } else if (auto c = e->asConvert()) {
- cloned = block->CONVERT(clone(c->expr), c->type);
- } else if (auto u = e->asUnop()) {
- cloned = block->UNOP(u->op, clone(u->expr));
- } else if (auto b = e->asBinop()) {
- cloned = block->BINOP(b->op, clone(b->left), clone(b->right));
- } else if (auto c = e->asCall()) {
- cloned = block->CALL(clone(c->base), clone(c->args));
- } else if (auto n = e->asNew()) {
- cloned = block->NEW(clone(n->base), clone(n->args));
- } else if (auto s = e->asSubscript()) {
- cloned = block->SUBSCRIPT(clone(s->base), clone(s->index));
- } else if (auto m = e->asMember()) {
- cloned = block->MEMBER(clone(m->base), m->name, m->property, m->kind, m->idIndex);
- } else {
- Q_UNREACHABLE();
- }
-}
-
-IRPrinter::IRPrinter(QTextStream *out)
- : out(out)
- , positionSize(Stmt::InvalidId)
- , currentBB(0)
-{
-}
-
-IRPrinter::~IRPrinter()
-{
-}
-
-void IRPrinter::print(Stmt *s)
-{
- visit(s);
-}
-
-void IRPrinter::print(const Expr &e)
-{
- visit(const_cast<Expr *>(&e));
-}
-
-void IRPrinter::print(Expr *e)
-{
- visit(e);
-}
-
-void IRPrinter::print(Function *f)
-{
- if (positionSize == Stmt::InvalidId)
- positionSize = QString::number(f->statementCount()).size();
-
- QString n = f->name ? *f->name : QString();
- if (n.isEmpty())
- n.sprintf("%p", f);
- *out << "function " << n << '(';
-
- for (int i = 0; i < f->formals.size(); ++i) {
- if (i != 0)
- *out << ", ";
- *out << *f->formals.at(i);
- }
- *out << ')' << endl
- << '{' << endl;
-
- for (const QString *local : qAsConst(f->locals))
- *out << " local var " << *local << endl;
-
- bool needsSeperator = !f->locals.isEmpty();
- for (BasicBlock *bb : f->basicBlocks()) {
- if (bb->isRemoved())
- continue;
-
- if (needsSeperator)
- *out << endl;
- else
- needsSeperator = true;
- print(bb);
- }
- *out << '}' << endl;
-}
-
-void IRPrinter::print(BasicBlock *bb)
-{
- std::swap(currentBB, bb);
- printBlockStart();
-
- for (Stmt *s : currentBB->statements()) {
- if (!s)
- continue;
-
- QByteArray str;
- QBuffer buf(&str);
- buf.open(QIODevice::WriteOnly);
- QTextStream os(&buf);
- QTextStream *prevOut = &os;
- std::swap(out, prevOut);
- addStmtNr(s);
- visit(s);
- if (s->location.startLine) {
- out->flush();
- for (int i = 58 - str.length(); i > 0; --i)
- *out << ' ';
- *out << " ; line: " << s->location.startLine << ", column: " << s->location.startColumn;
- }
-
- out->flush();
- std::swap(out, prevOut);
-
- *out << " " << str << endl;
- }
-
- std::swap(currentBB, bb);
-}
-
-void IRPrinter::visit(Stmt *s)
-{
- if (auto e = s->asExp()) {
- visitExp(e);
- } else if (auto m = s->asMove()) {
- visitMove(m);
- } else if (auto j = s->asJump()) {
- visitJump(j);
- } else if (auto c = s->asCJump()) {
- visitCJump(c);
- } else if (auto r = s->asRet()) {
- visitRet(r);
- } else if (auto p = s->asPhi()) {
- visitPhi(p);
- } else {
- Q_UNREACHABLE();
- }
-}
-
-void IRPrinter::visitExp(Exp *s)
-{
- *out << "void ";
- visit(s->expr);
-}
-
-void IRPrinter::visitMove(Move *s)
-{
- if (Temp *targetTemp = s->target->asTemp())
- if (!s->swap && targetTemp->type != UnknownType)
- *out << typeName(targetTemp->type) << ' ';
-
- visit(s->target);
- *out << ' ';
- if (s->swap)
- *out << "<=> ";
- else
- *out << "= ";
- visit(s->source);
-}
-
-void IRPrinter::visitJump(Jump *s)
-{
- *out << "goto L" << s->target->index();
-}
-
-void IRPrinter::visitCJump(CJump *s)
-{
- *out << "if ";
- visit(s->cond);
- *out << " goto L" << s->iftrue->index()
- << " else goto L" << s->iffalse->index();
-}
-
-void IRPrinter::visitRet(Ret *s)
-{
- *out << "return";
- if (s->expr) {
- *out << ' ';
- visit(s->expr);
- }
-}
-
-void IRPrinter::visitPhi(Phi *s)
-{
- if (s->targetTemp->type != UnknownType)
- *out << typeName(s->targetTemp->type) << ' ';
-
- visit(s->targetTemp);
- *out << " = phi ";
- for (int i = 0, ei = s->incoming.size(); i < ei; ++i) {
- if (i > 0)
- *out << ", ";
- if (currentBB)
- *out << 'L' << currentBB->in.at(i)->index() << ": ";
- if (s->incoming[i])
- visit(s->incoming[i]);
- }
-}
-
-void IRPrinter::visit(Expr *e)
-{
- if (auto c = e->asConst()) {
- visitConst(c);
- } else if (auto s = e->asString()) {
- visitString(s);
- } else if (auto r = e->asRegExp()) {
- visitRegExp(r);
- } else if (auto n = e->asName()) {
- visitName(n);
- } else if (auto t = e->asTemp()) {
- visitTemp(t);
- } else if (auto a = e->asArgLocal()) {
- visitArgLocal(a);
- } else if (auto c = e->asClosure()) {
- visitClosure(c);
- } else if (auto c = e->asConvert()) {
- visitConvert(c);
- } else if (auto u = e->asUnop()) {
- visitUnop(u);
- } else if (auto b = e->asBinop()) {
- visitBinop(b);
- } else if (auto c = e->asCall()) {
- visitCall(c);
- } else if (auto n = e->asNew()) {
- visitNew(n);
- } else if (auto s = e->asSubscript()) {
- visitSubscript(s);
- } else if (auto m = e->asMember()) {
- visitMember(m);
- } else {
- Q_UNREACHABLE();
- }
-}
-
-void IRPrinter::visitConst(Const *e)
-{
- switch (e->type) {
- case QV4::IR::UndefinedType:
- *out << "undefined";
- break;
- case QV4::IR::NullType:
- *out << "null";
- break;
- case QV4::IR::BoolType:
- *out << (e->value ? "true" : "false");
- break;
- case QV4::IR::MissingType:
- *out << "missing";
- break;
- default:
- if (int(e->value) == 0 && int(e->value) == e->value) {
- if (isNegative(e->value))
- *out << "-0";
- else
- *out << "0";
- } else {
- *out << QString::number(e->value, 'g', 16);
- }
- break;
- }
-}
-
-void IRPrinter::visitString(String *e)
-{
- *out << '"' << escape(*e->value) << '"';
-}
-
-void IRPrinter::visitRegExp(RegExp *e)
-{
- char f[3];
- int i = 0;
- if (e->flags & RegExp::RegExp_Global)
- f[i++] = 'g';
- if (e->flags & RegExp::RegExp_IgnoreCase)
- f[i++] = 'i';
- if (e->flags & RegExp::RegExp_Multiline)
- f[i++] = 'm';
- f[i] = 0;
-
- *out << '/' << *e->value << '/' << f;
-}
-
-void IRPrinter::visitName(Name *e)
-{
- if (e->id) {
- if (*e->id != QLatin1String("this"))
- *out << '.';
- *out << *e->id;
- } else {
- *out << builtin_to_string(e->builtin);
- }
-}
-
-void IRPrinter::visitTemp(Temp *e)
-{
- switch (e->kind) {
- case Temp::VirtualRegister: *out << '%' << e->index; break;
- case Temp::PhysicalRegister: *out << (e->type == DoubleType ? "fp" : "r")
- << e->index; break;
- case Temp::StackSlot: *out << '&' << e->index; break;
- default: *out << "INVALID";
- }
-}
-
-void IRPrinter::visitArgLocal(ArgLocal *e)
-{
- switch (e->kind) {
- case ArgLocal::Formal: *out << '#' << e->index; break;
- case ArgLocal::ScopedFormal: *out << '#' << e->index
- << '@' << e->scope; break;
- case ArgLocal::Local: *out << '$' << e->index; break;
- case ArgLocal::ScopedLocal: *out << '$' << e->index
- << '@' << e->scope; break;
- default: *out << "INVALID";
- }
-}
-
-void IRPrinter::visitClosure(Closure *e)
-{
- QString name = e->functionName ? *e->functionName : QString();
- if (name.isEmpty())
- name.sprintf("%x", e->value);
- *out << "closure " << name;
-}
-
-void IRPrinter::visitConvert(Convert *e)
-{
- *out << "convert " << typeName(e->expr->type) << " to " << typeName(e->type) << ' ';
- visit(e->expr);
-}
-
-void IRPrinter::visitUnop(Unop *e)
-{
- *out << opname(e->op) << ' ';
- visit(e->expr);
-}
-
-void IRPrinter::visitBinop(Binop *e)
-{
- *out << opname(e->op) << ' ';
- visit(e->left);
- *out << ", ";
- visit(e->right);
-}
-
-void IRPrinter::visitCall(Call *e)
-{
- *out << "call ";
- visit(e->base);
- *out << '(';
- for (ExprList *it = e->args; it; it = it->next) {
- if (it != e->args)
- *out << ", ";
- visit(it->expr);
- }
- *out << ')';
-}
-
-void IRPrinter::visitNew(New *e)
-{
- *out << "new ";
- visit(e->base);
- *out << '(';
- for (ExprList *it = e->args; it; it = it->next) {
- if (it != e->args)
- *out << ", ";
- visit(it->expr);
- }
- *out << ')';
-}
-
-void IRPrinter::visitSubscript(Subscript *e)
-{
- visit(e->base);
- *out << '[';
- visit(e->index);
- *out << ']';
-}
-
-void IRPrinter::visitMember(Member *e)
-{
- if (e->kind != Member::MemberOfEnum && e->kind != Member::MemberOfIdObjectsArray
- && e->attachedPropertiesId != 0 && !e->base->asTemp())
- *out << "[[attached property from " << e->attachedPropertiesId << "]]";
- else
- visit(e->base);
- *out << '.' << *e->name;
-#ifndef V4_BOOTSTRAP
- if (e->property)
- *out << " (meta-property " << e->property->coreIndex()
- << " <" << QMetaType::typeName(e->property->propType())
- << ">)";
- else if (e->kind == Member::MemberOfIdObjectsArray)
- *out << "(id object " << e->idIndex << ")";
-#endif
-}
-
-QString IRPrinter::escape(const QString &s)
-{
- QString r;
- for (int i = 0; i < s.length(); ++i) {
- const QChar ch = s.at(i);
- if (ch == QLatin1Char('\n'))
- r += QLatin1String("\\n");
- else if (ch == QLatin1Char('\r'))
- r += QLatin1String("\\r");
- else if (ch == QLatin1Char('\\'))
- r += QLatin1String("\\\\");
- else if (ch == QLatin1Char('"'))
- r += QLatin1String("\\\"");
- else if (ch == QLatin1Char('\''))
- r += QLatin1String("\\'");
- else
- r += ch;
- }
- return r;
-}
-
-void IRPrinter::addStmtNr(Stmt *s)
-{
- if (s->id() >= 0)
- addJustifiedNr(s->id());
-}
-
-void IRPrinter::addJustifiedNr(int pos)
-{
- if (positionSize == Stmt::InvalidId) {
- *out << pos << ": ";
- } else {
- QString posStr;
- if (pos != Stmt::InvalidId)
- posStr = QString::number(pos);
- *out << posStr.rightJustified(positionSize);
- if (pos == Stmt::InvalidId)
- *out << " ";
- else
- *out << ": ";
- }
-}
-
-void IRPrinter::printBlockStart()
-{
- if (currentBB->isRemoved()) {
- *out << "(block has been removed)";
- return;
- }
-
- QByteArray str;
- str.append('L');
- str.append(QByteArray::number(currentBB->index()));
- str.append(':');
- if (currentBB->catchBlock) {
- str.append(" (exception handler L");
- str.append(QByteArray::number(currentBB->catchBlock->index()));
- str.append(')');
- }
- for (int i = 66 - str.length(); i; --i)
- str.append(' ');
- *out << str;
-
- *out << "; predecessors:";
- for (BasicBlock *in : qAsConst(currentBB->in))
- *out << " L" << in->index();
- if (currentBB->in.isEmpty())
- *out << " none";
- if (BasicBlock *container = currentBB->containingGroup())
- *out << ", container: L" << container->index();
- if (currentBB->isGroupStart())
- *out << ", loop_header: yes";
- *out << endl;
-}
-
-} // end of namespace IR
-} // end of namespace QV4
-
-QT_END_NAMESPACE