variant_config/dsl/
fn_translator.rs

1use super::frontend::*;
2use super::utils::get_string_hash;
3use super::HashMap;
4use super::RandomState;
5use super::{BOOL, INT};
6use anyhow::bail;
7use cranelift::prelude::*;
8
9pub struct ValueWrapper {
10    pub value: Value,
11    pub r#type: Type,
12}
13
14impl ValueWrapper {
15    pub fn new(value: Value, r#type: Type) -> ValueWrapper {
16        ValueWrapper { value, r#type }
17    }
18}
19
20pub struct FunctionTranslator<'a> {
21    random_state: &'a RandomState,
22    builder: &'a mut FunctionBuilder<'a>,
23    variables: &'a mut HashMap<String, Variable>,
24    entry_block: Block,
25}
26
27impl<'a> FunctionTranslator<'a> {
28    pub fn new(
29        random_state: &'a RandomState,
30        builder: &'a mut FunctionBuilder<'a>,
31        variables: &'a mut HashMap<String, Variable>,
32        entry_block: Block,
33    ) -> FunctionTranslator<'a> {
34        FunctionTranslator {
35            random_state,
36            builder,
37            variables,
38            entry_block,
39        }
40    }
41
42    pub fn convert_int_to_bool(&mut self, v: ValueWrapper) -> ValueWrapper {
43        if v.r#type == BOOL {
44            v
45        } else {
46            let return_true = self.builder.ins().bconst(BOOL, true);
47            let return_false = self.builder.ins().bconst(BOOL, false);
48            ValueWrapper::new(
49                self.builder
50                    .ins()
51                    .select(v.value, return_true, return_false),
52                BOOL,
53            )
54        }
55    }
56
57    fn translate_expr_bool(&mut self, expr: Expr) -> anyhow::Result<ValueWrapper> {
58        let ret = self.translate_expr(expr)?;
59        Ok(self.convert_int_to_bool(ret))
60    }
61
62    fn translate_expr_int(&mut self, expr: Expr) -> anyhow::Result<ValueWrapper> {
63        let v = self.translate_expr(expr)?;
64        if v.r#type != INT {
65            bail!(format!("Invalid type {}", v.r#type))
66        } else {
67            Ok(v)
68        }
69    }
70
71    pub fn translate_expr(&mut self, expr: Expr) -> anyhow::Result<ValueWrapper> {
72        match expr {
73            Expr::IntLiteral(literal) => Ok(ValueWrapper::new(
74                self.builder.ins().iconst(INT, literal),
75                INT,
76            )),
77
78            Expr::BoolLiteral(literal) => Ok(ValueWrapper::new(
79                self.builder.ins().bconst(BOOL, literal),
80                BOOL,
81            )),
82
83            Expr::StringLiteral(literal) => {
84                let hash = get_string_hash(self.random_state, &literal);
85                Ok(ValueWrapper::new(
86                    self.builder.ins().iconst(INT, hash),
87                    types::R64,
88                ))
89            }
90
91            Expr::Add(lhs, rhs) => {
92                let lhs = self.translate_expr_int(*lhs)?;
93                let rhs = self.translate_expr_int(*rhs)?;
94                Ok(ValueWrapper::new(
95                    self.builder.ins().iadd(lhs.value, rhs.value),
96                    INT,
97                ))
98            }
99
100            Expr::Sub(lhs, rhs) => {
101                let lhs = self.translate_expr_int(*lhs)?;
102                let rhs = self.translate_expr_int(*rhs)?;
103                Ok(ValueWrapper::new(
104                    self.builder.ins().isub(lhs.value, rhs.value),
105                    INT,
106                ))
107            }
108
109            Expr::Mul(lhs, rhs) => {
110                let lhs = self.translate_expr_int(*lhs)?;
111                let rhs = self.translate_expr_int(*rhs)?;
112                Ok(ValueWrapper::new(
113                    self.builder.ins().imul(lhs.value, rhs.value),
114                    INT,
115                ))
116            }
117
118            Expr::Div(lhs, rhs) => {
119                let lhs = self.translate_expr_int(*lhs)?;
120                let rhs = self.translate_expr_int(*rhs)?;
121                Ok(ValueWrapper::new(
122                    self.builder.ins().sdiv(lhs.value, rhs.value),
123                    INT,
124                ))
125            }
126
127            Expr::Mod(lhs, rhs) => {
128                let lhs = self.translate_expr_int(*lhs)?;
129                let rhs = self.translate_expr_int(*rhs)?;
130                Ok(ValueWrapper::new(
131                    self.builder.ins().srem(lhs.value, rhs.value),
132                    INT,
133                ))
134            }
135
136            Expr::And(lhs, rhs) => {
137                let lhs = self.translate_expr_bool(*lhs)?;
138                let rhs = self.translate_expr_bool(*rhs)?;
139                Ok(ValueWrapper::new(
140                    self.builder.ins().band(lhs.value, rhs.value),
141                    BOOL,
142                ))
143            }
144
145            Expr::Or(lhs, rhs) => {
146                let lhs = self.translate_expr_bool(*lhs)?;
147                let rhs = self.translate_expr_bool(*rhs)?;
148                Ok(ValueWrapper::new(
149                    self.builder.ins().bor(lhs.value, rhs.value),
150                    BOOL,
151                ))
152            }
153
154            Expr::Eq(lhs, rhs) => self.translate_icmp(IntCC::Equal, *lhs, *rhs),
155            Expr::Ne(lhs, rhs) => self.translate_icmp(IntCC::NotEqual, *lhs, *rhs),
156            Expr::Lt(lhs, rhs) => self.translate_icmp(IntCC::SignedLessThan, *lhs, *rhs),
157            Expr::Le(lhs, rhs) => self.translate_icmp(IntCC::SignedLessThanOrEqual, *lhs, *rhs),
158            Expr::Gt(lhs, rhs) => self.translate_icmp(IntCC::SignedGreaterThan, *lhs, *rhs),
159            Expr::Ge(lhs, rhs) => self.translate_icmp(IntCC::SignedGreaterThanOrEqual, *lhs, *rhs),
160            Expr::Identifier(name) => {
161                if let Some(&variable) = self.variables.get(&name) {
162                    Ok(ValueWrapper::new(self.builder.use_var(variable), INT))
163                } else {
164                    let idx = self.variables.len();
165                    let var = Variable::new(idx);
166                    self.variables.insert(name, var);
167                    self.builder.declare_var(var, INT);
168                    let val = self.builder.block_params(self.entry_block)[idx];
169                    self.builder.def_var(var, val);
170                    Ok(ValueWrapper::new(val, INT))
171                }
172            }
173        }
174    }
175
176    fn translate_icmp(&mut self, cmp: IntCC, lhs: Expr, rhs: Expr) -> anyhow::Result<ValueWrapper> {
177        match cmp {
178            IntCC::Equal | IntCC::NotEqual => {
179                let lhs = self.translate_expr(lhs)?;
180                let rhs = self.translate_expr(rhs)?;
181                Ok(ValueWrapper::new(
182                    self.builder.ins().icmp(cmp, lhs.value, rhs.value),
183                    INT,
184                ))
185            }
186            _ => {
187                let lhs = self.translate_expr_int(lhs)?;
188                let rhs = self.translate_expr_int(rhs)?;
189                Ok(ValueWrapper::new(
190                    self.builder.ins().icmp(cmp, lhs.value, rhs.value),
191                    INT,
192                ))
193            }
194        }
195    }
196
197    pub fn return_and_finalize(&mut self, ret: Value) {
198        self.builder.ins().return_(&[ret]);
199        self.builder.finalize();
200    }
201}