xo-jit: + LlvmContext to keepalive native LLVMContext
This commit is contained in:
parent
f3af5d27bf
commit
a927d44e0e
7 changed files with 94 additions and 17 deletions
|
|
@ -6,6 +6,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "xo/refcnt/Refcounted.hpp"
|
||||
#include "LlvmContext.hpp"
|
||||
|
||||
/* stuff from kaleidoscope.cpp */
|
||||
#include "llvm/ADT/APFloat.h"
|
||||
|
|
@ -46,13 +47,16 @@ namespace xo {
|
|||
**/
|
||||
class IrPipeline : public ref::Refcount {
|
||||
public:
|
||||
explicit IrPipeline(llvm::LLVMContext & llvm_cx);
|
||||
explicit IrPipeline(ref::rp<LlvmContext> llvm_cx);
|
||||
|
||||
void run_pipeline(llvm::Function & fn);
|
||||
|
||||
private:
|
||||
// ----- transforms (also adapted from kaleidescope.cpp) ------
|
||||
|
||||
/** keepalive for contained llvm::LLVMContext **/
|
||||
ref::rp<LlvmContext> llvm_cx_;
|
||||
|
||||
/** manages all the passes+analaysis (?) **/
|
||||
std::unique_ptr<llvm::FunctionPassManager> llvm_fpmgr_;
|
||||
/** loop analysis (?) **/
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "xo/refcnt/Refcounted.hpp"
|
||||
#include "IrPipeline.hpp"
|
||||
#include "LlvmContext.hpp"
|
||||
#include "xo/expression/Expression.hpp"
|
||||
#include "xo/expression/ConstantInterface.hpp"
|
||||
#include "xo/expression/PrimitiveInterface.hpp"
|
||||
|
|
@ -31,7 +32,6 @@
|
|||
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorSymbolDef.h"
|
||||
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include <memory>
|
||||
#endif
|
||||
|
||||
|
|
@ -159,7 +159,8 @@ namespace xo {
|
|||
* Not threadsafe, but ok to have multiple threads,
|
||||
* each with its own LLVMContext
|
||||
**/
|
||||
std::unique_ptr<llvm::LLVMContext> llvm_cx_;
|
||||
ref::rp<LlvmContext> llvm_cx_;
|
||||
//std::unique_ptr<llvm::LLVMContext> llvm_cx_;
|
||||
/** builder for intermediate-representation objects **/
|
||||
std::unique_ptr<llvm::IRBuilder<>> llvm_ir_builder_;
|
||||
/** a module (1:1 with library) being prepared by llvm.
|
||||
|
|
|
|||
40
include/xo/jit/LlvmContext.hpp
Normal file
40
include/xo/jit/LlvmContext.hpp
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/** @file LlvmContext.hpp
|
||||
*
|
||||
* Author: Roland Conybeare
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "xo/refcnt/Refcounted.hpp"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
//#include <cstdint>
|
||||
|
||||
namespace xo {
|
||||
namespace jit {
|
||||
/** @class LlvmContext
|
||||
* @brief Keepalive for a llvm::LLVMContext instance.
|
||||
*
|
||||
* For example IrPipeline holds an rp<LlvmContext>
|
||||
* to help ensure validity of embedded llvm::LLVMContext reference
|
||||
**/
|
||||
class LlvmContext : public ref::Refcount {
|
||||
public:
|
||||
static xo::ref::rp<LlvmContext> make();
|
||||
|
||||
llvm::LLVMContext & llvm_cx_ref() { return *llvm_cx_; }
|
||||
std::unique_ptr<llvm::LLVMContext> & llvm_cx() { return llvm_cx_; }
|
||||
|
||||
private:
|
||||
LlvmContext();
|
||||
|
||||
private:
|
||||
/** Llvm context. Ties together fragments of code generation
|
||||
* for AST subtrees that go into the same module.
|
||||
**/
|
||||
std::unique_ptr<llvm::LLVMContext> llvm_cx_;
|
||||
}; /*LlvmContext*/
|
||||
} /*namespace jit*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
||||
/** end LlvmContext.hpp **/
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
set(SELF_LIB xo_jit)
|
||||
set(SELF_SRCS
|
||||
LlvmContext.cpp
|
||||
IrPipeline.cpp
|
||||
Jit.cpp
|
||||
)
|
||||
|
|
|
|||
|
|
@ -4,17 +4,20 @@
|
|||
|
||||
namespace xo {
|
||||
namespace jit {
|
||||
IrPipeline::IrPipeline(llvm::LLVMContext & llvm_cx)
|
||||
IrPipeline::IrPipeline(ref::rp<LlvmContext> llvm_cx)
|
||||
{
|
||||
using std::make_unique;
|
||||
|
||||
this->llvm_cx_ = std::move(llvm_cx);
|
||||
|
||||
this->llvm_fpmgr_ = make_unique<llvm::FunctionPassManager>();
|
||||
this->llvm_lamgr_ = std::make_unique<llvm::LoopAnalysisManager>();
|
||||
this->llvm_famgr_ = std::make_unique<llvm::FunctionAnalysisManager>();
|
||||
this->llvm_cgamgr_ = std::make_unique<llvm::CGSCCAnalysisManager>();
|
||||
this->llvm_mamgr_ = std::make_unique<llvm::ModuleAnalysisManager>();
|
||||
this->llvm_pic_ = std::make_unique<llvm::PassInstrumentationCallbacks>();
|
||||
this->llvm_si_ = std::make_unique<llvm::StandardInstrumentations>(llvm_cx,
|
||||
/* reference kept alive by @ref llvm_cx_ */
|
||||
this->llvm_si_ = std::make_unique<llvm::StandardInstrumentations>(llvm_cx_->llvm_cx_ref(),
|
||||
/*DebugLogging*/ true);
|
||||
|
||||
this->llvm_si_->registerCallbacks(*llvm_pic_, llvm_mamgr_.get());
|
||||
|
|
|
|||
|
|
@ -132,9 +132,10 @@ namespace xo {
|
|||
void
|
||||
Jit::recreate_llvm_ir_pipeline()
|
||||
{
|
||||
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_);
|
||||
//llvm_cx_ = std::make_unique<llvm::LLVMContext>();
|
||||
llvm_cx_ = LlvmContext::make();
|
||||
llvm_ir_builder_ = std::make_unique<llvm::IRBuilder<>>(llvm_cx_->llvm_cx_ref());
|
||||
llvm_module_ = std::make_unique<llvm::Module>("xojit", llvm_cx_->llvm_cx_ref());
|
||||
|
||||
llvm_module_->setDataLayout(kal_jit_->getDataLayout());
|
||||
|
||||
|
|
@ -148,7 +149,7 @@ namespace xo {
|
|||
throw std::runtime_error("Jit::ctor: expected non-empty llvm module");
|
||||
}
|
||||
|
||||
ir_pipeline_ = new IrPipeline(*llvm_cx_);
|
||||
ir_pipeline_ = new IrPipeline(llvm_cx_);
|
||||
} /*recreate_llvm_ir_pipeline*/
|
||||
|
||||
const std::string &
|
||||
|
|
@ -176,10 +177,10 @@ namespace xo {
|
|||
TypeDescr td = expr->value_td();
|
||||
|
||||
if (td->is_native<double>()) {
|
||||
return llvm::ConstantFP::get(*llvm_cx_,
|
||||
return llvm::ConstantFP::get(llvm_cx_->llvm_cx_ref(),
|
||||
llvm::APFloat(*(expr->value_tp().recover_native<double>())));
|
||||
} else if (td->is_native<float>()) {
|
||||
return llvm::ConstantFP::get(*llvm_cx_,
|
||||
return llvm::ConstantFP::get(llvm_cx_->llvm_cx_ref(),
|
||||
llvm::APFloat(*(expr->value_tp().recover_native<float>())));
|
||||
}
|
||||
|
||||
|
|
@ -230,7 +231,7 @@ namespace xo {
|
|||
log && log(xtag("i_arg", i), xtag("arg_td", arg_td->short_name()));
|
||||
|
||||
if (arg_td->is_native<double>()) {
|
||||
llvm_argtype_v.push_back(llvm::Type::getDoubleTy(*llvm_cx_));
|
||||
llvm_argtype_v.push_back(llvm::Type::getDoubleTy(llvm_cx_->llvm_cx_ref()));
|
||||
|
||||
// TODO: extend with other native types here...
|
||||
} else {
|
||||
|
|
@ -252,7 +253,7 @@ namespace xo {
|
|||
llvm::Type * llvm_retval = nullptr;
|
||||
|
||||
if (retval_td->is_native<double>()) {
|
||||
llvm_retval = llvm::Type::getDoubleTy(*llvm_cx_);
|
||||
llvm_retval = llvm::Type::getDoubleTy(llvm_cx_->llvm_cx_ref());
|
||||
} else {
|
||||
cerr << "Jit::codegen_primitive: error: primitive f returning T where double expected"
|
||||
<< xtag("f", expr->name())
|
||||
|
|
@ -363,9 +364,9 @@ namespace xo {
|
|||
// PLACEHOLDER
|
||||
// just handle double arguments + return type for now
|
||||
|
||||
std::vector<llvm::Type *> double_v(1, llvm::Type::getDoubleTy(*llvm_cx_));
|
||||
std::vector<llvm::Type *> double_v(1, llvm::Type::getDoubleTy(llvm_cx_->llvm_cx_ref()));
|
||||
|
||||
auto * llvm_fn_type = llvm::FunctionType::get(llvm::Type::getDoubleTy(*llvm_cx_),
|
||||
auto * llvm_fn_type = llvm::FunctionType::get(llvm::Type::getDoubleTy(llvm_cx_->llvm_cx_ref()),
|
||||
double_v,
|
||||
false /*!varargs*/);
|
||||
|
||||
|
|
@ -381,7 +382,7 @@ namespace xo {
|
|||
|
||||
/* generate function body */
|
||||
|
||||
auto block = llvm::BasicBlock::Create(*llvm_cx_, "entry", fn);
|
||||
auto block = llvm::BasicBlock::Create(llvm_cx_->llvm_cx_ref(), "entry", fn);
|
||||
|
||||
llvm_ir_builder_->SetInsertPoint(block);
|
||||
|
||||
|
|
@ -459,8 +460,15 @@ namespace xo {
|
|||
|
||||
auto tracker = kal_jit_->getMainJITDylib().createResourceTracker();
|
||||
|
||||
/* invalidates llvm_cx_->llvm_cx_ref(); will discard and re-create
|
||||
*
|
||||
* Note that @ref ir_pipeline_ holds reference, which is invalidated here
|
||||
*/
|
||||
auto ts_module = llvm::orc::ThreadSafeModule(std::move(llvm_module_),
|
||||
std::move(llvm_cx_));
|
||||
std::move(llvm_cx_->llvm_cx()));
|
||||
|
||||
/* note does not discard llvm_cx_->llvm_cx(), it's already been moved */
|
||||
this->llvm_cx_ = nullptr;
|
||||
|
||||
llvm_exit_on_err(kal_jit_->addModule(std::move(ts_module), tracker));
|
||||
|
||||
|
|
|
|||
20
src/jit/LlvmContext.cpp
Normal file
20
src/jit/LlvmContext.cpp
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/* @file LlvmContext.cpp */
|
||||
|
||||
#include "LlvmContext.hpp"
|
||||
|
||||
namespace xo {
|
||||
namespace jit {
|
||||
xo::ref::rp<LlvmContext>
|
||||
LlvmContext::make() {
|
||||
return new LlvmContext();
|
||||
}
|
||||
|
||||
LlvmContext::LlvmContext()
|
||||
: llvm_cx_{std::make_unique<llvm::LLVMContext>()}
|
||||
{}
|
||||
|
||||
} /*namespace jit*/
|
||||
} /*namespace xo*/
|
||||
|
||||
|
||||
/* end LlvmContext.cpp */
|
||||
Loading…
Add table
Add a link
Reference in a new issue