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)
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);
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);
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);
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()) {
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;
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);
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);
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>();
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));
struct Name;
struct Temp;
struct Closure;
+struct Convert;
struct Unop;
struct Binop;
struct Call;
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;
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; }
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;
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);
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 *);
protected:
virtual void visitPhi(Phi *) {};
+ virtual void visitConvert(Convert *e) { e->expr->accept(this); };
virtual void visitConst(Const *) {}
virtual void visitString(String *) {}
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); }
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); }
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:
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) {
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:
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)
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);
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);