diff options
| author | Michael Williamson <mike@zwobble.org> | 2026-04-05 23:03:49 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2026-04-05 23:03:49 +0100 |
| commit | 0d2157f1236c760cab7c5092b21e779e35caa9f2 (patch) | |
| tree | 5281a81ad93a86ac009acac2d7ff96042e3a1c21 | |
| parent | 423e5565da7261aa1c3337abc67fed5eac16cc60 (diff) | |
Support calling pointers in patio-to-cranelift
| -rw-r--r-- | patio-to-cranelift/src/codegen/mod.rs | 96 | ||||
| -rw-r--r-- | patio-to-cranelift/src/patio/flatbuffers.rs | 21 | ||||
| -rw-r--r-- | patio-to-cranelift/src/patio/instructions.rs | 7 | ||||
| -rw-r--r-- | patio-to-cranelift/src/patio/operands.rs | 2 |
4 files changed, 113 insertions, 13 deletions
diff --git a/patio-to-cranelift/src/codegen/mod.rs b/patio-to-cranelift/src/codegen/mod.rs index 75e13ba2..1a383a7c 100644 --- a/patio-to-cranelift/src/codegen/mod.rs +++ b/patio-to-cranelift/src/codegen/mod.rs @@ -3,7 +3,10 @@ use std::path::Path; use cranelift::prelude::InstBuilder; use crate::{ - codegen::context::{CompilerContext, CompilerFunctionContext, Mutability}, + codegen::{ + context::{CompilerContext, CompilerFunctionContext, Mutability}, + types::patio_type_to_cranelift_type, + }, errors::CompileError, patio::{ compilation_unit::{ @@ -12,10 +15,10 @@ use crate::{ PatioLocal, PatioLocalType, PatioVisibility, }, instructions::{ - PatioBlock, PatioBoolToInt, PatioCall, PatioIf, PatioInstruction, PatioIntAdd, - PatioIntEquals, PatioIntNotEqual, PatioIntSub, PatioIntToBool, PatioLocalStore, - PatioMemoryLoad, PatioMemoryStore, PatioResume, PatioReturn, PatioReturnVoid, - PatioVarLoad, PatioVarStore, + PatioBlock, PatioBoolToInt, PatioCall, PatioCallPointer, PatioIf, PatioInstruction, + PatioIntAdd, PatioIntEquals, PatioIntNotEqual, PatioIntSub, PatioIntToBool, + PatioLocalStore, PatioMemoryLoad, PatioMemoryStore, PatioResume, PatioReturn, + PatioReturnVoid, PatioVarLoad, PatioVarStore, }, operands::{PatioLocalRef, PatioOperand}, types::PatioType, @@ -235,6 +238,10 @@ fn compile_instruction(instruction: &PatioInstruction, context: &mut CompilerFun compile_call(call, context); } + PatioInstruction::CallPointer(call_pointer) => { + compile_call_pointer(call_pointer, context); + } + PatioInstruction::If(if_) => { compile_if(if_, context); } @@ -334,6 +341,41 @@ fn compile_call(call: &PatioCall, context: &mut CompilerFunctionContext<'_>) { } } +fn compile_call_pointer( + call_pointer: &PatioCallPointer, + context: &mut CompilerFunctionContext<'_>, +) { + let mut cranelift_signature = new_cranelift_signature(); + for arg in &call_pointer.args { + cranelift_signature + .params + .push(cranelift_codegen::ir::AbiParam::new( + patio_operand_to_cranelift_type(arg, context), + )); + } + cranelift_signature + .returns + .push(cranelift_codegen::ir::AbiParam::new( + context.var_type(&call_pointer.destination.name), + )); + + let cranelift_signature_ref = context + .function_builder + .import_signature(cranelift_signature); + + let cranelift_function_pointer = compile_operand(&call_pointer.function_pointer, context); + let cranelift_args = compile_operands(call_pointer.args.iter(), context); + + let cranelift_call = context.function_builder.ins().call_indirect( + cranelift_signature_ref, + cranelift_function_pointer, + &cranelift_args, + ); + + let cranelift_value = context.function_builder.inst_results(cranelift_call)[0]; + def_destination(&call_pointer.destination, cranelift_value, context); +} + fn compile_if(if_: &PatioIf, context: &mut CompilerFunctionContext<'_>) { let cranelift_condition = compile_operand(&if_.condition, context); let cranelift_then_block = context.function_builder.create_block(); @@ -565,6 +607,16 @@ fn compile_operand( PatioOperand::DataPtrConst(value) => compile_data_ptr_value(&value, context), + PatioOperand::FunctionPtrConst(name) => { + let func_ref = context.func_id(name); + let function_ptr_type = context.pointer_type(); + + context + .function_builder + .ins() + .func_addr(function_ptr_type, func_ref) + } + PatioOperand::IntConst(value) => { let cranelift_int_type = types::cranelift_int_type(&context.target_triple); compile_int_value(&value, cranelift_int_type, context) @@ -637,13 +689,16 @@ fn def_destination( .def_var(cranelift_destination, value); } +fn new_cranelift_signature() -> cranelift::prelude::Signature { + cranelift_codegen::ir::Signature::new(cranelift_codegen::isa::CallConv::SystemV) +} + fn cranelift_signature<'a>( locals: impl Iterator<Item = &'a PatioLocal>, return_type: PatioType, target_triple: &target_lexicon::Triple, ) -> cranelift::prelude::Signature { - let mut signature = - cranelift::prelude::Signature::new(cranelift_codegen::isa::CallConv::SystemV); + let mut signature = new_cranelift_signature(); for local in locals { if local.local_type == PatioLocalType::Param { @@ -669,3 +724,30 @@ fn patio_visibility_to_cranelift_linkage(visibility: PatioVisibility) -> craneli PatioVisibility::Public => cranelift_module::Linkage::Export, } } + +fn patio_operand_to_cranelift_type( + operand: &PatioOperand, + context: &mut CompilerFunctionContext<'_>, +) -> cranelift_codegen::ir::Type { + match operand { + PatioOperand::BoolConst(_) => { + patio_type_to_cranelift_type(PatioType::Bool, &context.target_triple) + } + PatioOperand::ByteConst(_) => { + patio_type_to_cranelift_type(PatioType::Byte, &context.target_triple) + } + PatioOperand::DataPtrConst(_) => { + patio_type_to_cranelift_type(PatioType::DataPtr, &context.target_triple) + } + PatioOperand::FunctionPtrConst(_) => { + patio_type_to_cranelift_type(PatioType::FunctionPtr, &context.target_triple) + } + PatioOperand::IntConst(_) => { + patio_type_to_cranelift_type(PatioType::Int, &context.target_triple) + } + PatioOperand::Int32Const(_) => { + patio_type_to_cranelift_type(PatioType::Int32, &context.target_triple) + } + PatioOperand::LocalRef(local_ref) => context.var_type(&local_ref.name), + } +} diff --git a/patio-to-cranelift/src/patio/flatbuffers.rs b/patio-to-cranelift/src/patio/flatbuffers.rs index 7548d35d..c219d823 100644 --- a/patio-to-cranelift/src/patio/flatbuffers.rs +++ b/patio-to-cranelift/src/patio/flatbuffers.rs @@ -6,10 +6,10 @@ use crate::{ PatioLocal, PatioLocalType, PatioVisibility, }, instructions::{ - PatioBlock, PatioBoolToInt, PatioCall, PatioIf, PatioInstruction, PatioIntAdd, - PatioIntEquals, PatioIntNotEqual, PatioIntSub, PatioIntToBool, PatioLocalStore, - PatioMemoryLoad, PatioMemoryStore, PatioResume, PatioReturn, PatioReturnVoid, - PatioVarLoad, PatioVarStore, + PatioBlock, PatioBoolToInt, PatioCall, PatioCallPointer, PatioIf, PatioInstruction, + PatioIntAdd, PatioIntEquals, PatioIntNotEqual, PatioIntSub, PatioIntToBool, + PatioLocalStore, PatioMemoryLoad, PatioMemoryStore, PatioResume, PatioReturn, + PatioReturnVoid, PatioVarLoad, PatioVarStore, }, operands::{PatioLocalRef, PatioOperand}, types::{PatioDataLayout, PatioType}, @@ -164,6 +164,16 @@ impl From<patio_generated::patio::PatioInstruction<'_>> for PatioInstruction { }) } + patio_generated::patio::PatioInstructionValue::PatioCallPointer => { + let call_pointer = value.value_as_patio_call_pointer().unwrap(); + + Self::CallPointer(PatioCallPointer { + destination: call_pointer.destination().into(), + function_pointer: call_pointer.function_pointer().into(), + args: call_pointer.args().iter().map(Into::into).collect(), + }) + } + patio_generated::patio::PatioInstructionValue::PatioIf => { let if_ = value.value_as_patio_if().unwrap(); @@ -332,7 +342,8 @@ impl From<patio_generated::patio::PatioOperand<'_>> for PatioOperand { } patio_generated::patio::PatioOperandValue::PatioFunctionPtrConst => { - Self::FunctionPtrConst + let function_ptr_const = value.value_as_patio_function_ptr_const().unwrap(); + Self::FunctionPtrConst(function_ptr_const.name().to_string()) } patio_generated::patio::PatioOperandValue::PatioIntConst => { diff --git a/patio-to-cranelift/src/patio/instructions.rs b/patio-to-cranelift/src/patio/instructions.rs index 39c39964..1cba2953 100644 --- a/patio-to-cranelift/src/patio/instructions.rs +++ b/patio-to-cranelift/src/patio/instructions.rs @@ -7,6 +7,7 @@ pub(crate) enum PatioInstruction { Block(PatioBlock), BoolToInt(PatioBoolToInt), Call(PatioCall), + CallPointer(PatioCallPointer), If(PatioIf), IntAdd(PatioIntAdd), IntEquals(PatioIntEquals), @@ -39,6 +40,12 @@ pub(crate) struct PatioCall { pub(crate) args: Vec<PatioOperand>, } +pub(crate) struct PatioCallPointer { + pub(crate) destination: PatioLocalRef, + pub(crate) function_pointer: PatioOperand, + pub(crate) args: Vec<PatioOperand>, +} + pub(crate) struct PatioIf { pub(crate) destinations: Vec<PatioLocalRef>, pub(crate) condition: PatioOperand, diff --git a/patio-to-cranelift/src/patio/operands.rs b/patio-to-cranelift/src/patio/operands.rs index 05f9eec3..ca8eb3bc 100644 --- a/patio-to-cranelift/src/patio/operands.rs +++ b/patio-to-cranelift/src/patio/operands.rs @@ -5,7 +5,7 @@ pub(crate) enum PatioOperand { BoolConst(bool), ByteConst(u8), DataPtrConst(PatioDataPtrValue), - FunctionPtrConst, + FunctionPtrConst(String), IntConst(PatioIntValue), Int32Const(PatioIntValue), LocalRef(PatioLocalRef), |
