168 lines
5.1 KiB
Rust
168 lines
5.1 KiB
Rust
|
|
||
|
use laddertypes::{parser::*, unparser::*, SugaredStructMember, SugaredTypeTerm, TypeDict, TypeTerm};
|
||
|
|
||
|
#[derive(Clone, Copy, Debug)]
|
||
|
pub enum ObjectSize {
|
||
|
Static(u64),
|
||
|
Dynamic(/* function to get size at runtime */),
|
||
|
Unknown
|
||
|
}
|
||
|
|
||
|
|
||
|
pub fn get_type_size( dict: &mut impl TypeDict, ty: TypeTerm ) -> ObjectSize {
|
||
|
let ty = ty.clone().get_lnf_vec().last().unwrap().clone();
|
||
|
|
||
|
if ty == dict.parse("native.UInt8").expect("") {
|
||
|
return ObjectSize::Static(1);
|
||
|
}
|
||
|
if ty == dict.parse("native.UInt16").expect("") {
|
||
|
return ObjectSize::Static(2);
|
||
|
}
|
||
|
if ty == dict.parse("native.UInt32").expect("") ||
|
||
|
ty == dict.parse("native.Float").expect("") {
|
||
|
return ObjectSize::Static(4);
|
||
|
}
|
||
|
if ty == dict.parse("native.UInt64").expect("") ||
|
||
|
ty == dict.parse("native.Double").expect("") {
|
||
|
return ObjectSize::Static(8);
|
||
|
}
|
||
|
|
||
|
if let Some(layout) = StructLayout::parse( dict, ty ) {
|
||
|
return layout.get_size();
|
||
|
}
|
||
|
|
||
|
ObjectSize::Unknown
|
||
|
}
|
||
|
|
||
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||
|
enum LayoutType {
|
||
|
Natural,
|
||
|
Packed
|
||
|
}
|
||
|
|
||
|
#[derive(Clone, Debug)]
|
||
|
pub struct StructLayout {
|
||
|
ty: laddertypes::TypeTerm,
|
||
|
item_type: laddertypes::TypeTerm,
|
||
|
pub members: Vec< (String, laddertypes::TypeTerm) >,
|
||
|
offsets: std::collections::HashMap< String, u64 >,
|
||
|
size: ObjectSize
|
||
|
}
|
||
|
|
||
|
impl StructLayout {
|
||
|
pub fn get_type(&self) -> TypeTerm {
|
||
|
self.ty.clone()
|
||
|
}
|
||
|
|
||
|
pub fn get_size(&self) -> ObjectSize {
|
||
|
self.size
|
||
|
}
|
||
|
|
||
|
pub fn get_offset(&self, name: &String) -> u64 {
|
||
|
*self.offsets.get(name).expect("")
|
||
|
}
|
||
|
|
||
|
pub fn calculate_offsets(&mut self, dict: &mut impl TypeDict) {
|
||
|
let layout_type = LayoutType::Natural;
|
||
|
let mut offset = 0;
|
||
|
|
||
|
for (field_name, field_type) in self.members.iter() {
|
||
|
//let field_c_type = crate::c_gen::get_c_repr_type(dict, field_type.clone(), true).expect("cant get c-repr for struct field");
|
||
|
match get_type_size( dict, field_type.clone() ) {
|
||
|
ObjectSize::Static(field_size) => {
|
||
|
if layout_type == LayoutType::Natural {
|
||
|
// add padding to natural alignment
|
||
|
if offset % field_size > 0 {
|
||
|
offset = field_size * ((offset / field_size)+1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// take offset
|
||
|
self.offsets.insert(field_name.clone(), offset);
|
||
|
|
||
|
// advance by current size
|
||
|
offset += field_size;
|
||
|
}
|
||
|
ObjectSize::Dynamic() => {
|
||
|
eprintln!("dynamically sized Field in struct!");
|
||
|
self.offsets.insert(field_name.clone(), offset);
|
||
|
self.size = ObjectSize::Dynamic();
|
||
|
return;
|
||
|
}
|
||
|
ObjectSize::Unknown => {
|
||
|
eprintln!("unknown field size!");
|
||
|
self.offsets.insert(field_name.clone(), offset);
|
||
|
self.size = ObjectSize::Unknown;
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
match self.size {
|
||
|
ObjectSize::Dynamic() => {
|
||
|
|
||
|
}
|
||
|
_ => {
|
||
|
self.size = ObjectSize::Static(offset);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub fn generate_members(&self, dict: &mut impl TypeDict, prefix: &str, base_ptr: &str) {
|
||
|
let mut offset = 0;
|
||
|
|
||
|
for (field_name, field_type) in self.members.iter() {
|
||
|
let field_c_type = crate::c_gen::get_c_repr_type(dict, field_type.clone(), true).expect("cant get c-repr for struct field");
|
||
|
let offset = self.get_offset(field_name);
|
||
|
println!(" {} * restrict {}_{} = {} + {};",
|
||
|
field_c_type, prefix, field_name, base_ptr, offset
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub fn parse(dict: &mut impl TypeDict, struct_type: TypeTerm) -> Option <Self> {
|
||
|
match struct_type.sugar(dict) {
|
||
|
SugaredTypeTerm::Struct(sugared_members) => {
|
||
|
let mut members = Vec::new();
|
||
|
let mut item_type = dict.parse("Byte").expect("");
|
||
|
|
||
|
for SugaredStructMember{ symbol, ty } in sugared_members {
|
||
|
members.push((symbol, ty.desugar(dict)));
|
||
|
}
|
||
|
|
||
|
let mut sl = StructLayout {
|
||
|
ty: TypeTerm::unit(),
|
||
|
item_type,
|
||
|
members,
|
||
|
offsets: std::collections::HashMap::new(),
|
||
|
size: ObjectSize::Unknown
|
||
|
};
|
||
|
|
||
|
sl.calculate_offsets(dict);
|
||
|
sl.calculate_type(dict);
|
||
|
|
||
|
Some(sl)
|
||
|
}
|
||
|
|
||
|
_ => {
|
||
|
eprintln!("not a struct");
|
||
|
None
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fn calculate_type(&mut self, dict: &mut impl TypeDict) {
|
||
|
self.ty =
|
||
|
SugaredTypeTerm::Struct(
|
||
|
self.members
|
||
|
.iter()
|
||
|
.cloned()
|
||
|
.map(|(symbol,ty)|
|
||
|
SugaredStructMember{ symbol, ty:ty.sugar(dict) })
|
||
|
.collect()
|
||
|
)
|
||
|
.desugar(dict);
|
||
|
|
||
|
}
|
||
|
}
|