} else if (IR::Binop *b = s->source->asBinop()) {
Instruction::Binop binop;
binop.alu = aluOpFunction(b->op);
- binop.lhsTempIndex = b->left->index;
- binop.rhsTempIndex = b->right->index;
+// binop.lhsTempIndex = b->left->index;
+// binop.rhsTempIndex = b->right->index;
addInstruction(binop);
} else if (IR::Call *c = s->source->asCall()) {
if (c->base->asName()) {
} else if (IR::Binop *b = s->cond->asBinop()) {
Instruction::Binop binop;
binop.alu = aluOpFunction(b->op);
- binop.lhsTempIndex = b->left->index;
- binop.rhsTempIndex = b->right->index;
+// binop.lhsTempIndex = b->left->index;
+// binop.rhsTempIndex = b->right->index;
addInstruction(binop);
} else {
Q_UNREACHABLE();
static inline bool integerCompatible(Value a, Value b) {
return ((a.tag & b.tag) & ConvertibleToInt) == ConvertibleToInt;
}
+ static inline bool bothDouble(Value a, Value b) {
+ return ((a.tag | b.tag) & NotDouble_Mask) != NotDouble_Mask;
+ }
inline bool tryIntegerConversion() {
bool b = isConvertibleToInt();
if (b)
if (Value::integerCompatible(left, right))
return add_int32(left.integerValue(), right.integerValue());
- if (left.isDouble() & right.isDouble())
+ if (Value::bothDouble(left, right))
return Value::fromDouble(left.doubleValue() + right.doubleValue());
return __qmljs_add_helper(left, right, ctx);
if (Value::integerCompatible(left, right))
return left.integerValue() > right.integerValue();
- if (left.isDouble() && right.isDouble()) {
+ if (Value::bothDouble(left, right)) {
return left.doubleValue() > right.doubleValue();
} else if (left.isString() && right.isString()) {
return __qmljs_string_compare(ctx, right.stringValue(), left.stringValue());
if (Value::integerCompatible(left, right))
return left.integerValue() < right.integerValue();
- if (left.isDouble() && right.isDouble()) {
+ if (Value::bothDouble(left, right)) {
return left.doubleValue() < right.doubleValue();
} else if (left.isString() && right.isString()) {
return __qmljs_string_compare(ctx, left.stringValue(), right.stringValue());
if (Value::integerCompatible(left, right))
return left.integerValue() >= right.integerValue();
- if (left.isDouble() && right.isDouble()) {
+ if (Value::bothDouble(left, right)) {
return left.doubleValue() >= right.doubleValue();
} else if (left.isString() && right.isString()) {
return !__qmljs_string_compare(ctx, left.stringValue(), right.stringValue());
if (Value::integerCompatible(left, right))
return left.integerValue() <= right.integerValue();
- if (left.isDouble() && right.isDouble()) {
+ if (Value::bothDouble(left, right)) {
return left.doubleValue() <= right.doubleValue();
} else if (left.isString() && right.isString()) {
return !__qmljs_string_compare(ctx, right.stringValue(), left.stringValue());
TRACE2(left, right);
// need to test for doubles first as NaN != NaN
- if (left.isDouble() && right.isDouble())
+ if (Value::bothDouble(left, right))
return left.doubleValue() == right.doubleValue();
if (left.val == right.val)
return true;
}
}
- if (!left->asTemp()) {
+ if (!left->asTemp() && !left->asConst()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), left);
left = _block->TEMP(t);
}
- if (!right->asTemp()) {
+ if (!right->asTemp() && !right->asConst()) {
const unsigned t = _block->newTemp();
move(_block->TEMP(t), right);
right = _block->TEMP(t);
}
- assert(left->asTemp() && right->asTemp());
- return _block->BINOP(op, left->asTemp(), right->asTemp());
+ assert(left->asTemp() || left->asConst());
+ assert(right->asTemp() || right->asConst());
+
+ return _block->BINOP(op, left, right);
}
IR::Expr *Codegen::call(IR::Expr *base, IR::ExprList *args)
return e;
}
-Expr *BasicBlock::BINOP(AluOp op, Temp *left, Temp *right)
+Expr *BasicBlock::BINOP(AluOp op, Expr *left, Expr *right)
{
Binop *e = function->New<Binop>();
e->init(op, left, right);
struct Binop: Expr {
AluOp op;
- Temp *left;
- Temp *right;
+ Expr *left; // Temp or Const
+ Expr *right; // Temp or Const
- void init(AluOp op, Temp *left, Temp *right)
+ void init(AluOp op, Expr *left, Expr *right)
{
this->op = op;
this->left = left;
Closure *CLOSURE(Function *function);
Expr *UNOP(AluOp op, Temp *expr);
- Expr *BINOP(AluOp op, Temp *left, Temp *right);
+ Expr *BINOP(AluOp op, Expr *left, Expr *right);
Expr *CALL(Expr *base, ExprList *args = 0);
Expr *NEW(Expr *base, ExprList *args = 0);
Expr *SUBSCRIPT(Temp *base, Temp *index);
return;
}
} else if (IR::Binop *b = s->source->asBinop()) {
- IR::Temp *l = b->left->asTemp();
- IR::Temp *r = b->right->asTemp();
- if (l && r) {
+ if ((b->left->asTemp() || b->left->asConst()) &&
+ (b->right->asTemp() || b->right->asConst())) {
Value (*op)(const Value, const Value, Context *) = 0;
const char* opName = 0;
}
if (op) {
- generateFunctionCallImp(t, opName, op, l, r, ContextRegister);
+ generateFunctionCallImp(t, opName, op, b->left, b->right, ContextRegister);
}
return;
}
jumpToBlock(s->iffalse);
return;
} else if (IR::Binop *b = s->cond->asBinop()) {
- IR::Temp *l = b->left->asTemp();
- IR::Temp *r = b->right->asTemp();
- if (l && r) {
+ if ((b->left->asTemp() || b->left->asConst()) &&
+ (b->right->asTemp() || b->right->asConst())) {
Bool (*op)(const Value, const Value, Context *ctx) = 0;
const char *opName = 0;
switch (b->op) {
case IR::OpIn: setOp(op, opName, __qmljs_cmp_in); break;
} // switch
- generateFunctionCallImp(ReturnValueRegister, opName, op, l, r, ContextRegister);
+ generateFunctionCallImp(ReturnValueRegister, opName, op, b->left, b->right, ContextRegister);
Jump target = branch32(NotEqual, ReturnValueRegister, TrustedImm32(0));
_patches[s->iftrue].append(target);
load64(addr, dest);
}
}
+
+ void loadArgument(IR::Const* c, RegisterID dest)
+ {
+ VM::Value v;
+ switch (c->type) {
+ case IR::NullType:
+ v = VM::Value::nullValue();
+ break;
+ case IR::UndefinedType:
+ v = VM::Value::undefinedValue();
+ break;
+ case IR::BoolType:
+ v = VM::Value::fromBoolean(c->value != 0);
+ break;
+ case IR::NumberType: {
+ int ival = (int)c->value;
+ if (ival == c->value) {
+ v = VM::Value::fromInt32(ival);
+ } else {
+ v = VM::Value::fromDouble(c->value);
+ }
+ }
+ }
+ move(TrustedImm64(v.val), dest);
+ }
+
+ void loadArgument(IR::Expr* expr, RegisterID dest)
+ {
+ if (!expr) {
+ VM::Value undefined = VM::Value::undefinedValue();
+ move(TrustedImm64(undefined.val), dest);
+ } else if (expr->asTemp()){
+ loadArgument(expr->asTemp(), dest);
+ } else if (expr->asConst()) {
+ loadArgument(expr->asConst(), dest);
+ } else {
+ assert(!"unimplemented expression type in loadArgument");
+ }
+ }
#endif
void loadArgument(VM::String* string, RegisterID dest)
}
}
+ void push(IR::Const* c)
+ {
+ VM::Value v;
+ switch (c->type) {
+ case IR::NullType:
+ v = VM::Value::nullValue();
+ break;
+ case IR::UndefinedType:
+ v = VM::Value::undefinedValue();
+ break;
+ case IR::BoolType:
+ v = VM::Value::fromBoolean(c->value != 0);
+ break;
+ case IR::NumberType: {
+ int ival = (int)c->value;
+ if (ival == c->value) {
+ v = VM::Value::fromInt32(ival);
+ } else {
+ v = VM::Value::fromDouble(c->value);
+ }
+ }
+ }
+ push(v);
+ }
+
+ void push(IR::Expr* e)
+ {
+ if (!e) {
+ VM::Value undefined = VM::Value::undefinedValue();
+ push(undefined);
+ } else if (IR::Const *c = e->asConst())
+ push(c);
+ else if (IR::Temp *t = e->asTemp()) {
+ push(t);
+ } else {
+ assert(!"Trying to push an expression that is not a Temp or Const");
+ }
+ }
+
void push(TrustedImmPtr ptr)
{
move(TrustedImmPtr(ptr), ScratchRegister);
{ return RegisterSize; }
static inline int sizeOfArgument(IR::Temp*)
{ return 8; } // Size of value
+ static inline int sizeOfArgument(IR::Expr*)
+ { return 8; } // Size of value
static inline int sizeOfArgument(const Pointer&)
{ return sizeof(void*); }
static inline int sizeOfArgument(VM::String* string)