charon_lib/transform/
ops_to_function_calls.rs

1//! Desugar some unary/binary operations and the array repeats to function calls.
2//! For instance, we desugar ArrayToSlice from an unop to a function call.
3//! This allows a more uniform treatment later on.
4//! TODO: actually transform all the unops and binops to function calls?
5use crate::transform::TransformCtx;
6use crate::ullbc_ast::*;
7
8use super::ctx::UllbcPass;
9
10fn transform_st(s: &mut Statement) {
11    match &s.content {
12        // Transform the ArrayToSlice unop
13        RawStatement::Assign(p, Rvalue::UnaryOp(UnOp::ArrayToSlice(ref_kind, ty, cg), op)) => {
14            // We could avoid the clone operations below if we take the content of
15            // the statement. In practice, this shouldn't have much impact.
16            let id = match ref_kind {
17                RefKind::Mut => BuiltinFunId::ArrayToSliceMut,
18                RefKind::Shared => BuiltinFunId::ArrayToSliceShared,
19            };
20            let func = FunIdOrTraitMethodRef::mk_builtin(id);
21            let generics = GenericArgs::new(
22                vec![Region::Erased].into(),
23                vec![ty.clone()].into(),
24                vec![cg.clone()].into(),
25                vec![].into(),
26                GenericsSource::Builtin,
27            );
28            let func = FnOperand::Regular(FnPtr { func, generics });
29            s.content = RawStatement::Call(Call {
30                func,
31                args: vec![op.clone()],
32                dest: p.clone(),
33            });
34        }
35        // Transform the array aggregates to function calls
36        RawStatement::Assign(p, Rvalue::Repeat(op, ty, cg)) => {
37            // We could avoid the clone operations below if we take the content of
38            // the statement. In practice, this shouldn't have much impact.
39            let id = BuiltinFunId::ArrayRepeat;
40            let func = FunIdOrTraitMethodRef::mk_builtin(id);
41            let generics = GenericArgs::new(
42                vec![Region::Erased].into(),
43                vec![ty.clone()].into(),
44                vec![cg.clone()].into(),
45                vec![].into(),
46                GenericsSource::Builtin,
47            );
48            let func = FnOperand::Regular(FnPtr { func, generics });
49            s.content = RawStatement::Call(Call {
50                func,
51                args: vec![op.clone()],
52                dest: p.clone(),
53            });
54        }
55        // Transform the raw pointer aggregate to a function call
56        RawStatement::Assign(p, Rvalue::Aggregate(AggregateKind::RawPtr(ty, is_mut), ops)) => {
57            let id = BuiltinFunId::PtrFromParts(is_mut.clone());
58            let func = FunIdOrTraitMethodRef::mk_builtin(id);
59            let generics = GenericArgs::new(
60                vec![Region::Erased].into(),
61                vec![ty.clone()].into(),
62                vec![].into(),
63                vec![].into(),
64                GenericsSource::Builtin,
65            );
66
67            let func = FnOperand::Regular(FnPtr { func, generics });
68            s.content = RawStatement::Call(Call {
69                func,
70                args: ops.clone(),
71                dest: p.clone(),
72            });
73        }
74        _ => {}
75    }
76}
77
78pub struct Transform;
79impl UllbcPass for Transform {
80    fn transform_body(&self, _ctx: &mut TransformCtx, b: &mut ExprBody) {
81        b.visit_statements(&mut transform_st);
82    }
83}