cly_impl/
enhancer.rs

1// SPDX-License-Identifier: GPL-3.0-or-later
2use 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}