diff options
Diffstat (limited to 'src/qml/compiler/qv4jsir.cpp')
-rw-r--r-- | src/qml/compiler/qv4jsir.cpp | 994 |
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 |