diff options
author | Roberto Raggi <roberto.raggi@nokia.com> | 2012-06-06 14:59:42 +0200 |
---|---|---|
committer | Roberto Raggi <roberto.raggi@nokia.com> | 2012-06-06 14:59:42 +0200 |
commit | 9366999ac2b7af81e3e1ce6e89160fc759a8c637 (patch) | |
tree | b76b6c63dac15784ff24375d4399da37402ea5cc /qv4isel_llvm.cpp | |
parent | 01bca93863d61ed25d3d5935a7e150174d68be32 (diff) |
Generate code for closures.
Diffstat (limited to 'qv4isel_llvm.cpp')
-rw-r--r-- | qv4isel_llvm.cpp | 60 |
1 files changed, 54 insertions, 6 deletions
diff --git a/qv4isel_llvm.cpp b/qv4isel_llvm.cpp index 374aeaf5d2..a997272fa3 100644 --- a/qv4isel_llvm.cpp +++ b/qv4isel_llvm.cpp @@ -72,16 +72,31 @@ llvm::Module *LLVMInstructionSelection::getLLVMModule(IR::Module *module) foreach (IR::Function *function, module->functions) - (void) getLLVMFunction(function); + (void) compileLLVMFunction(function); qSwap(_llvmModule, llvmModule); return llvmModule; } llvm::Function *LLVMInstructionSelection::getLLVMFunction(IR::Function *function) { - llvm::Function *llvmFunction = - llvm::Function::Create(_functionTy, llvm::Function::ExternalLinkage, // ### make it internal - llvm::Twine(function->name ? qPrintable(*function->name) : 0), _llvmModule); + llvm::Function *&f = _functionMap[function]; + if (! f) { + QString name = QStringLiteral("__qmljs_native_"); + if (function->name) { + if (*function->name == QStringLiteral("%entry")) + name = *function->name; + else + name += *function->name; + } + f = llvm::Function::Create(_functionTy, llvm::Function::ExternalLinkage, // ### make it internal + qPrintable(name), _llvmModule); + } + return f; +} + +llvm::Function *LLVMInstructionSelection::compileLLVMFunction(IR::Function *function) +{ + llvm::Function *llvmFunction = getLLVMFunction(function); QHash<IR::BasicBlock *, llvm::BasicBlock *> blockMap; QVector<llvm::Value *> tempMap; @@ -355,9 +370,13 @@ void LLVMInstructionSelection::visitTemp(IR::Temp *e) } } -void LLVMInstructionSelection::visitClosure(IR::Closure *) +void LLVMInstructionSelection::visitClosure(IR::Closure *e) { - Q_UNIMPLEMENTED(); + llvm::Value *tmp = newLLVMTemp(_valueTy); + llvm::Value *clos = getLLVMFunction(e->value); + CreateCall3(_llvmModule->getFunction("__qmljs_init_native_function"), + _llvmFunction->arg_begin(), tmp, clos); + _llvmValue = CreateLoad(tmp); } void LLVMInstructionSelection::visitUnop(IR::Unop *e) @@ -525,11 +544,40 @@ void LLVMInstructionSelection::genConstructMember(IR::New *e, llvm::Value *resul _llvmValue = CreateLoad(result); } +void LLVMInstructionSelection::genCallTemp(IR::Call *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 *thisObject = llvm::Constant::getNullValue(_valueTy->getPointerTo()); + + llvm::Value *actuals[] = { + _llvmFunction->arg_begin(), + result, + thisObject, + func, + args, + getInt32(argc) + }; + + CreateCall(_llvmModule->getFunction("__qmljs_llvm_call_value"), actuals); + + _llvmValue = CreateLoad(result); +} + void LLVMInstructionSelection::visitCall(IR::Call *e) { if (e->base->asMember()) { genCallMember(e); return; + } else if (e->base->asTemp()) { + genCallTemp(e); + return; } llvm::Value *func = 0; |