We can always loosen these again if we need to.
#include <QtCore/QBitArray>
#include <QtCore/QStack>
#include <private/qqmljsast_p.h>
+#include <math.h>
#include <iostream>
#include <cassert>
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);
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)
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)
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;
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);
return s;
}
-Stmt *BasicBlock::RET(Expr *expr, Type type)
+Stmt *BasicBlock::RET(Temp *expr, Type type)
{
if (isTerminated())
return 0;
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;
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;
};
struct Call: Expr {
- Expr *base;
- ExprList *args;
+ Expr *base; // Name, Member, Temp
+ ExprList *args; // List of Temps
void init(Expr *base, ExprList *args)
{
};
struct New: Expr {
- Expr *base;
- ExprList *args;
+ Expr *base; // Name, Member, Temp
+ ExprList *args; // List of Temps
void init(Expr *base, ExprList *args)
{
};
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;
};
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;
};
struct Move: Stmt {
- Expr *target;
+ Expr *target; // LHS - Temp, Name, Member or Subscript
Expr *source;
AluOp op;
};
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;
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);
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);
};