aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler/qv4codegen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/compiler/qv4codegen.cpp')
-rw-r--r--src/qml/compiler/qv4codegen.cpp172
1 files changed, 124 insertions, 48 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 693a4230ba..5b7a7f9050 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -113,6 +113,18 @@ static inline void setJumpOutLocation(IR::Stmt *s, const Statement *body,
}
}
+static inline bool isSimpleExpr(IR::Expr *e)
+{
+ switch (e->exprKind) {
+ case IR::Expr::TempExpr:
+ case IR::Expr::ArgLocalExpr:
+ case IR::Expr::ConstExpr:
+ return true;
+ default:
+ return false;
+ }
+}
+
Codegen::ScanFunctions::ScanFunctions(Codegen *cg, const QString &sourceCode, CompilationMode defaultProgramMode)
: _cg(cg)
, _sourceCode(sourceCode)
@@ -573,28 +585,6 @@ IR::Expr *Codegen::member(IR::Expr *base, const QString *name)
}
}
-IR::Expr *Codegen::subscript(IR::Expr *base, IR::Expr *index)
-{
- if (hasError)
- return 0;
-
- if (! base->asTemp() && !base->asArgLocal()) {
- const unsigned t = _block->newTemp();
- move(_block->TEMP(t), base);
- base = _block->TEMP(t);
- }
-
- if (! index->asTemp() && !index->asArgLocal() && !index->asConst()) {
- const unsigned t = _block->newTemp();
- move(_block->TEMP(t), index);
- index = _block->TEMP(t);
- }
-
- Q_ASSERT(base->asTemp() || base->asArgLocal());
- Q_ASSERT(index->asTemp() || index->asArgLocal() || index->asConst());
- return _block->SUBSCRIPT(base, index);
-}
-
IR::Expr *Codegen::argument(IR::Expr *expr)
{
if (expr && !expr->asTemp()) {
@@ -647,12 +637,14 @@ IR::Expr *Codegen::unop(IR::AluOp op, IR::Expr *expr, const SourceLocation &loc)
}
}
}
- if (!expr->asTemp() && !expr->asArgLocal()) {
- const unsigned t = _block->newTemp();
- setLocation(move(_block->TEMP(t), expr), loc);
- expr = _block->TEMP(t);
- }
- Q_ASSERT(expr->asTemp() || expr->asArgLocal());
+
+ TempScope scope(_function);
+ if (isSimpleExpr(expr))
+ return _block->UNOP(op, expr);
+
+ const unsigned t = _block->newTemp();
+ setLocation(move(_block->TEMP(t), expr), loc);
+ expr = _block->TEMP(t);
return _block->UNOP(op, expr);
}
@@ -661,6 +653,8 @@ IR::Expr *Codegen::binop(IR::AluOp op, IR::Expr *left, IR::Expr *right, const AS
if (hasError)
return 0;
+ TempScope scope(_function);
+
if (IR::Const *c1 = left->asConst()) {
if (IR::Const *c2 = right->asConst()) {
if ((c1->type & IR::NumberType) && (c2->type & IR::NumberType)) {
@@ -748,6 +742,8 @@ IR::Stmt *Codegen::move(IR::Expr *target, IR::Expr *source, IR::AluOp op)
return move(target, binop(op, target, source));
}
+ TempScope scope(_function);
+
if (!source->asTemp() && !source->asConst() && !target->asTemp() && !source->asArgLocal() && !target->asArgLocal()) {
unsigned t = _block->newTemp();
_block->MOVE(_block->TEMP(t), source);
@@ -767,6 +763,8 @@ IR::Stmt *Codegen::cjump(IR::Expr *cond, IR::BasicBlock *iftrue, IR::BasicBlock
if (hasError)
return 0;
+ TempScope scope(_function);
+
if (! (cond->asTemp() || (cond->asBinop() && cjumpCanHandle(cond->asBinop()->op)) )) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), cond);
@@ -786,12 +784,16 @@ void Codegen::accept(Node *node)
void Codegen::statement(Statement *ast)
{
+ TempScope scope(_function);
+
_block->nextLocation = ast->firstSourceLocation();
accept(ast);
}
void Codegen::statement(ExpressionNode *ast)
{
+ TempScope scope(_function);
+
if (! ast) {
return;
} else {
@@ -900,6 +902,7 @@ void Codegen::variableDeclaration(VariableDeclaration *ast)
if (lhs->asArgLocal()) {
move(lhs, initializer);
} else {
+ TempScope scope(_function);
int initialized = _block->newTemp();
move(_block->TEMP(initialized), initializer);
move(lhs, _block->TEMP(initialized));
@@ -1103,6 +1106,10 @@ bool Codegen::visit(ArrayLiteral *ast)
if (hasError)
return false;
+ const unsigned t = _block->newTemp();
+
+ TempScope scope(_function);
+
IR::ExprList *args = 0;
IR::ExprList *current = 0;
for (ElementList *it = ast->elements; it; it = it->next) {
@@ -1148,7 +1155,6 @@ bool Codegen::visit(ArrayLiteral *ast)
current->expr = _block->CONST(IR::MissingType, 0);
}
- const unsigned t = _block->newTemp();
move(_block->TEMP(t), _block->CALL(_block->NAME(IR::Name::builtin_define_array, 0, 0), args));
_expr.code = _block->TEMP(t);
return false;
@@ -1159,11 +1165,25 @@ bool Codegen::visit(ArrayMemberExpression *ast)
if (hasError)
return false;
- Result base = expression(ast->base);
- Result index = expression(ast->expression);
+ IR::Expr *base = *expression(ast->base);
+ if (hasError)
+ return false;
+ if (!isSimpleExpr(base)) {
+ const unsigned t = _block->newTemp();
+ move(_block->TEMP(t), base);
+ base = _block->TEMP(t);
+ }
+
+ IR::Expr *index = *expression(ast->expression);
if (hasError)
return false;
- _expr.code = subscript(*base, *index);
+ if (!isSimpleExpr(index)) {
+ const unsigned t = _block->newTemp();
+ move(_block->TEMP(t), index);
+ index = _block->TEMP(t);
+ }
+
+ _expr.code = _block->SUBSCRIPT(base, index);
return false;
}
@@ -1299,14 +1319,12 @@ bool Codegen::visit(BinaryExpression *ast)
return false;
}
- if (_expr.accept(nx)) {
- move(left, *right, baseOp(ast->op));
- } else {
- const unsigned t = _block->newTemp();
- move(_block->TEMP(t), *right);
- move(left, _block->TEMP(t), baseOp(ast->op));
+ TempScope scope(_function);
+ const unsigned t = _block->newTemp();
+ move(_block->TEMP(t), *right);
+ move(left, _block->TEMP(t), baseOp(ast->op));
+ if (!_expr.accept(nx))
_expr.code = left;
- }
break;
}
@@ -1320,6 +1338,7 @@ bool Codegen::visit(BinaryExpression *ast)
case QSOperator::Lt:
case QSOperator::StrictEqual:
case QSOperator::StrictNotEqual: {
+ TempScope scope(_function);
if (!left->asTemp() && !left->asArgLocal() && !left->asConst()) {
const unsigned t = _block->newTemp();
setLocation(move(_block->TEMP(t), left), ast->operatorToken);
@@ -1349,6 +1368,7 @@ bool Codegen::visit(BinaryExpression *ast)
case QSOperator::RShift:
case QSOperator::Sub:
case QSOperator::URShift: {
+ TempScope scope(_function);
if (!left->asTemp() && !left->asArgLocal() && !left->asConst()) {
const unsigned t = _block->newTemp();
setLocation(move(_block->TEMP(t), left), ast->operatorToken);
@@ -1400,6 +1420,7 @@ bool Codegen::visit(ConditionalExpression *ast)
IR::BasicBlock *endif = _function->newBasicBlock(exceptionHandler());
const unsigned t = _block->newTemp();
+ TempScope scope(_function);
condition(ast->expression, iftrue, iffalse);
@@ -1503,6 +1524,8 @@ bool Codegen::visit(FunctionExpression *ast)
if (hasError)
return false;
+ TempScope scope(_function);
+
int function = defineFunction(ast->name.toString(), ast, ast->formals, ast->body ? ast->body->elements : 0);
_expr.code = _block->CLOSURE(function);
return false;
@@ -1583,6 +1606,7 @@ bool Codegen::visit(NewExpression *ast)
{
if (hasError)
return false;
+ TempScope scope(_function);
Result base = expression(ast->expression);
if (hasError)
@@ -1602,6 +1626,10 @@ bool Codegen::visit(NewMemberExpression *ast)
if (hasError)
return false;
+ const unsigned t = _block->newTemp();
+
+ TempScope scope(_function);
+
Result base = expression(ast->base);
if (hasError)
return false;
@@ -1622,7 +1650,6 @@ bool Codegen::visit(NewMemberExpression *ast)
(*args_it)->init(actual);
args_it = &(*args_it)->next;
}
- const unsigned t = _block->newTemp();
move(_block->TEMP(t), _block->NEW(expr, args));
_expr.code = _block->TEMP(t);
return false;
@@ -1633,10 +1660,12 @@ bool Codegen::visit(NotExpression *ast)
if (hasError)
return false;
+ const unsigned r = _block->newTemp();
+ TempScope scope(_function);
+
Result expr = expression(ast->expression);
if (hasError)
return false;
- const unsigned r = _block->newTemp();
setLocation(move(_block->TEMP(r), unop(IR::OpNot, *expr, ast->notToken)), ast->notToken);
_expr.code = _block->TEMP(r);
return false;
@@ -1689,6 +1718,9 @@ bool Codegen::visit(ObjectLiteral *ast)
QMap<QString, ObjectPropertyValue> valueMap;
+ const unsigned t = _block->newTemp();
+ TempScope scope(_function);
+
for (PropertyAssignmentList *it = ast->properties; it; it = it->next) {
QString name = it->assignment->name->asString();
if (PropertyNameAndValue *nv = AST::cast<AST::PropertyNameAndValue *>(it->assignment)) {
@@ -1702,7 +1734,13 @@ bool Codegen::visit(ObjectLiteral *ast)
return false;
}
- valueMap[name].value = *value;
+ if (IR::Const *c = (*value)->asConst()) {
+ valueMap[name].value = c;
+ } else {
+ unsigned t = _block->newTemp();
+ move(_block->TEMP(t), *value);
+ valueMap[name].value = _block->TEMP(t);
+ }
} else if (PropertyGetterSetter *gs = AST::cast<AST::PropertyGetterSetter *>(it->assignment)) {
const int function = defineFunction(name, gs, gs->formals, gs->functionBody ? gs->functionBody->elements : 0);
ObjectPropertyValue &v = valueMap[name];
@@ -1773,12 +1811,9 @@ bool Codegen::visit(ObjectLiteral *ast)
current = current->next;
current->expr = _block->CONST(IR::BoolType, true);
- unsigned value = _block->newTemp();
- move(_block->TEMP(value), it->value);
-
current->next = _function->New<IR::ExprList>();
current = current->next;
- current->expr = _block->TEMP(value);
+ current->expr = it->value;
} else {
current->next = _function->New<IR::ExprList>();
current = current->next;
@@ -1811,7 +1846,6 @@ bool Codegen::visit(ObjectLiteral *ast)
args->next = arrayEntries;
}
- const unsigned t = _block->newTemp();
move(_block->TEMP(t), _block->CALL(_block->NAME(IR::Name::builtin_define_object_literal,
ast->firstSourceLocation().startLine, ast->firstSourceLocation().startColumn), args));
@@ -1837,6 +1871,7 @@ bool Codegen::visit(PostDecrementExpression *ast)
const unsigned oldValue = _block->newTemp();
setLocation(move(_block->TEMP(oldValue), unop(IR::OpUPlus, *expr, ast->decrementToken)), ast->decrementToken);
+ TempScope scope(_function);
const unsigned newValue = _block->newTemp();
setLocation(move(_block->TEMP(newValue), binop(IR::OpSub, _block->TEMP(oldValue), _block->CONST(IR::NumberType, 1), ast->decrementToken)), ast->decrementToken);
setLocation(move(*expr, _block->TEMP(newValue)), ast->decrementToken);
@@ -1865,6 +1900,7 @@ bool Codegen::visit(PostIncrementExpression *ast)
const unsigned oldValue = _block->newTemp();
setLocation(move(_block->TEMP(oldValue), unop(IR::OpUPlus, *expr, ast->incrementToken)), ast->incrementToken);
+ TempScope scope(_function);
const unsigned newValue = _block->newTemp();
setLocation(move(_block->TEMP(newValue), binop(IR::OpAdd, _block->TEMP(oldValue), _block->CONST(IR::NumberType, 1), ast->incrementToken)), ast->incrementToken);
setLocation(move(*expr, _block->TEMP(newValue)), ast->incrementToken);
@@ -1961,10 +1997,12 @@ bool Codegen::visit(TildeExpression *ast)
if (hasError)
return false;
+ const unsigned t = _block->newTemp();
+ TempScope scope(_function);
+
Result expr = expression(ast->expression);
if (hasError)
return false;
- const unsigned t = _block->newTemp();
setLocation(move(_block->TEMP(t), unop(IR::OpCompl, *expr, ast->tildeToken)), ast->tildeToken);
_expr.code = _block->TEMP(t);
return false;
@@ -1988,6 +2026,8 @@ bool Codegen::visit(TypeOfExpression *ast)
if (hasError)
return false;
+ TempScope scope(_function);
+
Result expr = expression(ast->expression);
if (hasError)
return false;
@@ -2030,6 +2070,8 @@ bool Codegen::visit(VoidExpression *ast)
if (hasError)
return false;
+ TempScope scope(_function);
+
statement(ast->expression);
_expr.code = _block->CONST(IR::UndefinedType, 0);
return false;
@@ -2040,6 +2082,8 @@ bool Codegen::visit(FunctionDeclaration * ast)
if (hasError)
return false;
+ TempScope scope(_function);
+
if (_variableEnvironment->compilationMode == QmlBinding)
move(_block->TEMP(_returnAddress), _block->NAME(ast->name.toString(), 0, 0));
_expr.accept(nx);
@@ -2203,6 +2247,8 @@ bool Codegen::visit(Block *ast)
if (hasError)
return false;
+ TempScope scope(_function);
+
for (StatementList *it = ast->statements; it; it = it->next) {
statement(it->statement);
}
@@ -2214,6 +2260,8 @@ bool Codegen::visit(BreakStatement *ast)
if (hasError)
return false;
+ TempScope scope(_function);
+
if (!_loop) {
throwSyntaxError(ast->lastSourceLocation(), QStringLiteral("Break outside of loop"));
return false;
@@ -2241,6 +2289,8 @@ bool Codegen::visit(ContinueStatement *ast)
if (hasError)
return false;
+ TempScope scope(_function);
+
Loop *loop = 0;
if (ast->label.isEmpty()) {
for (loop = _loop; loop; loop = loop->parent) {
@@ -2280,6 +2330,8 @@ bool Codegen::visit(DoWhileStatement *ast)
if (hasError)
return true;
+ TempScope scope(_function);
+
IR::BasicBlock *loopbody = _function->newBasicBlock(exceptionHandler());
IR::BasicBlock *loopcond = _function->newBasicBlock(exceptionHandler());
IR::BasicBlock *loopend = _function->newBasicBlock(exceptionHandler());
@@ -2315,6 +2367,8 @@ bool Codegen::visit(ExpressionStatement *ast)
if (hasError)
return true;
+ TempScope scope(_function);
+
if (_variableEnvironment->compilationMode == EvalCode || _variableEnvironment->compilationMode == QmlBinding) {
Result e = expression(ast->expression);
if (*e)
@@ -2330,6 +2384,8 @@ bool Codegen::visit(ForEachStatement *ast)
if (hasError)
return true;
+ TempScope scope(_function);
+
IR::BasicBlock *foreachin = _function->newBasicBlock(exceptionHandler());
IR::BasicBlock *foreachbody = _function->newBasicBlock(exceptionHandler());
IR::BasicBlock *foreachend = _function->newBasicBlock(exceptionHandler());
@@ -2376,6 +2432,8 @@ bool Codegen::visit(ForStatement *ast)
if (hasError)
return true;
+ TempScope scope(_function);
+
IR::BasicBlock *forcond = _function->newBasicBlock(exceptionHandler());
IR::BasicBlock *forbody = _function->newBasicBlock(exceptionHandler());
IR::BasicBlock *forstep = _function->newBasicBlock(exceptionHandler());
@@ -2412,6 +2470,8 @@ bool Codegen::visit(IfStatement *ast)
if (hasError)
return true;
+ TempScope scope(_function);
+
IR::BasicBlock *iftrue = _function->newBasicBlock(exceptionHandler());
IR::BasicBlock *iffalse = ast->ko ? _function->newBasicBlock(exceptionHandler()) : 0;
IR::BasicBlock *endif = _function->newBasicBlock(exceptionHandler());
@@ -2438,6 +2498,8 @@ bool Codegen::visit(LabelledStatement *ast)
if (hasError)
return true;
+ TempScope scope(_function);
+
// check that no outer loop contains the label
Loop *l = _loop;
while (l) {
@@ -2475,6 +2537,8 @@ bool Codegen::visit(LocalForEachStatement *ast)
if (hasError)
return true;
+ TempScope scope(_function);
+
IR::BasicBlock *foreachin = _function->newBasicBlock(exceptionHandler());
IR::BasicBlock *foreachbody = _function->newBasicBlock(exceptionHandler());
IR::BasicBlock *foreachend = _function->newBasicBlock(exceptionHandler());
@@ -2515,6 +2579,8 @@ bool Codegen::visit(LocalForStatement *ast)
if (hasError)
return true;
+ TempScope scope(_function);
+
IR::BasicBlock *forcond = _function->newBasicBlock(exceptionHandler());
IR::BasicBlock *forbody = _function->newBasicBlock(exceptionHandler());
IR::BasicBlock *forstep = _function->newBasicBlock(exceptionHandler());
@@ -2577,6 +2643,8 @@ bool Codegen::visit(SwitchStatement *ast)
if (hasError)
return true;
+ TempScope scope(_function);
+
IR::BasicBlock *switchend = _function->newBasicBlock(exceptionHandler());
if (ast->block) {
@@ -2672,6 +2740,8 @@ bool Codegen::visit(ThrowStatement *ast)
if (hasError)
return true;
+ TempScope scope(_function);
+
Result expr = expression(ast->expression);
move(_block->TEMP(_returnAddress), *expr);
IR::ExprList *throwArgs = _function->New<IR::ExprList>();
@@ -2685,6 +2755,8 @@ bool Codegen::visit(TryStatement *ast)
if (hasError)
return true;
+ TempScope scope(_function);
+
_function->hasTry = true;
if (_function->isStrict && ast->catchExpression &&
@@ -2763,6 +2835,8 @@ bool Codegen::visit(TryStatement *ast)
_function->addBasicBlock(finallyBody);
_block = finallyBody;
+ TempScope scope(_function);
+
int hasException = _block->newTemp();
move(_block->TEMP(hasException), _block->CALL(_block->NAME(IR::Name::builtin_unwind_exception, /*line*/0, /*column*/0), 0));
@@ -2847,6 +2921,8 @@ bool Codegen::visit(WithStatement *ast)
if (hasError)
return true;
+ TempScope scope(_function);
+
_function->hasWith = true;
const int withObject = _block->newTemp();