Some cleanups.

This commit is contained in:
2023-03-28 22:16:48 -05:00
parent c3e1c90261
commit 289997af5a
10 changed files with 190 additions and 246 deletions

View File

@@ -1,85 +1,74 @@
mod error;
mod into_crane; mod into_crane;
mod runtime; mod runtime;
use std::collections::HashMap; use std::collections::HashMap;
pub use self::error::BackendError;
pub use self::runtime::{RuntimeFunctionError, RuntimeFunctions}; pub use self::runtime::{RuntimeFunctionError, RuntimeFunctions};
use crate::ir; use cranelift_codegen::settings::{Configurable};
use codespan_reporting::diagnostic::Diagnostic; use cranelift_codegen::{isa, settings};
use cranelift_codegen::isa::LookupError; use cranelift_jit::{JITModule, JITBuilder};
use cranelift_codegen::settings::{Configurable, SetError}; use cranelift_module::{default_libcall_names, DataContext, DataId, Module, Linkage, FuncId};
use cranelift_codegen::{isa, settings, CodegenError};
use cranelift_module::{default_libcall_names, FuncId, ModuleError};
use cranelift_object::{object, ObjectBuilder, ObjectModule}; use cranelift_object::{object, ObjectBuilder, ObjectModule};
use target_lexicon::Triple; use target_lexicon::Triple;
use thiserror::Error;
pub struct Program { const EMPTY_DATUM: [u8; 8] = [0; 8];
_func_id: FuncId,
module: ObjectModule, pub struct Backend<M: Module> {
pub module: M,
data_ctx: DataContext,
runtime_functions: RuntimeFunctions,
defined_strings: HashMap<String, DataId>,
defined_symbols: HashMap<String, DataId>,
} }
#[derive(Debug, Error)] impl Backend<JITModule> {
pub enum BackendError { pub fn jit() -> Result<Self, BackendError> {
#[error("Cranelift module error: {0}")] let platform = Triple::host();
Cranelift(#[from] ModuleError), let isa_builder = isa::lookup(platform.clone())?;
#[error("Builtin function error: {0}")] let mut settings_builder = settings::builder();
BuiltinError(#[from] RuntimeFunctionError), settings_builder.set("use_colocated_libcalls", "false")?;
#[error("Internal variable lookup error")] settings_builder.set("is_pic", "false")?;
VariableLookupFailure, let isa = isa_builder.finish(settings::Flags::new(settings_builder))?;
#[error(transparent)] let mut builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names());
CodegenError(#[from] CodegenError),
#[error(transparent)] RuntimeFunctions::register_jit_implementations(&mut builder);
SetError(#[from] SetError),
#[error(transparent)] let mut module = JITModule::new(builder);
LookupError(#[from] LookupError), let runtime_functions = RuntimeFunctions::new(&platform, &mut module)?;
Ok(Backend {
module,
data_ctx: DataContext::new(),
runtime_functions,
defined_strings: HashMap::new(),
defined_symbols: HashMap::new(),
})
} }
impl From<BackendError> for Diagnostic<usize> { pub fn bytes(&self, function_id: FuncId) -> *const u8 {
fn from(value: BackendError) -> Self { self.module.get_finalized_function(function_id)
match value {
BackendError::Cranelift(me) => {
Diagnostic::error().with_message(format!("Internal cranelift error: {}", me))
}
BackendError::BuiltinError(me) => {
Diagnostic::error().with_message(format!("Internal runtime function error: {}", me))
}
BackendError::VariableLookupFailure => {
Diagnostic::error().with_message("Internal variable lookup error!")
}
BackendError::CodegenError(me) => {
Diagnostic::error().with_message(format!("Internal codegen error: {}", me))
}
BackendError::SetError(me) => {
Diagnostic::error().with_message(format!("Internal backend setup error: {}", me))
}
BackendError::LookupError(me) => {
Diagnostic::error().with_message(format!("Internal error: {}", me))
}
}
} }
} }
impl Program { impl Backend<ObjectModule> {
pub fn new(platform: Triple, ir: ir::Program) -> Result<Program, BackendError> { pub fn object_file(platform: Triple) -> Result<Self, BackendError> {
let isa_builder = isa::lookup(platform.clone())?; let isa_builder = isa::lookup(platform.clone())?;
let mut settings_builder = settings::builder(); let mut settings_builder = settings::builder();
settings_builder.set("is_pic", "true")?; settings_builder.set("is_pic", "true")?;
let isa = isa_builder.finish(settings::Flags::new(settings_builder))?; let isa = isa_builder.finish(settings::Flags::new(settings_builder))?;
let object_builder = ObjectBuilder::new(isa, "example", default_libcall_names())?; let object_builder = ObjectBuilder::new(isa, "example", default_libcall_names())?;
let mut object_module = ObjectModule::new(object_builder); let mut module = ObjectModule::new(object_builder);
let rtfuns = RuntimeFunctions::new(&platform, &mut object_module)?; let runtime_functions = RuntimeFunctions::new(&platform, &mut module)?;
Ok(Program { Ok(Backend {
_func_id: ir.into_cranelift::<BackendError, _>( module,
&mut object_module, data_ctx: DataContext::new(),
"gogogo", runtime_functions,
&rtfuns, defined_strings: HashMap::new(),
&HashMap::new(), defined_symbols: HashMap::new(),
&HashMap::new(),
)?,
module: object_module,
}) })
} }
@@ -87,3 +76,30 @@ impl Program {
self.module.finish().emit() self.module.finish().emit()
} }
} }
impl<M: Module> Backend<M>
{
pub fn define_string(&mut self, s: &str) -> Result<DataId, BackendError> {
let name = format!("<string_constant>{}", s);
let global_id = self
.module
.declare_data(&name, Linkage::Local, false, false)?;
let mut data_context = DataContext::new();
data_context.set_align(8);
data_context.define(s.to_owned().into_boxed_str().into_boxed_bytes());
self.module.define_data(global_id, &data_context)?;
self.defined_strings.insert(s.to_owned(), global_id);
Ok(global_id)
}
pub fn define_variable(&mut self, name: String) -> Result<DataId, BackendError> {
self.data_ctx.define(Box::new(EMPTY_DATUM));
let id = self
.module
.declare_data(&name, Linkage::Export, true, false)?;
self.module.define_data(id, &self.data_ctx)?;
self.data_ctx.clear();
self.defined_symbols.insert(name, id);
Ok(id)
}
}

47
src/backend/error.rs Normal file
View File

@@ -0,0 +1,47 @@
use codespan_reporting::diagnostic::Diagnostic;
use cranelift_codegen::{CodegenError, settings::SetError, isa::LookupError};
use cranelift_module::ModuleError;
use crate::backend::runtime::RuntimeFunctionError;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum BackendError {
#[error("Cranelift module error: {0}")]
Cranelift(#[from] ModuleError),
#[error("Builtin function error: {0}")]
BuiltinError(#[from] RuntimeFunctionError),
#[error("Internal variable lookup error")]
VariableLookupFailure,
#[error(transparent)]
CodegenError(#[from] CodegenError),
#[error(transparent)]
SetError(#[from] SetError),
#[error(transparent)]
LookupError(#[from] LookupError),
}
impl From<BackendError> for Diagnostic<usize> {
fn from(value: BackendError) -> Self {
match value {
BackendError::Cranelift(me) => {
Diagnostic::error().with_message(format!("Internal cranelift error: {}", me))
}
BackendError::BuiltinError(me) => {
Diagnostic::error().with_message(format!("Internal runtime function error: {}", me))
}
BackendError::VariableLookupFailure => {
Diagnostic::error().with_message("Internal variable lookup error!")
}
BackendError::CodegenError(me) => {
Diagnostic::error().with_message(format!("Internal codegen error: {}", me))
}
BackendError::SetError(me) => {
Diagnostic::error().with_message(format!("Internal backend setup error: {}", me))
}
BackendError::LookupError(me) => {
Diagnostic::error().with_message(format!("Internal error: {}", me))
}
}
}
}

View File

@@ -1,6 +1,5 @@
use std::collections::HashMap; use std::collections::HashMap;
use crate::backend::runtime::RuntimeFunctions;
use crate::ir::{Expression, Primitive, Program, Statement, Value, ValueOrRef}; use crate::ir::{Expression, Primitive, Program, Statement, Value, ValueOrRef};
use cranelift_codegen::entity::EntityRef; use cranelift_codegen::entity::EntityRef;
use cranelift_codegen::ir::{ use cranelift_codegen::ir::{
@@ -9,26 +8,20 @@ use cranelift_codegen::ir::{
use cranelift_codegen::isa::CallConv; use cranelift_codegen::isa::CallConv;
use cranelift_codegen::Context; use cranelift_codegen::Context;
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable}; use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable};
use cranelift_module::{DataContext, DataId, FuncId, Linkage, Module, ModuleError}; use cranelift_module::{FuncId, Linkage, Module, ModuleError};
use internment::ArcIntern; use internment::ArcIntern;
use super::RuntimeFunctionError; use crate::backend::Backend;
use crate::backend::error::BackendError;
type StringTable = HashMap<ArcIntern<String>, GlobalValue>; type StringTable = HashMap<ArcIntern<String>, GlobalValue>;
impl Program { impl<M: Module> Backend<M> {
pub fn into_cranelift<E, M>( pub fn compile_function(
mut self, &mut self,
module: &mut M,
function_name: &str, function_name: &str,
rtfuns: &RuntimeFunctions, mut program: Program,
pre_defined_strings: &HashMap<String, DataId>, ) -> Result<FuncId, BackendError>
pre_defined_symbols: &HashMap<String, DataId>,
) -> Result<FuncId, E>
where
E: From<ModuleError>,
E: From<RuntimeFunctionError>,
M: Module,
{ {
let basic_signature = Signature { let basic_signature = Signature {
params: vec![], params: vec![],
@@ -36,19 +29,20 @@ impl Program {
call_conv: CallConv::SystemV, call_conv: CallConv::SystemV,
}; };
let func_id = module.declare_function(function_name, Linkage::Export, &basic_signature)?; let func_id = self.module.declare_function(function_name, Linkage::Export, &basic_signature)?;
let mut ctx = Context::new(); let mut ctx = Context::new();
ctx.func = ctx.func =
Function::with_name_signature(UserFuncName::user(0, func_id.as_u32()), basic_signature); Function::with_name_signature(UserFuncName::user(0, func_id.as_u32()), basic_signature);
let string_table = self.build_string_table(module, &mut ctx.func, pre_defined_strings)?; let string_table = self.build_string_table(&mut ctx.func, &program)?;
let mut variable_table = HashMap::new(); let mut variable_table = HashMap::new();
let mut next_var_num = 1; let mut next_var_num = 1;
let print_func_ref = rtfuns.include_runtime_function("print", module, &mut ctx.func)?; let print_func_ref = self.runtime_functions.include_runtime_function("print", &mut self.module, &mut ctx.func)?;
let pre_defined_symbols: HashMap<String, GlobalValue> = pre_defined_symbols let pre_defined_symbols: HashMap<String, GlobalValue> = self
.defined_symbols
.iter() .iter()
.map(|(k, v)| { .map(|(k, v)| {
let local_data = module.declare_data_in_func(*v, &mut ctx.func); let local_data = self.module.declare_data_in_func(*v, &mut ctx.func);
(k.clone(), local_data) (k.clone(), local_data)
}) })
.collect(); .collect();
@@ -58,7 +52,7 @@ impl Program {
let main_block = builder.create_block(); let main_block = builder.create_block();
builder.switch_to_block(main_block); builder.switch_to_block(main_block);
for stmt in self.statements.drain(..) { for stmt in program.statements.drain(..) {
match stmt { match stmt {
Statement::Print(ann, var) => { Statement::Print(ann, var) => {
let local_name_ref = string_table.get(&var).unwrap(); let local_name_ref = string_table.get(&var).unwrap();
@@ -121,43 +115,24 @@ impl Program {
builder.seal_block(main_block); builder.seal_block(main_block);
builder.finalize(); builder.finalize();
let _ = module.define_function(func_id, &mut ctx)?; let _ = self.module.define_function(func_id, &mut ctx)?;
Ok(func_id) Ok(func_id)
} }
fn build_string_table<M: Module>( fn build_string_table(
&self, &mut self,
module: &mut M,
func: &mut Function, func: &mut Function,
pre_defined_strings: &HashMap<String, DataId>, program: &Program,
) -> Result<StringTable, ModuleError> { ) -> Result<StringTable, BackendError> {
let mut string_table = HashMap::new(); let mut string_table = HashMap::new();
for (idx, interned_value) in self.strings().drain().enumerate() { for interned_value in program.strings().drain() {
let global_id = match pre_defined_strings.get(interned_value.as_str()) { let global_id = match self.defined_strings.get(interned_value.as_str()) {
Some(x) => *x, Some(x) => *x,
None => { None => self.define_string(interned_value.as_str())?,
let global_id = module.declare_data(
&format!("local-string-{}", idx),
Linkage::Local,
false,
false,
)?;
let mut data_context = DataContext::new();
data_context.set_align(8);
data_context.define(
interned_value
.as_str()
.to_owned()
.into_boxed_str()
.into_boxed_bytes(),
);
module.define_data(global_id, &data_context)?;
global_id
}
}; };
let local_data = module.declare_data_in_func(global_id, func); let local_data = self.module.declare_data_in_func(global_id, func);
string_table.insert(interned_value, local_data); string_table.insert(interned_value, local_data);
} }

8
src/backend/object.rs Normal file
View File

@@ -0,0 +1,8 @@
struct BackendObject {
}
impl BackendObject {
pub fn new() -> Result<Self, ()> {
unimplemented!()
}
}

View File

@@ -1,7 +1,9 @@
use cranelift_codegen::ir::{types, AbiParam, FuncRef, Function, Signature}; use cranelift_codegen::ir::{types, AbiParam, FuncRef, Function, Signature};
use cranelift_codegen::isa::CallConv; use cranelift_codegen::isa::CallConv;
use cranelift_jit::JITBuilder;
use cranelift_module::{FuncId, Linkage, Module, ModuleResult}; use cranelift_module::{FuncId, Linkage, Module, ModuleResult};
use std::collections::HashMap; use std::collections::HashMap;
use std::ffi::CStr;
use target_lexicon::Triple; use target_lexicon::Triple;
use thiserror::Error; use thiserror::Error;
@@ -16,6 +18,12 @@ pub enum RuntimeFunctionError {
CannotFindRuntimeFunction(String), CannotFindRuntimeFunction(String),
} }
extern "C" fn runtime_print(name: *const i8, value: u64) {
let cstr = unsafe { CStr::from_ptr(name) };
let reconstituted = cstr.to_string_lossy();
println!("{} = {}", reconstituted, value);
}
impl RuntimeFunctions { impl RuntimeFunctions {
pub fn new<M: Module>(platform: &Triple, module: &mut M) -> ModuleResult<RuntimeFunctions> { pub fn new<M: Module>(platform: &Triple, module: &mut M) -> ModuleResult<RuntimeFunctions> {
let mut builtin_functions = HashMap::new(); let mut builtin_functions = HashMap::new();
@@ -54,4 +62,9 @@ impl RuntimeFunctions {
Some(func_id) => Ok(module.declare_func_in_func(*func_id, func)), Some(func_id) => Ok(module.declare_func_in_func(*func_id, func)),
} }
} }
pub fn register_jit_implementations(builder: &mut JITBuilder) {
builder.symbol("print", runtime_print as *const u8);
}
} }

View File

@@ -6,7 +6,7 @@ use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
use cranelift_object::object; use cranelift_object::object;
use ngr::backend::BackendError; use ngr::backend::BackendError;
use ngr::backend::Program as Cranelift; use ngr::backend::Backend;
use ngr::ir::Program as IR; use ngr::ir::Program as IR;
use ngr::syntax::{ParserError, Program as Syntax}; use ngr::syntax::{ParserError, Program as Syntax};
use target_lexicon::Triple; use target_lexicon::Triple;
@@ -70,8 +70,9 @@ fn compile(file_database: &mut SimpleFiles<String, String>) -> Result<(), MainEr
} }
let ir = IR::from(syntax.simplify()); let ir = IR::from(syntax.simplify());
let compiled = Cranelift::new(Triple::host(), ir)?; let mut backend = Backend::object_file(Triple::host())?;
let bytes = compiled.bytes()?; backend.compile_function("gogogo", ir)?;
let bytes = backend.bytes()?;
std::fs::write(args.output.unwrap_or_else(|| "output.o".to_string()), bytes)?; std::fs::write(args.output.unwrap_or_else(|| "output.o".to_string()), bytes)?;
Ok(()) Ok(())
} }

View File

@@ -1,8 +1,10 @@
use codespan_reporting::diagnostic::Diagnostic; use codespan_reporting::diagnostic::Diagnostic;
use codespan_reporting::files::SimpleFiles; use codespan_reporting::files::SimpleFiles;
use codespan_reporting::term::{self, Config}; use codespan_reporting::term::{self, Config};
use cranelift_jit::JITModule;
use cranelift_module::ModuleError;
use ngr::backend::{Backend, BackendError};
use ngr::ir::Program as IR; use ngr::ir::Program as IR;
use ngr::jit::{JITEngine, JITError};
use ngr::syntax::{Location, ParserError, Statement}; use ngr::syntax::{Location, ParserError, Statement};
use pretty::termcolor::{ColorChoice, StandardStream, WriteColor}; use pretty::termcolor::{ColorChoice, StandardStream, WriteColor};
use rustyline::error::ReadlineError; use rustyline::error::ReadlineError;
@@ -11,7 +13,7 @@ use std::collections::HashMap;
pub struct RunLoop<'a> { pub struct RunLoop<'a> {
file_database: SimpleFiles<&'a str, String>, file_database: SimpleFiles<&'a str, String>,
jitter: JITEngine, jitter: Backend<JITModule>,
variable_binding_sites: HashMap<String, Location>, variable_binding_sites: HashMap<String, Location>,
gensym_index: usize, gensym_index: usize,
writer: &'a mut dyn WriteColor, writer: &'a mut dyn WriteColor,
@@ -24,7 +26,9 @@ enum REPLError {
#[error("Error parsing statement: {0}")] #[error("Error parsing statement: {0}")]
Parser(#[from] ParserError), Parser(#[from] ParserError),
#[error("JIT error: {0}")] #[error("JIT error: {0}")]
JIT(#[from] JITError), JIT(#[from] BackendError),
#[error("Internal cranelift error: {0}")]
Cranelift(#[from] ModuleError),
#[error(transparent)] #[error(transparent)]
Reporting(#[from] codespan_reporting::files::Error), Reporting(#[from] codespan_reporting::files::Error),
} }
@@ -34,16 +38,17 @@ impl From<REPLError> for Diagnostic<usize> {
match value { match value {
REPLError::Parser(err) => Diagnostic::from(&err), REPLError::Parser(err) => Diagnostic::from(&err),
REPLError::JIT(err) => Diagnostic::from(err), REPLError::JIT(err) => Diagnostic::from(err),
REPLError::Cranelift(err) => Diagnostic::bug().with_message(format!("{}", err)),
REPLError::Reporting(err) => Diagnostic::bug().with_message(format!("{}", err)), REPLError::Reporting(err) => Diagnostic::bug().with_message(format!("{}", err)),
} }
} }
} }
impl<'a> RunLoop<'a> { impl<'a> RunLoop<'a> {
pub fn new(writer: &'a mut dyn WriteColor, config: Config) -> Result<Self, JITError> { pub fn new(writer: &'a mut dyn WriteColor, config: Config) -> Result<Self, BackendError> {
Ok(RunLoop { Ok(RunLoop {
file_database: SimpleFiles::new(), file_database: SimpleFiles::new(),
jitter: JITEngine::new()?, jitter: Backend::jit()?,
variable_binding_sites: HashMap::new(), variable_binding_sites: HashMap::new(),
gensym_index: 1, gensym_index: 1,
writer, writer,
@@ -83,7 +88,7 @@ impl<'a> RunLoop<'a> {
// then we won't use this definition until someone tries again. // then we won't use this definition until someone tries again.
if let Statement::Binding(_, ref name, _) = syntax { if let Statement::Binding(_, ref name, _) = syntax {
if !self.variable_binding_sites.contains_key(name.as_str()) { if !self.variable_binding_sites.contains_key(name.as_str()) {
self.jitter.define_string(name.clone())?; self.jitter.define_string(name)?;
self.jitter.define_variable(name.clone())?; self.jitter.define_variable(name.clone())?;
} }
}; };
@@ -104,13 +109,17 @@ impl<'a> RunLoop<'a> {
} }
let ir = IR::from(syntax.simplify(&mut self.gensym_index)); let ir = IR::from(syntax.simplify(&mut self.gensym_index));
let compiled = self.jitter.compile(line_no, ir)?; let name = format!("line{}", line_no);
compiled(); let function_id = self.jitter.compile_function(&name, ir)?;
self.jitter.module.finalize_definitions()?;
let compiled_bytes = self.jitter.bytes(function_id);
let compiled_function = unsafe { std::mem::transmute::<_, fn() -> ()>(compiled_bytes) };
compiled_function();
Ok(()) Ok(())
} }
} }
fn main() -> Result<(), JITError> { fn main() -> Result<(), BackendError> {
let mut editor = DefaultEditor::new().expect("rustyline works"); let mut editor = DefaultEditor::new().expect("rustyline works");
let mut line_no = 0; let mut line_no = 0;
let mut writer = StandardStream::stdout(ColorChoice::Auto); let mut writer = StandardStream::stdout(ColorChoice::Auto);

View File

@@ -1,32 +0,0 @@
use crate::backend::RuntimeFunctionError;
use codespan_reporting::diagnostic::Diagnostic;
use cranelift_codegen::{isa, settings::SetError, CodegenError};
use cranelift_module::ModuleError;
pub mod engine;
pub use self::engine::JITEngine;
#[derive(Debug, thiserror::Error)]
pub enum JITError {
#[error("JIT code generation error: {0}")]
Codegen(#[from] CodegenError),
#[error("JIT configuration flag error: {0}")]
Set(#[from] SetError),
#[error("ISA lookup error: {0}")]
Lookup(#[from] isa::LookupError),
#[error("Cranelift module error: {0}")]
Cranelift(#[from] ModuleError),
#[error("Runtime function error: {0}")]
Runtime(#[from] RuntimeFunctionError),
}
impl From<JITError> for Diagnostic<usize> {
fn from(value: JITError) -> Self {
Diagnostic::bug().with_message(format!("{}", value))
}
}

View File

@@ -1,92 +0,0 @@
use crate::backend::RuntimeFunctions;
use crate::ir::Program as IR;
use crate::jit::JITError;
use cranelift_codegen::{
isa,
settings::{self, Configurable},
};
use cranelift_jit::{JITBuilder, JITModule};
use cranelift_module::{DataContext, DataId, Linkage, Module};
use std::{collections::HashMap, ffi::CStr};
use target_lexicon::Triple;
const EMPTY_DATUM: [u8; 8] = [0; 8];
pub struct JITEngine {
data_ctx: DataContext,
module: JITModule,
runtime_functions: RuntimeFunctions,
defined_strings: HashMap<String, DataId>,
defined_symbols: HashMap<String, DataId>,
}
extern "C" fn runtime_print(name: *const i8, value: u64) {
let cstr = unsafe { CStr::from_ptr(name) };
let reconstituted = cstr.to_string_lossy();
println!("{} = {}", reconstituted, value);
}
impl JITEngine {
pub fn new() -> Result<JITEngine, JITError> {
let platform = Triple::host();
let isa_builder = isa::lookup(platform.clone())?;
let mut settings_builder = settings::builder();
settings_builder.set("use_colocated_libcalls", "false")?;
settings_builder.set("is_pic", "false")?;
let isa = isa_builder.finish(settings::Flags::new(settings_builder))?;
let mut builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names());
builder.symbol("print", runtime_print as *const u8);
let mut module = JITModule::new(builder);
let runtime_functions = RuntimeFunctions::new(&platform, &mut module)?;
Ok(JITEngine {
data_ctx: DataContext::new(),
module,
runtime_functions,
defined_strings: HashMap::new(),
defined_symbols: HashMap::new(),
})
}
pub fn define_string(&mut self, s: String) -> Result<(), JITError> {
let name = format!("<string_constant>{}", s);
let global_id = self
.module
.declare_data(&name, Linkage::Local, false, false)?;
let mut data_context = DataContext::new();
data_context.set_align(8);
data_context.define(s.as_str().to_owned().into_boxed_str().into_boxed_bytes());
self.module.define_data(global_id, &data_context)?;
self.defined_strings.insert(s, global_id);
Ok(())
}
pub fn define_variable(&mut self, name: String) -> Result<(), JITError> {
self.data_ctx.define(Box::new(EMPTY_DATUM));
let id = self
.module
.declare_data(&name, Linkage::Export, true, false)?;
self.module.define_data(id, &self.data_ctx)?;
self.data_ctx.clear();
self.module.finalize_definitions()?;
self.defined_symbols.insert(name, id);
Ok(())
}
pub fn compile(&mut self, line: usize, program: IR) -> Result<fn() -> (), JITError> {
let function_name = format!("line{}", line);
let function_id = program.into_cranelift::<JITError, _>(
&mut self.module,
&function_name,
&self.runtime_functions,
&self.defined_strings,
&self.defined_symbols,
)?;
self.module.finalize_definitions()?;
let code_ptr = self.module.get_finalized_function(function_id);
unsafe { Ok(std::mem::transmute::<_, fn() -> ()>(code_ptr)) }
}
}

View File

@@ -1,4 +1,3 @@
pub mod backend; pub mod backend;
pub mod ir; pub mod ir;
pub mod jit;
pub mod syntax; pub mod syntax;