aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@digia.com>2014-08-05 14:11:16 +0200
committerErik Verbruggen <erik.verbruggen@digia.com>2014-08-13 12:53:19 +0200
commit2fea3d1899eb8cc81920b631ea73a1f130674950 (patch)
tree5e115b5fa3597b96b21176578aa1f741c76163f2
parentd6a79aa6b06726d19d231d1da3ecb5b6509f0f1a (diff)
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 <simon.hausmann@digia.com>
-rw-r--r--src/qml/compiler/qv4jsir.cpp246
-rw-r--r--src/qml/compiler/qv4jsir_p.h20
-rw-r--r--src/qml/compiler/qv4ssa.cpp6
-rw-r--r--src/qml/jit/qv4regalloc.cpp12
4 files changed, 146 insertions, 138 deletions
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<Stmt *> &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<Expr*>(e)->asTemp();
- if (e->type == QObjectType && temp && temp->memberResolver.isQObjectResolver) {
- result += QLatin1Char('<');
- result += QString::fromUtf8(static_cast<QQmlPropertyCache*>(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<BasicBlock *> &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<BasicBlock *> _basicBlocks;
QVector<BasicBlock *> *_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<Stmt *>(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;
}
}