F(CallBuiltinDeleteMember, callBuiltinDeleteMember) \
F(CallBuiltinDeleteSubscript, callBuiltinDeleteSubscript) \
F(CallBuiltinDeleteName, callBuiltinDeleteName) \
- F(CallBuiltinDeleteValue, callBuiltinDeleteValue) \
F(CallBuiltinTypeofMember, callBuiltinTypeofMember) \
F(CallBuiltinTypeofSubscript, callBuiltinTypeofSubscript) \
F(CallBuiltinTypeofName, callBuiltinTypeofName) \
VM::String *name;
int targetTempIndex;
};
- struct instr_callBuiltinDeleteValue {
- MOTH_INSTR_HEADER
- int tempIndex;
- int targetTempIndex;
- };
struct instr_callBuiltinTypeofMember {
MOTH_INSTR_HEADER
int base;
instr_callBuiltinDeleteMember callBuiltinDeleteMember;
instr_callBuiltinDeleteSubscript callBuiltinDeleteSubscript;
instr_callBuiltinDeleteName callBuiltinDeleteName;
- instr_callBuiltinDeleteValue callBuiltinDeleteValue;
instr_callBuiltinTypeofMember callBuiltinTypeofMember;
instr_callBuiltinTypeofSubscript callBuiltinTypeofSubscript;
instr_callBuiltinTypeofName callBuiltinTypeofName;
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);
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);
}
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...
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;
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
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);
};
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; }
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);
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);
__qmljs_builtin_pop_with(context);
break;
default:
+ assert(!"TODO!");
Q_UNREACHABLE();
}
MOTH_END_INSTR(CallBuiltin)
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)
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);
#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 *))
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();
}
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();
}
void InstructionSelection::getElement(IR::Temp *sourceBase, IR::Temp *sourceIndex, IR::Temp *target)
{
+ // TODO
assert(!"TODO!");
Q_UNREACHABLE();
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);
_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)
{
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();
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);
}
} 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);
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()) {
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();
+}
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;
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