Add type conversion nodes to the IR.
authorErik Verbruggen <erik.verbruggen@me.com>
Mon, 10 Jun 2013 14:32:48 +0000 (16:32 +0200)
committerSimon Hausmann <simon.hausmann@digia.com>
Tue, 11 Jun 2013 12:37:54 +0000 (14:37 +0200)
Change-Id: I5a5a69ccd2e2f2f3c9f8592c4b04455d6a567e83
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
src/qml/qml/v4/moth/qv4isel_moth.cpp
src/qml/qml/v4/moth/qv4isel_moth_p.h
src/qml/qml/v4/qv4isel_masm.cpp
src/qml/qml/v4/qv4isel_masm_p.h
src/qml/qml/v4/qv4isel_p.cpp
src/qml/qml/v4/qv4isel_p.h
src/qml/qml/v4/qv4jsir.cpp
src/qml/qml/v4/qv4jsir_p.h
src/qml/qml/v4/qv4ssa.cpp

index 9371806..e4a3738 100644 (file)
@@ -187,6 +187,12 @@ void InstructionSelection::callSubscript(V4IR::Temp *base, V4IR::Temp *index, V4
     addInstruction(call);
 }
 
+void InstructionSelection::convertType(V4IR::Temp *source, V4IR::Temp *target)
+{
+    // FIXME: do something more useful with this info
+    copyValue(source, target);
+}
+
 void InstructionSelection::constructActivationProperty(V4IR::Name *func,
                                                        V4IR::ExprList *args,
                                                        V4IR::Temp *result)
index 09d9de7..e969e33 100644 (file)
@@ -58,6 +58,7 @@ protected:
     virtual void callValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result);
     virtual void callProperty(V4IR::Temp *base, const QString &name, V4IR::ExprList *args, V4IR::Temp *result);
     virtual void callSubscript(V4IR::Temp *base, V4IR::Temp *index, V4IR::ExprList *args, V4IR::Temp *result);
+    virtual void convertType(V4IR::Temp *source, V4IR::Temp *target);
     virtual void constructActivationProperty(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result);
     virtual void constructProperty(V4IR::Temp *base, const QString &name, V4IR::ExprList *args, V4IR::Temp *result);
     virtual void constructValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result);
index 7a5467f..867100d 100644 (file)
@@ -1137,6 +1137,12 @@ void InstructionSelection::callSubscript(V4IR::Temp *base, V4IR::Temp *index, V4
                          Assembler::TrustedImm32(argc));
 }
 
+void InstructionSelection::convertType(V4IR::Temp *source, V4IR::Temp *target)
+{
+    // FIXME: do something more useful with this info
+    copyValue(source, target);
+}
+
 String *InstructionSelection::identifier(const QString &s)
 {
     String *str = engine()->newIdentifier(s);
index 8f47323..dc0299a 100644 (file)
@@ -792,9 +792,10 @@ protected:
     virtual void callBuiltinDefineProperty(V4IR::Temp *object, const QString &name, V4IR::Temp *value);
     virtual void callBuiltinDefineArray(V4IR::Temp *result, V4IR::ExprList *args);
     virtual void callBuiltinDefineObjectLiteral(V4IR::Temp *result, V4IR::ExprList *args);
+    virtual void callValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result);
     virtual void callProperty(V4IR::Temp *base, const QString &name, V4IR::ExprList *args, V4IR::Temp *result);
     virtual void callSubscript(V4IR::Temp *base, V4IR::Temp *index, V4IR::ExprList *args, V4IR::Temp *result);
-    virtual void callValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result);
+    virtual void convertType(V4IR::Temp *source, V4IR::Temp *target);
     virtual void loadThisObject(V4IR::Temp *temp);
     virtual void loadConst(V4IR::Const *sourceConst, V4IR::Temp *targetTemp);
     virtual void loadString(const QString &str, V4IR::Temp *targetTemp);
index 48678d8..3f9d599 100644 (file)
@@ -149,6 +149,10 @@ void InstructionSelection::visitMove(V4IR::Move *s)
                     callValue(value, c->args, t);
                     return;
                 }
+            } else if (V4IR::Convert *c = s->source->asConvert()) {
+                Q_ASSERT(c->expr->asTemp());
+                convertType(c->expr->asTemp(), t);
+                return;
             }
         } else if (V4IR::Member *m = s->target->asMember()) {
             if (V4IR::Temp *base = m->base->asTemp()) {
index be30e06..e0c202d 100644 (file)
@@ -131,6 +131,7 @@ public: // to implement by subclasses:
     virtual void callValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result) = 0;
     virtual void callProperty(V4IR::Temp *base, const QString &name, V4IR::ExprList *args, V4IR::Temp *result) = 0;
     virtual void callSubscript(V4IR::Temp *base, V4IR::Temp *index, V4IR::ExprList *args, V4IR::Temp *result) = 0;
+    virtual void convertType(V4IR::Temp *source, V4IR::Temp *target) = 0;
     virtual void constructActivationProperty(V4IR::Name *func, V4IR::ExprList *args, V4IR::Temp *result) = 0;
     virtual void constructProperty(V4IR::Temp *base, const QString &name, V4IR::ExprList *args, V4IR::Temp *result) = 0;
     virtual void constructValue(V4IR::Temp *value, V4IR::ExprList *args, V4IR::Temp *result) = 0;
index 6957067..fd0b866 100644 (file)
@@ -238,6 +238,11 @@ struct RemoveSharedExpressions: V4IR::StmtVisitor, V4IR::ExprVisitor
     virtual void visitTemp(Temp *) {}
     virtual void visitClosure(Closure *) {}
 
+    virtual void visitConvert(Convert *e)
+    {
+        e->expr = cleanup(e->expr);
+    }
+
     virtual void visitUnop(Unop *e)
     {
         e->expr = cleanup(e->expr);
@@ -452,6 +457,14 @@ void Closure::dump(QTextStream &out)
     out << "closure(" << name << ')';
 }
 
+void Convert::dump(QTextStream &out)
+{
+    out << dumpStart(this);
+    out << "convert(";
+    expr->dump(out);
+    out << ')' << dumpEnd(this);
+}
+
 void Unop::dump(QTextStream &out)
 {
     out << dumpStart(this) << opname(op);
@@ -733,6 +746,13 @@ Closure *BasicBlock::CLOSURE(Function *function)
     return clos;
 }
 
+Expr *BasicBlock::CONVERT(Expr *expr, Type type)
+{
+    Convert *e = function->New<Convert>();
+    e->init(expr, type);
+    return e;
+}
+
 Expr *BasicBlock::UNOP(AluOp op, Expr *expr)
 { 
     Unop *e = function->New<Unop>();
@@ -981,6 +1001,11 @@ void CloneExpr::visitClosure(Closure *e)
     cloned = block->CLOSURE(e->value);
 }
 
+void CloneExpr::visitConvert(Convert *e)
+{
+    cloned = block->CONVERT(clone(e->expr), e->type);
+}
+
 void CloneExpr::visitUnop(Unop *e)
 {
     cloned = block->UNOP(e->op, clone(e->expr));
index b78654a..c873344 100644 (file)
@@ -103,6 +103,7 @@ struct RegExp;
 struct Name;
 struct Temp;
 struct Closure;
+struct Convert;
 struct Unop;
 struct Binop;
 struct Call;
@@ -192,6 +193,7 @@ struct ExprVisitor {
     virtual void visitName(Name *) = 0;
     virtual void visitTemp(Temp *) = 0;
     virtual void visitClosure(Closure *) = 0;
+    virtual void visitConvert(Convert *) = 0;
     virtual void visitUnop(Unop *) = 0;
     virtual void visitBinop(Binop *) = 0;
     virtual void visitCall(Call *) = 0;
@@ -226,6 +228,7 @@ struct Expr {
     virtual Name *asName() { return 0; }
     virtual Temp *asTemp() { return 0; }
     virtual Closure *asClosure() { return 0; }
+    virtual Convert *asConvert() { return 0; }
     virtual Unop *asUnop() { return 0; }
     virtual Binop *asBinop() { return 0; }
     virtual Call *asCall() { return 0; }
@@ -367,6 +370,21 @@ struct Closure: Expr {
     virtual void dump(QTextStream &out);
 };
 
+struct Convert: Expr {
+    Expr *expr;
+
+    void init(Expr *expr, Type type)
+    {
+        this->expr = expr;
+        this->type = type;
+    }
+
+    virtual void accept(ExprVisitor *v) { v->visitConvert(this); }
+    virtual Convert *asConvert() { return this; }
+
+    virtual void dump(QTextStream &out);
+};
+
 struct Unop: Expr {
     AluOp op;
     Expr *expr;
@@ -786,6 +804,7 @@ struct BasicBlock {
 
     Closure *CLOSURE(Function *function);
 
+    Expr *CONVERT(Expr *expr, Type type);
     Expr *UNOP(AluOp op, Expr *expr);
     Expr *BINOP(AluOp op, Expr *left, Expr *right);
     Expr *CALL(Expr *base, ExprList *args = 0);
@@ -854,6 +873,7 @@ protected:
     virtual void visitName(Name *);
     virtual void visitTemp(Temp *);
     virtual void visitClosure(Closure *);
+    virtual void visitConvert(Convert *);
     virtual void visitUnop(Unop *);
     virtual void visitBinop(Binop *);
     virtual void visitCall(Call *);
index 82a6506..f7daf26 100644 (file)
@@ -447,6 +447,7 @@ public:
 
 protected:
     virtual void visitPhi(Phi *) {};
+    virtual void visitConvert(Convert *e) { e->expr->accept(this); };
 
     virtual void visitConst(Const *) {}
     virtual void visitString(String *) {}
@@ -683,6 +684,7 @@ protected:
         tempMapping[newIdx] = origIdx;
     }
 
+    virtual void visitConvert(Convert *e) { e->expr->accept(this); }
     virtual void visitPhi(Phi *s) { renameTemp(s->targetTemp); }
 
     virtual void visitExp(Exp *s) { s->expr->accept(this); }
@@ -894,6 +896,7 @@ protected:
     virtual void visitRegExp(RegExp *) {}
     virtual void visitName(Name *) {}
     virtual void visitClosure(Closure *) {}
+    virtual void visitConvert(Convert *e) { e->expr->accept(this); }
     virtual void visitUnop(Unop *e) { e->expr->accept(this); }
     virtual void visitBinop(Binop *e) { e->left->accept(this); e->right->accept(this); }
     virtual void visitSubscript(Subscript *e) { e->base->accept(this); e->index->accept(this); }
@@ -1034,6 +1037,11 @@ protected:
     virtual void visitTemp(Temp *e) {
     }
     virtual void visitClosure(Closure *) {}
+    virtual void visitConvert(Convert *e) {
+        // we do not have type information yet, so:
+        _sideEffect = true;
+    }
+
     virtual void visitUnop(Unop *e) {
         switch (e->op) {
         case V4IR::OpIncrement:
@@ -1181,6 +1189,10 @@ protected:
         setType(e, _ty.type);
     }
     virtual void visitClosure(Closure *) { _ty = TypingResult(ObjectType); } // TODO: VERIFY THIS!
+    virtual void visitConvert(Convert *e) {
+        _ty = run(e->expr);
+    }
+
     virtual void visitUnop(Unop *e) {
         _ty = run(e->expr);
         switch (e->op) {
@@ -1318,19 +1330,69 @@ protected:
 class TypePropagation: public StmtVisitor, public ExprVisitor {
     Type _ty;
 
-    void run(Expr *e, Type requestedType = UnknownType) {
+    void run(Expr *&e, Type requestedType = UnknownType) {
         qSwap(_ty, requestedType);
         e->accept(this);
         qSwap(_ty, requestedType);
+
+        if (requestedType != UnknownType)
+            if (e->type != requestedType)
+                if (requestedType & NumberType) {
+                    qDebug()<<"adding conversion from"<<typeName(e->type)<<"to"<<typeName(requestedType);
+                    addConversion(e, requestedType);
+                }
+    }
+
+    struct Conversion {
+        Expr **expr;
+        Type targetType;
+        Stmt *stmt;
+
+        Conversion(Expr **expr = 0, Type targetType = UnknownType, Stmt *stmt = 0)
+            : expr(expr)
+            , targetType(targetType)
+            , stmt(stmt)
+        {}
+    };
+
+    Stmt *_currStmt;
+    QVector<Conversion> _conversions;
+
+    void addConversion(Expr *&expr, Type targetType) {
+        _conversions.append(Conversion(&expr, targetType, _currStmt));
     }
 
 public:
     TypePropagation() : _ty(UnknownType) {}
 
     void run(Function *f) {
-        foreach (BasicBlock *bb, f->basicBlocks)
-            foreach (Stmt *s, bb->statements)
+        foreach (BasicBlock *bb, f->basicBlocks) {
+            _conversions.clear();
+
+            foreach (Stmt *s, bb->statements) {
+                _currStmt = s;
                 s->accept(this);
+            }
+
+            foreach (const Conversion &conversion, _conversions) {
+                if (conversion.stmt->asMove() && conversion.stmt->asMove()->source->asTemp()) {
+                    *conversion.expr = bb->CONVERT(*conversion.expr, conversion.targetType);
+                } else {
+                    Temp *target = bb->TEMP(bb->newTemp());
+                    target->type = conversion.targetType;
+                    Expr *convert = bb->CONVERT(*conversion.expr, conversion.targetType);
+                    Move *convCall = f->New<Move>();
+                    convCall->init(target, convert, OpInvalid);
+
+                    Temp *source = bb->TEMP(target->index);
+                    source->type = conversion.targetType;
+                    *conversion.expr = source;
+
+                    int idx = bb->statements.indexOf(conversion.stmt);
+                    bb->statements.insert(idx, convCall);
+                }
+            }
+        }
     }
 
 protected:
@@ -1345,8 +1407,57 @@ protected:
     virtual void visitName(Name *) {}
     virtual void visitTemp(Temp *) {}
     virtual void visitClosure(Closure *) {}
+    virtual void visitConvert(Convert *e) { run(e->expr, e->type); }
     virtual void visitUnop(Unop *e) { run(e->expr, e->type); }
-    virtual void visitBinop(Binop *e) { run(e->left, e->type); run(e->right, e->type); }
+    virtual void visitBinop(Binop *e) {
+        // FIXME: This routine needs more tuning!
+        switch (e->op) {
+        case OpAdd:
+        case OpSub:
+        case OpMul:
+        case OpDiv:
+        case OpMod:
+        case OpBitAnd:
+        case OpBitOr:
+        case OpBitXor:
+        case OpLShift:
+        case OpRShift:
+        case OpURShift:
+            run(e->left, e->type);
+            run(e->right, e->type);
+            break;
+
+        case OpGt:
+        case OpLt:
+        case OpGe:
+        case OpLe:
+            if (e->left->type == DoubleType)
+                run(e->right, DoubleType);
+            else if (e->right->type == DoubleType)
+                run(e->left, DoubleType);
+            else {
+                run(e->left, e->type);
+                run(e->right, e->type);
+            }
+            break;
+
+        case OpEqual:
+        case OpNotEqual:
+        case OpStrictEqual:
+        case OpStrictNotEqual:
+            break;
+
+        case OpInstanceof:
+        case OpIn:
+            run(e->left, e->type);
+            run(e->right, e->type);
+            break;
+
+        default:
+            Q_UNIMPLEMENTED();
+            Q_UNREACHABLE();
+        }
+    }
     virtual void visitCall(Call *e) {
         run(e->base);
         for (ExprList *it = e->args; it; it = it->next)
@@ -1375,11 +1486,15 @@ protected:
     virtual void visitPhi(Phi *s) {
         Type ty = s->targetTemp->type;
         foreach (Expr *e, s->incoming)
-            run(e, ty);
+            if (e->asConst())
+                run(e, ty);
     }
 };
 
 void insertMove(Function *function, BasicBlock *basicBlock, Temp *target, Expr *source) {
+    if (target->type != source->type)
+        source = basicBlock->CONVERT(source, target->type);
+
     Move *s = function->New<Move>();
     s->init(target, source, OpInvalid);
     basicBlock->statements.insert(basicBlock->statements.size() - 1, s);
@@ -1672,22 +1787,8 @@ void QQmlJS::linearize(V4IR::Function *function)
             function->basicBlocks[i]->index = i;
     }
 #endif
-    function->removeSharedExpressions();
-//    if (qgetenv("NO_OPT").isEmpty())
-//        ConstantPropagation().run(function);
-
-//#ifndef QV4_NO_LIVENESS
-//    liveness(function);
-//#endif
 
-//    if (qgetenv("NO_OPT").isEmpty()) {
-//        removeDeadAssignments(function);
-//        removeUnreachableBlocks(function);
-//    }
-
-//    showMeTheCode(function);
-//    splitEdges(function);
-//    showMeTheCode(function);
+    function->removeSharedExpressions();
 
 //    showMeTheCode(function);