Files
ngr/src/backend.rs

90 lines
3.1 KiB
Rust

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<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))
}
}
}
}
impl Program {
pub fn new(platform: Triple, ir: ir::Program) -> Result<Program, BackendError> {
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::<BackendError, _>(
&mut object_module,
"gogogo",
&rtfuns,
&HashMap::new(),
&HashMap::new(),
)?,
module: object_module,
})
}
pub fn bytes(self) -> Result<Vec<u8>, object::write::Error> {
self.module.finish().emit()
}
}