diff --git a/llvm_runtime.cpp b/llvm_runtime.cpp index 87b9fb04c0..4f7375a64a 100644 --- a/llvm_runtime.cpp +++ b/llvm_runtime.cpp @@ -175,9 +175,9 @@ void __qmljs_llvm_not(Context *ctx, Value *result, const Value *value) __qmljs_not(ctx, result, value); } -String *__qmljs_llvm_get_identifier(Context *ctx, const char *str) +String *__qmljs_llvm_identifier_from_utf8(Context *ctx, const char *str) { - return __qmljs_string_from_utf8(ctx, str); // ### make it unique + return __qmljs_identifier_from_utf8(ctx, str); // ### make it unique } void __qmljs_llvm_call_activation_property(Context *context, Value *result, String *name, Value *args, int argc) @@ -195,6 +195,11 @@ void __qmljs_llvm_construct_activation_property(Context *context, Value *result, __qmljs_construct_activation_property(context, result, name, args, argc); } +void __qmljs_llvm_construct_value(Context *context, Value *result, const Value *func, Value *args, int argc) +{ + __qmljs_construct_value(context, result, func, args, argc); +} + void __qmljs_llvm_get_activation_property(Context *ctx, Value *result, String *name) { __qmljs_get_activation_property(ctx, result, name); @@ -275,4 +280,10 @@ void __qmljs_llvm_delete_value(Context *ctx, Value *result, Value *value) __qmljs_delete_value(ctx, result, value); } +void __qmljs_llvm_init_this_object(Context *ctx) +{ + if (ctx->calledAsConstructor) + __qmljs_new_object(ctx, &ctx->thisObject); +} + } // extern "C" diff --git a/qmljs_runtime.cpp b/qmljs_runtime.cpp index 4bcef59bfa..0680955f9c 100644 --- a/qmljs_runtime.cpp +++ b/qmljs_runtime.cpp @@ -494,6 +494,11 @@ String *__qmljs_string_from_utf8(Context *ctx, const char *s) return ctx->engine->newString(QString::fromUtf8(s)); } +String *__qmljs_identifier_from_utf8(Context *ctx, const char *s) +{ + return ctx->engine->identifier(QString::fromUtf8(s)); +} + int __qmljs_string_length(Context *, String *string) { return string->toQString().length(); @@ -581,6 +586,11 @@ void __qmljs_throw_type_error(Context *ctx, Value *result) *result = ctx->result; } +void __qmljs_new_object(Context *ctx, Value *result) +{ + __qmljs_init_object(result, ctx->engine->newObject()); +} + void __qmljs_new_boolean_object(Context *ctx, Value *result, bool boolean) { Value value; diff --git a/qmljs_runtime.h b/qmljs_runtime.h index 642619114a..d6ab5e20cb 100644 --- a/qmljs_runtime.h +++ b/qmljs_runtime.h @@ -99,10 +99,12 @@ void __qmljs_string_from_number(Context *ctx, Value *result, double number); bool __qmljs_string_compare(Context *ctx, String *left, String *right); bool __qmljs_string_equal(Context *ctx, String *left, String *right); String *__qmljs_string_concat(Context *ctx, String *first, String *second); +String *__qmljs_identifier_from_utf8(Context *ctx, const char *s); // objects void __qmljs_object_default_value(Context *ctx, Value *result, const Value *object, int typeHint); void __qmljs_throw_type_error(Context *ctx, Value *result); +void __qmljs_new_object(Context *ctx, Value *result); void __qmljs_new_boolean_object(Context *ctx, Value *result, bool boolean); void __qmljs_new_number_object(Context *ctx, Value *result, double n); void __qmljs_new_string_object(Context *ctx, Value *result, String *string); diff --git a/qv4isel_llvm.cpp b/qv4isel_llvm.cpp index 7c666c7fe2..7ec7065a16 100644 --- a/qv4isel_llvm.cpp +++ b/qv4isel_llvm.cpp @@ -106,6 +106,10 @@ llvm::Function *LLVMInstructionSelection::compileLLVMFunction(IR::Function *func qSwap(_tempMap, tempMap); qSwap(_blockMap, blockMap); + // create the LLVM blocks + foreach (IR::BasicBlock *block, _function->basicBlocks) + (void) getLLVMBasicBlock(block); + // entry block SetInsertPoint(getLLVMBasicBlock(_function->basicBlocks.first())); @@ -122,6 +126,9 @@ llvm::Function *LLVMInstructionSelection::compileLLVMFunction(IR::Function *func CreateStore(llvm::Constant::getNullValue(_valueTy), t); } + CreateCall(_llvmModule->getFunction("__qmljs_llvm_init_this_object"), + _llvmFunction->arg_begin()); + foreach (IR::BasicBlock *block, _function->basicBlocks) { qSwap(_block, block); SetInsertPoint(getLLVMBasicBlock(_block)); @@ -222,7 +229,7 @@ llvm::Value *LLVMInstructionSelection::getStringPtr(const QString &s) llvm::Value *LLVMInstructionSelection::getIdentifier(const QString &s) { llvm::Value *str = getStringPtr(s); - llvm::Value *id = CreateCall2(_llvmModule->getFunction("__qmljs_llvm_get_identifier"), + llvm::Value *id = CreateCall2(_llvmModule->getFunction("__qmljs_identifier_from_utf8"), _llvmFunction->arg_begin(), str); return id; } @@ -576,6 +583,29 @@ void LLVMInstructionSelection::genCallTemp(IR::Call *e, llvm::Value *result) _llvmValue = CreateLoad(result); } +void LLVMInstructionSelection::genConstructTemp(IR::New *e, llvm::Value *result) +{ + if (! result) + result = newLLVMTemp(_valueTy); + + llvm::Value *func = getLLVMTempReference(e->base); + + int argc = 0; + llvm::Value *args = genArguments(e->args, argc); + + llvm::Value *actuals[] = { + _llvmFunction->arg_begin(), + result, + func, + args, + getInt32(argc) + }; + + CreateCall(_llvmModule->getFunction("__qmljs_llvm_construct_value"), actuals); + + _llvmValue = CreateLoad(result); +} + void LLVMInstructionSelection::genCallName(IR::Call *e, llvm::Value *result) { IR::Name *base = e->base->asName(); @@ -656,6 +686,28 @@ void LLVMInstructionSelection::genCallName(IR::Call *e, llvm::Value *result) } } +void LLVMInstructionSelection::genConstructName(IR::New *e, llvm::Value *result) +{ + IR::Name *base = e->base->asName(); + + if (! result) + result = newLLVMTemp(_valueTy); + + if (! base->id) { + Q_UNREACHABLE(); + } else { + llvm::Value *name = getIdentifier(*base->id); + + int argc = 0; + llvm::Value *args = genArguments(e->args, argc); + + CreateCall5(_llvmModule->getFunction("__qmljs_construct_activation_property"), + _llvmFunction->arg_begin(), result, name, args, getInt32(argc)); + + _llvmValue = CreateLoad(result); + } +} + void LLVMInstructionSelection::visitCall(IR::Call *e) { if (e->base->asMember()) { @@ -684,30 +736,20 @@ void LLVMInstructionSelection::visitNew(IR::New *e) { if (e->base->asMember()) { genConstructMember(e); - return; - } + } else if (e->base->asTemp()) { + genConstructTemp(e); + } else if (e->base->asName()) { + genConstructName(e); + } else if (IR::Temp *t = e->base->asTemp()) { + llvm::Value *base = getLLVMTemp(t); - llvm::Value *func = 0; - llvm::Value *base = 0; - if (IR::Temp *t = e->base->asTemp()) { - base = getLLVMTemp(t); - func = _llvmModule->getFunction("__qmljs_llvm_construct_value"); - } else if (IR::Name *n = e->base->asName()) { - if (n->id) { - llvm::Value *str = getStringPtr(*n->id); - base = CreateCall2(_llvmModule->getFunction("__qmljs_llvm_get_identifier"), - _llvmFunction->arg_begin(), str); - func = _llvmModule->getFunction("__qmljs_llvm_construct_activation_property"); - } - } + int argc = 0; + llvm::Value *args = genArguments(e->args, argc); - int argc = 0; - llvm::Value *args = genArguments(e->args, argc); - - if (func) { llvm::Value *result = newLLVMTemp(_valueTy); CreateStore(llvm::Constant::getNullValue(_valueTy), result); - CreateCall5(func, _llvmFunction->arg_begin(), result, base, args, getInt32(argc)); + CreateCall5(_llvmModule->getFunction("__qmljs_llvm_construct_value"), + _llvmFunction->arg_begin(), result, base, args, getInt32(argc)); _llvmValue = CreateLoad(result); } else { Q_UNIMPLEMENTED(); diff --git a/qv4isel_llvm_p.h b/qv4isel_llvm_p.h index 64511f86c5..5f67f2d66a 100644 --- a/qv4isel_llvm_p.h +++ b/qv4isel_llvm_p.h @@ -30,9 +30,11 @@ public: void genBinop(llvm::Value *result, IR::Binop *e); llvm::AllocaInst *newLLVMTemp(llvm::Type *type, llvm::Value *size = 0); llvm::Value * genArguments(IR::ExprList *args, int &argc); - void genCallMember(IR::Call *e, llvm::Value *result = 0); void genCallTemp(IR::Call *e, llvm::Value *result = 0); void genCallName(IR::Call *e, llvm::Value *result = 0); + void genCallMember(IR::Call *e, llvm::Value *result = 0); + void genConstructTemp(IR::New *e, llvm::Value *result = 0); + void genConstructName(IR::New *e, llvm::Value *result = 0); void genConstructMember(IR::New *e, llvm::Value *result = 0); void genMoveSubscript(IR::Move *s); void genMoveMember(IR::Move *s); diff --git a/qv4isel_x86_64.cpp b/qv4isel_x86_64.cpp index e60dd5655f..a0e3c9dab0 100644 --- a/qv4isel_x86_64.cpp +++ b/qv4isel_x86_64.cpp @@ -219,6 +219,9 @@ void InstructionSelection::callActivationProperty(IR::Call *call, IR::Temp *resu amd64_mov_reg_imm(_codePtr, AMD64_RCX, argc); amd64_call_code(_codePtr, __qmljs_builtin_typeof); break; + case IR::Name::builtin_delete: + Q_UNREACHABLE(); + break; case IR::Name::builtin_throw: amd64_lea_membase(_codePtr, AMD64_RDX, AMD64_RSP, 0); amd64_mov_reg_imm(_codePtr, AMD64_RCX, argc);