mod into_crane; mod runtime; use std::collections::HashMap; pub use self::runtime::{RuntimeFunctionError, RuntimeFunctions}; use crate::ir; use codespan_reporting::diagnostic::Diagnostic; use cranelift_codegen::isa::LookupError; use cranelift_codegen::settings::{Configurable, SetError}; use cranelift_codegen::{isa, settings, CodegenError}; use cranelift_module::{default_libcall_names, FuncId, ModuleError}; use cranelift_object::{object, ObjectBuilder, ObjectModule}; use target_lexicon::Triple; use thiserror::Error; pub struct Program { _func_id: FuncId, module: ObjectModule, } #[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 for Diagnostic { 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)) } } } } impl Program { pub fn new(platform: Triple, ir: ir::Program) -> Result { let isa_builder = isa::lookup(platform.clone())?; let mut settings_builder = settings::builder(); settings_builder.set("is_pic", "true")?; let isa = isa_builder.finish(settings::Flags::new(settings_builder))?; let object_builder = ObjectBuilder::new(isa, "example", default_libcall_names())?; let mut object_module = ObjectModule::new(object_builder); let rtfuns = RuntimeFunctions::new(&platform, &mut object_module)?; Ok(Program { _func_id: ir.into_cranelift::( &mut object_module, "gogogo", &rtfuns, &HashMap::new(), &HashMap::new(), )?, module: object_module, }) } pub fn bytes(self) -> Result, object::write::Error> { self.module.finish().emit() } }