repc_impl/builder/sysv_like/
mingw.rs1use crate::builder::sysv_like::{Dialect, RecordLayoutBuilder};
3use crate::layout::{FieldLayout, RecordField, RecordKind, Type, TypeLayout};
4use crate::result::{err, ErrorType, Result};
5use crate::target::Target;
6use crate::util::{
7 align_to, annotation_alignment, is_attr_packed, size_add, MaxAssign, MinAssign, BITS_PER_BYTE,
8};
9
10pub(crate) fn compute_layout(target: Target, ty: &Type<()>) -> Result<Type<TypeLayout>> {
11 super::compute_layout(target, ty, Dialect::Mingw)
12}
13
14pub(super) struct OngoingBitfield {
15 ty_size_bits: u64,
18 unused_size_bits: u64,
21}
22
23pub(super) fn layout_fields(
24 rlb: &mut RecordLayoutBuilder,
25 fields: &[RecordField<()>],
26) -> Result<()> {
27 for f in fields {
28 layout_field(rlb, f)?;
29 }
30 Ok(())
31}
32
33fn layout_field(rlb: &mut RecordLayoutBuilder, field: &RecordField<()>) -> Result<()> {
34 let ty = compute_layout(rlb.target, &field.ty)?;
35 let annotation_alignment_bits =
36 annotation_alignment(rlb.target, &field.annotations).unwrap_or(BITS_PER_BYTE);
37 let is_attr_packed = rlb.attr_packed || is_attr_packed(&field.annotations);
40 let ignore_type_alignment = match (is_attr_packed, field.bit_width, &rlb.ongoing_bitfield) {
47 (true, _, _) => true,
48 (_, Some(_), Some(o)) if o.ty_size_bits == ty.layout.size_bits => true,
49 (_, Some(0), None) => true,
50 _ => false,
51 };
52 let mut field_alignment_bits = ty.layout.field_alignment_bits;
53 if ignore_type_alignment {
54 field_alignment_bits = BITS_PER_BYTE;
55 }
56 field_alignment_bits.assign_max(annotation_alignment_bits);
57 field_alignment_bits.assign_min(rlb.max_field_alignment_bits);
58 let update_record_alignment = field.bit_width == None
64 || field.bit_width == Some(0) && rlb.ongoing_bitfield.is_some()
65 || field.bit_width != Some(0) && !is_attr_packed;
66 if update_record_alignment {
70 let mut ty_alignment_bits = ty.layout.field_alignment_bits;
71 if is_attr_packed && field.bit_width != Some(0) {
72 ty_alignment_bits = BITS_PER_BYTE;
73 }
74 ty_alignment_bits.assign_max(annotation_alignment_bits);
75 ty_alignment_bits.assign_min(rlb.max_field_alignment_bits);
76 rlb.alignment_bits.assign_max(ty_alignment_bits);
77 }
78 let layout = match field.bit_width {
87 Some(width) => layout_bit_field(
88 rlb,
89 ty.layout.size_bits,
90 field_alignment_bits,
91 field.named,
92 width,
93 ),
94 None => layout_regular_field(rlb, ty.layout.size_bits, field_alignment_bits),
95 }?;
96 rlb.record_fields.push(RecordField {
97 layout,
98 annotations: field.annotations.clone(),
99 named: field.named,
100 bit_width: field.bit_width,
101 ty,
102 });
103 Ok(())
104}
105
106fn layout_bit_field(
107 rlb: &mut RecordLayoutBuilder,
108 ty_size_bits: u64,
109 field_alignment_bits: u64,
110 named: bool,
111 width: u64,
112) -> Result<Option<FieldLayout>> {
113 macro_rules! ok {
114 ($offset:expr) => {
115 Ok(match named {
116 true => Some(FieldLayout {
117 offset_bits: $offset,
118 size_bits: width,
119 }),
120 false => None,
121 })
122 };
123 }
124 if width > ty_size_bits {
125 return Err(err(ErrorType::OversizedBitfield));
126 }
127 if rlb.kind == RecordKind::Union {
130 rlb.size_bits.assign_max(width);
131 return ok!(0);
132 }
133 match width {
134 0 => rlb.ongoing_bitfield = None,
135 _ => {
136 if let Some(ref mut p) = &mut rlb.ongoing_bitfield {
141 if p.ty_size_bits == ty_size_bits && p.unused_size_bits >= width {
142 let offset_bits = rlb.size_bits - p.unused_size_bits;
143 p.unused_size_bits -= width;
144 return ok!(offset_bits);
145 }
146 }
147 rlb.ongoing_bitfield = Some(OngoingBitfield {
149 ty_size_bits,
150 unused_size_bits: ty_size_bits - width,
151 });
152 }
153 }
154 let offset_bits = align_to(rlb.size_bits, field_alignment_bits)?;
155 rlb.size_bits = match width {
156 0 => offset_bits,
160 _ => size_add(offset_bits, ty_size_bits)?,
164 };
165 ok!(offset_bits)
166}
167
168fn layout_regular_field(
169 rlb: &mut RecordLayoutBuilder,
170 ty_size_bits: u64,
171 field_alignment_bits: u64,
172) -> Result<Option<FieldLayout>> {
173 rlb.ongoing_bitfield = None;
174 let offset_bits = match rlb.kind {
175 RecordKind::Struct => align_to(rlb.size_bits, field_alignment_bits)?,
178 RecordKind::Union => 0,
180 };
181 rlb.size_bits
184 .assign_max(size_add(offset_bits, ty_size_bits)?);
185 Ok(Some(FieldLayout {
186 offset_bits,
187 size_bits: ty_size_bits,
188 }))
189}