aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2026-03-29 10:33:35 +0100
committerMichael Williamson <mike@zwobble.org>2026-03-29 10:33:35 +0100
commit0f3cc97b0e07cf96d8df5b05d3ab8cc5a9429f0c (patch)
treecb4ba696fce992cd7586cb092b8fb66334ac0688
parenta1f6380416af3f8b6314d2eda7624faee4b2f446 (diff)
Generate empty functions
-rw-r--r--patio-to-cranelift/src/main.rs90
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.