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