DEFINE_BOOL_CONFIG_OPTION(bindingsDump, QML_BINDINGS_DUMP)
DEFINE_BOOL_CONFIG_OPTION(qmlDisableOptimizer, QML_DISABLE_OPTIMIZER)
-DEFINE_BOOL_CONFIG_OPTION(qmlExperimental, QML_EXPERIMENTAL)
DEFINE_BOOL_CONFIG_OPTION(qmlVerboseCompiler, QML_VERBOSE_COMPILER)
DEFINE_BOOL_CONFIG_OPTION(qmlBindingsTestEnv, QML_BINDINGS_TEST)
gen(i);
} break;
+ case IR::NullType: {
+ Instr::LoadNull i;
+ i.reg = currentReg;
+ gen(i);
+ } break;
+
default:
if (qmlVerboseCompiler())
qWarning() << Q_FUNC_INFO << "unexpected type";
gen(attached);
} break;
+ case IR::Name::ModuleObject: {
+ /*
+ Existing module object lookup methods include:
+ 1. string -> module object (search via importCache->query(name))
+ 2. QQmlMetaType::ModuleApi -> module object (via QQmlEnginePrivate::moduleApiInstance() cache)
+ We currently use 1, which is not ideal for performance
+ */
+ _subscribeName << *e->id;
+
+ registerLiteralString(currentReg, e->id);
+
+ Instr::LoadModuleObject module;
+ module.reg = currentReg;
+ gen(module);
+ } break;
+
case IR::Name::Property: {
_subscribeName << *e->id;
return V4Instr::LeReal;
case IR::OpEqual:
+ if (e->left->type == IR::ObjectType || e->right->type == IR::ObjectType)
+ return V4Instr::EqualObject;
if (e->left->type == IR::StringType)
return V4Instr::EqualString;
return V4Instr::EqualReal;
case IR::OpNotEqual:
+ if (e->left->type == IR::ObjectType || e->right->type == IR::ObjectType)
+ return V4Instr::NotEqualObject;
if (e->left->type == IR::StringType)
return V4Instr::NotEqualString;
return V4Instr::NotEqualReal;
case IR::OpStrictEqual:
+ if (e->left->type == IR::ObjectType || e->right->type == IR::ObjectType)
+ return V4Instr::StrictEqualObject;
if (e->left->type == IR::StringType)
return V4Instr::StrictEqualString;
return V4Instr::StrictEqualReal;
case IR::OpStrictNotEqual:
+ if (e->left->type == IR::ObjectType || e->right->type == IR::ObjectType)
+ return V4Instr::StrictNotEqualObject;
if (e->left->type == IR::StringType)
return V4Instr::StrictNotEqualString;
return V4Instr::StrictNotEqualReal;
void QV4CompilerPrivate::visitBinop(IR::Binop *e)
{
+ if (e->type == IR::InvalidType) {
+ discard();
+ return;
+ }
+
int left = currentReg;
int right = currentReg + 1;
- if (e->left->asTemp() && e->type != IR::StringType) // Not sure if the e->type != String test is needed
- left = e->left->asTemp()->index;
- else
- traceExpression(e->left, left);
+ traceExpression(e->left, left);
+ traceExpression(e->right, right);
- if (IR::Temp *t = e->right->asTemp())
- right = t->index;
- else
- traceExpression(e->right, right);
-
- if (e->left->type != e->right->type) {
- if (qmlVerboseCompiler())
- qWarning().nospace() << "invalid operands to binary operator " << IR::binaryOperator(e->op)
- << "(`" << IR::binaryOperator(e->left->type)
- << "' and `"
- << IR::binaryOperator(e->right->type)
- << "'";
- discard();
- return;
- }
+ // At this point it is possible that the type of the
+ // subexpressions is different. This can happen because
+ // we keep BINOP expressions in HIR.
switch (e->op) {
case IR::OpInvalid:
case IR::OpNotEqual:
case IR::OpStrictEqual:
case IR::OpStrictNotEqual:
- if (e->left->type != IR::StringType) {
+ if (e->left->type >= IR::FirstNumberType) {
convertToReal(e->left, left);
convertToReal(e->right, right);
}
gen(i);
} return;
+ case IR::MathAbsBuiltinFunction: {
+ Instr::MathAbsReal i;
+ i.output = i.src = currentReg;
+ gen(i);
+ } return;
+
case IR::MathRoundBultinFunction: {
Instr::MathRoundReal i;
i.output = i.src = currentReg;
gen(i);
} return;
+ case IR::MathCeilBuiltinFunction: {
+ Instr::MathCeilReal i;
+ i.output = i.src = currentReg;
+ gen(i);
+ } return;
+
case IR::MathPIBuiltinConstant:
+ default:
break;
} // switch
+ } else {
+ if (name->builtin == IR::MathMaxBuiltinFunction ||
+ name->builtin == IR::MathMinBuiltinFunction) {
+
+ //only handles the most common case of exactly two arguments
+ if (call->args && call->args->next && !call->args->next->next) {
+ IR::Expr *arg1 = call->args->expr;
+ IR::Expr *arg2 = call->args->next->expr;
+
+ if (arg1 != 0 && arg1->type == IR::RealType &&
+ arg2 != 0 && arg2->type == IR::RealType) {
+
+ traceExpression(arg1, currentReg);
+ traceExpression(arg2, currentReg + 1);
+
+ if (name->builtin == IR::MathMaxBuiltinFunction) {
+ Instr::MathMaxReal i;
+ i.left = currentReg;
+ i.right = currentReg + 1;
+ i.output = currentReg;
+ gen(i);
+ return;
+ } else if (name->builtin == IR::MathMinBuiltinFunction) {
+ Instr::MathMinReal i;
+ i.left = currentReg;
+ i.right = currentReg + 1;
+ i.output = currentReg;
+ gen(i);
+ return;
+ }
+ }
+ }
+ }
}
}
case IR::StringType: opcode = V4Instr::ConvertStringToBool; break;
case IR::UrlType: opcode = V4Instr::ConvertUrlToBool; break;
case IR::ColorType: opcode = V4Instr::ConvertColorToBool; break;
+ case IR::ObjectType: opcode = V4Instr::ConvertObjectToBool; break;
default: break;
} // switch
} else if (targetTy == IR::IntType) {
case IR::StringType: opcode = V4Instr::ConvertStringToColor; break;
default: break;
} // switch
+ } else if (targetTy == IR::ObjectType) {
+ switch (sourceTy) {
+ case IR::NullType: opcode = V4Instr::ConvertNullToObject; break;
+ default: break;
+ } // switch
}
if (opcode != V4Instr::Noop) {
V4Instr conv;
{
if (!expression.expression.asAST()) return false;
- if (!qmlExperimental() && expression.property->isValueTypeSubProperty)
- return -1;
-
if (qmlDisableOptimizer() || !qmlEnableV4)
return -1;