diff options
| author | Michael Williamson <mike@zwobble.org> | 2026-07-31 14:45:04 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2026-07-31 15:22:40 +0100 |
| commit | 91860485774924e82da9b0774179d4c3c8da810a (patch) | |
| tree | e06f52f147502e80aea139c20adac706479cb7ea /patio-to-cranelift/src/codegen | |
| parent | 410fff7b7ecf6f36a0a46ab1d90553169e3728f1 (diff) | |
Use transient-0 instead of flatbuffersmain
Diffstat (limited to 'patio-to-cranelift/src/codegen')
| -rw-r--r-- | patio-to-cranelift/src/codegen/mod.rs | 159 | ||||
| -rw-r--r-- | patio-to-cranelift/src/codegen/types.rs | 321 | ||||
| -rw-r--r-- | patio-to-cranelift/src/codegen/values.rs | 157 |
3 files changed, 399 insertions, 238 deletions
diff --git a/patio-to-cranelift/src/codegen/mod.rs b/patio-to-cranelift/src/codegen/mod.rs index be98a0a3..a9cfab5b 100644 --- a/patio-to-cranelift/src/codegen/mod.rs +++ b/patio-to-cranelift/src/codegen/mod.rs @@ -9,12 +9,10 @@ use crate::{ }, errors::CompileError, patio::{ - compilation_unit::{ - PatioCompilationUnit, PatioCompilationUnitElement, PatioDataElementImmutableDefinition, - PatioDataElementMutableDeclaration, PatioDataElementMutableDefinition, - PatioFunctionDeclaration, PatioFunctionDefinition, PatioLocal, PatioLocalType, - PatioVisibility, - }, + PatioCompilationUnit, PatioCompilationUnitElement, PatioDataElementImmutableDefinition, + PatioDataElementMutableDeclaration, PatioDataElementMutableDefinition, + PatioFunctionDeclaration, PatioFunctionDefinition, PatioLocal, PatioLocalType, + PatioVisibility, instructions::{ PatioBlock, PatioBoolToInt, PatioCall, PatioCallPointer, PatioDataPtrToInt, PatioIf, PatioInstruction, PatioIntAdd, PatioIntEquals, PatioIntNotEqual, PatioIntSub, @@ -23,7 +21,10 @@ use crate::{ PatioUnreachable, PatioVarLoad, PatioVarStore, }, operands::{PatioLocalRef, PatioOperand}, - types::PatioType, + types::{ + PatioBoolType, PatioByteType, PatioDataPtrType, PatioFunctionPtrType, PatioInt32Type, + PatioIntType, PatioType, + }, values::{PatioDataPtrValue, PatioIntValue}, }, }; @@ -84,29 +85,31 @@ fn declare_compilation_unit_element( context: &mut CompilerContext, ) { match element { - PatioCompilationUnitElement::DataElementImmutableDefinition( + PatioCompilationUnitElement::PatioDataElementImmutableDefinition( data_element_immutable_definition, ) => { declare_data_element_immutable_definition(data_element_immutable_definition, context); } - PatioCompilationUnitElement::DataElementMutableDeclaration( + PatioCompilationUnitElement::PatioDataElementMutableDeclaration( data_element_mutable_declaration, ) => { declare_data_element_mutable_declaration(data_element_mutable_declaration, context); } - PatioCompilationUnitElement::DataElementMutableDefinition( + PatioCompilationUnitElement::PatioDataElementMutableDefinition( data_element_mutable_definition, ) => { declare_data_element_mutable_definition(data_element_mutable_definition, context); } - PatioCompilationUnitElement::FunctionDeclaration(function_declaration) => { + PatioCompilationUnitElement::PatioExceptionTypeDefinition(_) => todo!(), + + PatioCompilationUnitElement::PatioFunctionDeclaration(function_declaration) => { declare_function_declaration(function_declaration, context); } - PatioCompilationUnitElement::FunctionDefinition(function_definition) => { + PatioCompilationUnitElement::PatioFunctionDefinition(function_definition) => { declare_function_definition(function_definition, context); } } @@ -117,23 +120,25 @@ fn define_compilation_unit_element( context: &mut CompilerContext, ) { match element { - PatioCompilationUnitElement::DataElementImmutableDefinition( + PatioCompilationUnitElement::PatioDataElementImmutableDefinition( data_element_immutable_definition, ) => { define_data_element_immutable_definition(data_element_immutable_definition, context); } - PatioCompilationUnitElement::DataElementMutableDeclaration(_) => {} + PatioCompilationUnitElement::PatioDataElementMutableDeclaration(_) => {} - PatioCompilationUnitElement::DataElementMutableDefinition( + PatioCompilationUnitElement::PatioDataElementMutableDefinition( data_element_mutable_definition, ) => { define_data_element_mutable_definition(data_element_mutable_definition, context); } - PatioCompilationUnitElement::FunctionDeclaration(_) => {} + PatioCompilationUnitElement::PatioExceptionTypeDefinition(_) => todo!(), - PatioCompilationUnitElement::FunctionDefinition(function_definition) => { + PatioCompilationUnitElement::PatioFunctionDeclaration(_) => {} + + PatioCompilationUnitElement::PatioFunctionDefinition(function_definition) => { define_function_definition(&function_definition, context); } } @@ -254,7 +259,7 @@ fn define_function_definition( for local in &function_definition.locals { let cranelift_type = types::patio_type_to_cranelift_type( - local.type_, + &local.r#type, &function_context.target_triple, ); @@ -284,95 +289,103 @@ fn define_function_definition( fn compile_instruction(instruction: &PatioInstruction, context: &mut CompilerFunctionContext<'_>) { match instruction { - PatioInstruction::Block(block) => { + PatioInstruction::PatioBlock(block) => { compile_block(block, context); } - PatioInstruction::BoolToInt(bool_to_int) => { + PatioInstruction::PatioBoolToInt(bool_to_int) => { compile_bool_to_int(bool_to_int, context); } - PatioInstruction::Call(call) => { + PatioInstruction::PatioCall(call) => { compile_call(call, context); } - PatioInstruction::CallPointer(call_pointer) => { + PatioInstruction::PatioCallPointer(call_pointer) => { compile_call_pointer(call_pointer, context); } - PatioInstruction::DataPtrToInt(data_ptr_to_int) => { + PatioInstruction::PatioDataPtrToInt(data_ptr_to_int) => { compile_data_ptr_to_int(data_ptr_to_int, context); } - PatioInstruction::If(if_) => { + PatioInstruction::PatioIf(if_) => { compile_if(if_, context); } - PatioInstruction::IntAdd(int_add) => { + PatioInstruction::PatioIntAdd(int_add) => { compile_int_add(int_add, context); } - PatioInstruction::IntEquals(int_equals) => { + PatioInstruction::PatioIntEquals(int_equals) => { compile_int_equals(int_equals, context); } - PatioInstruction::IntNotEqual(int_not_equal) => { + PatioInstruction::PatioIntNotEqual(int_not_equal) => { compile_int_not_equal(int_not_equal, context); } - PatioInstruction::IntSub(int_sub) => { + PatioInstruction::PatioIntSub(int_sub) => { compile_int_sub(int_sub, context); } - PatioInstruction::IntToBool(int_to_bool) => { + PatioInstruction::PatioIntToBool(int_to_bool) => { compile_int_to_bool(int_to_bool, context); } - PatioInstruction::IntToDataPtr(int_to_data_ptr) => { + PatioInstruction::PatioIntToDataPtr(int_to_data_ptr) => { compile_int_to_data_ptr(int_to_data_ptr, context); } - PatioInstruction::LocalStore(local_store) => { + PatioInstruction::PatioLocalStore(local_store) => { compile_local_store(local_store, context); } - PatioInstruction::Loop(loop_) => { + PatioInstruction::PatioLoop(loop_) => { compile_loop(loop_, context); } - PatioInstruction::LoopBreak(loop_break) => { + PatioInstruction::PatioLoopBreak(loop_break) => { compile_loop_break(loop_break, context); } - PatioInstruction::LoopContinue(loop_continue) => { + PatioInstruction::PatioLoopContinue(loop_continue) => { compile_loop_continue(loop_continue, context); } - PatioInstruction::MemoryLoad(memory_load) => { + PatioInstruction::PatioMemoryLoad(memory_load) => { compile_memory_load(memory_load, context); } - PatioInstruction::MemoryStore(memory_store) => { + PatioInstruction::PatioMemoryStore(memory_store) => { compile_memory_store(memory_store, context); } - PatioInstruction::Return(return_) => { + PatioInstruction::PatioReturn(return_) => { compile_return(return_, context); } - PatioInstruction::Switch(switch) => { + PatioInstruction::PatioSwitch(switch) => { compile_switch(switch, context); } - PatioInstruction::Unreachable(unreachable) => { + PatioInstruction::PatioThrow(_) => { + todo!(); + } + + PatioInstruction::PatioTry(_) => { + todo!(); + } + + PatioInstruction::PatioUnreachable(unreachable) => { compile_unreachable(unreachable, context); } - PatioInstruction::VarLoad(var_load) => { + PatioInstruction::PatioVarLoad(var_load) => { compile_var_load(var_load, context); } - PatioInstruction::VarStore(var_store) => { + PatioInstruction::PatioVarStore(var_store) => { compile_var_store(var_store, context); } } @@ -640,7 +653,7 @@ fn compile_memory_load(memory_load: &PatioMemoryLoad, context: &mut CompilerFunc let value_layout = types::data_layout_element_at(&memory_load.layout, &memory_load.element_offsets); let value_type = types::data_layout_to_type(value_layout); - let cranelift_type = types::patio_type_to_cranelift_type(value_type, &context.target_triple); + let cranelift_type = types::patio_type_to_cranelift_type(&value_type, &context.target_triple); let cranelift_pointer = compile_operand(&memory_load.pointer, context); let cranelift_flags = cranelift_codegen::ir::MemFlags::new(); @@ -719,7 +732,7 @@ fn compile_switch(switch: &PatioSwitch, context: &mut CompilerFunctionContext<'_ // Create the jump itself. let mut cranelift_switch = cranelift::frontend::Switch::new(); for (case, case_block) in switch.cases.iter().zip(&case_blocks) { - cranelift_switch.set_entry(case.value.into(), *case_block); + cranelift_switch.set_entry(case.value.try_into().unwrap(), *case_block); } cranelift_switch.emit( &mut context.function_builder, @@ -796,8 +809,8 @@ fn compile_operand( context: &mut CompilerFunctionContext<'_>, ) -> cranelift::prelude::Value { match operand { - PatioOperand::BoolConst(value) => { - let integer_value = if *value { 1 } else { 0 }; + PatioOperand::PatioBoolConst(bool_const) => { + let integer_value = if bool_const.value { 1 } else { 0 }; context .function_builder @@ -805,10 +818,12 @@ fn compile_operand( .iconst(types::CRANELIFT_BOOL_TYPE, integer_value) } - PatioOperand::DataPtrConst(value) => compile_data_ptr_value(&value, context), + PatioOperand::PatioDataPtrConst(data_ptr_const) => { + compile_data_ptr_value(&data_ptr_const.value, context) + } - PatioOperand::FunctionPtrConst(name) => { - let func_ref = context.func_id(name); + PatioOperand::PatioFunctionPtrConst(function_ptr_const) => { + let func_ref = context.func_id(&function_ptr_const.name); let function_ptr_type = context.pointer_type(); context @@ -817,16 +832,16 @@ fn compile_operand( .func_addr(function_ptr_type, func_ref) } - PatioOperand::IntConst(value) => { + PatioOperand::PatioIntConst(int_const) => { let cranelift_int_type = types::cranelift_int_type(&context.target_triple); - compile_int_value(&value, cranelift_int_type, context) + compile_int_value(&int_const.value, cranelift_int_type, context) } - PatioOperand::Int32Const(value) => { - compile_int_value(&value, types::CRANELIFT_INT_32_TYPE, context) + PatioOperand::PatioInt32Const(int_32_const) => { + compile_int_value(&int_32_const.value, types::CRANELIFT_INT_32_TYPE, context) } - PatioOperand::LocalRef(local_ref) => context.local_load(&local_ref.name), + PatioOperand::PatioLocalRef(local_ref) => context.local_load(&local_ref.name), _ => { todo!("Unhandled operand: {operand:?}",) @@ -841,15 +856,17 @@ fn compile_data_ptr_value( let data_ptr_type = context.pointer_type(); match data_ptr_value { - PatioDataPtrValue::DataElement { name } => { - let global_value = context.data_ptr(name); + PatioDataPtrValue::PatioDataPtrValueDataElement(data_element) => { + let global_value = context.data_ptr(&data_element.name); context .function_builder .ins() .global_value(data_ptr_type, global_value) } - PatioDataPtrValue::Null => context.function_builder.ins().iconst(data_ptr_type, 0), + PatioDataPtrValue::PatioDataPtrValueNull(_) => { + context.function_builder.ins().iconst(data_ptr_type, 0) + } } } @@ -896,7 +913,7 @@ fn cranelift_signature<'a>( for local in locals { if local.local_type == PatioLocalType::Param { - let param_type = types::patio_type_to_cranelift_type(local.type_, &target_triple); + let param_type = types::patio_type_to_cranelift_type(&local.r#type, &target_triple); let param = cranelift::prelude::AbiParam::new(param_type); signature.params.push(param); } @@ -904,7 +921,7 @@ fn cranelift_signature<'a>( for return_type in return_types { let cranelift_return_type = - types::patio_type_to_cranelift_type(*return_type, &target_triple); + types::patio_type_to_cranelift_type(return_type, &target_triple); let returns = cranelift::prelude::AbiParam::new(cranelift_return_type); signature.returns.push(returns); } @@ -924,25 +941,25 @@ fn patio_operand_to_cranelift_type( context: &mut CompilerFunctionContext<'_>, ) -> cranelift_codegen::ir::Type { match operand { - PatioOperand::BoolConst(_) => { - patio_type_to_cranelift_type(PatioType::Bool, &context.target_triple) + PatioOperand::PatioBoolConst(_) => { + patio_type_to_cranelift_type(&PatioBoolType.into(), &context.target_triple) } - PatioOperand::ByteConst(_) => { - patio_type_to_cranelift_type(PatioType::Byte, &context.target_triple) + PatioOperand::PatioByteConst(_) => { + patio_type_to_cranelift_type(&PatioByteType.into(), &context.target_triple) } - PatioOperand::DataPtrConst(_) => { - patio_type_to_cranelift_type(PatioType::DataPtr, &context.target_triple) + PatioOperand::PatioDataPtrConst(_) => { + patio_type_to_cranelift_type(&PatioDataPtrType.into(), &context.target_triple) } - PatioOperand::FunctionPtrConst(_) => { - patio_type_to_cranelift_type(PatioType::FunctionPtr, &context.target_triple) + PatioOperand::PatioFunctionPtrConst(_) => { + patio_type_to_cranelift_type(&PatioFunctionPtrType.into(), &context.target_triple) } - PatioOperand::IntConst(_) => { - patio_type_to_cranelift_type(PatioType::Int, &context.target_triple) + PatioOperand::PatioIntConst(_) => { + patio_type_to_cranelift_type(&PatioIntType.into(), &context.target_triple) } - PatioOperand::Int32Const(_) => { - patio_type_to_cranelift_type(PatioType::Int32, &context.target_triple) + PatioOperand::PatioInt32Const(_) => { + patio_type_to_cranelift_type(&PatioInt32Type.into(), &context.target_triple) } - PatioOperand::LocalRef(local_ref) => context.local_type(&local_ref.name), + PatioOperand::PatioLocalRef(local_ref) => context.local_type(&local_ref.name), } } diff --git a/patio-to-cranelift/src/codegen/types.rs b/patio-to-cranelift/src/codegen/types.rs index 21833f3f..616520f7 100644 --- a/patio-to-cranelift/src/codegen/types.rs +++ b/patio-to-cranelift/src/codegen/types.rs @@ -1,21 +1,28 @@ -use crate::patio::types::{PatioDataLayout, PatioType}; +use crate::patio::types::{ + PatioBoolType, PatioByteType, PatioDataLayout, PatioDataPtrType, PatioFunctionPtrType, + PatioInt32Type, PatioIntType, PatioType, +}; pub(crate) fn patio_type_to_cranelift_type( - patio_type: PatioType, + patio_type: &PatioType, target_triple: &target_lexicon::Triple, ) -> cranelift::prelude::Type { match patio_type { - PatioType::Bool => CRANELIFT_BOOL_TYPE, + PatioType::PatioBoolType(_) => CRANELIFT_BOOL_TYPE, - PatioType::Byte => CRANELIFT_BYTE_TYPE, + PatioType::PatioByteType(_) => CRANELIFT_BYTE_TYPE, - PatioType::DataPtr => cranelift::prelude::Type::triple_pointer_type(&target_triple), + PatioType::PatioDataPtrType(_) => { + cranelift::prelude::Type::triple_pointer_type(&target_triple) + } - PatioType::FunctionPtr => cranelift::prelude::Type::triple_pointer_type(&target_triple), + PatioType::PatioFunctionPtrType(_) => { + cranelift::prelude::Type::triple_pointer_type(&target_triple) + } - PatioType::Int => cranelift_int_type(target_triple), + PatioType::PatioIntType(_) => cranelift_int_type(target_triple), - PatioType::Int32 => CRANELIFT_INT_32_TYPE, + PatioType::PatioInt32Type(_) => CRANELIFT_INT_32_TYPE, } } @@ -41,27 +48,29 @@ pub(crate) fn data_layout_byte_size( target_triple: &target_lexicon::Triple, ) -> u32 { match layout { - PatioDataLayout::Array { element, size } => { - data_layout_byte_size(element, target_triple) * size + PatioDataLayout::PatioDataLayoutArray(array) => { + data_layout_byte_size(&array.element, target_triple) + * u32::try_from(array.size).unwrap() } - PatioDataLayout::Bool => CRANELIFT_BOOL_TYPE.bytes(), + PatioDataLayout::PatioDataLayoutBool(_) => CRANELIFT_BOOL_TYPE.bytes(), - PatioDataLayout::Byte => CRANELIFT_BYTE_TYPE.bytes(), + PatioDataLayout::PatioDataLayoutByte(_) => CRANELIFT_BYTE_TYPE.bytes(), - PatioDataLayout::DataPtr => { + PatioDataLayout::PatioDataLayoutDataPtr(_) => { cranelift::prelude::Type::triple_pointer_type(&target_triple).bytes() } - PatioDataLayout::FunctionPtr => { + PatioDataLayout::PatioDataLayoutFunctionPtr(_) => { cranelift::prelude::Type::triple_pointer_type(&target_triple).bytes() } - PatioDataLayout::Int => cranelift_int_type(target_triple).bytes(), + PatioDataLayout::PatioDataLayoutInt(_) => cranelift_int_type(target_triple).bytes(), - PatioDataLayout::Int32 => CRANELIFT_INT_32_TYPE.bytes(), + PatioDataLayout::PatioDataLayoutInt32(_) => CRANELIFT_INT_32_TYPE.bytes(), - PatioDataLayout::Struct { elements } => elements + PatioDataLayout::PatioDataLayoutStruct(layout_struct) => layout_struct + .elements .iter() .map(|element| data_layout_byte_size(element, target_triple)) .sum(), @@ -72,7 +81,11 @@ pub(crate) fn data_layout_byte_size( mod data_layout_byte_size_test { use std::str::FromStr; - use crate::patio::types::PatioDataLayout; + use crate::patio::types::{ + PatioDataLayout, PatioDataLayoutArray, PatioDataLayoutBool, PatioDataLayoutByte, + PatioDataLayoutDataPtr, PatioDataLayoutFunctionPtr, PatioDataLayoutInt, + PatioDataLayoutInt32, PatioDataLayoutStruct, + }; fn data_layout_byte_size(layout: &PatioDataLayout) -> u32 { super::data_layout_byte_size( @@ -83,38 +96,44 @@ mod data_layout_byte_size_test { #[test] fn bool_is_one_byte() { - assert_eq!(data_layout_byte_size(&PatioDataLayout::Bool), 1); + assert_eq!(data_layout_byte_size(&PatioDataLayoutBool.into()), 1); } #[test] fn byte_is_one_byte() { - assert_eq!(data_layout_byte_size(&PatioDataLayout::Byte), 1); + assert_eq!(data_layout_byte_size(&PatioDataLayoutByte.into()), 1); } #[test] fn data_ptr_is_width_of_pointer() { - assert_eq!(data_layout_byte_size(&PatioDataLayout::DataPtr), 8); + assert_eq!(data_layout_byte_size(&PatioDataLayoutDataPtr.into()), 8); } #[test] fn function_ptr_is_width_of_pointer() { - assert_eq!(data_layout_byte_size(&PatioDataLayout::FunctionPtr), 8); + assert_eq!(data_layout_byte_size(&PatioDataLayoutFunctionPtr.into()), 8); } #[test] fn int_is_width_of_pointer_and_at_least_32_bits() { - assert_eq!(data_layout_byte_size(&PatioDataLayout::Int), 8); + assert_eq!(data_layout_byte_size(&PatioDataLayoutInt.into()), 8); } #[test] fn int32_is_four_bytes() { - assert_eq!(data_layout_byte_size(&PatioDataLayout::Int32), 4); + assert_eq!(data_layout_byte_size(&PatioDataLayoutInt32.into()), 4); } #[test] fn array_size_is_size_of_each_element_multiplied_by_number_of_elements() { assert_eq!( - data_layout_byte_size(&PatioDataLayout::array(PatioDataLayout::Int32, 7)), + data_layout_byte_size( + &PatioDataLayoutArray { + element: PatioDataLayoutInt32.into(), + size: 7 + } + .into() + ), 28 ); } @@ -122,10 +141,15 @@ mod data_layout_byte_size_test { #[test] fn struct_size_is_sum_of_element_sizes() { assert_eq!( - data_layout_byte_size(&PatioDataLayout::struct_(vec![ - PatioDataLayout::Int32, - PatioDataLayout::Byte - ])), + data_layout_byte_size( + &PatioDataLayoutStruct { + elements: vec![ + PatioDataLayout::PatioDataLayoutInt32(PatioDataLayoutInt32), + PatioDataLayout::PatioDataLayoutByte(PatioDataLayoutByte) + ] + } + .into() + ), 5 ); } @@ -133,7 +157,7 @@ mod data_layout_byte_size_test { pub(crate) fn data_layout_byte_offset( layout: &PatioDataLayout, - element_offsets: &[u32], + element_offsets: &[i32], target_triple: &target_lexicon::Triple, ) -> u32 { let mut byte_offset = 0; @@ -141,24 +165,32 @@ pub(crate) fn data_layout_byte_offset( for element_offset in element_offsets { match current_element { - PatioDataLayout::Array { element, size: _ } => { - byte_offset += data_layout_byte_size(element, target_triple) * element_offset; - current_element = element; + PatioDataLayout::PatioDataLayoutArray(array) => { + byte_offset += data_layout_byte_size(&array.element, target_triple) + * u32::try_from(*element_offset).unwrap(); + current_element = &array.element; } - PatioDataLayout::Bool => panic!("offset not allowed for bool"), - PatioDataLayout::Byte => panic!("offset not allowed for byte"), - PatioDataLayout::DataPtr => panic!("offset not allowed for data ptr"), - PatioDataLayout::FunctionPtr => panic!("offset not allowed for function ptr"), - PatioDataLayout::Int => panic!("offset not allowed for int"), - PatioDataLayout::Int32 => panic!("offset not allowed for int32"), - - PatioDataLayout::Struct { elements } => { - for element in elements.iter().take((*element_offset).try_into().unwrap()) { + PatioDataLayout::PatioDataLayoutBool(_) => panic!("offset not allowed for bool"), + PatioDataLayout::PatioDataLayoutByte(_) => panic!("offset not allowed for byte"), + PatioDataLayout::PatioDataLayoutDataPtr(_) => panic!("offset not allowed for data ptr"), + PatioDataLayout::PatioDataLayoutFunctionPtr(_) => { + panic!("offset not allowed for function ptr") + } + PatioDataLayout::PatioDataLayoutInt(_) => panic!("offset not allowed for int"), + PatioDataLayout::PatioDataLayoutInt32(_) => panic!("offset not allowed for int32"), + + PatioDataLayout::PatioDataLayoutStruct(layout_struct) => { + for element in layout_struct + .elements + .iter() + .take((*element_offset).try_into().unwrap()) + { byte_offset += data_layout_byte_size(element, target_triple); } - current_element = &elements[usize::try_from(*element_offset).unwrap()]; + current_element = + &layout_struct.elements[usize::try_from(*element_offset).unwrap()]; } } } @@ -170,9 +202,12 @@ pub(crate) fn data_layout_byte_offset( mod data_layout_byte_offset_test { use std::str::FromStr; - use crate::patio::types::PatioDataLayout; + use crate::patio::types::{ + PatioDataLayout, PatioDataLayoutArray, PatioDataLayoutByte, PatioDataLayoutDataPtr, + PatioDataLayoutInt32, PatioDataLayoutStruct, + }; - fn data_layout_byte_offset(layout: &PatioDataLayout, element_offsets: Vec<u32>) -> u32 { + fn data_layout_byte_offset(layout: &PatioDataLayout, element_offsets: Vec<i32>) -> u32 { super::data_layout_byte_offset( layout, &element_offsets, @@ -182,7 +217,11 @@ mod data_layout_byte_offset_test { #[test] fn byte_offset_of_first_element_of_array_is_zero() { - let layout = PatioDataLayout::array(PatioDataLayout::Int32, 2); + let layout = PatioDataLayoutArray { + element: PatioDataLayoutInt32.into(), + size: 2, + } + .into(); let byte_offset = data_layout_byte_offset(&layout, vec![0]); @@ -191,7 +230,11 @@ mod data_layout_byte_offset_test { #[test] fn byte_offset_of_element_of_array_is_size_of_skipped_elements() { - let layout = PatioDataLayout::array(PatioDataLayout::Int32, 5); + let layout = PatioDataLayoutArray { + element: PatioDataLayoutInt32.into(), + size: 5, + } + .into(); let byte_offset = data_layout_byte_offset(&layout, vec![2]); @@ -200,7 +243,15 @@ mod data_layout_byte_offset_test { #[test] fn byte_offset_of_element_of_element_of_array_is_size_of_skipped_elements() { - let layout = PatioDataLayout::array(PatioDataLayout::array(PatioDataLayout::Byte, 7), 5); + let layout = PatioDataLayoutArray { + element: PatioDataLayoutArray { + element: PatioDataLayoutByte.into(), + size: 7, + } + .into(), + size: 5, + } + .into(); let byte_offset = data_layout_byte_offset(&layout, vec![2, 3]); @@ -209,11 +260,14 @@ mod data_layout_byte_offset_test { #[test] fn byte_offset_of_first_element_of_struct_is_zero() { - let layout = PatioDataLayout::struct_(vec![ - PatioDataLayout::Int32, - PatioDataLayout::Byte, - PatioDataLayout::DataPtr, - ]); + let layout = PatioDataLayoutStruct { + elements: vec![ + PatioDataLayoutInt32.into(), + PatioDataLayoutByte.into(), + PatioDataLayoutDataPtr.into(), + ], + } + .into(); let byte_offset = data_layout_byte_offset(&layout, vec![0]); @@ -222,11 +276,14 @@ mod data_layout_byte_offset_test { #[test] fn byte_offset_of_element_of_struct_is_size_of_skipped_elements() { - let layout = PatioDataLayout::struct_(vec![ - PatioDataLayout::Int32, - PatioDataLayout::Byte, - PatioDataLayout::DataPtr, - ]); + let layout = PatioDataLayoutStruct { + elements: vec![ + PatioDataLayoutInt32.into(), + PatioDataLayoutByte.into(), + PatioDataLayoutDataPtr.into(), + ], + } + .into(); let byte_offset = data_layout_byte_offset(&layout, vec![2]); @@ -235,15 +292,21 @@ mod data_layout_byte_offset_test { #[test] fn byte_offset_of_element_of_element_of_struct_is_size_of_skipped_elements() { - let layout = PatioDataLayout::struct_(vec![ - PatioDataLayout::Int32, - PatioDataLayout::struct_(vec![ - PatioDataLayout::Byte, - PatioDataLayout::DataPtr, - PatioDataLayout::Byte, - ]), - PatioDataLayout::Int32, - ]); + let layout = PatioDataLayoutStruct { + elements: vec![ + PatioDataLayoutInt32.into(), + PatioDataLayoutStruct { + elements: vec![ + PatioDataLayoutByte.into(), + PatioDataLayoutDataPtr.into(), + PatioDataLayoutByte.into(), + ], + } + .into(), + PatioDataLayoutInt32.into(), + ], + } + .into(); let byte_offset = data_layout_byte_offset(&layout, vec![1, 2]); @@ -253,25 +316,28 @@ mod data_layout_byte_offset_test { pub(crate) fn data_layout_element_at<'a>( layout: &'a PatioDataLayout, - element_offsets: &[u32], + element_offsets: &[i32], ) -> &'a PatioDataLayout { let mut current_element = layout; for element_offset in element_offsets { match current_element { - PatioDataLayout::Array { element, size: _ } => { - current_element = element; + PatioDataLayout::PatioDataLayoutArray(array) => { + current_element = &array.element; } - PatioDataLayout::Bool => panic!("offset not allowed for bool"), - PatioDataLayout::Byte => panic!("offset not allowed for byte"), - PatioDataLayout::DataPtr => panic!("offset not allowed for data ptr"), - PatioDataLayout::FunctionPtr => panic!("offset not allowed for function ptr"), - PatioDataLayout::Int => panic!("offset not allowed for int"), - PatioDataLayout::Int32 => panic!("offset not allowed for int32"), + PatioDataLayout::PatioDataLayoutBool(_) => panic!("offset not allowed for bool"), + PatioDataLayout::PatioDataLayoutByte(_) => panic!("offset not allowed for byte"), + PatioDataLayout::PatioDataLayoutDataPtr(_) => panic!("offset not allowed for data ptr"), + PatioDataLayout::PatioDataLayoutFunctionPtr(_) => { + panic!("offset not allowed for function ptr") + } + PatioDataLayout::PatioDataLayoutInt(_) => panic!("offset not allowed for int"), + PatioDataLayout::PatioDataLayoutInt32(_) => panic!("offset not allowed for int32"), - PatioDataLayout::Struct { elements } => { - current_element = &elements[usize::try_from(*element_offset).unwrap()]; + PatioDataLayout::PatioDataLayoutStruct(layout_struct) => { + current_element = + &layout_struct.elements[usize::try_from(*element_offset).unwrap()]; } } } @@ -281,86 +347,113 @@ pub(crate) fn data_layout_element_at<'a>( #[cfg(test)] mod data_layout_element_at_test { - use crate::patio::types::PatioDataLayout; + use crate::patio::types::{ + PatioDataLayout, PatioDataLayoutArray, PatioDataLayoutByte, PatioDataLayoutDataPtr, + PatioDataLayoutInt32, PatioDataLayoutStruct, + }; fn data_layout_element_at( layout: &PatioDataLayout, - element_offsets: Vec<u32>, + element_offsets: Vec<i32>, ) -> &PatioDataLayout { super::data_layout_element_at(layout, &element_offsets) } #[test] fn element_of_array_is_element_layout() { - let layout = PatioDataLayout::array(PatioDataLayout::Int32, 2); + let layout = PatioDataLayoutArray { + element: PatioDataLayoutInt32.into(), + size: 2, + } + .into(); let element = data_layout_element_at(&layout, vec![0]); - assert_eq!(element, &PatioDataLayout::Int32); + assert_eq!(element, &PatioDataLayoutInt32.into()); } #[test] fn element_of_element_of_array() { - let layout = PatioDataLayout::array(PatioDataLayout::array(PatioDataLayout::Byte, 7), 5); + let layout = PatioDataLayoutArray { + element: PatioDataLayoutArray { + element: PatioDataLayoutByte.into(), + size: 7, + } + .into(), + size: 5, + } + .into(); let element = data_layout_element_at(&layout, vec![2, 3]); - assert_eq!(element, &PatioDataLayout::Byte); + assert_eq!(element, &PatioDataLayoutByte.into()); } #[test] fn first_element_of_struct() { - let layout = PatioDataLayout::struct_(vec![ - PatioDataLayout::Int32, - PatioDataLayout::Byte, - PatioDataLayout::DataPtr, - ]); + let layout = PatioDataLayoutStruct { + elements: vec![ + PatioDataLayoutInt32.into(), + PatioDataLayoutByte.into(), + PatioDataLayoutDataPtr.into(), + ], + } + .into(); let element = data_layout_element_at(&layout, vec![0]); - assert_eq!(element, &PatioDataLayout::Int32); + assert_eq!(element, &PatioDataLayoutInt32.into()); } #[test] fn non_first_element_of_struct() { - let layout = PatioDataLayout::struct_(vec![ - PatioDataLayout::Int32, - PatioDataLayout::Byte, - PatioDataLayout::DataPtr, - ]); + let layout = PatioDataLayoutStruct { + elements: vec![ + PatioDataLayoutInt32.into(), + PatioDataLayoutByte.into(), + PatioDataLayoutDataPtr.into(), + ], + } + .into(); let element = data_layout_element_at(&layout, vec![2]); - assert_eq!(element, &PatioDataLayout::DataPtr); + assert_eq!(element, &PatioDataLayoutDataPtr.into()); } #[test] fn element_of_element_of_struct() { - let layout = PatioDataLayout::struct_(vec![ - PatioDataLayout::Int32, - PatioDataLayout::struct_(vec![ - PatioDataLayout::Byte, - PatioDataLayout::DataPtr, - PatioDataLayout::Byte, - ]), - PatioDataLayout::Int32, - ]); + let layout = PatioDataLayoutStruct { + elements: vec![ + PatioDataLayoutInt32.into(), + PatioDataLayoutStruct { + elements: vec![ + PatioDataLayoutByte.into(), + PatioDataLayoutDataPtr.into(), + PatioDataLayoutByte.into(), + ], + } + .into(), + PatioDataLayoutInt32.into(), + ], + } + .into(); let element = data_layout_element_at(&layout, vec![1, 2]); - assert_eq!(element, &PatioDataLayout::Byte); + assert_eq!(element, &PatioDataLayoutByte.into()); } } pub(crate) fn data_layout_to_type(layout: &PatioDataLayout) -> PatioType { match layout { - PatioDataLayout::Array { .. } => panic!("array cannot be represented as type"), - PatioDataLayout::Bool => PatioType::Bool, - PatioDataLayout::Byte => PatioType::Byte, - PatioDataLayout::DataPtr => PatioType::DataPtr, - PatioDataLayout::FunctionPtr => PatioType::FunctionPtr, - PatioDataLayout::Int => PatioType::Int, - PatioDataLayout::Int32 => PatioType::Int32, - PatioDataLayout::Struct { .. } => panic!("struct cannot be represented as type"), + PatioDataLayout::PatioDataLayoutArray(_) => panic!("array cannot be represented as type"), + PatioDataLayout::PatioDataLayoutBool(_) => PatioBoolType.into(), + PatioDataLayout::PatioDataLayoutByte(_) => PatioByteType.into(), + PatioDataLayout::PatioDataLayoutDataPtr(_) => PatioDataPtrType.into(), + PatioDataLayout::PatioDataLayoutFunctionPtr(_) => PatioFunctionPtrType.into(), + PatioDataLayout::PatioDataLayoutInt(_) => PatioIntType.into(), + PatioDataLayout::PatioDataLayoutInt32(_) => PatioInt32Type.into(), + PatioDataLayout::PatioDataLayoutStruct(_) => panic!("struct cannot be represented as type"), } } diff --git a/patio-to-cranelift/src/codegen/values.rs b/patio-to-cranelift/src/codegen/values.rs index 229dbc6f..e4bcec2b 100644 --- a/patio-to-cranelift/src/codegen/values.rs +++ b/patio-to-cranelift/src/codegen/values.rs @@ -1,6 +1,9 @@ use crate::{ codegen::types, - patio::values::{PatioDataPtrValue, PatioDataValue, PatioIntValue}, + patio::{ + types::{PatioDataValue, PatioDataValueDataPtr}, + values::{PatioDataPtrValue, PatioIntValue}, + }, }; pub(crate) fn data_value_to_bytes( @@ -24,37 +27,38 @@ fn write_data_value( target_triple: &target_lexicon::Triple, ) { match value { - PatioDataValue::Array { - element_layout: _, - elements, - } => { - for element in elements { + PatioDataValue::PatioDataValueArray(array) => { + for element in &array.elements { write_data_value(element, bytes, target_triple); } } - PatioDataValue::Bool(value) => bytes.push(if *value { 1 } else { 0 }), + PatioDataValue::PatioDataValueBool(bool) => bytes.push(if bool.value { 1 } else { 0 }), - PatioDataValue::Byte(value) => bytes.push(*value), + PatioDataValue::PatioDataValueByte(byte) => bytes.push(byte.value as u8), - PatioDataValue::DataPtr(PatioDataPtrValue::DataElement { name: _ }) => todo!(), + PatioDataValue::PatioDataValueDataPtr(PatioDataValueDataPtr { + value: PatioDataPtrValue::PatioDataPtrValueDataElement(_), + }) => todo!(), - PatioDataValue::DataPtr(PatioDataPtrValue::Null) => { + PatioDataValue::PatioDataValueDataPtr(PatioDataValueDataPtr { + value: PatioDataPtrValue::PatioDataPtrValueNull(_), + }) => { write_patio_int(0, bytes, target_triple); } - PatioDataValue::Int(int_value) => { - let value = eval_int_value(int_value, target_triple); + PatioDataValue::PatioDataValueInt(int_value) => { + let value = eval_int_value(&int_value.value, target_triple); write_patio_int(value, bytes, target_triple); } - PatioDataValue::Int32(int_value) => { - let value: i32 = eval_int_value(int_value, target_triple); + PatioDataValue::PatioDataValueInt32(int_value) => { + let value: i32 = eval_int_value(&int_value.value, target_triple); bytes.extend_from_slice(&value.to_le_bytes()); } - PatioDataValue::Struct { elements } => { - for element in elements { + PatioDataValue::PatioDataValueStruct(value_struct) => { + for element in &value_struct.elements { write_data_value(element, bytes, target_triple); } } @@ -80,18 +84,21 @@ fn write_patio_int(value: i32, bytes: &mut Vec<u8>, target_triple: &target_lexic pub(crate) fn eval_int_value(value: &PatioIntValue, target_triple: &target_lexicon::Triple) -> i32 { match value { - PatioIntValue::ByteOffsetOf { - layout, - element_offsets, - } => types::data_layout_byte_offset(layout, element_offsets, target_triple) - .try_into() - .unwrap(), + PatioIntValue::PatioIntValueByteOffsetOf(byte_offset_of) => types::data_layout_byte_offset( + &byte_offset_of.layout, + &byte_offset_of.element_offsets, + target_triple, + ) + .try_into() + .unwrap(), - PatioIntValue::ByteSizeOf { layout } => types::data_layout_byte_size(layout, target_triple) - .try_into() - .unwrap(), + PatioIntValue::PatioIntValueByteSizeOf(byte_size_of) => { + types::data_layout_byte_size(&byte_size_of.layout, target_triple) + .try_into() + .unwrap() + } - PatioIntValue::Literal { value } => *value, + PatioIntValue::PatioIntValueLiteral(literal) => literal.value, } } @@ -100,8 +107,12 @@ mod data_value_to_bytes_test { use std::str::FromStr; use crate::patio::{ - types::PatioDataLayout, - values::{PatioDataPtrValue, PatioDataValue, PatioIntValue}, + types::{ + PatioDataLayoutInt32, PatioDataValue, PatioDataValueArray, PatioDataValueBool, + PatioDataValueByte, PatioDataValueDataPtr, PatioDataValueInt, PatioDataValueInt32, + PatioDataValueStruct, + }, + values::{PatioDataPtrValueNull, PatioIntValueLiteral}, }; fn data_value_to_bytes(data_value: PatioDataValue) -> Box<[u8]> { @@ -113,13 +124,20 @@ mod data_value_to_bytes_test { #[test] fn array_is_written_as_elements() { - let data_value = PatioDataValue::Array { - element_layout: PatioDataLayout::Int32, + let data_value = PatioDataValueArray { + element_layout: PatioDataLayoutInt32.into(), elements: vec![ - PatioDataValue::Int32(PatioIntValue::Literal { value: 0x12345678 }), - PatioDataValue::Int32(PatioIntValue::Literal { value: 0x23456789 }), + PatioDataValueInt32 { + value: PatioIntValueLiteral { value: 0x12345678 }.into(), + } + .into(), + PatioDataValueInt32 { + value: PatioIntValueLiteral { value: 0x23456789 }.into(), + } + .into(), ], - }; + } + .into(); let bytes = data_value_to_bytes(data_value); @@ -131,7 +149,7 @@ mod data_value_to_bytes_test { #[test] fn false_is_single_byte_0() { - let data_value = PatioDataValue::Bool(false); + let data_value = PatioDataValueBool { value: false }.into(); let bytes = data_value_to_bytes(data_value); @@ -140,7 +158,7 @@ mod data_value_to_bytes_test { #[test] fn true_is_single_byte_1() { - let data_value = PatioDataValue::Bool(true); + let data_value = PatioDataValueBool { value: true }.into(); let bytes = data_value_to_bytes(data_value); @@ -149,7 +167,7 @@ mod data_value_to_bytes_test { #[test] fn byte_is_written_as_single_byte() { - let data_value = PatioDataValue::Byte(42); + let data_value = PatioDataValueByte { value: 42 }.into(); let bytes = data_value_to_bytes(data_value); @@ -159,7 +177,10 @@ mod data_value_to_bytes_test { #[test] fn given_pointer_is_64_bits_wide_then_null_data_ptr_is_written_as_64_bit_0() { let target_triple = target_lexicon::Triple::from_str("x86_64-unknown-linux-gnu").unwrap(); - let data_value = PatioDataValue::DataPtr(PatioDataPtrValue::Null); + let data_value = PatioDataValueDataPtr { + value: PatioDataPtrValueNull {}.into(), + } + .into(); let bytes = super::data_value_to_bytes(&data_value, &target_triple); @@ -169,7 +190,10 @@ mod data_value_to_bytes_test { #[test] fn given_pointer_is_32_bits_wide_then_null_data_ptr_is_written_as_32_bit_0() { let target_triple = target_lexicon::Triple::from_str("i686-unknown-linux-gnu").unwrap(); - let data_value = PatioDataValue::DataPtr(PatioDataPtrValue::Null); + let data_value = PatioDataValueDataPtr { + value: PatioDataPtrValueNull {}.into(), + } + .into(); let bytes = super::data_value_to_bytes(&data_value, &target_triple); @@ -179,7 +203,10 @@ mod data_value_to_bytes_test { #[test] fn given_pointer_is_64_bits_wide_then_int_is_written_with_pointer_width() { let target_triple = target_lexicon::Triple::from_str("x86_64-unknown-linux-gnu").unwrap(); - let data_value = PatioDataValue::Int(PatioIntValue::Literal { value: 0x12345678 }); + let data_value = PatioDataValueInt { + value: PatioIntValueLiteral { value: 0x12345678 }.into(), + } + .into(); let bytes = super::data_value_to_bytes(&data_value, &target_triple); @@ -189,7 +216,10 @@ mod data_value_to_bytes_test { #[test] fn given_pointer_is_32_bits_wide_then_int_is_written_with_pointer_width() { let target_triple = target_lexicon::Triple::from_str("i686-unknown-linux-gnu").unwrap(); - let data_value = PatioDataValue::Int(PatioIntValue::Literal { value: 0x12345678 }); + let data_value = PatioDataValueInt { + value: PatioIntValueLiteral { value: 0x12345678 }.into(), + } + .into(); let bytes = super::data_value_to_bytes(&data_value, &target_triple); @@ -198,7 +228,10 @@ mod data_value_to_bytes_test { #[test] fn int_32_is_written_as_four_bytes() { - let data_value = PatioDataValue::Int32(PatioIntValue::Literal { value: 0x12345678 }); + let data_value = PatioDataValueInt32 { + value: PatioIntValueLiteral { value: 0x12345678 }.into(), + } + .into(); let bytes = data_value_to_bytes(data_value); @@ -207,12 +240,19 @@ mod data_value_to_bytes_test { #[test] fn struct_is_written_as_elements() { - let data_value = PatioDataValue::Struct { + let data_value = PatioDataValueStruct { elements: vec![ - PatioDataValue::Int32(PatioIntValue::Literal { value: 0x12345678 }), - PatioDataValue::Int32(PatioIntValue::Literal { value: 0x23456789 }), + PatioDataValueInt32 { + value: PatioIntValueLiteral { value: 0x12345678 }.into(), + } + .into(), + PatioDataValueInt32 { + value: PatioIntValueLiteral { value: 0x23456789 }.into(), + } + .into(), ], - }; + } + .into(); let bytes = data_value_to_bytes(data_value); @@ -227,7 +267,12 @@ mod data_value_to_bytes_test { mod eval_int_value_test { use std::str::FromStr; - use crate::patio::{types::PatioDataLayout, values::PatioIntValue}; + use crate::patio::{ + types::{PatioDataLayoutArray, PatioDataLayoutInt32}, + values::{ + PatioIntValue, PatioIntValueByteOffsetOf, PatioIntValueByteSizeOf, PatioIntValueLiteral, + }, + }; fn eval_int_value(int_value: PatioIntValue) -> i32 { super::eval_int_value( @@ -238,7 +283,7 @@ mod eval_int_value_test { #[test] fn int_value_literal_is_used_verbatim() { - let int_value = PatioIntValue::Literal { value: 0x12345678 }; + let int_value = PatioIntValueLiteral { value: 0x12345678 }.into(); let value = eval_int_value(int_value); @@ -247,9 +292,10 @@ mod eval_int_value_test { #[test] fn int_can_have_size_of_layout() { - let int_value = PatioIntValue::ByteSizeOf { - layout: PatioDataLayout::Int32, - }; + let int_value = PatioIntValueByteSizeOf { + layout: PatioDataLayoutInt32.into(), + } + .into(); let value = eval_int_value(int_value); @@ -258,10 +304,15 @@ mod eval_int_value_test { #[test] fn int_can_have_byte_offset() { - let int_value = PatioIntValue::ByteOffsetOf { - layout: PatioDataLayout::array(PatioDataLayout::Int32, 7), + let int_value = PatioIntValueByteOffsetOf { + layout: PatioDataLayoutArray { + element: PatioDataLayoutInt32.into(), + size: 7, + } + .into(), element_offsets: vec![5], - }; + } + .into(); let value = eval_int_value(int_value); |
