Moved callBuiltin into the common super class.
authorErik Verbruggen <erik.verbruggen@me.com>
Wed, 16 Jan 2013 14:49:42 +0000 (15:49 +0100)
committerLars Knoll <lars.knoll@digia.com>
Wed, 16 Jan 2013 15:00:57 +0000 (16:00 +0100)
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 <lars.knoll@digia.com>
moth/qv4instr_moth_p.h
moth/qv4isel_moth.cpp
moth/qv4isel_moth_p.h
moth/qv4vme_moth.cpp
qv4isel_llvm.cpp
qv4isel_llvm_p.h
qv4isel_masm.cpp
qv4isel_masm_p.h
qv4isel_p.cpp
qv4isel_p.h

index fd0dbb4..8136a68 100644 (file)
@@ -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;
index 01a5866..1267534 100644 (file)
@@ -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
index c0e8595..58c7969 100644 (file)
@@ -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; }
index 2d21b2f..27b92a4 100644 (file)
@@ -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);
index de84722..269dabd 100644 (file)
 #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();
 
index 53d9a8d..1cd1004 100644 (file)
@@ -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);
index b73bddc..1c78dc6 100644 (file)
@@ -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();
index c042bd6..e1eb16b 100644 (file)
@@ -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);
index 9326a2f..603c593 100644 (file)
@@ -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();
+}
index 59464c6..275c3ec 100644 (file)
@@ -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