From: Erik Verbruggen Date: Wed, 16 Jan 2013 14:49:42 +0000 (+0100) Subject: Moved callBuiltin into the common super class. X-Git-Tag: upstream/5.2.1~669^2~659^2~500 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1925eb6c9a45ae10815d8bca0755ec873fe4eb59;p=platform%2Fupstream%2Fqtdeclarative.git Moved callBuiltin into the common super class. Now the backends do not need to duplicate the tedious switch, but can just implement the specific methods. It also prevents backends from missing out on cases. Change-Id: I45a25c6955af584f60b6e69cf6a616ca3e2dc640 Reviewed-by: Lars Knoll --- diff --git a/moth/qv4instr_moth_p.h b/moth/qv4instr_moth_p.h index fd0dbb4..8136a68 100644 --- a/moth/qv4instr_moth_p.h +++ b/moth/qv4instr_moth_p.h @@ -22,7 +22,6 @@ F(CallBuiltinDeleteMember, callBuiltinDeleteMember) \ F(CallBuiltinDeleteSubscript, callBuiltinDeleteSubscript) \ F(CallBuiltinDeleteName, callBuiltinDeleteName) \ - F(CallBuiltinDeleteValue, callBuiltinDeleteValue) \ F(CallBuiltinTypeofMember, callBuiltinTypeofMember) \ F(CallBuiltinTypeofSubscript, callBuiltinTypeofSubscript) \ F(CallBuiltinTypeofName, callBuiltinTypeofName) \ @@ -185,11 +184,6 @@ union Instr VM::String *name; int targetTempIndex; }; - struct instr_callBuiltinDeleteValue { - MOTH_INSTR_HEADER - int tempIndex; - int targetTempIndex; - }; struct instr_callBuiltinTypeofMember { MOTH_INSTR_HEADER int base; @@ -322,7 +316,6 @@ union Instr instr_callBuiltinDeleteMember callBuiltinDeleteMember; instr_callBuiltinDeleteSubscript callBuiltinDeleteSubscript; instr_callBuiltinDeleteName callBuiltinDeleteName; - instr_callBuiltinDeleteValue callBuiltinDeleteValue; instr_callBuiltinTypeofMember callBuiltinTypeofMember; instr_callBuiltinTypeofSubscript callBuiltinTypeofSubscript; instr_callBuiltinTypeofName callBuiltinTypeofName; diff --git a/moth/qv4isel_moth.cpp b/moth/qv4isel_moth.cpp index 01a5866..1267534 100644 --- a/moth/qv4isel_moth.cpp +++ b/moth/qv4isel_moth.cpp @@ -327,220 +327,20 @@ void InstructionSelection::run(VM::Function *vmFunction, IR::Function *function) delete[] codeStart; } -void InstructionSelection::callActivationProperty(IR::Call *c, IR::Temp *temp) -{ - const int targetTempIndex = temp ? temp->index : scratchTempIndex(); -; - IR::Name *baseName = c->base->asName(); - Q_ASSERT(baseName); - - switch (baseName->builtin) { - case IR::Name::builtin_invalid: { - const int scratchIndex = scratchTempIndex(); - - Instruction::LoadName load; - load.name = engine()->newString(*baseName->id); - load.targetTempIndex = scratchIndex; - addInstruction(load); - - Instruction::CallValue call; - prepareCallArgs(c->args, call.argc, call.args); - call.destIndex = scratchIndex; - call.targetTempIndex = targetTempIndex; - addInstruction(call); - } break; - - case IR::Name::builtin_typeof: { - if (IR::Member *m = c->args->expr->asMember()) { - Instruction::CallBuiltinTypeofMember call; - call.base = m->base->asTemp()->index; - call.member = engine()->identifier(*m->name); - call.targetTempIndex = targetTempIndex; - addInstruction(call); - } else if (IR::Subscript *ss = c->args->expr->asSubscript()) { - Instruction::CallBuiltinTypeofSubscript call; - call.base = ss->base->asTemp()->index; - call.index = ss->index->asTemp()->index; - call.targetTempIndex = targetTempIndex; - addInstruction(call); - } else if (IR::Name *n = c->args->expr->asName()) { - Instruction::CallBuiltinTypeofName call; - call.name = engine()->identifier(*n->id); - call.targetTempIndex = targetTempIndex; - addInstruction(call); - } else if (IR::Temp *arg = c->args->expr->asTemp()){ - assert(arg != 0); - Instruction::CallBuiltinTypeofValue call; - call.tempIndex = arg->index; - call.targetTempIndex = targetTempIndex; - addInstruction(call); - } else { - assert(false); - } - } break; - - case IR::Name::builtin_delete: { - if (IR::Member *m = c->args->expr->asMember()) { - Instruction::CallBuiltinDeleteMember call; - call.base = m->base->asTemp()->index; - call.member = engine()->newString(*m->name); - call.targetTempIndex = targetTempIndex; - addInstruction(call); - } else if (IR::Subscript *ss = c->args->expr->asSubscript()) { - Instruction::CallBuiltinDeleteSubscript call; - call.base = ss->base->asTemp()->index; - call.index = ss->index->asTemp()->index; - call.targetTempIndex = targetTempIndex; - addInstruction(call); - } else if (IR::Name *n = c->args->expr->asName()) { - Instruction::CallBuiltinDeleteName call; - call.name = engine()->newString(*n->id); - call.targetTempIndex = targetTempIndex; - addInstruction(call); - } else { - Instruction::CallBuiltinDeleteValue call; - call.tempIndex = c->args->expr->asTemp()->index; - call.targetTempIndex = targetTempIndex; - addInstruction(call); - } - } break; - - case IR::Name::builtin_throw: { - IR::Temp *arg = c->args->expr->asTemp(); - assert(arg != 0); - - Instruction::CallBuiltin call; - call.builtin = Instruction::CallBuiltin::builtin_throw; - prepareCallArgs(c->args, call.argc, call.args); - call.targetTempIndex = targetTempIndex; - addInstruction(call); - } break; - - case IR::Name::builtin_rethrow: { - Instruction::CallBuiltin call; - call.builtin = Instruction::CallBuiltin::builtin_rethrow; - call.targetTempIndex = targetTempIndex; - addInstruction(call); - } break; - - case IR::Name::builtin_create_exception_handler: { - Instruction::CallBuiltin call; - call.builtin = Instruction::CallBuiltin::builtin_create_exception_handler; - call.targetTempIndex = targetTempIndex; - addInstruction(call); - } break; - - case IR::Name::builtin_delete_exception_handler: { - Instruction::CallBuiltin call; - call.builtin = Instruction::CallBuiltin::builtin_delete_exception_handler; - call.targetTempIndex = targetTempIndex; - addInstruction(call); - } break; - - case IR::Name::builtin_get_exception: { - Instruction::CallBuiltin call; - call.builtin = Instruction::CallBuiltin::builtin_get_exception; - call.targetTempIndex = targetTempIndex; - addInstruction(call); - } break; - - case IR::Name::builtin_foreach_iterator_object: { - Instruction::CallBuiltin call; - call.builtin = Instruction::CallBuiltin::builtin_foreach_iterator_object; - prepareCallArgs(c->args, call.argc, call.args); - call.targetTempIndex = targetTempIndex; - addInstruction(call); - } break; - - case IR::Name::builtin_foreach_next_property_name: { - Instruction::CallBuiltin call; - call.builtin = Instruction::CallBuiltin::builtin_foreach_next_property_name; - prepareCallArgs(c->args, call.argc, call.args); - call.targetTempIndex = targetTempIndex; - addInstruction(call); - } break; - - case IR::Name::builtin_push_with: { - Instruction::CallBuiltin call; - call.builtin = Instruction::CallBuiltin::builtin_push_with; - prepareCallArgs(c->args, call.argc, call.args); - assert(call.argc == 1); - addInstruction(call); - } break; - - case IR::Name::builtin_pop_with: { - Instruction::CallBuiltin call; - call.builtin = Instruction::CallBuiltin::builtin_pop_with; - addInstruction(call); - } break; - - case IR::Name::builtin_declare_vars: if (c->args) { - IR::Const *deletable = c->args->expr->asConst(); - assert(deletable->type == IR::BoolType); - const bool isDeletable = deletable->value != 0; - for (IR::ExprList *it = c->args->next; it; it = it->next) { - Instruction::CallBuiltinDeclareVar call; - call.isDeletable = isDeletable; - call.varName = engine()->newString(*it->expr->asName()->id); - addInstruction(call); - } - } break; - - case IR::Name::builtin_define_getter_setter: { - if (!c->args) - return; - IR::ExprList *args = c->args; - Instruction::CallBuiltinDefineGetterSetter call; - call.objectTemp = args->expr->asTemp()->index; - args = args->next; - assert(args); - call.name = engine()->newString(*args->expr->asName()->id); - args = args->next; - assert(args); - call.getterTemp = args->expr->asTemp()->index; - args = args->next; - assert(args); - call.setterTemp = args->expr->asTemp()->index; - addInstruction(call); - } break; - - case IR::Name::builtin_define_property: { - if (!c->args) - return; - IR::ExprList *args = c->args; - Instruction::CallBuiltinDefineProperty call; - call.objectTemp = args->expr->asTemp()->index; - args = args->next; - assert(args); - call.name = engine()->newString(*args->expr->asName()->id); - args = args->next; - assert(args); - call.valueTemp = args->expr->asTemp()->index; - addInstruction(call); - } break; - - default: - Q_UNIMPLEMENTED(); - c->dump(qout); qout << endl; - } -} - -void InstructionSelection::callValue(IR::Call *c, IR::Temp *temp) +void InstructionSelection::callValue(IR::Call *c, IR::Temp *result) { - const int targetTempIndex = temp ? temp->index : scratchTempIndex(); IR::Temp *t = c->base->asTemp(); Q_ASSERT(t); Instruction::CallValue call; prepareCallArgs(c->args, call.argc, call.args); call.destIndex = t->index; - call.targetTempIndex = targetTempIndex; + call.targetTempIndex = result ? result->index : scratchTempIndex(); addInstruction(call); } -void InstructionSelection::callProperty(IR::Call *c, IR::Temp *temp) +void InstructionSelection::callProperty(IR::Call *c, IR::Temp *result) { - const int targetTempIndex = temp ? temp->index : scratchTempIndex(); IR::Member *m = c->base->asMember(); Q_ASSERT(m); @@ -549,7 +349,7 @@ void InstructionSelection::callProperty(IR::Call *c, IR::Temp *temp) call.baseTemp = m->base->asTemp()->index; call.name = engine()->newString(*m->name); prepareCallArgs(c->args, call.argc, call.args); - call.targetTempIndex = targetTempIndex; + call.targetTempIndex = result ? result->index : scratchTempIndex(); addInstruction(call); } @@ -804,11 +604,15 @@ void InstructionSelection::inplaceMemberOp(IR::AluOp oper, IR::Expr *source, IR: addInstruction(imo); } -void InstructionSelection::prepareCallArgs(IR::ExprList *e, quint32 &argc, quint32 &args) +void InstructionSelection::prepareCallArg(IR::Expr *e, quint32 &argc, quint32 &args) { - argc = 0; - args = 0; + // We pass single arguments as references to the stack, but only if it's not a local or an argument. + argc = 1; + args = e->asTemp()->index; +} +void InstructionSelection::prepareCallArgs(IR::ExprList *e, quint32 &argc, quint32 &args) +{ bool singleArgIsTemp = false; if (e && e->next == 0) { // ok, only 1 argument in the cal... @@ -822,12 +626,12 @@ void InstructionSelection::prepareCallArgs(IR::ExprList *e, quint32 &argc, quint if (singleArgIsTemp) { // We pass single arguments as references to the stack, but only if it's not a local or an argument. - argc = 1; - args = e->expr->asTemp()->index; + prepareCallArg(e->expr, argc, args); } else if (e) { // We need to move all the temps into the function arg array int argLocation = outgoingArgumentTempStart(); assert(argLocation >= 0); + argc = 0; args = argLocation; while (e) { Instruction::MoveTemp move; @@ -888,6 +692,191 @@ void InstructionSelection::visitRet(IR::Ret *s) addInstruction(ret); } +void InstructionSelection::callBuiltinInvalid(IR::Expr *func, IR::ExprList *args, IR::Temp *result) +{ + const int scratchIndex = scratchTempIndex(); + + Instruction::LoadName load; + load.name = engine()->newString(*func->asCall()->base->asName()->id); + load.targetTempIndex = scratchIndex; + addInstruction(load); + + const int targetTempIndex = result ? result->index : scratchTempIndex(); + + Instruction::CallValue call; + prepareCallArgs(args, call.argc, call.args); + call.destIndex = scratchIndex; + call.targetTempIndex = targetTempIndex; + addInstruction(call); +} + +void InstructionSelection::callBuiltinTypeofMember(IR::Temp *base, const QString &name, IR::Temp *result) +{ + Instruction::CallBuiltinTypeofMember call; + call.base = base->index; + call.member = engine()->identifier(name); + call.targetTempIndex = result ? result->index : scratchTempIndex(); + addInstruction(call); +} + +void InstructionSelection::callBuiltinTypeofSubscript(IR::Temp *base, IR::Temp *index, IR::Temp *result) +{ + Instruction::CallBuiltinTypeofSubscript call; + call.base = base->index; + call.index = index->index; + call.targetTempIndex = result ? result->index : scratchTempIndex(); + addInstruction(call); +} + +void InstructionSelection::callBuiltinTypeofName(const QString &name, IR::Temp *result) +{ + Instruction::CallBuiltinTypeofName call; + call.name = engine()->identifier(name); + call.targetTempIndex = result ? result->index : scratchTempIndex(); + addInstruction(call); +} + +void InstructionSelection::callBuiltinTypeofValue(IR::Temp *value, IR::Temp *result) +{ + Instruction::CallBuiltinTypeofValue call; + call.tempIndex = value->index; + call.targetTempIndex = result ? result->index : scratchTempIndex(); + addInstruction(call); +} + +void InstructionSelection::callBuiltinDeleteMember(IR::Temp *base, const QString &name, IR::Temp *result) +{ + Instruction::CallBuiltinDeleteMember call; + call.base = base->index; + call.member = engine()->newString(name); + call.targetTempIndex = result ? result->index : scratchTempIndex(); + addInstruction(call); +} + +void InstructionSelection::callBuiltinDeleteSubscript(IR::Temp *base, IR::Temp *index, IR::Temp *result) +{ + Instruction::CallBuiltinDeleteSubscript call; + call.base = base->index; + call.index = index->index; + call.targetTempIndex = result ? result->index : scratchTempIndex(); + addInstruction(call); +} + +void InstructionSelection::callBuiltinDeleteName(const QString &name, IR::Temp *result) +{ + Instruction::CallBuiltinDeleteName call; + call.name = engine()->newString(name); + call.targetTempIndex = result ? result->index : scratchTempIndex(); + addInstruction(call); +} + +void InstructionSelection::callBuiltinDeleteValue(IR::Temp *result) +{ + Instruction::LoadValue load; + load.value = VM::Value::fromBoolean(false); + load.targetTempIndex = result ? result->index : scratchTempIndex(); + addInstruction(load); +} + +void InstructionSelection::callBuiltinThrow(IR::Temp *arg) +{ + Instruction::CallBuiltin call; + call.builtin = Instruction::CallBuiltin::builtin_throw; + prepareCallArg(arg, call.argc, call.args); + addInstruction(call); +} + +void InstructionSelection::callBuiltinRethrow() +{ + Instruction::CallBuiltin call; + call.builtin = Instruction::CallBuiltin::builtin_rethrow; + addInstruction(call); +} + +void InstructionSelection::callBuiltinCreateExceptionHandler(IR::Temp *result) +{ + Instruction::CallBuiltin call; + call.builtin = Instruction::CallBuiltin::builtin_create_exception_handler; + call.targetTempIndex = result ? result->index : scratchTempIndex(); + addInstruction(call); +} + +void InstructionSelection::callBuiltinDeleteExceptionHandler() +{ + Instruction::CallBuiltin call; + call.builtin = Instruction::CallBuiltin::builtin_delete_exception_handler; + addInstruction(call); +} + +void InstructionSelection::callBuiltinGetException(IR::Temp *result) +{ + Instruction::CallBuiltin call; + call.builtin = Instruction::CallBuiltin::builtin_get_exception; + call.targetTempIndex = result ? result->index : scratchTempIndex(); + addInstruction(call); +} + +void InstructionSelection::callBuiltinForeachIteratorObject(IR::Temp *arg, IR::Temp *result) +{ + Instruction::CallBuiltin call; + call.builtin = Instruction::CallBuiltin::builtin_foreach_iterator_object; + prepareCallArg(arg, call.argc, call.args); + call.targetTempIndex = result ? result->index : scratchTempIndex(); + addInstruction(call); +} + +void InstructionSelection::callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result) +{ + Instruction::CallBuiltin call; + call.builtin = Instruction::CallBuiltin::builtin_foreach_next_property_name; + prepareCallArg(arg, call.argc, call.args); + call.targetTempIndex = result ? result->index : scratchTempIndex(); + addInstruction(call); +} + +void InstructionSelection::callBuiltinPushWith(IR::Temp *arg) +{ + Instruction::CallBuiltin call; + call.builtin = Instruction::CallBuiltin::builtin_push_with; + prepareCallArg(arg, call.argc, call.args); + assert(call.argc == 1); + addInstruction(call); +} + +void InstructionSelection::callBuiltinPopWith() +{ + Instruction::CallBuiltin call; + call.builtin = Instruction::CallBuiltin::builtin_pop_with; + addInstruction(call); +} + +void InstructionSelection::callBuiltinDeclareVar(bool deletable, const QString &name) +{ + Instruction::CallBuiltinDeclareVar call; + call.isDeletable = deletable; + call.varName = engine()->newString(name); + addInstruction(call); +} + +void InstructionSelection::callBuiltinDefineGetterSetter(IR::Temp *object, const QString &name, IR::Temp *getter, IR::Temp *setter) +{ + Instruction::CallBuiltinDefineGetterSetter call; + call.objectTemp = object->index; + call.name = engine()->newString(name); + call.getterTemp = getter->index; + call.setterTemp = setter->index; + addInstruction(call); +} + +void InstructionSelection::callBuiltinDefineProperty(IR::Temp *object, const QString &name, IR::Temp *value) +{ + Instruction::CallBuiltinDefineProperty call; + call.objectTemp = object->index; + call.name = engine()->newString(name); + call.valueTemp = value->index; + addInstruction(call); +} + ptrdiff_t InstructionSelection::addInstructionHelper(Instr::Type type, Instr &instr) { #ifdef MOTH_THREADED_INTERPRETER diff --git a/moth/qv4isel_moth_p.h b/moth/qv4isel_moth_p.h index c0e8595..58c7969 100644 --- a/moth/qv4isel_moth_p.h +++ b/moth/qv4isel_moth_p.h @@ -24,9 +24,29 @@ protected: virtual void visitCJump(IR::CJump *); virtual void visitRet(IR::Ret *); - virtual void callActivationProperty(IR::Call *c, IR::Temp *temp); - virtual void callValue(IR::Call *c, IR::Temp *temp); - virtual void callProperty(IR::Call *c, IR::Temp *temp); + virtual void callBuiltinInvalid(IR::Expr *func, IR::ExprList *args, IR::Temp *result); + virtual void callBuiltinTypeofMember(IR::Temp *base, const QString &name, IR::Temp *result); + virtual void callBuiltinTypeofSubscript(IR::Temp *base, IR::Temp *index, IR::Temp *result); + virtual void callBuiltinTypeofName(const QString &name, IR::Temp *result); + virtual void callBuiltinTypeofValue(IR::Temp *value, IR::Temp *result); + virtual void callBuiltinDeleteMember(IR::Temp *base, const QString &name, IR::Temp *result); + virtual void callBuiltinDeleteSubscript(IR::Temp *base, IR::Temp *index, IR::Temp *result); + virtual void callBuiltinDeleteName(const QString &name, IR::Temp *result); + virtual void callBuiltinDeleteValue(IR::Temp *result); + virtual void callBuiltinThrow(IR::Temp *arg); + virtual void callBuiltinRethrow(); + virtual void callBuiltinCreateExceptionHandler(IR::Temp *result); + virtual void callBuiltinDeleteExceptionHandler(); + virtual void callBuiltinGetException(IR::Temp *result); + virtual void callBuiltinForeachIteratorObject(IR::Temp *arg, IR::Temp *result); + virtual void callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result); + virtual void callBuiltinPushWith(IR::Temp *arg); + virtual void callBuiltinPopWith(); + virtual void callBuiltinDeclareVar(bool deletable, const QString &name); + virtual void callBuiltinDefineGetterSetter(IR::Temp *object, const QString &name, IR::Temp *getter, IR::Temp *setter); + virtual void callBuiltinDefineProperty(IR::Temp *object, const QString &name, IR::Temp *value); + virtual void callValue(IR::Call *c, IR::Temp *result); + virtual void callProperty(IR::Call *c, IR::Temp *result); virtual void constructActivationProperty(IR::New *call, IR::Temp *result); virtual void constructProperty(IR::New *call, IR::Temp *result); virtual void constructValue(IR::New *call, IR::Temp *result); @@ -58,6 +78,7 @@ private: }; void simpleMove(IR::Move *); + void prepareCallArg(IR::Expr *e, quint32 &argc, quint32 &args); void prepareCallArgs(IR::ExprList *, quint32 &, quint32 &); int outgoingArgumentTempStart() const { return _function->tempCount; } diff --git a/moth/qv4vme_moth.cpp b/moth/qv4vme_moth.cpp index 2d21b2f..27b92a4 100644 --- a/moth/qv4vme_moth.cpp +++ b/moth/qv4vme_moth.cpp @@ -156,7 +156,7 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co MOTH_BEGIN_INSTR(LoadValue) TEMP(instr.targetTempIndex) = instr.value; - MOTH_END_INSTR(LoadUndefined) + MOTH_END_INSTR(LoadValue) MOTH_BEGIN_INSTR(LoadClosure) VM::Value c = __qmljs_init_closure(instr.value, context); @@ -237,6 +237,9 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co Q_ASSERT(instr.argc == 1); __qmljs_builtin_throw(args[0], context); break; + case Instr::instr_callBuiltin::builtin_rethrow: + __qmljs_builtin_rethrow(context); + break; case Instr::instr_callBuiltin::builtin_create_exception_handler: { TRACE(builtin_create_exception_handler, "%s", ""); buf = __qmljs_create_exception_handler(context); @@ -279,6 +282,7 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co __qmljs_builtin_pop_with(context); break; default: + assert(!"TODO!"); Q_UNREACHABLE(); } MOTH_END_INSTR(CallBuiltin) @@ -295,10 +299,6 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co TEMP(instr.targetTempIndex) = __qmljs_delete_name(context, instr.name); MOTH_END_INSTR(CallBuiltinDeleteName) - MOTH_BEGIN_INSTR(CallBuiltinDeleteValue) - TEMP(instr.targetTempIndex) = VM::Value::fromBoolean(false); - MOTH_END_INSTR(CallBuiltinDeleteValue) - MOTH_BEGIN_INSTR(CallBuiltinTypeofMember) TEMP(instr.targetTempIndex) = __qmljs_builtin_typeof_member(TEMP(instr.base), instr.member, context); MOTH_END_INSTR(CallBuiltinTypeofMember) @@ -317,7 +317,7 @@ VM::Value VME::operator()(QQmlJS::VM::ExecutionContext *context, const uchar *co MOTH_BEGIN_INSTR(CallBuiltinDeclareVar) __qmljs_builtin_declare_var(context, instr.isDeletable, instr.varName); - MOTH_END_INSTR(CallBuiltinDeleteValue) + MOTH_END_INSTR(CallBuiltinDeclareVar) MOTH_BEGIN_INSTR(CallBuiltinDefineGetterSetter) __qmljs_builtin_define_getter_setter(TEMP(instr.objectTemp), instr.name, TEMP(instr.getterTemp), TEMP(instr.setterTemp), context); diff --git a/qv4isel_llvm.cpp b/qv4isel_llvm.cpp index de84722..269dabd 100644 --- a/qv4isel_llvm.cpp +++ b/qv4isel_llvm.cpp @@ -81,10 +81,6 @@ #include "qv4ir_p.h" #include "qv4string.h" -namespace { -QTextStream qout(stderr, QIODevice::WriteOnly); -} // anonymous namespace - namespace QQmlJS { int compileWithLLVM(IR::Module *module, const QString &fileName, LLVMOutputType outputType, int (*exec)(void *)) @@ -304,70 +300,192 @@ void InstructionSelection::buildLLVMModule(IR::Module *module, llvm::Module *llv qSwap(_llvmModule, llvmModule); } -void InstructionSelection::callActivationProperty(IR::Call *c, IR::Temp *temp) +void InstructionSelection::callBuiltinInvalid(IR::Expr *func, IR::ExprList *args, IR::Temp *result) { - IR::Name *baseName = c->base->asName(); - Q_ASSERT(baseName); + // TODO + assert(!"TODO!"); + Q_UNREACHABLE(); +} - switch (baseName->builtin) { - case IR::Name::builtin_declare_vars: { - if (!c->args) - return; - IR::Const *deletable = c->args->expr->asConst(); - assert(deletable->type == IR::BoolType); - llvm::ConstantInt *isDeletable = getInt1(deletable->value != 0); - for (IR::ExprList *it = c->args->next; it; it = it->next) { - IR::Name *arg = it->expr->asName(); - assert(arg != 0); - - llvm::Value *name = getIdentifier(*arg->id); - CreateCall3(getRuntimeFunction("__qmljs_builtin_declare_var"), - _llvmFunction->arg_begin(), isDeletable, name); - } - } return; - default: - break; - } // switch +void InstructionSelection::callBuiltinTypeofMember(IR::Temp *base, const QString &name, IR::Temp *result) +{ + // TODO + assert(!"TODO!"); + Q_UNREACHABLE(); +} + +void InstructionSelection::callBuiltinTypeofSubscript(IR::Temp *base, IR::Temp *index, IR::Temp *result) +{ + // TODO + assert(!"TODO!"); + Q_UNREACHABLE(); +} + +void InstructionSelection::callBuiltinTypeofName(const QString &name, IR::Temp *result) +{ + // TODO + assert(!"TODO!"); + Q_UNREACHABLE(); +} + +void InstructionSelection::callBuiltinTypeofValue(IR::Temp *value, IR::Temp *result) +{ + // TODO + assert(!"TODO!"); + Q_UNREACHABLE(); +} + +void InstructionSelection::callBuiltinDeleteMember(IR::Temp *base, const QString &name, IR::Temp *result) +{ + // TODO + assert(!"TODO!"); + Q_UNREACHABLE(); +} + +void InstructionSelection::callBuiltinDeleteSubscript(IR::Temp *base, IR::Temp *index, IR::Temp *result) +{ + // TODO + assert(!"TODO!"); + Q_UNREACHABLE(); +} + +void InstructionSelection::callBuiltinDeleteName(const QString &name, IR::Temp *result) +{ + // TODO + assert(!"TODO!"); + Q_UNREACHABLE(); +} + +void InstructionSelection::callBuiltinDeleteValue(IR::Temp *result) +{ + // TODO + assert(!"TODO!"); + Q_UNREACHABLE(); +} + +void InstructionSelection::callBuiltinThrow(IR::Temp *arg) +{ + // TODO + assert(!"TODO!"); + Q_UNREACHABLE(); +} + +void InstructionSelection::callBuiltinRethrow() +{ + // TODO + assert(!"TODO!"); + Q_UNREACHABLE(); +} + +void InstructionSelection::callBuiltinCreateExceptionHandler(IR::Temp *result) +{ + // TODO + assert(!"TODO!"); + Q_UNREACHABLE(); +} + +void InstructionSelection::callBuiltinDeleteExceptionHandler() +{ + // TODO + assert(!"TODO!"); + Q_UNREACHABLE(); +} + +void InstructionSelection::callBuiltinGetException(IR::Temp *result) +{ + // TODO + assert(!"TODO!"); + Q_UNREACHABLE(); +} + +void InstructionSelection::callBuiltinForeachIteratorObject(IR::Temp *arg, IR::Temp *result) +{ + // TODO + assert(!"TODO!"); + Q_UNREACHABLE(); +} - Q_UNIMPLEMENTED(); - c->dump(qout); - qout << endl; +void InstructionSelection::callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result) +{ + // TODO + assert(!"TODO!"); + Q_UNREACHABLE(); +} + +void InstructionSelection::callBuiltinPushWith(IR::Temp *arg) +{ + // TODO + assert(!"TODO!"); + Q_UNREACHABLE(); +} + +void InstructionSelection::callBuiltinPopWith() +{ + // TODO + assert(!"TODO!"); + Q_UNREACHABLE(); +} + +void InstructionSelection::callBuiltinDeclareVar(bool deletable, const QString &name) +{ + llvm::ConstantInt *isDeletable = getInt1(deletable != 0); + llvm::Value *varName = getIdentifier(name); + CreateCall3(getRuntimeFunction("__qmljs_builtin_declare_var"), + _llvmFunction->arg_begin(), isDeletable, varName); +} + +void InstructionSelection::callBuiltinDefineGetterSetter(IR::Temp *object, const QString &name, IR::Temp *getter, IR::Temp *setter) +{ + // TODO + assert(!"TODO!"); + Q_UNREACHABLE(); +} + +void InstructionSelection::callBuiltinDefineProperty(IR::Temp *object, const QString &name, IR::Temp *value) +{ + // TODO assert(!"TODO!"); Q_UNREACHABLE(); } void InstructionSelection::callValue(IR::Call *c, IR::Temp *temp) { - // TODO: implement instead of visitExp + // TODO + assert(!"TODO!"); Q_UNREACHABLE(); } void InstructionSelection::callProperty(IR::Call *c, IR::Temp *temp) { - // TODO: implement instead of visitExp + // TODO + assert(!"TODO!"); Q_UNREACHABLE(); } void InstructionSelection::constructActivationProperty(IR::New *call, IR::Temp *result) { + // TODO assert(!"TODO!"); Q_UNREACHABLE(); } void InstructionSelection::constructProperty(IR::New *call, IR::Temp *result) { + // TODO assert(!"TODO!"); Q_UNREACHABLE(); } void InstructionSelection::constructValue(IR::New *call, IR::Temp *result) { + // TODO assert(!"TODO!"); Q_UNREACHABLE(); } void InstructionSelection::loadThisObject(IR::Temp *temp) { + // TODO assert(!"TODO!"); Q_UNREACHABLE(); } @@ -381,18 +499,21 @@ void InstructionSelection::loadConst(IR::Const *con, IR::Temp *temp) void InstructionSelection::loadString(const QString &str, IR::Temp *targetTemp) { + // TODO assert(!"TODO!"); Q_UNREACHABLE(); } void InstructionSelection::loadRegexp(IR::RegExp *sourceRegexp, IR::Temp *targetTemp) { + // TODO assert(!"TODO!"); Q_UNREACHABLE(); } void InstructionSelection::getActivationProperty(const QString &name, IR::Temp *temp) { + // TODO assert(!"TODO!"); Q_UNREACHABLE(); } @@ -449,6 +570,7 @@ void InstructionSelection::setProperty(IR::Expr *source, IR::Temp *targetBase, c void InstructionSelection::getElement(IR::Temp *sourceBase, IR::Temp *sourceIndex, IR::Temp *target) { + // TODO assert(!"TODO!"); Q_UNREACHABLE(); diff --git a/qv4isel_llvm_p.h b/qv4isel_llvm_p.h index 53d9a8d..1cd1004 100644 --- a/qv4isel_llvm_p.h +++ b/qv4isel_llvm_p.h @@ -70,7 +70,27 @@ public: void buildLLVMModule(IR::Module *module, llvm::Module *llvmModule, llvm::FunctionPassManager *fpm); public: // methods from InstructionSelection: - virtual void callActivationProperty(IR::Call *c, IR::Temp *temp); + virtual void callBuiltinInvalid(IR::Expr *func, IR::ExprList *args, IR::Temp *result); + virtual void callBuiltinTypeofMember(IR::Temp *base, const QString &name, IR::Temp *result); + virtual void callBuiltinTypeofSubscript(IR::Temp *base, IR::Temp *index, IR::Temp *result); + virtual void callBuiltinTypeofName(const QString &name, IR::Temp *result); + virtual void callBuiltinTypeofValue(IR::Temp *value, IR::Temp *result); + virtual void callBuiltinDeleteMember(IR::Temp *base, const QString &name, IR::Temp *result); + virtual void callBuiltinDeleteSubscript(IR::Temp *base, IR::Temp *index, IR::Temp *result); + virtual void callBuiltinDeleteName(const QString &name, IR::Temp *result); + virtual void callBuiltinDeleteValue(IR::Temp *result); + virtual void callBuiltinThrow(IR::Temp *arg); + virtual void callBuiltinRethrow(); + virtual void callBuiltinCreateExceptionHandler(IR::Temp *result); + virtual void callBuiltinDeleteExceptionHandler(); + virtual void callBuiltinGetException(IR::Temp *result); + virtual void callBuiltinForeachIteratorObject(IR::Temp *arg, IR::Temp *result); + virtual void callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result); + virtual void callBuiltinPushWith(IR::Temp *arg); + virtual void callBuiltinPopWith(); + virtual void callBuiltinDeclareVar(bool deletable, const QString &name); + virtual void callBuiltinDefineGetterSetter(IR::Temp *object, const QString &name, IR::Temp *getter, IR::Temp *setter); + virtual void callBuiltinDefineProperty(IR::Temp *object, const QString &name, IR::Temp *value); virtual void callValue(IR::Call *c, IR::Temp *temp); virtual void callProperty(IR::Call *c, IR::Temp *temp); virtual void constructActivationProperty(IR::New *call, IR::Temp *result); diff --git a/qv4isel_masm.cpp b/qv4isel_masm.cpp index b73bddc..1c78dc6 100644 --- a/qv4isel_masm.cpp +++ b/qv4isel_masm.cpp @@ -428,148 +428,114 @@ void InstructionSelection::run(VM::Function *vmFunction, IR::Function *function) _asm = oldAssembler; } -String *InstructionSelection::identifier(const QString &s) +void InstructionSelection::callBuiltinInvalid(IR::Expr *func, IR::ExprList *args, IR::Temp *result) { - return engine()->identifier(s); + callRuntimeMethod(result, __qmljs_call_activation_property, func, args); } -void InstructionSelection::callActivationProperty(IR::Call *call, IR::Temp *result) +void InstructionSelection::callBuiltinTypeofMember(IR::Temp *base, const QString &name, IR::Temp *result) { - IR::Name *baseName = call->base->asName(); - assert(baseName != 0); + generateFunctionCall(result, __qmljs_builtin_typeof_member, base, identifier(name), Assembler::ContextRegister); +} - switch (baseName->builtin) { - case IR::Name::builtin_invalid: - callRuntimeMethod(result, __qmljs_call_activation_property, call->base, call->args); - break; - case IR::Name::builtin_typeof: { - if (IR::Member *m = call->args->expr->asMember()) { - generateFunctionCall(result, __qmljs_builtin_typeof_member, m->base->asTemp(), identifier(*m->name), Assembler::ContextRegister); - return; - } else if (IR::Subscript *ss = call->args->expr->asSubscript()) { - generateFunctionCall(result, __qmljs_builtin_typeof_element, ss->base->asTemp(), ss->index->asTemp(), Assembler::ContextRegister); - return; - } else if (IR::Name *n = call->args->expr->asName()) { - generateFunctionCall(result, __qmljs_builtin_typeof_name, identifier(*n->id), Assembler::ContextRegister); - return; - } else if (IR::Temp *arg = call->args->expr->asTemp()){ - assert(arg != 0); - generateFunctionCall(result, __qmljs_builtin_typeof, arg, Assembler::ContextRegister); - } else { - assert(false); - } - } - break; - case IR::Name::builtin_delete: { - if (IR::Member *m = call->args->expr->asMember()) { - generateFunctionCall(result, __qmljs_delete_member, Assembler::ContextRegister, m->base->asTemp(), identifier(*m->name)); - return; - } else if (IR::Subscript *ss = call->args->expr->asSubscript()) { - generateFunctionCall(result, __qmljs_delete_subscript, Assembler::ContextRegister, ss->base->asTemp(), ss->index->asTemp()); - return; - } else if (IR::Name *n = call->args->expr->asName()) { - generateFunctionCall(result, __qmljs_delete_name, Assembler::ContextRegister, identifier(*n->id)); - return; - } else if (call->args->expr->asTemp()){ - // ### should throw in strict mode - _asm->storeValue(Value::fromBoolean(false), result); - return; - } - break; - } - case IR::Name::builtin_throw: { - IR::Temp *arg = call->args->expr->asTemp(); - assert(arg != 0); - generateFunctionCall(Assembler::Void, __qmljs_builtin_throw, arg, Assembler::ContextRegister); - } - break; - case IR::Name::builtin_rethrow: - generateFunctionCall(Assembler::Void, __qmljs_builtin_rethrow, Assembler::ContextRegister); - break; - case IR::Name::builtin_create_exception_handler: - generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_create_exception_handler, Assembler::ContextRegister); - generateFunctionCall(result, setjmp, Assembler::ReturnValueRegister); - break; - case IR::Name::builtin_delete_exception_handler: - generateFunctionCall(Assembler::Void, __qmljs_delete_exception_handler, Assembler::ContextRegister); - break; - case IR::Name::builtin_get_exception: - generateFunctionCall(result, __qmljs_get_exception, Assembler::ContextRegister); - break; - case IR::Name::builtin_foreach_iterator_object: { - IR::Temp *arg = call->args->expr->asTemp(); - assert(arg != 0); - generateFunctionCall(result, __qmljs_foreach_iterator_object, arg, Assembler::ContextRegister); - } - break; - case IR::Name::builtin_foreach_next_property_name: { - IR::Temp *arg = call->args->expr->asTemp(); - assert(arg != 0); - generateFunctionCall(result, __qmljs_foreach_next_property_name, arg); - } - break; - case IR::Name::builtin_push_with: { - IR::Temp *arg = call->args->expr->asTemp(); - assert(arg != 0); - generateFunctionCall(Assembler::Void, __qmljs_builtin_push_with, arg, Assembler::ContextRegister); - } - break; - case IR::Name::builtin_pop_with: - generateFunctionCall(Assembler::Void, __qmljs_builtin_pop_with, Assembler::ContextRegister); - break; - case IR::Name::builtin_declare_vars: { - if (!call->args) - return; - IR::Const *deletable = call->args->expr->asConst(); - assert(deletable->type == IR::BoolType); - for (IR::ExprList *it = call->args->next; it; it = it->next) { - IR::Name *arg = it->expr->asName(); - assert(arg != 0); - generateFunctionCall(Assembler::Void, __qmljs_builtin_declare_var, Assembler::ContextRegister, - Assembler::TrustedImm32(deletable->value != 0), identifier(*arg->id)); - } - break; - } - case IR::Name::builtin_define_getter_setter: { - if (!call->args) - return; - IR::ExprList *args = call->args; - IR::Temp *object = args->expr->asTemp(); - assert(object); - args = args->next; - assert(args); - IR::Name *name = args->expr->asName(); - args = args->next; - assert(args); - IR::Temp *getter = args->expr->asTemp(); - args = args->next; - assert(args); - IR::Temp *setter = args->expr->asTemp(); - - generateFunctionCall(Assembler::Void, __qmljs_builtin_define_getter_setter, - object, identifier(*name->id), getter, setter, Assembler::ContextRegister); - break; - } - case IR::Name::builtin_define_property: { - if (!call->args) - return; - IR::ExprList *args = call->args; - IR::Temp *object = args->expr->asTemp(); - assert(object); - args = args->next; - assert(args); - IR::Name *name = args->expr->asName(); - args = args->next; - assert(args); - IR::Temp *value = args->expr->asTemp(); - - generateFunctionCall(Assembler::Void, __qmljs_builtin_define_property, - object, identifier(*name->id), value, Assembler::ContextRegister); - break; - } - } +void InstructionSelection::callBuiltinTypeofSubscript(IR::Temp *base, IR::Temp *index, IR::Temp *result) +{ + generateFunctionCall(result, __qmljs_builtin_typeof_element, base, index, Assembler::ContextRegister); +} + +void InstructionSelection::callBuiltinTypeofName(const QString &name, IR::Temp *result) +{ + generateFunctionCall(result, __qmljs_builtin_typeof_name, identifier(name), Assembler::ContextRegister); } +void InstructionSelection::callBuiltinTypeofValue(IR::Temp *value, IR::Temp *result) +{ + generateFunctionCall(result, __qmljs_builtin_typeof, value, Assembler::ContextRegister); +} + +void InstructionSelection::callBuiltinDeleteMember(IR::Temp *base, const QString &name, IR::Temp *result) +{ + generateFunctionCall(result, __qmljs_delete_member, Assembler::ContextRegister, base, identifier(name)); +} + +void InstructionSelection::callBuiltinDeleteSubscript(IR::Temp *base, IR::Temp *index, IR::Temp *result) +{ + generateFunctionCall(result, __qmljs_delete_subscript, Assembler::ContextRegister, base, index); +} + +void InstructionSelection::callBuiltinDeleteName(const QString &name, IR::Temp *result) +{ + generateFunctionCall(result, __qmljs_delete_name, Assembler::ContextRegister, identifier(name)); +} + +void InstructionSelection::callBuiltinDeleteValue(IR::Temp *result) +{ + _asm->storeValue(Value::fromBoolean(false), result); +} + +void InstructionSelection::callBuiltinThrow(IR::Temp *arg) +{ + generateFunctionCall(Assembler::Void, __qmljs_builtin_throw, arg, Assembler::ContextRegister); +} + +void InstructionSelection::callBuiltinRethrow() +{ + generateFunctionCall(Assembler::Void, __qmljs_builtin_rethrow, Assembler::ContextRegister); +} + +void InstructionSelection::callBuiltinCreateExceptionHandler(IR::Temp *result) +{ + generateFunctionCall(Assembler::ReturnValueRegister, __qmljs_create_exception_handler, Assembler::ContextRegister); + generateFunctionCall(result, setjmp, Assembler::ReturnValueRegister); +} + +void InstructionSelection::callBuiltinDeleteExceptionHandler() +{ + generateFunctionCall(Assembler::Void, __qmljs_delete_exception_handler, Assembler::ContextRegister); +} + +void InstructionSelection::callBuiltinGetException(IR::Temp *result) +{ + generateFunctionCall(result, __qmljs_get_exception, Assembler::ContextRegister); +} + +void InstructionSelection::callBuiltinForeachIteratorObject(IR::Temp *arg, IR::Temp *result) +{ + generateFunctionCall(result, __qmljs_foreach_iterator_object, arg, Assembler::ContextRegister); +} + +void InstructionSelection::callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result) +{ + generateFunctionCall(result, __qmljs_foreach_next_property_name, arg); +} + +void InstructionSelection::callBuiltinPushWith(IR::Temp *arg) +{ + generateFunctionCall(Assembler::Void, __qmljs_builtin_push_with, arg, Assembler::ContextRegister); +} + +void InstructionSelection::callBuiltinPopWith() +{ + generateFunctionCall(Assembler::Void, __qmljs_builtin_pop_with, Assembler::ContextRegister); +} + +void InstructionSelection::callBuiltinDeclareVar(bool deletable, const QString &name) +{ + generateFunctionCall(Assembler::Void, __qmljs_builtin_declare_var, Assembler::ContextRegister, + Assembler::TrustedImm32(deletable), identifier(name)); +} + +void InstructionSelection::callBuiltinDefineGetterSetter(IR::Temp *object, const QString &name, IR::Temp *getter, IR::Temp *setter) +{ + generateFunctionCall(Assembler::Void, __qmljs_builtin_define_getter_setter, + object, identifier(name), getter, setter, Assembler::ContextRegister); +} + +void InstructionSelection::callBuiltinDefineProperty(IR::Temp *object, const QString &name, IR::Temp *value) +{ + generateFunctionCall(Assembler::Void, __qmljs_builtin_define_property, + object, identifier(name), value, Assembler::ContextRegister); +} void InstructionSelection::callValue(IR::Call *call, IR::Temp *result) { @@ -764,6 +730,11 @@ void InstructionSelection::callProperty(IR::Call *call, IR::Temp *result) generateFunctionCall(result, __qmljs_call_property, Assembler::ContextRegister, member->base->asTemp(), identifier(*member->name), baseAddressForCallArguments(), Assembler::TrustedImm32(argc)); } +String *InstructionSelection::identifier(const QString &s) +{ + return engine()->identifier(s); +} + void InstructionSelection::constructActivationProperty(IR::New *call, IR::Temp *result) { IR::Name *baseName = call->base->asName(); diff --git a/qv4isel_masm_p.h b/qv4isel_masm_p.h index c042bd6..e1eb16b 100644 --- a/qv4isel_masm_p.h +++ b/qv4isel_masm_p.h @@ -652,7 +652,27 @@ public: virtual void run(VM::Function *vmFunction, IR::Function *function); protected: - virtual void callActivationProperty(IR::Call *call, IR::Temp *result); + virtual void callBuiltinInvalid(IR::Expr *func, IR::ExprList *args, IR::Temp *result); + virtual void callBuiltinTypeofMember(IR::Temp *base, const QString &name, IR::Temp *result); + virtual void callBuiltinTypeofSubscript(IR::Temp *base, IR::Temp *index, IR::Temp *result); + virtual void callBuiltinTypeofName(const QString &name, IR::Temp *result); + virtual void callBuiltinTypeofValue(IR::Temp *value, IR::Temp *result); + virtual void callBuiltinDeleteMember(IR::Temp *base, const QString &name, IR::Temp *result); + virtual void callBuiltinDeleteSubscript(IR::Temp *base, IR::Temp *index, IR::Temp *result); + virtual void callBuiltinDeleteName(const QString &name, IR::Temp *result); + virtual void callBuiltinDeleteValue(IR::Temp *result); + virtual void callBuiltinThrow(IR::Temp *arg); + virtual void callBuiltinRethrow(); + virtual void callBuiltinCreateExceptionHandler(IR::Temp *result); + virtual void callBuiltinDeleteExceptionHandler(); + virtual void callBuiltinGetException(IR::Temp *result); + virtual void callBuiltinForeachIteratorObject(IR::Temp *arg, IR::Temp *result); + virtual void callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result); + virtual void callBuiltinPushWith(IR::Temp *arg); + virtual void callBuiltinPopWith(); + virtual void callBuiltinDeclareVar(bool deletable, const QString &name); + virtual void callBuiltinDefineGetterSetter(IR::Temp *object, const QString &name, IR::Temp *getter, IR::Temp *setter); + virtual void callBuiltinDefineProperty(IR::Temp *object, const QString &name, IR::Temp *value); virtual void callProperty(IR::Call *call, IR::Temp *result); virtual void callValue(IR::Call *call, IR::Temp *result); virtual void loadThisObject(IR::Temp *temp); diff --git a/qv4isel_p.cpp b/qv4isel_p.cpp index 9326a2f..603c593 100644 --- a/qv4isel_p.cpp +++ b/qv4isel_p.cpp @@ -126,7 +126,7 @@ void InstructionSelection::visitMove(IR::Move *s) } } else if (IR::Call *c = s->source->asCall()) { if (c->base->asName()) { - callActivationProperty(c, t); + callBuiltin(c, t); return; } else if (c->base->asMember()) { callProperty(c, t); @@ -201,7 +201,7 @@ void InstructionSelection::visitExp(IR::Exp *s) if (IR::Call *c = s->expr->asCall()) { // These are calls where the result is ignored. if (c->base->asName()) { - callActivationProperty(c, 0); + callBuiltin(c, 0); } else if (c->base->asTemp()) { callValue(c, 0); } else if (c->base->asMember()) { @@ -213,3 +213,147 @@ void InstructionSelection::visitExp(IR::Exp *s) Q_UNREACHABLE(); } } + +void InstructionSelection::callBuiltin(IR::Call *call, IR::Temp *result) +{ + IR::Name *baseName = call->base->asName(); + assert(baseName != 0); + + switch (baseName->builtin) { + case IR::Name::builtin_invalid: + callBuiltinInvalid(call->base, call->args, result); + return; + + case IR::Name::builtin_typeof: { + if (IR::Member *m = call->args->expr->asMember()) { + callBuiltinTypeofMember(m->base->asTemp(), *m->name, result); + return; + } else if (IR::Subscript *ss = call->args->expr->asSubscript()) { + callBuiltinTypeofSubscript(ss->base->asTemp(), ss->index->asTemp(), result); + return; + } else if (IR::Name *n = call->args->expr->asName()) { + callBuiltinTypeofName(*n->id, result); + return; + } else if (IR::Temp *arg = call->args->expr->asTemp()){ + assert(arg != 0); + callBuiltinTypeofValue(arg, result); + return; + } + } break; + + case IR::Name::builtin_delete: { + if (IR::Member *m = call->args->expr->asMember()) { + callBuiltinDeleteMember(m->base->asTemp(), *m->name, result); + return; + } else if (IR::Subscript *ss = call->args->expr->asSubscript()) { + callBuiltinDeleteSubscript(ss->base->asTemp(), ss->index->asTemp(), result); + return; + } else if (IR::Name *n = call->args->expr->asName()) { + callBuiltinDeleteName(*n->id, result); + return; + } else if (call->args->expr->asTemp()){ + // TODO: should throw in strict mode + callBuiltinDeleteValue(result); + return; + } + } break; + + case IR::Name::builtin_throw: { + IR::Temp *arg = call->args->expr->asTemp(); + assert(arg != 0); + callBuiltinThrow(arg); + } return; + + case IR::Name::builtin_rethrow: + callBuiltinRethrow(); + return; + + case IR::Name::builtin_create_exception_handler: + callBuiltinCreateExceptionHandler(result); + return; + + case IR::Name::builtin_delete_exception_handler: + callBuiltinDeleteExceptionHandler(); + return; + + case IR::Name::builtin_get_exception: + callBuiltinGetException(result); + return; + + case IR::Name::builtin_foreach_iterator_object: { + IR::Temp *arg = call->args->expr->asTemp(); + assert(arg != 0); + callBuiltinForeachIteratorObject(arg, result); + } return; + + case IR::Name::builtin_foreach_next_property_name: { + IR::Temp *arg = call->args->expr->asTemp(); + assert(arg != 0); + callBuiltinForeachNextPropertyname(arg, result); + } return; + case IR::Name::builtin_push_with: { + IR::Temp *arg = call->args->expr->asTemp(); + assert(arg != 0); + callBuiltinPushWith(arg); + } return; + + case IR::Name::builtin_pop_with: + callBuiltinPopWith(); + return; + + case IR::Name::builtin_declare_vars: { + if (!call->args) + return; + IR::Const *deletable = call->args->expr->asConst(); + assert(deletable->type == IR::BoolType); + for (IR::ExprList *it = call->args->next; it; it = it->next) { + IR::Name *arg = it->expr->asName(); + assert(arg != 0); + callBuiltinDeclareVar(deletable->value != 0, *arg->id); + } + } return; + + case IR::Name::builtin_define_getter_setter: { + if (!call->args) + return; + IR::ExprList *args = call->args; + IR::Temp *object = args->expr->asTemp(); + assert(object); + args = args->next; + assert(args); + IR::Name *name = args->expr->asName(); + args = args->next; + assert(args); + IR::Temp *getter = args->expr->asTemp(); + args = args->next; + assert(args); + IR::Temp *setter = args->expr->asTemp(); + + callBuiltinDefineGetterSetter(object, *name->id, getter, setter); + } return; + + case IR::Name::builtin_define_property: { + if (!call->args) + return; + IR::ExprList *args = call->args; + IR::Temp *object = args->expr->asTemp(); + assert(object); + args = args->next; + assert(args); + IR::Name *name = args->expr->asName(); + args = args->next; + assert(args); + IR::Temp *value = args->expr->asTemp(); + + callBuiltinDefineProperty(object, *name->id, value); + } return; + + default: + break; + } + + Q_UNIMPLEMENTED(); + call->dump(qout); qout << endl; + assert(!"TODO!"); + Q_UNREACHABLE(); +} diff --git a/qv4isel_p.h b/qv4isel_p.h index 59464c6..275c3ec 100644 --- a/qv4isel_p.h +++ b/qv4isel_p.h @@ -80,7 +80,27 @@ public: // visitor methods for StmtVisitor: virtual void visitExp(IR::Exp *s); public: // to implement by subclasses: - virtual void callActivationProperty(IR::Call *c, IR::Temp *temp) = 0; + virtual void callBuiltinInvalid(IR::Expr *func, IR::ExprList *args, IR::Temp *result) = 0; + virtual void callBuiltinTypeofMember(IR::Temp *base, const QString &name, IR::Temp *result) = 0; + virtual void callBuiltinTypeofSubscript(IR::Temp *base, IR::Temp *index, IR::Temp *result) = 0; + virtual void callBuiltinTypeofName(const QString &name, IR::Temp *result) = 0; + virtual void callBuiltinTypeofValue(IR::Temp *value, IR::Temp *result) = 0; + virtual void callBuiltinDeleteMember(IR::Temp *base, const QString &name, IR::Temp *result) = 0; + virtual void callBuiltinDeleteSubscript(IR::Temp *base, IR::Temp *index, IR::Temp *result) = 0; + virtual void callBuiltinDeleteName(const QString &name, IR::Temp *result) = 0; + virtual void callBuiltinDeleteValue(IR::Temp *result) = 0; + virtual void callBuiltinThrow(IR::Temp *arg) = 0; + virtual void callBuiltinRethrow() = 0; + virtual void callBuiltinCreateExceptionHandler(IR::Temp *result) = 0; + virtual void callBuiltinDeleteExceptionHandler() = 0; + virtual void callBuiltinGetException(IR::Temp *result) = 0; + virtual void callBuiltinForeachIteratorObject(IR::Temp *arg, IR::Temp *result) = 0; + virtual void callBuiltinForeachNextPropertyname(IR::Temp *arg, IR::Temp *result) = 0; + virtual void callBuiltinPushWith(IR::Temp *arg) = 0; + virtual void callBuiltinPopWith() = 0; + virtual void callBuiltinDeclareVar(bool deletable, const QString &name) = 0; + virtual void callBuiltinDefineGetterSetter(IR::Temp *object, const QString &name, IR::Temp *getter, IR::Temp *setter) = 0; + virtual void callBuiltinDefineProperty(IR::Temp *object, const QString &name, IR::Temp *value) = 0; virtual void callValue(IR::Call *c, IR::Temp *temp) = 0; virtual void callProperty(IR::Call *c, IR::Temp *temp) = 0; virtual void constructActivationProperty(IR::New *call, IR::Temp *result) = 0; @@ -103,6 +123,9 @@ public: // to implement by subclasses: virtual void inplaceNameOp(IR::AluOp oper, IR::Expr *sourceExpr, const QString &targetName) = 0; virtual void inplaceElementOp(IR::AluOp oper, IR::Expr *sourceExpr, IR::Temp *targetBaseTemp, IR::Temp *targetIndexTemp) = 0; virtual void inplaceMemberOp(IR::AluOp oper, IR::Expr *source, IR::Temp *targetBase, const QString &targetName) = 0; + +private: + void callBuiltin(IR::Call *c, IR::Temp *temp); }; } // namespace IR