1use crate::ast;
3use crate::ast::DeclarationType;
4use crate::converter::ConversionResult;
5use repc_impl::layout::{Annotation, Array, Record, RecordField, Type, TypeLayout, TypeVariant};
6use repc_impl::util::BITS_PER_BYTE;
7
8pub fn enhance_declarations(d: &[ast::Declaration], m: &ConversionResult) -> Vec<ast::Declaration> {
9 let mut res = vec![];
10 for d in d {
11 res.push(ast::Declaration {
12 name: d.name.clone(),
13 span: d.span,
14 ty: match &d.ty {
15 DeclarationType::Type(t) => {
16 DeclarationType::Type(enhance_type(t, m.types.get(&d.name).unwrap()))
17 }
18 DeclarationType::Const(c) => DeclarationType::Const(enhance_top_level_expr(
19 c,
20 *m.consts.get(&d.name).unwrap(),
21 )),
22 },
23 });
24 }
25 res
26}
27
28fn enhance_type(t: &ast::Type, ty: &Type<TypeLayout>) -> ast::Type {
29 let variant = match (&t.variant, &ty.variant) {
30 (ast::TypeVariant::Record(r), TypeVariant::Record(rc)) => {
31 ast::TypeVariant::Record(enhance_record(r, rc))
32 }
33 (ast::TypeVariant::Typedef(t), TypeVariant::Typedef(td)) => {
34 ast::TypeVariant::Typedef(Box::new(enhance_type(t, td)))
35 }
36 (ast::TypeVariant::Array(a), TypeVariant::Array(ar)) => {
37 ast::TypeVariant::Array(enhance_array(a, ar))
38 }
39 (ast::TypeVariant::Enum(a), TypeVariant::Enum(ar)) => {
40 ast::TypeVariant::Enum(enhance_enum(a, ar))
41 }
42 (_, _) => t.variant.clone(),
43 };
44 ast::Type {
45 id: t.id,
46 lo: t.lo,
47 layout: Some(ty.layout),
48 layout_hi: t.layout_hi,
49 annotations: enhance_annotations(&t.annotations, &ty.annotations),
50 variant,
51 }
52}
53
54fn enhance_record(r: &ast::Record, rc: &Record<TypeLayout>) -> ast::Record {
55 ast::Record {
56 kind: r.kind,
57 fields: r
58 .fields
59 .iter()
60 .zip(rc.fields.iter())
61 .map(|(f, fc)| enhance_record_field(f, fc))
62 .collect(),
63 }
64}
65
66fn enhance_record_field(f: &ast::RecordField, fc: &RecordField<TypeLayout>) -> ast::RecordField {
67 let mut bit_width = f.bit_width.clone();
68 if let (Some(bit_width), Some(bw)) = (&mut bit_width, fc.bit_width) {
69 bit_width.value = Some(bw as i128);
70 }
71 ast::RecordField {
72 parent_id: f.parent_id,
73 pos: f.pos,
74 lo: f.lo,
75 layout: fc.layout,
76 layout_hi: f.layout_hi,
77 annotations: enhance_annotations(&f.annotations, &fc.annotations),
78 name: f.name.clone(),
79 bit_width,
80 ty: enhance_type(&f.ty, &fc.ty),
81 }
82}
83
84fn enhance_array(a: &ast::Array, ar: &Array<TypeLayout>) -> ast::Array {
85 ast::Array {
86 element_type: Box::new(enhance_type(&a.element_type, &ar.element_type)),
87 num_elements: match (&a.num_elements, ar.num_elements) {
88 (Some(n), Some(ne)) => Some(Box::new(enhance_top_level_expr(n, ne as i128))),
89 _ => None,
90 },
91 }
92}
93
94fn enhance_enum(a: &[ast::Expr], ar: &[i128]) -> Vec<ast::Expr> {
95 a.iter()
96 .zip(ar.iter())
97 .map(|(l, r)| enhance_top_level_expr(l, *r))
98 .collect()
99}
100
101fn enhance_annotations(a: &[ast::Annotation], an: &[Annotation]) -> Vec<ast::Annotation> {
102 a.iter()
103 .zip(an.iter())
104 .map(|(l, r)| enhance_annotation(l, r))
105 .collect()
106}
107
108fn enhance_annotation(a: &ast::Annotation, an: &Annotation) -> ast::Annotation {
109 match (a, an) {
110 (ast::Annotation::Aligned(Some(l)), Annotation::Align(Some(r))) => {
111 let mut a = l.clone();
112 a.value = Some((*r / BITS_PER_BYTE) as i128);
113 ast::Annotation::Aligned(Some(a))
114 }
115 (ast::Annotation::PragmaPack(l), Annotation::PragmaPack(r)) => {
116 let mut a = l.clone();
117 a.value = Some((*r / BITS_PER_BYTE) as i128);
118 ast::Annotation::PragmaPack(a)
119 }
120 _ => a.clone(),
121 }
122}
123
124fn enhance_top_level_expr(e: &ast::Expr, v: i128) -> ast::Expr {
125 let mut e = e.clone();
126 e.value = Some(v);
127 e
128}