Here's a rundown of my situation:
- I am creating a library that previously used the
llvm-sys
crate. - I am using the crate to provide dynamic code generation and JIT compilation.
- I want to replace my usage of this crate with
inkwell
, a type-safe wrapper around the-sys
crate. - In both crates, there is the concept of a 'context', an object which makes available many other features.
- The context is used to create a 'module', which is where any code that will be dynamically compiled should be placed.
- The context cannot be destroyed before the module.
- Considering all these things, I want to create a struct that can store and execute a dynamically generated program. Using the
-sys
crate, my code looked something like this:
fn create_program() -> ProgramData {
let context: LLVMContextRef = unsafe { LLVMCreateContext() };
let module: LLVMModuleRef = unsafe { LLVMCreateModuleInContext(context) };
// Add code to the module...
// Run optimization passes...
ProgramData::new(context, module)
}
struct ProgramData {
context: LLVMContextRef,
module: LLVMModuleRef,
executor: LLVMExecutorRef,
}
impl ProgramData {
fn new(context: LLVMContextRef, module: LLVMModuleRef) -> Self {
let executor = unsafe { LLVMCreateExecutor(context, module) };
Self { context, module, executor }
}
fn execute(&self) -> i32 {
unsafe { self.executor.execute() }
}
}
impl Drop for ProgramData {
fn drop(&mut self) {
unsafe {
LLVMDestroyExecutor(self.executor);
LLVMDestroyModule(self.module);
LLVMDestroyContext(self.context);
}
}
}
The safe wrapper inkwell
uses a lifetime parameter to ensure that the module only lives as long as the context was borrowed to create it, making create_program
look something like this:
fn create_program() -> ProgramData {
let context: Context = create_context();
let context_ref: &'ctx Context = &context;
let module: Module<'ctx> = context.create_module();
// Do module stuff...
unimplemented!();
}
The problem now is that the ProgramData
struct needs to be self-referential. It needs to contain the context
as well as a struct which refers to the lifetime of a reference to t