diff options
Diffstat (limited to 'patio-to-cranelift/src/codegen/types.rs')
| -rw-r--r-- | patio-to-cranelift/src/codegen/types.rs | 321 |
1 files changed, 207 insertions, 114 deletions
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"), } } |
