[spv-in] Handle structs with no offset decorations

This commit is contained in:
João Capucho
2021-09-04 16:28:56 +01:00
committed by Dzmitry Malyshau
parent 4fa280d931
commit 803093e710
4 changed files with 35 additions and 34 deletions

View File

@@ -13,7 +13,7 @@ use super::{
error::{Error, ErrorKind},
SourceMetadata,
};
use crate::{Arena, Constant, Handle, Type, TypeInner};
use crate::{front::align_up, Arena, Constant, Handle, Type, TypeInner};
/// Struct with information needed for defining a struct member.
///
@@ -170,20 +170,3 @@ pub fn calculate_offset(
TypeAlignSpan { ty, align, span }
}
/// Helper function used for aligning `value` to the next multiple of `align`
///
/// # Notes:
/// - `align` must be a power of two.
/// - The returned value will be greater or equal to `value`.
/// # Examples:
/// ```ignore
/// assert_eq!(0, align_up(0, 16));
/// assert_eq!(16, align_up(1, 16));
/// assert_eq!(16, align_up(16, 16));
/// assert_eq!(334, align_up(333, 2));
/// assert_eq!(384, align_up(257, 128));
/// ```
pub fn align_up(value: u32, align: u32) -> u32 {
((value.wrapping_sub(1)) & !(align - 1)).wrapping_add(align)
}

View File

@@ -597,7 +597,7 @@ impl<'source> ParsingContext<'source> {
&mut parser.errors,
);
span = offset::align_up(span, info.align);
span = crate::front::align_up(span, info.align);
align = align.max(info.align);
members.push(StructMember {
@@ -614,7 +614,7 @@ impl<'source> ParsingContext<'source> {
}
}
span = offset::align_up(span, align);
span = crate::front::align_up(span, align);
Ok(span)
}

View File

@@ -127,3 +127,20 @@ impl ops::Index<Handle<crate::Expression>> for Typifier {
&self.resolutions[handle.index()]
}
}
/// Helper function used for aligning `value` to the next multiple of `align`
///
/// # Notes:
/// - `align` must be a power of two.
/// - The returned value will be greater or equal to `value`.
/// # Examples:
/// ```ignore
/// assert_eq!(0, align_up(0, 16));
/// assert_eq!(16, align_up(1, 16));
/// assert_eq!(16, align_up(16, 16));
/// assert_eq!(334, align_up(333, 2));
/// assert_eq!(384, align_up(257, 128));
/// ```
pub fn align_up(value: u32, align: u32) -> u32 {
((value.wrapping_sub(1)) & !(align - 1)).wrapping_add(align)
}

View File

@@ -40,7 +40,7 @@ use function::*;
use crate::{
arena::{Arena, Handle},
proc::{Alignment, Layouter},
proc::Layouter,
FastHashMap,
};
@@ -3245,10 +3245,11 @@ impl<I: Iterator<Item = u32>> Parser<I> {
.update(&module.types, &module.constants)
.unwrap();
let mut struct_alignment = Alignment::new(1).unwrap();
let mut members = Vec::<crate::StructMember>::with_capacity(inst.wc as usize - 2);
let mut member_lookups = Vec::with_capacity(members.capacity());
let mut storage_access = crate::StorageAccess::empty();
let mut span = 0;
let mut alignment = 1;
for i in 0..u32::from(inst.wc) - 2 {
let type_id = self.next()?;
let ty = self.lookup_type.lookup(type_id)?.handle;
@@ -3264,9 +3265,16 @@ impl<I: Iterator<Item = u32>> Parser<I> {
row_major: decor.matrix_major == Some(Majority::Row),
});
span = crate::front::align_up(span, self.layouter[ty].alignment.get());
alignment = self.layouter[ty].alignment.get().max(alignment);
let binding = decor.io_binding().ok();
// I/O structs don't have to have offsets, others do
let offset = decor.offset.unwrap_or(0);
if let Some(offset) = decor.offset {
span = offset;
}
let offset = span;
span += self.layouter[ty].size;
if let crate::TypeInner::Matrix {
columns,
@@ -3292,8 +3300,6 @@ impl<I: Iterator<Item = u32>> Parser<I> {
}
}
struct_alignment = struct_alignment.max(self.layouter[ty].alignment);
members.push(crate::StructMember {
name: decor.name,
ty,
@@ -3302,16 +3308,11 @@ impl<I: Iterator<Item = u32>> Parser<I> {
});
}
span = crate::front::align_up(span, alignment);
let inner = crate::TypeInner::Struct {
top_level: block_decor.is_some(),
span: members
.iter()
.map(|member| {
let end = member.offset + module.types[member.ty].inner.span(&module.constants);
((end - 1) | (struct_alignment.get() - 1)) + 1
})
.max()
.unwrap_or(4), //do we support this?
span,
members,
};