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}