diff options
| author | Michael Williamson <mike@zwobble.org> | 2026-03-29 10:33:35 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2026-03-29 10:33:35 +0100 |
| commit | 0f3cc97b0e07cf96d8df5b05d3ab8cc5a9429f0c (patch) | |
| tree | cb4ba696fce992cd7586cb092b8fb66334ac0688 | |
| parent | a1f6380416af3f8b6314d2eda7624faee4b2f446 (diff) | |
Generate empty functions
| -rw-r--r-- | patio-to-cranelift/src/main.rs | 90 |
1 files changed, 87 insertions, 3 deletions
diff --git a/patio-to-cranelift/src/main.rs b/patio-to-cranelift/src/main.rs index 65119c16..c932c386 100644 --- a/patio-to-cranelift/src/main.rs +++ b/patio-to-cranelift/src/main.rs @@ -1,7 +1,11 @@ use std::path::{Path, PathBuf}; use clap::Parser; -use cranelift::prelude::Configurable; +use cranelift::prelude::{Configurable, FunctionBuilder, FunctionBuilderContext}; +use cranelift_codegen::ir::{Function, UserFuncName}; +use cranelift_module::Module; + +use crate::patio_generated::patio::{PatioCompilationUnitElement, PatioCompilationUnitElementValue, PatioLocalType, PatioVisibility}; #[allow(dead_code, unused_imports)] #[path = "./gen/patio_generated.rs"] @@ -33,7 +37,7 @@ fn main() { fn compile(source_path: &Path, target: &str) -> Result<(), CompileError> { let source_bytes = std::fs::read(source_path).map_err(CompileError::ReadSourceBytes)?; - let _compilation_unit = patio_generated::patio::root_as_patio_compilation_unit(&source_bytes) + let compilation_unit = patio_generated::patio::root_as_patio_compilation_unit(&source_bytes) .map_err(CompileError::InvalidFlatbuffer)?; let object_builder = cranelift_object::ObjectBuilder::new( @@ -41,7 +45,12 @@ fn compile(source_path: &Path, target: &str) -> Result<(), CompileError> { source_path.as_os_str().as_encoded_bytes(), cranelift_module::default_libcall_names() ).map_err(CompileError::ObjectBuilderNewFailed)?; - let module = cranelift_object::ObjectModule::new(object_builder); + let mut module = cranelift_object::ObjectModule::new(object_builder); + let mut context = CompilerContext::new(); + + for element in compilation_unit.elements() { + compile_compilation_unit_element(&element, &mut module, &mut context); + } let object = module.finish(); let object_bytes = object.emit().map_err(CompileError::ObjectEmitFailed)?; @@ -61,6 +70,81 @@ fn isa(target: &str) -> Result<std::sync::Arc<dyn cranelift::prelude::isa::Targe .map_err(CompileError::BuildIsa) } +fn compile_compilation_unit_element( + element: &PatioCompilationUnitElement, + module: &mut cranelift_object::ObjectModule, + context: &mut CompilerContext, +) { + match element.value_compilation_unit_element_value_type() { + PatioCompilationUnitElementValue::PatioFunctionDefinition => { + let function_definition = element + .value_compilation_unit_element_value_as_patio_function_definition() + .unwrap(); + + let signature = cranelift::prelude::Signature::new(cranelift_codegen::isa::CallConv::SystemV); + for local in function_definition.locals() { + if local.local_type() == PatioLocalType::PARAM { + todo!(); + } + } + + let mut func = Function::with_name_signature(context.func_name(), signature.clone()); + + let mut func_builder_context = FunctionBuilderContext::new(); + let _function_builder = FunctionBuilder::new(&mut func, &mut func_builder_context); + + let func_id = module.declare_function( + function_definition.name(), + patio_visibility_to_cranelift_linkage(function_definition.visibility()), + &signature, + ).unwrap(); + + // TODO: reuse context + let mut func_context = cranelift_codegen::Context::for_function(func); + module.define_function(func_id, &mut func_context).unwrap(); + } + + _ => todo!( + "Unsupported compilation unit element type: {}", + element.value_compilation_unit_element_value_type().0 + ), + } +} + +fn patio_visibility_to_cranelift_linkage(visibility: PatioVisibility) -> cranelift_module::Linkage { + match visibility { + PatioVisibility::PRIVATE => + cranelift_module::Linkage::Local, + + PatioVisibility::PUBLIC => + cranelift_module::Linkage::Export, + + _ => + panic!("Unsupported visibility: {}", visibility.0) + } +} + +struct CompilerContext { + next_func_name_index: u32, +} + +impl CompilerContext { + fn new() -> Self { + CompilerContext { + next_func_name_index: 0, + } + } + + /// Generate a function name for Cranelift. + fn func_name(&mut self) -> UserFuncName { + // Cranelift doesn't assign any particular meaning to the values, so we + // just use an incrementing index in a constant namespace. + let name = UserFuncName::user(0, self.next_func_name_index); + self.next_func_name_index += 1; + name + } +} + #[derive(Debug)] enum CompileError { /// Reading the bytes of the patio source file failed. |
