1use super::{JITRunTime, context::BuildContext};
2use cranelift::prelude::*;
3use cranelift_module::{DataDescription, Module};
4use dynamic::{Dynamic, Type};
5use parser::{BinaryOp, Expr};
6
7use anyhow::{Result, anyhow};
8
9impl JITRunTime {
10 fn struct_to_dynamic(&mut self, ctx: &mut BuildContext, base: Value, ty: &Type) -> Result<Value> {
11 let Type::Struct { params: _, fields: _ } = ty else {
12 return Err(anyhow!("不是结构体 {:?}", ty));
13 };
14 let id = self.module.declare_anonymous_data(true, false)?;
15 let mut desc = DataDescription::new();
16 let ty_ptr = Box::into_raw(Box::new(ty.clone()));
17 desc.define((ty_ptr as i64).to_le_bytes().into());
18 self.module.define_data(id, &desc)?;
19 let ty_data = self.module.declare_data_in_func(id, &mut ctx.builder.func);
20 let ty_addr = ctx.builder.ins().global_value(crate::ptr_type(), ty_data);
21 let ty_ptr = ctx.builder.ins().load(crate::ptr_type(), MemFlags::new(), ty_addr, 0);
22 let f = self.get_fn(self.get_id("__struct_from_ptr")?, &[Type::I64, Type::I64])?;
23 self.call(ctx, f, vec![base, ty_ptr]).map(|(v, _)| v)
24 }
25
26 pub(crate) fn bool_value(&mut self, ctx: &mut BuildContext, vt: (Value, Type)) -> Result<Value> {
27 if vt.1.is_bool() {
28 Ok(vt.0)
29 } else if vt.1.is_any() {
30 self.call(ctx, self.get_method(&Type::Any, "to_bool")?, vec![vt.0]).map(|(v, _)| v)
31 } else if vt.1.is_int() || vt.1.is_uint() {
32 Ok(ctx.builder.ins().icmp_imm(IntCC::NotEqual, vt.0, 0))
33 } else if vt.1.is_f32() {
34 let zero = ctx.builder.ins().f32const(0.0);
35 Ok(ctx.builder.ins().fcmp(FloatCC::NotEqual, vt.0, zero))
36 } else if vt.1.is_f64() {
37 let zero = ctx.builder.ins().f64const(0.0);
38 Ok(ctx.builder.ins().fcmp(FloatCC::NotEqual, vt.0, zero))
39 } else {
40 Err(anyhow!("cannot convert {:?} to bool", vt.1))
41 }
42 }
43
44 pub fn convert(&mut self, ctx: &mut BuildContext, vt: (Value, Type), ty: Type) -> Result<Value> {
45 if vt.1 != ty {
46 if ty.is_any() {
47 if vt.1.is_struct() {
48 return self.struct_to_dynamic(ctx, vt.0, &vt.1);
49 } else if vt.1.is_bool() {
50 return self.call(ctx, self.get_method(&Type::Any, "from_bool")?, vec![vt.0]).map(|(v, _)| v);
51 } else if vt.1.is_uint() {
52 let v = if vt.1.width() < 8 { ctx.builder.ins().uextend(types::I64, vt.0) } else { vt.0 };
53 return self.call(ctx, self.get_method(&Type::Any, "from_i64")?, vec![v]).map(|(v, _)| v);
54 } else if vt.1.is_int() {
55 let v = if vt.1.width() < 8 { ctx.builder.ins().sextend(types::I64, vt.0) } else { vt.0 };
56 return self.call(ctx, self.get_method(&Type::Any, "from_i64")?, vec![v]).map(|(v, _)| v);
57 } else if vt.1.is_f32() {
58 let v = ctx.builder.ins().fpromote(types::F64, vt.0);
59 return self.call(ctx, self.get_method(&Type::Any, "from_f64")?, vec![v]).map(|(v, _)| v);
60 } else if vt.1.is_f64() {
61 return self.call(ctx, self.get_method(&Type::Any, "from_f64")?, vec![vt.0]).map(|(v, _)| v);
62 }
63 } else if vt.1.is_any() {
64 if ty.is_bool() {
65 return self.call(ctx, self.get_method(&Type::Any, "to_bool")?, vec![vt.0]).map(|(v, _)| v);
66 } else if ty.is_int() | ty.is_uint() {
67 let (v, _) = self.call(ctx, self.get_method(&Type::Any, "to_i64")?, vec![vt.0])?;
68 return Ok(match ty.width() {
69 1 => ctx.builder.ins().ireduce(types::I8, v),
70 2 => ctx.builder.ins().ireduce(types::I16, v),
71 4 => ctx.builder.ins().ireduce(types::I32, v),
72 _ => v,
73 });
74 } else if ty.is_f32() {
75 let v = self.call(ctx, self.get_method(&Type::Any, "to_f64")?, vec![vt.0]).map(|(v, _)| v)?;
76 return Ok(ctx.builder.ins().fdemote(types::F32, v));
77 } else if ty.is_f64() {
78 return self.call(ctx, self.get_method(&Type::Any, "to_f64")?, vec![vt.0]).map(|(v, _)| v);
79 } else {
80 return Ok(vt.0);
81 }
82 } else if ty.is_int() || ty.is_uint() {
83 if vt.1.is_f32() || vt.1.is_f64() {
84 let target = crate::get_type(&ty)?;
85 if ty.is_uint() {
86 return Ok(ctx.builder.ins().fcvt_to_uint(target, vt.0));
87 } else if ty.is_int() {
88 return Ok(ctx.builder.ins().fcvt_to_sint(target, vt.0));
89 }
90 }
91 if vt.1.is_int() || vt.1.is_uint() || vt.1.is_bool() {
92 let target = crate::get_type(&ty)?;
93 let actual = ctx.builder.func.dfg.value_type(vt.0);
94 if actual == target {
95 return Ok(vt.0);
96 }
97 if actual.is_int() && target.is_int() {
98 if actual.bits() > target.bits() {
99 return Ok(ctx.builder.ins().ireduce(target, vt.0));
100 }
101 if actual.bits() < target.bits() {
102 return if vt.1.is_int() { Ok(ctx.builder.ins().sextend(target, vt.0)) } else { Ok(ctx.builder.ins().uextend(target, vt.0)) };
103 }
104 }
105 }
106 } else if ty.is_f32() {
107 if vt.1.is_int() {
108 return Ok(ctx.builder.ins().fcvt_from_sint(types::F32, vt.0));
109 } else if vt.1.is_uint() {
110 return Ok(ctx.builder.ins().fcvt_from_uint(types::F32, vt.0));
111 } else if vt.1.is_f64() {
112 return Ok(ctx.builder.ins().fdemote(types::F32, vt.0));
113 }
114 } else if ty.is_f64() {
115 if vt.1.is_int() {
116 return Ok(ctx.builder.ins().fcvt_from_sint(types::F64, vt.0));
117 } else if vt.1.is_uint() {
118 return Ok(ctx.builder.ins().fcvt_from_uint(types::F64, vt.0));
119 } else if vt.1.is_f32() {
120 return Ok(ctx.builder.ins().fpromote(types::F64, vt.0));
121 }
122 } else if let Type::Symbol { id: _, params: _ } = ty {
123 log::info!("convert {:?} -> {:?}", vt, ty);
124 return Ok(vt.0); }
126 if vt.1.is_bool() {
127 let v = ctx.builder.ins().sextend(types::I64, vt.0);
128 return self.call(ctx, self.get_method(&Type::Any, "from_i64")?, vec![v]).map(|(v, _)| v);
129 }
130 log::error!("未实现 {:?} {:?}", vt, ty); Ok(vt.0)
132 } else {
133 Ok(vt.0)
134 }
135 }
136
137 pub(crate) fn binary(&mut self, ctx: &mut BuildContext, left: (Value, Type), op: BinaryOp, right: &Expr) -> Result<(Value, Type)> {
138 if matches!(op, BinaryOp::And | BinaryOp::Or) {
140 return self.short_circuit_logic(ctx, left, op, right);
141 }
142 let right = if right.is_value() {
143 let right = right.clone().value()?;
144 if right.is_f32() {
145 (ctx.builder.ins().f32const(right.as_float().unwrap() as f32), Type::F32)
146 } else if right.is_f64() {
147 (ctx.builder.ins().f64const(right.as_float().unwrap() as f64), Type::F64)
148 } else if left.1.is_any() {
149 if right.is_int() {
150 (ctx.builder.ins().iconst(types::I64, right.as_int().unwrap()), Type::I64)
151 } else if right.is_null() {
152 self.call(ctx, self.get_method(&Type::Any, "null")?, vec![])?
153 } else {
154 ctx.get_const(&right)?
155 }
156 } else {
157 return self.binary_imm(ctx, left, op, right);
158 }
159 } else {
160 self.eval(ctx, right)?.get(ctx).ok_or_else(|| anyhow!("没有返回值: {:?}", right))?
161 };
162 let ty = if op.is_add() && (left.1.is_any() || right.1.is_any()) { Type::Any } else { left.1.clone() + right.1.clone() }; let left = self.convert(ctx, left, ty.clone())?;
164 let right = self.convert(ctx, right, ty.clone())?;
165 if ty.is_any() {
166 if op.is_logic() {
167 let op = ctx.builder.ins().iconst(types::I32, i32::from(op) as i64);
168 return self.call(ctx, self.get_method(&Type::Any, "logic")?, vec![left, op, right]);
169 } else {
170 let op = ctx.builder.ins().iconst(types::I32, i32::from(op) as i64);
171 return self.call(ctx, self.get_method(&Type::Any, "binary")?, vec![left, op, right]);
172 }
173 }
174 match op {
175 BinaryOp::Add | BinaryOp::AddAssign => {
176 if ty.is_int() || ty.is_uint() {
177 return Ok((ctx.builder.ins().iadd(left, right), ty));
178 } else if ty.is_float() {
179 return Ok((ctx.builder.ins().fadd(left, right), ty));
180 }
181 }
182 BinaryOp::Sub | BinaryOp::SubAssign => {
183 if ty.is_int() || ty.is_uint() {
184 return Ok((ctx.builder.ins().isub(left, right), ty));
185 } else if ty.is_float() {
186 return Ok((ctx.builder.ins().fsub(left, right), ty));
187 }
188 }
189 BinaryOp::Mul | BinaryOp::MulAssign => {
190 if ty.is_int() || ty.is_uint() {
191 return Ok((ctx.builder.ins().imul(left, right), ty));
192 } else if ty.is_float() {
193 return Ok((ctx.builder.ins().fmul(left, right), ty));
194 }
195 }
196 BinaryOp::Div | BinaryOp::DivAssign => {
197 if ty.is_int() {
198 return Ok((ctx.builder.ins().sdiv(left, right), ty));
199 } else if ty.is_uint() {
200 return Ok((ctx.builder.ins().udiv(left, right), ty));
201 } else if ty.is_float() {
202 return Ok((ctx.builder.ins().fdiv(left, right), ty));
203 }
204 }
205 BinaryOp::Mod | BinaryOp::ModAssign => {
206 if ty.is_int() {
207 return Ok((ctx.builder.ins().srem(left, right), ty));
208 } else if ty.is_uint() {
209 return Ok((ctx.builder.ins().urem(left, right), ty));
210 }
211 }
212 BinaryOp::Shl | BinaryOp::ShlAssign => {
213 if ty.is_int() || ty.is_uint() {
214 return Ok((ctx.builder.ins().ishl(left, right), ty));
215 }
216 }
217 BinaryOp::Shr | BinaryOp::ShrAssign => {
218 if ty.is_int() {
219 return Ok((ctx.builder.ins().sshr(left, right), ty));
220 } else if ty.is_uint() {
221 return Ok((ctx.builder.ins().ushr(left, right), ty));
222 }
223 }
224 BinaryOp::BitAnd | BinaryOp::BitAndAssign => {
225 return Ok((ctx.builder.ins().band(left, right), ty));
226 }
227 BinaryOp::BitOr | BinaryOp::BitOrAssign => {
228 return Ok((ctx.builder.ins().bor(left, right), ty));
229 }
230 BinaryOp::BitXor | BinaryOp::BitXorAssign => {
231 return Ok((ctx.builder.ins().bxor(left, right), ty));
232 }
233 BinaryOp::Eq => {
234 if ty.is_int() | ty.is_uint() || ty.is_bool() {
235 return Ok((ctx.builder.ins().icmp(IntCC::Equal, left, right), Type::Bool));
236 } else if ty.is_float() {
237 return Ok((ctx.builder.ins().fcmp(FloatCC::Equal, left, right), Type::Bool));
238 }
239 }
240 BinaryOp::Ne => {
241 if ty.is_int() | ty.is_uint() || ty.is_bool() {
242 return Ok((ctx.builder.ins().icmp(IntCC::NotEqual, left, right), Type::Bool));
243 } else if ty.is_float() {
244 return Ok((ctx.builder.ins().fcmp(FloatCC::NotEqual, left, right), Type::Bool));
245 }
246 }
247 BinaryOp::Lt => {
248 if ty.is_int() {
249 return Ok((ctx.builder.ins().icmp(IntCC::SignedLessThan, left, right), Type::Bool));
250 } else if ty.is_uint() {
251 return Ok((ctx.builder.ins().icmp(IntCC::UnsignedLessThan, left, right), Type::Bool));
252 } else if ty.is_float() {
253 return Ok((ctx.builder.ins().fcmp(FloatCC::LessThan, left, right), Type::Bool));
254 }
255 }
256 BinaryOp::Le => {
257 if ty.is_int() {
258 return Ok((ctx.builder.ins().icmp(IntCC::SignedLessThanOrEqual, left, right), Type::Bool));
259 } else if ty.is_uint() {
260 return Ok((ctx.builder.ins().icmp(IntCC::UnsignedLessThanOrEqual, left, right), Type::Bool));
261 } else if ty.is_float() {
262 return Ok((ctx.builder.ins().fcmp(FloatCC::LessThanOrEqual, left, right), Type::Bool));
263 }
264 }
265 BinaryOp::Gt => {
266 if ty.is_int() {
267 return Ok((ctx.builder.ins().icmp(IntCC::SignedGreaterThan, left, right), Type::Bool));
268 } else if ty.is_uint() {
269 return Ok((ctx.builder.ins().icmp(IntCC::UnsignedGreaterThan, left, right), Type::Bool));
270 } else if ty.is_float() {
271 return Ok((ctx.builder.ins().fcmp(FloatCC::GreaterThan, left, right), Type::Bool));
272 }
273 }
274 BinaryOp::Ge => {
275 if ty.is_int() {
276 return Ok((ctx.builder.ins().icmp(IntCC::SignedGreaterThanOrEqual, left, right), Type::Bool));
277 } else if ty.is_uint() {
278 return Ok((ctx.builder.ins().icmp(IntCC::UnsignedGreaterThanOrEqual, left, right), Type::Bool));
279 } else if ty.is_float() {
280 return Ok((ctx.builder.ins().fcmp(FloatCC::GreaterThanOrEqual, left, right), Type::Bool));
281 }
282 }
283 _ => {}
284 }
285 panic!("未实现 {:?} {:?} {:?} {:?}", left, op, right, ty)
286 }
287
288 pub(crate) fn binary_imm<'a>(&mut self, ctx: &'a mut BuildContext, left: (Value, Type), op: BinaryOp, right: Dynamic) -> Result<(Value, Type)> {
289 let ty = left.1.clone() + right.get_type();
290 let left = self.convert(ctx, left, ty.clone())?;
291 match op {
292 BinaryOp::Add | BinaryOp::AddAssign => {
293 if ty.is_int() | ty.is_uint() {
294 return Ok((ctx.builder.ins().iadd_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
295 }
296 }
297 BinaryOp::Sub | BinaryOp::SubAssign => {
298 if ty.is_int() | ty.is_uint() {
299 return Ok((ctx.builder.ins().iadd_imm(left, -right.as_int().ok_or(anyhow!("非整数"))?), ty));
300 }
301 }
302 BinaryOp::Mul | BinaryOp::MulAssign => {
303 if ty.is_int() | ty.is_uint() {
304 return Ok((ctx.builder.ins().imul_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
305 }
306 }
307 BinaryOp::Div | BinaryOp::DivAssign => {
308 if ty.is_int() {
309 return Ok((ctx.builder.ins().sdiv_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
310 } else if ty.is_uint() {
311 return Ok((ctx.builder.ins().udiv_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
312 }
313 }
314 BinaryOp::Shl | BinaryOp::ShlAssign => {
315 if ty.is_int() || ty.is_uint() {
316 return Ok((ctx.builder.ins().ishl_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
317 }
318 }
319 BinaryOp::Shr | BinaryOp::ShrAssign => {
320 if ty.is_int() {
321 return Ok((ctx.builder.ins().sshr_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
322 } else if ty.is_uint() {
323 return Ok((ctx.builder.ins().ushr_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
324 }
325 }
326 BinaryOp::BitAnd | BinaryOp::BitAndAssign => {
327 return Ok((ctx.builder.ins().band_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
328 }
329 BinaryOp::BitOr | BinaryOp::BitOrAssign => {
330 return Ok((ctx.builder.ins().bor_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
331 }
332 BinaryOp::BitXor | BinaryOp::BitXorAssign => {
333 return Ok((ctx.builder.ins().bxor_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
334 }
335 BinaryOp::Eq => {
336 if ty.is_int() | ty.is_uint() {
337 return Ok((ctx.builder.ins().icmp_imm(IntCC::Equal, left, right.as_int().unwrap()), Type::Bool));
338 }
339 }
340 BinaryOp::Ne => {
341 if ty.is_int() | ty.is_uint() {
342 return Ok((ctx.builder.ins().icmp_imm(IntCC::NotEqual, left, right.as_int().unwrap()), Type::Bool));
343 }
344 }
345 BinaryOp::Le => {
346 if ty.is_int() {
347 return Ok((ctx.builder.ins().icmp_imm(IntCC::SignedLessThanOrEqual, left, right.as_int().unwrap()), Type::Bool));
348 } else if ty.is_uint() {
349 return Ok((ctx.builder.ins().icmp_imm(IntCC::UnsignedLessThanOrEqual, left, right.as_int().unwrap()), Type::Bool));
350 }
351 }
352 BinaryOp::Lt => {
353 if ty.is_int() {
354 return Ok((ctx.builder.ins().icmp_imm(IntCC::SignedLessThan, left, right.as_int().unwrap()), Type::Bool));
355 } else if ty.is_uint() {
356 return Ok((ctx.builder.ins().icmp_imm(IntCC::UnsignedLessThan, left, right.as_int().unwrap()), Type::Bool));
357 }
358 }
359 BinaryOp::Ge => {
360 if ty.is_int() {
361 return Ok((ctx.builder.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, left, right.as_int().unwrap()), Type::Bool));
362 } else if ty.is_uint() {
363 return Ok((ctx.builder.ins().icmp_imm(IntCC::UnsignedGreaterThanOrEqual, left, right.as_int().unwrap()), Type::Bool));
364 }
365 }
366 BinaryOp::Gt => {
367 if ty.is_int() {
368 return Ok((ctx.builder.ins().icmp_imm(IntCC::SignedGreaterThan, left, right.as_int().unwrap()), Type::Bool));
369 } else if ty.is_uint() {
370 return Ok((ctx.builder.ins().icmp_imm(IntCC::UnsignedGreaterThan, left, right.as_int().unwrap()), Type::Bool));
371 }
372 }
373 BinaryOp::Mod | BinaryOp::ModAssign => {
374 if ty.is_int() {
375 return Ok((ctx.builder.ins().srem_imm(left, right.as_int().unwrap()), ty));
376 } else if ty.is_uint() {
377 return Ok((ctx.builder.ins().urem_imm(left, right.as_int().unwrap()), ty));
378 }
379 }
380 exp => {
381 panic!("不支持的操作 {:?}", exp)
382 }
383 }
384 panic!("未实现 {:?} {:?} {:?}", ty, op, right.get_type())
385 }
386}