Keep references while moving other expressions into a temp
authorLars Knoll <lars.knoll@digia.com>
Sat, 8 Dec 2012 06:44:51 +0000 (22:44 -0800)
committerSimon Hausmann <simon.hausmann@digia.com>
Sat, 8 Dec 2012 16:22:23 +0000 (17:22 +0100)
delete and typeof need to get correct references as arguments.
But we still need to evaluate other expressions correctly. The
best way to do that is to store them in a temp.

Change-Id: I7bcd152742bf752df47fd63a837952c57ea70bf5
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
qv4codegen.cpp
qv4codegen_p.h

index 8159ede..9555523 100644 (file)
@@ -490,6 +490,17 @@ IR::Expr *Codegen::argument(IR::Expr *expr)
     return expr;
 }
 
+// keeps references alive, converts other expressions to temps
+IR::Expr *Codegen::reference(IR::Expr *expr)
+{
+    if (expr && !expr->asTemp() && !expr->asName() && !expr->asMember() && !expr->asSubscript()) {
+        const unsigned t = _block->newTemp();
+        move(_block->TEMP(t), expr);
+        expr = _block->TEMP(t);
+    }
+    return expr;
+}
+
 IR::Expr *Codegen::unop(IR::AluOp op, IR::Expr *expr)
 {
     if (IR::Const *c = expr->asConst()) {
@@ -1159,7 +1170,7 @@ bool Codegen::visit(DeleteExpression *ast)
 {
     Result expr = expression(ast->expression);
     IR::ExprList *args = _function->New<IR::ExprList>();
-    args->init(*expr);
+    args->init(reference(*expr));
     _expr.code = call(_block->NAME(IR::Name::builtin_delete, ast->deleteToken.startLine, ast->deleteToken.startColumn), args);
     return false;
 }
@@ -1384,7 +1395,7 @@ bool Codegen::visit(TypeOfExpression *ast)
 {
     Result expr = expression(ast->expression);
     IR::ExprList *args = _function->New<IR::ExprList>();
-    args->init(*expr);
+    args->init(reference(*expr));
     _expr.code = call(_block->NAME(IR::Name::builtin_typeof, ast->typeofToken.startLine, ast->typeofToken.startColumn), args);
     return false;
 }
index 474e558..ba3b477 100644 (file)
@@ -201,6 +201,7 @@ protected:
     IR::Expr *member(IR::Expr *base, const QString *name);
     IR::Expr *subscript(IR::Expr *base, IR::Expr *index);
     IR::Expr *argument(IR::Expr *expr);
+    IR::Expr *reference(IR::Expr *expr);
     IR::Expr *unop(IR::AluOp op, IR::Expr *expr);
     IR::Expr *binop(IR::AluOp op, IR::Expr *left, IR::Expr *right);
     IR::Expr *call(IR::Expr *base, IR::ExprList *args);