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