1use super::*;
2use crate::asg::*;
3use std::{collections::HashMap, sync::Arc};
4
5#[derive(Debug)]
6pub enum Constructable {
7 Struct {
8 name: String,
9 items: Vec<(String, usize)>,
10 },
11 Tuple(Vec<usize>),
12 TaggedTuple {
13 name: String,
14 items: Vec<usize>,
15 },
16 TaggedEnum {
17 name: String,
18 discriminant: String,
19 values: Vec<usize>,
20 },
21 TaggedEnumStruct {
22 name: String,
23 discriminant: String,
24 values: Vec<(String, usize)>,
25 },
26}
27
28#[derive(Debug)]
29pub enum Instruction {
30 Eval(usize, Expression),
31 Construct(usize, Constructable),
32 Constrict(Target, usize, usize),
34 WrapStream(Target, usize, Arc<Transform>, Vec<usize>), ConditionalWrapStream(
36 usize,
37 Vec<Instruction>,
38 Target,
39 usize,
40 Arc<Transform>,
41 Vec<usize>,
42 ), DecodeForeign(Target, usize, Arc<ForeignType>, Vec<usize>),
45 DecodeRef(Target, usize, String, Vec<usize>),
46 DecodeRepr(String, PrimitiveType, usize, Target),
47 DecodePrimitive(Target, usize, PrimitiveType),
48 DecodePrimitiveArray(Target, usize, PrimitiveType, Option<usize>),
49 DecodeReprArray(Target, usize, String, PrimitiveType, Option<usize>),
50 Skip(Target, usize),
52
53 Loop(
55 Target,
56 Option<usize>,
57 Option<usize>,
58 usize,
59 Vec<Instruction>,
60 ),
61 LoopOutput(usize, usize), Conditional(usize, usize, usize, Vec<Instruction>), ConditionalPredicate(usize, Vec<Instruction>), Return(usize),
66 Error(String),
67}
68
69#[derive(Debug)]
70pub struct Context {
71 pub register_count: usize,
72 pub field_register_map: HashMap<String, usize>,
73 pub instructions: Vec<Instruction>,
74 pub name: String,
75}
76
77impl Context {
78 fn alloc_register(&mut self) -> usize {
79 let x = self.register_count;
80 self.register_count += 1;
81 x
82 }
83}
84
85impl Context {
86 pub fn new() -> Context {
87 Context {
88 name: String::new(),
89 instructions: vec![],
90 field_register_map: HashMap::new(),
91 register_count: 0,
92 }
93 }
94
95 pub fn decode_field_top(&mut self, field: &Arc<Field>) {
96 assert!(field.toplevel);
97 self.name = field.name.clone();
98 let mut value = self.decode_field(Target::Direct, field);
99 match &*field.type_.borrow() {
100 Type::Foreign(_) => (),
101 Type::Container(_) => (),
102 Type::Enum(_) => (),
103 Type::Bitfield(_) => (),
104 _ => {
105 if let Some(old_value) = value {
106 let extra_value = self.alloc_register();
107 self.instructions.push(Instruction::Construct(
108 extra_value,
109 Constructable::TaggedTuple {
110 name: field.name.clone(),
111 items: vec![old_value],
112 },
113 ));
114 value = Some(extra_value);
115 }
116 }
117 }
118 if let Some(value) = value {
119 self.instructions.push(Instruction::Return(
120 value,
121 ));
122 }
123 }
124
125 fn decode_field_condition(&mut self, field: &Arc<Field>) -> Option<usize> {
126 if let Some(condition) = field.condition.borrow().as_ref() {
127 let value = self.alloc_register();
128 self.instructions
129 .push(Instruction::Eval(value, condition.clone()));
130 Some(value)
131 } else {
132 None
133 }
134 }
135
136 pub fn decode_field(&mut self, source: Target, field: &Arc<Field>) -> Option<usize> {
138 let field_condition = self.decode_field_condition(field);
139 let start = self.instructions.len();
140
141 let emitted = self.decode_field_unconditional(source, field);
142
143 if let Some(field_condition) = field_condition {
144 if emitted.is_none() {
145 unimplemented!("cannot have interior containers with field conditional");
146 }
147 let target = self.alloc_register();
148 let drained = self.instructions.drain(start..).collect();
149 self.instructions.push(Instruction::Conditional(
150 target,
151 emitted.unwrap(),
152 field_condition,
153 drained,
154 ));
155 Some(target)
156 } else {
157 emitted
158 }
159 }
160
161 fn decode_field_unconditional(&mut self, mut source: Target, field: &Arc<Field>) -> Option<usize> {
162 let mut new_streams = vec![];
163
164 for transform in field.transforms.borrow().iter().rev() {
165 let condition = if let Some(condition) = &transform.condition {
166 let value = self.alloc_register();
167 self.instructions
168 .push(Instruction::Eval(value, condition.clone()));
169 Some(value)
170 } else {
171 None
172 };
173
174 let argument_start = self.instructions.len();
175 let mut args = vec![];
176 for arg in transform.arguments.iter() {
177 let r = self.alloc_register();
178 self.instructions.push(Instruction::Eval(r, arg.clone()));
179 args.push(r);
180 }
181 let new_stream = self.alloc_register();
182 new_streams.push(new_stream);
183
184 if let Some(condition) = condition {
185 let drained = self.instructions.drain(argument_start..).collect();
186 self.instructions.push(Instruction::ConditionalWrapStream(
187 condition,
188 drained,
189 source,
190 new_stream,
191 transform.transform.clone(),
192 args,
193 ));
194 } else {
195 self.instructions.push(Instruction::WrapStream(
196 source,
197 new_stream,
198 transform.transform.clone(),
199 args,
200 ));
201 }
202 source = Target::Stream(new_stream);
203 }
204
205 let emitted = match &*field.type_.borrow() {
207 Type::Container(c) => {
208 let buf_target = if let Some(length) = &c.length {
209 let len_register = self.alloc_register();
211 self.instructions
212 .push(Instruction::Eval(len_register, length.clone()));
213 let buf = self.alloc_register();
214 self.instructions
215 .push(Instruction::Constrict(source, buf, len_register));
216 Target::Stream(buf)
217 } else {
218 source
219 };
220 if c.is_enum.get() {
221 for (name, child) in c.items.iter() {
222 let condition = self.decode_field_condition(child);
223 let start = self.instructions.len();
224 let decoded = self.decode_field_unconditional(buf_target, child);
225 let target = self.alloc_register();
226
227 let subtype = child.type_.borrow();
228 match &*subtype {
229 Type::Container(c) => {
230 let mut values = vec![];
231 for (subname, subchild) in c.flatten_view() {
232 if subchild.is_pad.get() || matches!(&*subchild.type_.borrow(), Type::Container(_)) {
233 continue;
234 }
235
236 values.push((
237 subname.clone(),
238 *self
239 .field_register_map
240 .get(&subname)
241 .expect("missing field in field_register_map"),
242 ));
243 }
244
245 self.instructions.push(Instruction::Construct(target, Constructable::TaggedEnumStruct {
246 name: field.name.clone(),
247 discriminant: name.clone(),
248 values,
249 }));
250 },
251 _ => {
252 let decoded = decoded.expect("enum discriminant was proper interior container, which is illegal");
253 self.instructions.push(Instruction::Construct(target, Constructable::TaggedEnum {
254 name: field.name.clone(),
255 discriminant: name.clone(),
256 values: vec![decoded],
257 }));
258 },
259 }
260
261 if let Some(condition) = condition {
262 self.instructions.push(Instruction::Return(target));
263 let drained = self.instructions.drain(start..).collect();
264 self.instructions.push(Instruction::ConditionalPredicate(
265 condition,
266 drained,
267 ));
268 } else {
269 return Some(target);
270 }
271 }
272 self.instructions.push(Instruction::Error(format!("no enum conditions matched for {}", field.name)));
273 None
274 } else {
275 for (name, child) in c.items.iter() {
276 let decoded = self.decode_field(buf_target, child);
277 if let Some(decoded) = decoded {
278 self.field_register_map.insert(name.clone(), decoded);
279 }
280 }
281 if field.toplevel {
282 let emitted = self.alloc_register();
283 let mut items = vec![];
284 for (name, child) in c.flatten_view() {
285 if child.is_pad.get() || matches!(&*child.type_.borrow(), Type::Container(_)) {
286 continue;
287 }
288 items.push((
289 name.clone(),
290 *self
291 .field_register_map
292 .get(&name)
293 .expect("missing field in field_register_map"),
294 ));
295 }
296 self.instructions.push(Instruction::Construct(
297 emitted,
298 Constructable::Struct {
299 name: field.name.clone(),
300 items,
301 },
302 ));
303 Some(emitted)
304 } else {
305 None
306 }
307 }
308 }
309 _ => self.decode_type(source, field),
310 };
311
312 emitted
313 }
314
315 pub fn decode_type(&mut self, source: Target, field: &Arc<Field>) -> Option<usize> {
316 let output = self.alloc_register();
317 Some(match &*field.type_.borrow() {
318 Type::Container(_) => unimplemented!(),
319 Type::Array(c) => {
320 if field.is_pad.get() {
321 let array_type = field.type_.borrow();
322 let array_type = match &*array_type {
323 Type::Array(a) => &**a,
324 _ => panic!("invalid type for pad"),
325 };
326 let len = array_type.length.value.as_ref().cloned().unwrap();
327 let length_register = self.alloc_register();
328 self.instructions.push(Instruction::Eval(length_register, len));
329 self.instructions.push(Instruction::Skip(source, length_register));
330 return None;
331 }
332 let terminator = if c.length.expandable && c.length.value.is_some() {
333 let len = c.length.value.as_ref().cloned().unwrap();
334 let r = self.alloc_register();
335 self.instructions.push(Instruction::Eval(r, len));
336 Some(r)
337 } else {
338 None
339 };
340
341 let len = if c.length.expandable {
342 None
343 } else {
344 let len = c.length.value.as_ref().cloned().unwrap();
345 let r = self.alloc_register();
346 self.instructions.push(Instruction::Eval(r, len));
347 Some(r)
348 };
349
350 if c.element.condition.borrow().is_none()
351 && c.element.transforms.borrow().len() == 0
352 && terminator.is_none()
353 {
354 let type_ = c.element.type_.borrow();
355 let type_ = type_.resolved();
356 match &*type_ {
357 Type::Container(_) | Type::Array(_) | Type::Foreign(_) | Type::Ref(_) => (),
359 Type::Enum(x) => {
360 self.instructions.push(Instruction::DecodeReprArray(
361 source,
362 output,
363 field.name.clone(),
364 PrimitiveType::Scalar(x.rep.clone()),
365 len,
366 ));
367 return Some(output);
368 }
369 Type::Bitfield(x) => {
370 self.instructions.push(Instruction::DecodeReprArray(
371 source,
372 output,
373 field.name.clone(),
374 PrimitiveType::Scalar(x.rep.clone()),
375 len,
376 ));
377 return Some(output);
378 }
379 Type::Scalar(x) => {
380 self.instructions.push(Instruction::DecodePrimitiveArray(
381 source,
382 output,
383 PrimitiveType::Scalar(*x),
384 len,
385 ));
386 return Some(output);
387 }
388 Type::F32 => {
389 self.instructions.push(Instruction::DecodePrimitiveArray(
390 source,
391 output,
392 PrimitiveType::F32,
393 len,
394 ));
395 return Some(output);
396 }
397 Type::F64 => {
398 self.instructions.push(Instruction::DecodePrimitiveArray(
399 source,
400 output,
401 PrimitiveType::F64,
402 len,
403 ));
404 return Some(output);
405 }
406 Type::Bool => {
407 self.instructions.push(Instruction::DecodePrimitiveArray(
408 source,
409 output,
410 PrimitiveType::Bool,
411 len,
412 ));
413 return Some(output);
414 }
415 }
416 }
417
418 let current_pos = self.instructions.len();
419 let item = self.decode_field(source, &c.element);
420 if item.is_none() {
421 unimplemented!("cannot have inline container inside array");
422 }
423 self.instructions
424 .push(Instruction::LoopOutput(output, item.unwrap()));
425 let drained = self.instructions.drain(current_pos..).collect();
426 self.instructions
427 .push(Instruction::Loop(source, len, terminator, output, drained));
428 output
429 }
430 Type::Enum(e) => {
431 self.instructions.push(Instruction::DecodeRepr(
432 field.name.clone(),
433 PrimitiveType::Scalar(e.rep.clone()),
434 output,
435 source,
436 ));
437 output
438 }
439 Type::Bitfield(e) => {
440 self.instructions.push(Instruction::DecodeRepr(
441 field.name.clone(),
442 PrimitiveType::Scalar(e.rep.clone()),
443 output,
444 source,
445 ));
446 output
447 }
448 Type::Scalar(s) => {
449 self.instructions.push(Instruction::DecodePrimitive(
450 source,
451 output,
452 PrimitiveType::Scalar(*s),
453 ));
454 output
455 }
456 Type::F32 => {
457 self.instructions.push(Instruction::DecodePrimitive(
458 source,
459 output,
460 PrimitiveType::F32,
461 ));
462 output
463 }
464 Type::F64 => {
465 self.instructions.push(Instruction::DecodePrimitive(
466 source,
467 output,
468 PrimitiveType::F64,
469 ));
470 output
471 }
472 Type::Bool => {
473 self.instructions.push(Instruction::DecodePrimitive(
474 source,
475 output,
476 PrimitiveType::Bool,
477 ));
478 output
479 }
480 Type::Foreign(f) => {
481 self.instructions.push(Instruction::DecodeForeign(
482 source,
483 output,
484 f.clone(),
485 vec![],
486 ));
487 output
488 }
489 Type::Ref(r) => {
490 let mut args = vec![];
491 for arg in r.arguments.iter() {
492 let r = self.alloc_register();
493 self.instructions.push(Instruction::Eval(r, arg.clone()));
494 args.push(r);
495 }
496 if let Type::Foreign(f) = &*r.target.type_.borrow() {
497 self.instructions.push(Instruction::DecodeForeign(
498 source,
499 output,
500 f.clone(),
501 args,
502 ));
503 } else {
504 self.instructions.push(Instruction::DecodeRef(
505 source,
506 output,
507 r.target.name.clone(),
508 args,
509 ));
510 }
511 output
512 }
513 })
514 }
515}