xo-jit: + compile Apply expressions [wip]
This commit is contained in:
parent
432c369a66
commit
69dfaa931a
3 changed files with 91 additions and 0 deletions
|
|
@ -3,6 +3,7 @@
|
|||
#include "xo/jit/Jit.hpp"
|
||||
#include "xo/expression/Constant.hpp"
|
||||
#include "xo/expression/Primitive.hpp"
|
||||
#include "xo/expression/Apply.hpp"
|
||||
#include <iostream>
|
||||
|
||||
int
|
||||
|
|
@ -10,6 +11,7 @@ main() {
|
|||
using xo::jit::Jit;
|
||||
using xo::ast::make_constant;
|
||||
using xo::ast::make_primitive;
|
||||
using xo::ast::make_apply;
|
||||
using xo::xtag;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
|
|
@ -51,6 +53,28 @@ main() {
|
|||
<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
/* (sqrt 2) */
|
||||
|
||||
auto fn = make_primitive("sqrt", ::sqrt);
|
||||
auto arg = make_constant(2.0);
|
||||
|
||||
auto call = make_apply(fn, arg);
|
||||
|
||||
auto llvm_ircode = jit->codegen(call);
|
||||
|
||||
if (llvm_ircode) {
|
||||
/* note: llvm:errs() is 'raw stderr stream' */
|
||||
cerr << "ex1 llvm_ircode:" << endl;
|
||||
llvm_ircode->print(llvm::errs());
|
||||
cerr << endl;
|
||||
} else {
|
||||
cerr << "ex1: code generation failed"
|
||||
<< xtag("expr", call)
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** end ex1.cpp **/
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include "xo/expression/Expression.hpp"
|
||||
#include "xo/expression/ConstantInterface.hpp"
|
||||
#include "xo/expression/PrimitiveInterface.hpp"
|
||||
#include "xo/expression/Apply.hpp"
|
||||
#include "llvm/ADT/APFloat.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/IR/BasicBlock.h"
|
||||
|
|
@ -50,6 +51,7 @@ namespace xo {
|
|||
|
||||
llvm::Value * codegen_constant(ref::brw<xo::ast::ConstantInterface> expr);
|
||||
llvm::Function * codegen_primitive(ref::brw<xo::ast::PrimitiveInterface> expr);
|
||||
llvm::Value * codegen_apply(ref::brw<xo::ast::Apply> expr);
|
||||
|
||||
llvm::Value * codegen(ref::brw<Expression> expr);
|
||||
|
||||
|
|
@ -64,6 +66,8 @@ namespace xo {
|
|||
* each with its own LLVMContext
|
||||
**/
|
||||
std::unique_ptr<llvm::LLVMContext> llvm_cx_;
|
||||
/** builder for intermediate-representation objects **/
|
||||
std::unique_ptr<llvm::IRBuilder<>> llvm_ir_builder_;
|
||||
/** a module (aka library) being prepared by llvm.
|
||||
* - function names are unique within a module.
|
||||
**/
|
||||
|
|
|
|||
|
|
@ -7,11 +7,15 @@ namespace xo {
|
|||
using xo::ast::Expression;
|
||||
using xo::ast::ConstantInterface;
|
||||
using xo::ast::PrimitiveInterface;
|
||||
using xo::ast::Apply;
|
||||
using xo::reflect::TypeDescr;
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
|
||||
namespace jit {
|
||||
Jit::Jit()
|
||||
: llvm_cx_{std::make_unique<llvm::LLVMContext>()},
|
||||
llvm_ir_builder_{std::make_unique<llvm::IRBuilder<>>(*llvm_cx_)},
|
||||
llvm_module_{std::make_unique<llvm::Module>("xojit", *llvm_cx_)}
|
||||
{}
|
||||
|
||||
|
|
@ -75,6 +79,60 @@ namespace xo {
|
|||
return fn;
|
||||
} /*codegen_primitive*/
|
||||
|
||||
llvm::Value *
|
||||
Jit::codegen_apply(ref::brw<Apply> apply)
|
||||
{
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
|
||||
/* editorial:
|
||||
*
|
||||
* to handle (computed functions) properly,
|
||||
* we will need a runtime representation for a 'primitive function pointer'
|
||||
*
|
||||
* For now, finesse by only handling PrimitiveInterface in function-callee position
|
||||
*/
|
||||
if (apply->fn()->extype() == exprtype::primitive) {
|
||||
auto pm = PrimitiveInterface::from(apply->fn());
|
||||
auto * fn = this->codegen_primitive(pm);
|
||||
|
||||
#ifdef NOT_USING_DEBUG
|
||||
cerr << "Jit::codegen_apply: fn:" << endl;
|
||||
fn->print(llvm::errs());
|
||||
cerr << endl;
|
||||
#endif
|
||||
|
||||
if (fn->arg_size() != apply->argv().size()) {
|
||||
cerr << "Jit::codegen_apply: error: callee f expecting n1 args where n2 supplied"
|
||||
<< xtag("f", pm->name())
|
||||
<< xtag("n1", pm->n_arg())
|
||||
<< xtag("n2", apply->argv().size())
|
||||
<< endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<llvm::Value *> args;
|
||||
args.reserve(apply->argv().size());
|
||||
|
||||
for (const auto & arg_expr : apply->argv()) {
|
||||
auto * arg = this->codegen(arg_expr);
|
||||
|
||||
#ifdef NOT_USING_DEBUG
|
||||
cerr << "Jit::codegen_apply: arg:" << endl;
|
||||
arg->print(llvm::errs());
|
||||
cerr << endl;
|
||||
#endif
|
||||
|
||||
args.push_back(arg);
|
||||
}
|
||||
|
||||
return llvm_ir_builder_->CreateCall(fn, args, "calltmp");
|
||||
} else {
|
||||
cerr << "Jit::codegen_apply: error: only allowing call to known primitives at present" << endl;
|
||||
return nullptr;
|
||||
}
|
||||
} /*codegen_apply*/
|
||||
|
||||
llvm::Value *
|
||||
Jit::codegen(ref::brw<Expression> expr)
|
||||
{
|
||||
|
|
@ -84,6 +142,7 @@ namespace xo {
|
|||
case exprtype::primitive:
|
||||
return this->codegen_primitive(PrimitiveInterface::from(expr));
|
||||
case exprtype::apply:
|
||||
return this->codegen_apply(Apply::from(expr));
|
||||
break;
|
||||
case exprtype::invalid:
|
||||
case exprtype::n_expr:
|
||||
|
|
@ -91,6 +150,10 @@ namespace xo {
|
|||
break;
|
||||
}
|
||||
|
||||
cerr << "Jit::codegen: error: no handler for expression of type T"
|
||||
<< xtag("T", expr->extype())
|
||||
<< endl;
|
||||
|
||||
return nullptr;
|
||||
} /*codegen*/
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue