Make IR types stricter
authorAaron Kennedy <aaron.kennedy@nokia.com>
Fri, 8 Jun 2012 19:09:13 +0000 (20:09 +0100)
committerAaron Kennedy <aaron.kennedy@nokia.com>
Mon, 11 Jun 2012 10:31:28 +0000 (11:31 +0100)
We can always loosen these again if we need to.

qv4codegen.cpp
qv4ir.cpp
qv4ir_p.h

index 277bfd126f4ba2d4479a6d66499026c4d86f3e2b..eb7037e3698f36dcd97867f51bc7fbd2337312c3 100644 (file)
@@ -6,6 +6,7 @@
 #include <QtCore/QBitArray>
 #include <QtCore/QStack>
 #include <private/qqmljsast_p.h>
+#include <math.h>
 #include <iostream>
 #include <cassert>
 
@@ -317,7 +318,7 @@ void Codegen::leaveLoop()
 IR::Expr *Codegen::member(IR::Expr *base, const QString *name)
 {
     if (base->asTemp() /*|| base->asName()*/)
-        return _block->MEMBER(base, name);
+        return _block->MEMBER(base->asTemp(), name);
     else {
         const unsigned t = _block->newTemp();
         move(_block->TEMP(t), base);
@@ -339,7 +340,8 @@ IR::Expr *Codegen::subscript(IR::Expr *base, IR::Expr *index)
         index = _block->TEMP(t);
     }
 
-    return _block->SUBSCRIPT(base, index);
+    assert(base->asTemp() && index->asTemp());
+    return _block->SUBSCRIPT(base->asTemp(), index->asTemp());
 }
 
 IR::Expr *Codegen::argument(IR::Expr *expr)
@@ -359,24 +361,75 @@ IR::Expr *Codegen::unop(IR::AluOp op, IR::Expr *expr)
         move(_block->TEMP(t), expr);
         expr = _block->TEMP(t);
     }
-    return _block->UNOP(op, expr);
+    assert(expr->asTemp());
+    return _block->UNOP(op, expr->asTemp());
 }
 
 IR::Expr *Codegen::binop(IR::AluOp op, IR::Expr *left, IR::Expr *right)
 {
-    if (left && ! left->asTemp()) {
+    if (IR::Const *c1 = left->asConst()) {
+        if (IR::Const *c2 = right->asConst()) {
+            const IR::Type ty = IR::Binop::typeForOp(op, left, right);
+
+            switch (op) {
+            case IR::OpAdd: return _block->CONST(ty, c1->value + c2->value);
+            case IR::OpAnd: return _block->CONST(ty, c1->value ? c2->value : 0);
+            case IR::OpBitAnd: return _block->CONST(ty, int(c1->value) & int(c2->value));
+            case IR::OpBitOr: return _block->CONST(ty, int(c1->value) | int(c2->value));
+            case IR::OpBitXor: return _block->CONST(ty, int(c1->value) ^ int(c2->value));
+            case IR::OpDiv: return _block->CONST(ty, c1->value / c2->value);
+            case IR::OpEqual: return _block->CONST(ty, c1->value == c2->value);
+            case IR::OpGe: return _block->CONST(ty, c1->value >= c2->value);
+            case IR::OpGt: return _block->CONST(ty, c1->value > c2->value);
+            case IR::OpLe: return _block->CONST(ty, c1->value <= c2->value);
+            case IR::OpLShift: return _block->CONST(ty, int(c1->value) << int(c2->value));
+            case IR::OpLt: return _block->CONST(ty, c1->value < c2->value);
+            case IR::OpMod: return _block->CONST(ty, ::fmod(c1->value, c2->value));
+            case IR::OpMul: return _block->CONST(ty, c1->value * c2->value);
+            case IR::OpNotEqual: return _block->CONST(ty, c1->value != c2->value);
+            case IR::OpOr: return _block->CONST(ty, c1->value ? c1->value : c2->value);
+            case IR::OpRShift: return _block->CONST(ty, int(c1->value) >> int(c2->value));
+            case IR::OpStrictEqual: return _block->CONST(ty, c1->value == c2->value);
+            case IR::OpStrictNotEqual: return _block->CONST(ty, c1->value != c2->value);
+            case IR::OpSub: return _block->CONST(ty, c1->value - c2->value);
+            case IR::OpURShift: return _block->CONST(ty, unsigned(c1->value) >> int(c2->value));
+
+            case IR::OpInstanceof:
+            case IR::OpIn:
+                assert(!"unreachabe");
+                break;
+
+            case IR::OpIfTrue: // unary ops
+            case IR::OpNot:
+            case IR::OpUMinus:
+            case IR::OpUPlus:
+            case IR::OpCompl:
+            case IR::OpInvalid:
+                break;
+            }
+        }
+    } else if (op == IR::OpAdd) {
+        if (IR::String *s1 = left->asString()) {
+            if (IR::String *s2 = right->asString()) {
+                return _block->STRING(_function->newString(*s1->value + *s2->value));
+            }
+        }
+    }
+
+    if (!left->asTemp()) {
         const unsigned t = _block->newTemp();
         move(_block->TEMP(t), left);
         left = _block->TEMP(t);
     }
 
-    if (right && ! right->asTemp()) {
+    if (!right->asTemp()) {
         const unsigned t = _block->newTemp();
         move(_block->TEMP(t), right);
         right = _block->TEMP(t);
     }
 
-    return _block->BINOP(op, left, right);
+    assert(left->asTemp() && right->asTemp());
+    return _block->BINOP(op, left->asTemp(), right->asTemp());
 }
 
 IR::Expr *Codegen::call(IR::Expr *base, IR::ExprList *args)
index 00779a9fe81af763b1bd7c958dc0c1d9f98c19bb..c915c9ad908e45a51d4102673a51e0f24250b076 100644 (file)
--- a/qv4ir.cpp
+++ b/qv4ir.cpp
@@ -561,66 +561,15 @@ Closure *BasicBlock::CLOSURE(Function *function)
     return clos;
 }
 
-Expr *BasicBlock::UNOP(AluOp op, Expr *expr) 
+Expr *BasicBlock::UNOP(AluOp op, Temp *expr)
 { 
     Unop *e = function->New<Unop>();
     e->init(op, expr);
     return e;
 }
 
-Expr *BasicBlock::BINOP(AluOp op, Expr *left, Expr *right)
-{
-    if (left && right) {
-        if (Const *c1 = left->asConst()) {
-            if (Const *c2 = right->asConst()) {
-                const IR::Type ty = Binop::typeForOp(op, left, right);
-
-                switch (op) {
-                case OpAdd: return CONST(ty, c1->value + c2->value);
-                case OpAnd: return CONST(ty, c1->value ? c2->value : 0);
-                case OpBitAnd: return CONST(ty, int(c1->value) & int(c2->value));
-                case OpBitOr: return CONST(ty, int(c1->value) | int(c2->value));
-                case OpBitXor: return CONST(ty, int(c1->value) ^ int(c2->value));
-                case OpDiv: return CONST(ty, c1->value / c2->value);
-                case OpEqual: return CONST(ty, c1->value == c2->value);
-                case OpGe: return CONST(ty, c1->value >= c2->value);
-                case OpGt: return CONST(ty, c1->value > c2->value);
-                case OpLe: return CONST(ty, c1->value <= c2->value);
-                case OpLShift: return CONST(ty, int(c1->value) << int(c2->value));
-                case OpLt: return CONST(ty, c1->value < c2->value);
-                case OpMod: return CONST(ty, ::fmod(c1->value, c2->value));
-                case OpMul: return CONST(ty, c1->value * c2->value);
-                case OpNotEqual: return CONST(ty, c1->value != c2->value);
-                case OpOr: return CONST(ty, c1->value ? c1->value : c2->value);
-                case OpRShift: return CONST(ty, int(c1->value) >> int(c2->value));
-                case OpStrictEqual: return CONST(ty, c1->value == c2->value);
-                case OpStrictNotEqual: return CONST(ty, c1->value != c2->value);
-                case OpSub: return CONST(ty, c1->value - c2->value);
-                case OpURShift: return CONST(ty, unsigned(c1->value) >> int(c2->value));
-
-                case OpInstanceof:
-                case OpIn:
-                    assert(!"unreachabe");
-                    break;
-
-                case OpIfTrue: // unary ops
-                case OpNot:
-                case OpUMinus:
-                case OpUPlus:
-                case OpCompl:
-                case OpInvalid:
-                    break;
-                }
-            }
-        } else if (op == OpAdd) {
-            if (String *s1 = left->asString()) {
-                if (String *s2 = right->asString()) {
-                    return STRING(function->newString(*s1->value + *s2->value));
-                }
-            }
-        }
-    }
-
+Expr *BasicBlock::BINOP(AluOp op, Temp *left, Temp *right)
+{
     Binop *e = function->New<Binop>();
     e->init(op, left, right);
     return e;
@@ -640,14 +589,14 @@ Expr *BasicBlock::NEW(Expr *base, ExprList *args)
     return e;
 }
 
-Expr *BasicBlock::SUBSCRIPT(Expr *base, Expr *index)
+Expr *BasicBlock::SUBSCRIPT(Temp *base, Temp *index)
 {
     Subscript *e = function->New<Subscript>();
     e->init(base, index);
     return e;
 }
 
-Expr *BasicBlock::MEMBER(Expr *base, const QString *name)
+Expr *BasicBlock::MEMBER(Temp *base, const QString *name)
 {
     Member*e = function->New<Member>();
     e->init(base, name);
@@ -745,7 +694,7 @@ Stmt *BasicBlock::CJUMP(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse)
     return s;
 }
 
-Stmt *BasicBlock::RET(Expr *expr, Type type)
+Stmt *BasicBlock::RET(Temp *expr, Type type)
 {
     if (isTerminated())
         return 0;
index f6467c98d3f78fe70320b68331b383b1d2bd36bb..c5e2af9e1cedb14c2f13b3a1a6fd5f289fbfd6d1 100644 (file)
--- a/qv4ir_p.h
+++ b/qv4ir_p.h
@@ -312,9 +312,9 @@ struct Closure: Expr {
 
 struct Unop: Expr {
     AluOp op;
-    Expr *expr;
+    Temp *expr;
 
-    void init(AluOp op, Expr *expr)
+    void init(AluOp op, Temp *expr)
     {
         this->type = this->typeForOp(op, expr);
         this->op = op;
@@ -332,10 +332,10 @@ private:
 
 struct Binop: Expr {
     AluOp op;
-    Expr *left;
-    Expr *right;
+    Temp *left;
+    Temp *right;
 
-    void init(AluOp op, Expr *left, Expr *right)
+    void init(AluOp op, Temp *left, Temp *right)
     {
         this->type = typeForOp(op, left, right);
         this->op = op;
@@ -352,8 +352,8 @@ struct Binop: Expr {
 };
 
 struct Call: Expr {
-    Expr *base;
-    ExprList *args;
+    Expr *base; // Name, Member, Temp
+    ExprList *args; // List of Temps
 
     void init(Expr *base, ExprList *args)
     {
@@ -378,8 +378,8 @@ private:
 };
 
 struct New: Expr {
-    Expr *base;
-    ExprList *args;
+    Expr *base; // Name, Member, Temp
+    ExprList *args; // List of Temps
 
     void init(Expr *base, ExprList *args)
     {
@@ -404,10 +404,10 @@ private:
 };
 
 struct Subscript: Expr {
-    Expr *base;
-    Expr *index;
+    Temp *base;
+    Temp *index;
 
-    void init(Expr *base, Expr *index)
+    void init(Temp *base, Temp *index)
     {
         this->type = typeForFunction(base);
         this->base = base;
@@ -424,10 +424,10 @@ private:
 };
 
 struct Member: Expr {
-    Expr *base;
+    Temp *base;
     const QString *name;
 
-    void init(Expr *base, const QString *name)
+    void init(Temp *base, const QString *name)
     {
         this->type = typeForFunction(base);
         this->base = base;
@@ -493,7 +493,7 @@ struct Exp: Stmt {
 };
 
 struct Move: Stmt {
-    Expr *target;
+    Expr *target; // LHS - Temp, Name, Member or Subscript
     Expr *source;
     AluOp op;
 
@@ -570,10 +570,10 @@ struct CJump: Stmt {
 };
 
 struct Ret: Stmt {
-    Expr *expr;
+    Temp *expr;
     Type type;
 
-    void init(Expr *expr, Type type)
+    void init(Temp *expr, Type type)
     {
         this->expr = expr;
         this->type = type;
@@ -685,12 +685,12 @@ struct BasicBlock {
 
     Closure *CLOSURE(Function *function);
 
-    Expr *UNOP(AluOp op, Expr *expr);
-    Expr *BINOP(AluOp op, Expr *left, Expr *right);
+    Expr *UNOP(AluOp op, Temp *expr);
+    Expr *BINOP(AluOp op, Temp *left, Temp *right);
     Expr *CALL(Expr *base, ExprList *args = 0);
     Expr *NEW(Expr *base, ExprList *args = 0);
-    Expr *SUBSCRIPT(Expr *base, Expr *index);
-    Expr *MEMBER(Expr *base, const QString *name);
+    Expr *SUBSCRIPT(Temp *base, Temp *index);
+    Expr *MEMBER(Temp *base, const QString *name);
 
     Stmt *EXP(Expr *expr);
     Stmt *ENTER(Expr *expr);
@@ -700,7 +700,7 @@ struct BasicBlock {
 
     Stmt *JUMP(BasicBlock *target);
     Stmt *CJUMP(Expr *cond, BasicBlock *iftrue, BasicBlock *iffalse);
-    Stmt *RET(Expr *expr, Type type);
+    Stmt *RET(Temp *expr, Type type);
 
     void dump(QTextStream &out, Stmt::Mode mode = Stmt::HIR);
 };