aboutsummaryrefslogtreecommitdiffstats
path: root/qv4isel_llvm.cpp
diff options
context:
space:
mode:
authorRoberto Raggi <roberto.raggi@nokia.com>2012-06-06 14:59:42 +0200
committerRoberto Raggi <roberto.raggi@nokia.com>2012-06-06 14:59:42 +0200
commit9366999ac2b7af81e3e1ce6e89160fc759a8c637 (patch)
treeb76b6c63dac15784ff24375d4399da37402ea5cc /qv4isel_llvm.cpp
parent01bca93863d61ed25d3d5935a7e150174d68be32 (diff)
Generate code for closures.
Diffstat (limited to 'qv4isel_llvm.cpp')
-rw-r--r--qv4isel_llvm.cpp60
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;