From 2fea3d1899eb8cc81920b631ea73a1f130674950 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Tue, 5 Aug 2014 14:11:16 +0200 Subject: V4 IR: change IR printing to be more readable. New structure: - "comments" now start with a semi-colon, and have a list of key: values. ; predecessors: L17 L26 L36, loop_header: yes ; line: 30, column: 3 - when a temporary has a known type, it is written in front of the teporary when it is being assigned, and not repeated. var %109 = this double %42 = 42 - an expression starts with the operation, followed by the operands that are separated by commas. The type of the operands is the type mentioned when they are assigned. int32 %115 = sub %184, %185 if gt %27, 0 goto L40 else goto L41 - conversions do mention the operand type in order to make them easier to read. double %178 = convert var to double %60 - phi node operands are prefixed by the from-label to make it easy to match those operands with the from-block. double %62 = phi L35: %58, L34: %61 - all names except for "this" and built-ins are prefixed by a dot in order to make it clear that a lookup will occur, just like member accesses. $6 = call .int2char($0) %7 = this %8 = %7.toString() Change-Id: I9f626a91f97ca7c3f27e01a5539f3c4fc10a46b4 Reviewed-by: Simon Hausmann --- src/qml/compiler/qv4jsir.cpp | 246 +++++++++++++++++++++++-------------------- src/qml/compiler/qv4jsir_p.h | 20 ++-- src/qml/compiler/qv4ssa.cpp | 6 +- src/qml/jit/qv4regalloc.cpp | 12 +-- 4 files changed, 146 insertions(+), 138 deletions(-) (limited to 'src') diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp index 4b26ff20b7..36fb66b164 100644 --- a/src/qml/compiler/qv4jsir.cpp +++ b/src/qml/compiler/qv4jsir.cpp @@ -86,41 +86,41 @@ const char *opname(AluOp op) case OpInvalid: return "?"; case OpIfTrue: return "(bool)"; - case OpNot: return "!"; - case OpUMinus: return "-"; - case OpUPlus: return "+"; - case OpCompl: return "~"; - case OpIncrement: return "++"; - case OpDecrement: return "--"; - - case OpBitAnd: return "&"; - case OpBitOr: return "|"; - case OpBitXor: return "^"; - - case OpAdd: return "+"; - case OpSub: return "-"; - case OpMul: return "*"; - case OpDiv: return "/"; - case OpMod: return "%"; - - case OpLShift: return "<<"; - case OpRShift: return ">>"; - case OpURShift: return ">>>"; - - case OpGt: return ">"; - case OpLt: return "<"; - case OpGe: return ">="; - case OpLe: return "<="; - case OpEqual: return "=="; - case OpNotEqual: return "!="; - case OpStrictEqual: return "==="; - case OpStrictNotEqual: return "!=="; + case OpNot: return "not"; + case OpUMinus: return "neg"; + case OpUPlus: return "plus"; + case OpCompl: return "invert"; + case OpIncrement: return "incr"; + case OpDecrement: return "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 "&&"; - case OpOr: return "||"; + case OpAnd: return "and"; + case OpOr: return "or"; default: return "?"; @@ -311,7 +311,7 @@ void Name::init(Builtin builtin, quint32 line, quint32 column) this->column = column; } -static const char *builtin_to_string(Name::Builtin b) +const char *builtin_to_string(Name::Builtin b) { switch (b) { case Name::builtin_invalid: @@ -494,6 +494,26 @@ void Function::renumberBasicBlocks() 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; +} + BasicBlock::~BasicBlock() { foreach (Stmt *s, _statements) @@ -760,7 +780,7 @@ void BasicBlock::setStatements(const QVector &newStatements) void BasicBlock::appendStatement(Stmt *statement) { Q_ASSERT(!isRemoved()); - if (nextLocation.isValid()) + if (nextLocation.startLine) statement->location = nextLocation; _statements.append(statement); } @@ -912,7 +932,8 @@ void CloneExpr::visitMember(Member *e) IRPrinter::IRPrinter(QTextStream *out) : out(out) - , printElse(true) + , positionSize(Stmt::InvalidId) + , currentBB(0) { } @@ -937,6 +958,9 @@ void IRPrinter::print(Expr *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); @@ -951,21 +975,28 @@ void IRPrinter::print(Function *f) << '{' << endl; foreach (const QString *local, f->locals) - *out << " var " << *local << ';' << endl; + *out << " local var " << *local << endl; - foreach (BasicBlock *bb, f->basicBlocks()) - if (!bb->isRemoved()) - print(bb); + bool needsSeperator = !f->locals.isEmpty(); + foreach (BasicBlock *bb, f->basicBlocks()) { + if (bb->isRemoved()) + continue; + + if (needsSeperator) + *out << endl; + else + needsSeperator = true; + print(bb); + } *out << '}' << endl; } void IRPrinter::print(BasicBlock *bb) { - bool prevPrintElse = false; - std::swap(printElse, prevPrintElse); - printBlockStart(bb); + std::swap(currentBB, bb); + printBlockStart(); - foreach (Stmt *s, bb->statements()) { + foreach (Stmt *s, currentBB->statements()) { QByteArray str; QBuffer buf(&str); buf.open(QIODevice::WriteOnly); @@ -974,36 +1005,34 @@ void IRPrinter::print(BasicBlock *bb) std::swap(out, prevOut); addStmtNr(s); s->accept(this); - if (s->location.isValid()) { + 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 << " ; line: " << s->location.startLine << ", column: " << s->location.startColumn; } out->flush(); std::swap(out, prevOut); - *out << " " << str; - *out << endl; - - if (s->asCJump()) { - *out << " else goto L" << s->asCJump()->iffalse->index() << ";" << endl; - } + *out << " " << str << endl; } - std::swap(printElse, prevPrintElse); + std::swap(currentBB, bb); } void IRPrinter::visitExp(Exp *s) { - *out << "(void) "; + *out << "void "; s->expr->accept(this); - *out << ';'; } void IRPrinter::visitMove(Move *s) { + if (Temp *targetTemp = s->target->asTemp()) + if (!s->swap && targetTemp->type != UnknownType) + *out << typeName(targetTemp->type) << ' '; + s->target->accept(this); *out << ' '; if (s->swap) @@ -1011,21 +1040,19 @@ void IRPrinter::visitMove(Move *s) else *out << "= "; s->source->accept(this); - *out << ';'; } void IRPrinter::visitJump(Jump *s) { - *out << "goto L" << s->target->index() << ';'; + *out << "goto L" << s->target->index(); } void IRPrinter::visitCJump(CJump *s) { - *out << "if ("; + *out << "if "; s->cond->accept(this); - *out << ") goto L" << s->iftrue->index() << ';'; - if (printElse) - *out << " else goto L" << s->iffalse->index() << ';'; + *out << " goto L" << s->iftrue->index() + << " else goto L" << s->iffalse->index(); } void IRPrinter::visitRet(Ret *s) @@ -1035,26 +1062,27 @@ void IRPrinter::visitRet(Ret *s) *out << ' '; s->expr->accept(this); } - *out << ';'; } void IRPrinter::visitPhi(Phi *s) { + if (s->targetTemp->type != UnknownType) + *out << typeName(s->targetTemp->type) << ' '; + s->targetTemp->accept(this); - *out << " = phi("; + *out << " = phi "; for (int i = 0, ei = s->d->incoming.size(); i < ei; ++i) { if (i > 0) *out << ", "; + if (currentBB) + *out << 'L' << currentBB->in.at(i)->index() << ": "; if (s->d->incoming[i]) s->d->incoming[i]->accept(this); } - *out << ");"; } void IRPrinter::visitConst(Const *e) { - if (e->type != UndefinedType && e->type != NullType) - *out << dumpStart(e); switch (e->type) { case QV4::IR::UndefinedType: *out << "undefined"; @@ -1079,8 +1107,6 @@ void IRPrinter::visitConst(Const *e) } break; } - if (e->type != UndefinedType && e->type != NullType) - *out << dumpEnd(e); } void IRPrinter::visitString(String *e) @@ -1105,15 +1131,17 @@ void IRPrinter::visitRegExp(RegExp *e) void IRPrinter::visitName(Name *e) { - if (e->id) + if (e->id) { + if (*e->id != QStringLiteral("this")) + *out << '.'; *out << *e->id; - else + } else { *out << builtin_to_string(e->builtin); + } } void IRPrinter::visitTemp(Temp *e) { - *out << dumpStart(e); switch (e->kind) { case Temp::VirtualRegister: *out << '%' << e->index; break; case Temp::PhysicalRegister: *out << (e->type == DoubleType ? "fp" : "r") @@ -1121,12 +1149,10 @@ void IRPrinter::visitTemp(Temp *e) case Temp::StackSlot: *out << '&' << e->index; break; default: *out << "INVALID"; } - *out << dumpEnd(e); } void IRPrinter::visitArgLocal(ArgLocal *e) { - *out << dumpStart(e); switch (e->kind) { case ArgLocal::Formal: *out << '#' << e->index; break; case ArgLocal::ScopedFormal: *out << '#' << e->index @@ -1136,7 +1162,6 @@ void IRPrinter::visitArgLocal(ArgLocal *e) << '@' << e->scope; break; default: *out << "INVALID"; } - *out << dumpEnd(e); } void IRPrinter::visitClosure(Closure *e) @@ -1144,35 +1169,32 @@ void IRPrinter::visitClosure(Closure *e) QString name = e->functionName ? *e->functionName : QString(); if (name.isEmpty()) name.sprintf("%x", e->value); - *out << "closure(" << name << ')'; + *out << "closure " << name; } void IRPrinter::visitConvert(Convert *e) { - *out << dumpStart(e); - *out << "convert("; + *out << "convert " << typeName(e->expr->type) << " to " << typeName(e->type) << ' '; e->expr->accept(this); - *out << ')' << dumpEnd(e); } void IRPrinter::visitUnop(Unop *e) { - *out << dumpStart(e) << opname(e->op); + *out << opname(e->op) << ' '; e->expr->accept(this); - *out << dumpEnd(e); } void IRPrinter::visitBinop(Binop *e) { - *out << dumpStart(e); + *out << opname(e->op) << ' '; e->left->accept(this); - *out << ' ' << opname(e->op) << ' '; + *out << ", "; e->right->accept(this); - *out << dumpEnd(e); } void IRPrinter::visitCall(Call *e) { + *out << "call "; e->base->accept(this); *out << '('; for (ExprList *it = e->args; it; it = it->next) { @@ -1244,64 +1266,54 @@ QString IRPrinter::escape(const QString &s) void IRPrinter::addStmtNr(Stmt *s) { if (s->id() >= 0) - *out << s->id() << ": "; + addJustifiedNr(s->id()); } -QString IRPrinter::dumpStart(const Expr *e) +void IRPrinter::addJustifiedNr(int pos) { - if (e->type == UnknownType) - return QString(); - - QString result = typeName(e->type); -#ifndef V4_BOOTSTRAP - const Temp *temp = const_cast(e)->asTemp(); - if (e->type == QObjectType && temp && temp->memberResolver.isQObjectResolver) { - result += QLatin1Char('<'); - result += QString::fromUtf8(static_cast(temp->memberResolver.data)->className()); - result += QLatin1Char('>'); + 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 << ": "; } -#endif - result += QLatin1Char('{'); - return result; -} - -const char *IRPrinter::dumpEnd(const Expr *e) -{ - if (e->type == UnknownType) - return ""; - else - return "}"; } -void IRPrinter::printBlockStart(BasicBlock *bb) +void IRPrinter::printBlockStart() { - if (bb->isRemoved()) { + if (currentBB->isRemoved()) { *out << "(block has been removed)"; return; } QByteArray str; str.append('L'); - str.append(QByteArray::number(bb->index())); + str.append(QByteArray::number(currentBB->index())); str.append(':'); - if (bb->catchBlock) { + if (currentBB->catchBlock) { str.append(" (exception handler L"); - str.append(QByteArray::number(bb->catchBlock->index())); + str.append(QByteArray::number(currentBB->catchBlock->index())); str.append(')'); } for (int i = 66 - str.length(); i; --i) str.append(' '); *out << str; - *out << "// predecessor blocks:"; - foreach (BasicBlock *in, bb->in) + *out << "; predecessors:"; + foreach (BasicBlock *in, currentBB->in) *out << " L" << in->index(); - if (bb->in.isEmpty()) - *out << " (none)"; - if (BasicBlock *container = bb->containingGroup()) - *out << "; container block: L" << container->index(); - if (bb->isGroupStart()) - *out << "; group start"; + 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; } diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h index fcdcdf9038..6f42a50a72 100644 --- a/src/qml/compiler/qv4jsir_p.h +++ b/src/qml/compiler/qv4jsir_p.h @@ -1043,13 +1043,17 @@ struct Function { void setScheduledBlocks(const QVector &scheduled); void renumberBasicBlocks(); - unsigned getNewStatementId() { return _statementCount++; } - unsigned statementCount() const { return _statementCount; } + int getNewStatementId() { return _statementCount++; } + int statementCount() const { return _statementCount; } + +private: + BasicBlock *getOrCreateBasicBlock(int index); + void setStatementCount(int cnt); private: QVector _basicBlocks; QVector *_allBasicBlocks; - unsigned _statementCount; + int _statementCount; }; class CloneExpr: protected IR::ExprVisitor @@ -1136,7 +1140,7 @@ private: IR::Expr *cloned; }; -class IRPrinter: public StmtVisitor, public ExprVisitor +class Q_AUTOTEST_EXPORT IRPrinter: public StmtVisitor, public ExprVisitor { public: IRPrinter(QTextStream *out); @@ -1175,13 +1179,13 @@ public: protected: virtual void addStmtNr(Stmt *s); - QString dumpStart(const Expr *e); - const char *dumpEnd(const Expr *e); - void printBlockStart(BasicBlock *bb); + void addJustifiedNr(int pos); + void printBlockStart(); protected: QTextStream *out; - bool printElse; + int positionSize; + BasicBlock *currentBB; }; } // end of namespace IR diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp index 8c5f2e30bb..9a597952eb 100644 --- a/src/qml/compiler/qv4ssa.cpp +++ b/src/qml/compiler/qv4ssa.cpp @@ -81,8 +81,10 @@ Q_GLOBAL_STATIC_WITH_ARGS(QTextStream, qout, (stderr, QIODevice::WriteOnly)); void showMeTheCode(IR::Function *function) { static bool showCode = !qgetenv("QV4_SHOW_IR").isNull(); - if (showCode) + if (showCode) { IRPrinter(&qout).print(function); + qout << endl; + } } class ProcessedBlocks @@ -1659,7 +1661,7 @@ class StatementWorklist public: StatementWorklist(IR::Function *function) : theFunction(function) - , stmts(function->statementCount(), 0) + , stmts(function->statementCount(), static_cast(0)) , worklist(function->statementCount(), false) , worklistSize(0) , replaced(function->statementCount(), Stmt::InvalidId) diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp index 588b6d9707..0639c5361f 100644 --- a/src/qml/jit/qv4regalloc.cpp +++ b/src/qml/jit/qv4regalloc.cpp @@ -85,15 +85,7 @@ public: protected: void addStmtNr(Stmt *s) { - QString posStr; - int pos = intervals->positionForStatement(s); - if (pos != Stmt::InvalidId) - posStr = QString::number(pos); - *out << posStr.rightJustified(positionSize); - if (pos == Stmt::InvalidId) - *out << " "; - else - *out << ": "; + addJustifiedNr(intervals->positionForStatement(s)); } }; @@ -126,9 +118,7 @@ protected: const RegisterInfo *ri = e->type == DoubleType ? _infoForFPRegister.value(e->index, 0) : _infoForRegularRegister.value(e->index, 0); if (ri) { - *out << dumpStart(e); *out << ri->prettyName(); - *out << dumpEnd(e); break; } } -- cgit v1.2.3