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