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