Generate LLVM code for constructor calls
This commit is contained in:
parent
5c869a3c81
commit
56de925f00
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue