1use super::{JITRunTime, context::BuildContext};
2use cranelift::prelude::*;
3use dynamic::{Dynamic, Type};
4use parser::{BinaryOp, Expr};
5
6use anyhow::{Result, anyhow};
7
8impl JITRunTime {
9 fn strcat(&mut self, ctx: &mut BuildContext, left: Value, right: Value) -> Result<Value> {
10 let fn_id = self.strcat_fn.ok_or_else(|| anyhow!("VM strcat runtime is not registered"))?;
11 let fn_ref = self.get_fn_ref(ctx, fn_id);
12 let call_inst = ctx.builder.ins().call(fn_ref, &[left, right]);
13 Ok(ctx.builder.inst_results(call_inst)[0])
14 }
15
16 fn strcat_i64(&mut self, ctx: &mut BuildContext, left: Value, right: Value) -> Result<Value> {
17 let fn_id = self.strcat_i64_fn.ok_or_else(|| anyhow!("VM strcat i64 runtime is not registered"))?;
18 let fn_ref = self.get_fn_ref(ctx, fn_id);
19 let call_inst = ctx.builder.ins().call(fn_ref, &[left, right]);
20 Ok(ctx.builder.inst_results(call_inst)[0])
21 }
22
23 fn strcat_assign(&mut self, ctx: &mut BuildContext, left: Value, right: Value) -> Result<Value> {
24 let fn_id = self.strcat_assign_fn.ok_or_else(|| anyhow!("VM strcat assign runtime is not registered"))?;
25 let fn_ref = self.get_fn_ref(ctx, fn_id);
26 let call_inst = ctx.builder.ins().call(fn_ref, &[left, right]);
27 Ok(ctx.builder.inst_results(call_inst)[0])
28 }
29
30 fn any_to_string(&mut self, ctx: &mut BuildContext, vt: (Value, Type)) -> Result<Value> {
31 let value = self.convert(ctx, vt, Type::Any)?;
32 self.call(ctx, self.get_method(&Type::Any, "to_string")?, vec![value]).map(|(v, _)| v)
33 }
34
35 fn any_logic(&mut self, ctx: &mut BuildContext, left: Value, op: BinaryOp, right: Value) -> Result<(Value, Type)> {
36 let op = ctx.builder.ins().iconst(types::I32, i32::from(op) as i64);
37 self.call(ctx, self.get_method(&Type::Any, "logic")?, vec![left, op, right])
38 }
39
40 fn any_binary(&mut self, ctx: &mut BuildContext, left: Value, op: BinaryOp, right: Value) -> Result<(Value, Type)> {
41 let op = ctx.builder.ins().iconst(types::I32, i32::from(op) as i64);
42 self.call(ctx, self.get_method(&Type::Any, "binary")?, vec![left, op, right])
43 }
44
45 fn struct_to_dynamic(&mut self, ctx: &mut BuildContext, base: Value, ty: &Type) -> Result<Value> {
46 let Type::Struct { params: _, fields: _ } = ty else {
47 return Err(anyhow!("不是结构体 {:?}", ty));
48 };
49 let ty_ptr = Self::type_ptr_const(ctx, ty);
50 let fn_id = self.struct_from_ptr_fn.ok_or_else(|| anyhow!("VM struct Dynamic runtime is not registered"))?;
51 let fn_ref = self.get_fn_ref(ctx, fn_id);
52 let call_inst = ctx.builder.ins().call(fn_ref, &[base, ty_ptr]);
53 Ok(ctx.builder.inst_results(call_inst)[0])
54 }
55
56 fn array_to_dynamic(&mut self, ctx: &mut BuildContext, base: Value, ty: &Type) -> Result<Value> {
57 let Type::Array(_, _) = ty else {
58 return Err(anyhow!("不是数组 {:?}", ty));
59 };
60 let ty_ptr = Self::type_ptr_const(ctx, ty);
61 let fn_id = self.array_from_ptr_fn.ok_or_else(|| anyhow!("VM array Dynamic runtime is not registered"))?;
62 let fn_ref = self.get_fn_ref(ctx, fn_id);
63 let call_inst = ctx.builder.ins().call(fn_ref, &[base, ty_ptr]);
64 Ok(ctx.builder.inst_results(call_inst)[0])
65 }
66
67 pub(crate) fn bool_value(&mut self, ctx: &mut BuildContext, vt: (Value, Type)) -> Result<Value> {
68 if vt.1.is_bool() {
69 Ok(vt.0)
70 } else if vt.1.is_void() {
71 Ok(ctx.builder.ins().iconst(types::I8, 0))
72 } else if vt.1.is_any() {
73 self.call(ctx, self.get_method(&Type::Any, "to_bool")?, vec![vt.0]).map(|(v, _)| v)
74 } else if vt.1.is_int() || vt.1.is_uint() {
75 Ok(ctx.builder.ins().icmp_imm(IntCC::NotEqual, vt.0, 0))
76 } else if vt.1.is_f32() {
77 let zero = ctx.builder.ins().f32const(0.0);
78 Ok(ctx.builder.ins().fcmp(FloatCC::NotEqual, vt.0, zero))
79 } else if vt.1.is_f64() {
80 let zero = ctx.builder.ins().f64const(0.0);
81 Ok(ctx.builder.ins().fcmp(FloatCC::NotEqual, vt.0, zero))
82 } else {
83 Err(anyhow!("cannot convert {:?} to bool", vt.1))
84 }
85 }
86
87 pub fn convert(&mut self, ctx: &mut BuildContext, vt: (Value, Type), ty: Type) -> Result<Value> {
88 let vt = if matches!(vt.1, Type::Symbol { .. }) {
89 let resolved = self.compiler.symbols.get_type(&vt.1).unwrap_or_else(|_| vt.1.clone());
90 (vt.0, resolved)
91 } else {
92 vt
93 };
94 if vt.1 != ty {
95 if ty.is_any() {
96 if self.is_opaque_custom_ty(&vt.1) {
97 return Ok(vt.0);
98 } else if vt.1.is_array() {
99 return self.array_to_dynamic(ctx, vt.0, &vt.1);
100 } else if vt.1.is_struct() {
101 return self.struct_to_dynamic(ctx, vt.0, &vt.1);
102 } else if vt.1.is_bool() {
103 return self.call(ctx, self.get_method(&Type::Any, "from_bool")?, vec![vt.0]).map(|(v, _)| v);
104 } else if vt.1.is_uint() {
105 if vt.1.width() == 8 {
106 return self.call(ctx, self.get_method(&Type::Any, "from_u64")?, vec![vt.0]).map(|(v, _)| v);
108 }
109 let v = ctx.builder.ins().uextend(types::I64, vt.0);
110 return self.call(ctx, self.get_method(&Type::Any, "from_i64")?, vec![v]).map(|(v, _)| v);
111 } else if vt.1.is_int() {
112 let v = if vt.1.width() < 8 { ctx.builder.ins().sextend(types::I64, vt.0) } else { vt.0 };
113 return self.call(ctx, self.get_method(&Type::Any, "from_i64")?, vec![v]).map(|(v, _)| v);
114 } else if vt.1.is_f32() {
115 let v = ctx.builder.ins().fpromote(types::F64, vt.0);
116 return self.call(ctx, self.get_method(&Type::Any, "from_f64")?, vec![v]).map(|(v, _)| v);
117 } else if vt.1.is_f64() {
118 return self.call(ctx, self.get_method(&Type::Any, "from_f64")?, vec![vt.0]).map(|(v, _)| v);
119 } else if vt.1.is_str() {
120 return Ok(vt.0);
121 } else if matches!(vt.1, Type::Map | Type::List(_) | Type::Iter) {
122 return Ok(vt.0);
123 } else if matches!(vt.1, Type::Symbol { .. }) {
124 return Ok(vt.0);
125 }
126 } else if vt.1.is_any() {
127 if ty.is_bool() {
128 return self.call(ctx, self.get_method(&Type::Any, "to_bool")?, vec![vt.0]).map(|(v, _)| v);
129 } else if ty.is_array() {
130 return self.any_to_array(ctx, vt.0, &ty);
131 } else if ty.is_str() {
132 return self.call(ctx, self.get_method(&Type::Any, "to_string")?, vec![vt.0]).map(|(v, _)| v);
133 } else if ty.is_int() | ty.is_uint() {
134 let (v, _) = self.call(ctx, self.get_method(&Type::Any, "to_i64")?, vec![vt.0])?;
135 return Ok(match ty.width() {
136 1 => ctx.builder.ins().ireduce(types::I8, v),
137 2 => ctx.builder.ins().ireduce(types::I16, v),
138 4 => ctx.builder.ins().ireduce(types::I32, v),
139 _ => v,
140 });
141 } else if ty.is_f32() {
142 let v = self.call(ctx, self.get_method(&Type::Any, "to_f64")?, vec![vt.0]).map(|(v, _)| v)?;
143 return Ok(ctx.builder.ins().fdemote(types::F32, v));
144 } else if ty.is_f64() {
145 return self.call(ctx, self.get_method(&Type::Any, "to_f64")?, vec![vt.0]).map(|(v, _)| v);
146 } else {
147 return Ok(vt.0);
148 }
149 } else if ty.is_str() {
150 return self.any_to_string(ctx, vt);
151 } else if ty.is_int() || ty.is_uint() {
152 if vt.1.is_f32() || vt.1.is_f64() {
153 let target = crate::get_type(&ty)?;
154 if ty.is_uint() {
155 return Ok(ctx.builder.ins().fcvt_to_uint(target, vt.0));
156 } else if ty.is_int() {
157 return Ok(ctx.builder.ins().fcvt_to_sint(target, vt.0));
158 }
159 }
160 if vt.1.is_int() || vt.1.is_uint() || vt.1.is_bool() {
161 let target = crate::get_type(&ty)?;
162 let actual = ctx.builder.func.dfg.value_type(vt.0);
163 if actual == target {
164 return Ok(vt.0);
165 }
166 if actual.is_int() && target.is_int() {
167 if actual.bits() > target.bits() {
168 return Ok(ctx.builder.ins().ireduce(target, vt.0));
169 }
170 if actual.bits() < target.bits() {
171 return if vt.1.is_int() { Ok(ctx.builder.ins().sextend(target, vt.0)) } else { Ok(ctx.builder.ins().uextend(target, vt.0)) };
172 }
173 }
174 }
175 if vt.1.is_str() {
176 let (v, _) = self.call(ctx, self.get_method(&Type::Any, "to_i64")?, vec![vt.0])?;
177 return Ok(match ty.width() {
178 1 => ctx.builder.ins().ireduce(types::I8, v),
179 2 => ctx.builder.ins().ireduce(types::I16, v),
180 4 => ctx.builder.ins().ireduce(types::I32, v),
181 _ => v,
182 });
183 }
184 } else if ty.is_f32() {
185 if vt.1.is_int() {
186 return Ok(ctx.builder.ins().fcvt_from_sint(types::F32, vt.0));
187 } else if vt.1.is_uint() {
188 return Ok(ctx.builder.ins().fcvt_from_uint(types::F32, vt.0));
189 } else if vt.1.is_f64() {
190 return Ok(ctx.builder.ins().fdemote(types::F32, vt.0));
191 } else if vt.1.is_str() {
192 let v = self.call(ctx, self.get_method(&Type::Any, "to_f64")?, vec![vt.0]).map(|(v, _)| v)?;
193 return Ok(ctx.builder.ins().fdemote(types::F32, v));
194 }
195 } else if ty.is_f64() {
196 if vt.1.is_int() {
197 return Ok(ctx.builder.ins().fcvt_from_sint(types::F64, vt.0));
198 } else if vt.1.is_uint() {
199 return Ok(ctx.builder.ins().fcvt_from_uint(types::F64, vt.0));
200 } else if vt.1.is_f32() {
201 return Ok(ctx.builder.ins().fpromote(types::F64, vt.0));
202 } else if vt.1.is_str() {
203 return self.call(ctx, self.get_method(&Type::Any, "to_f64")?, vec![vt.0]).map(|(v, _)| v);
204 }
205 } else if let Type::Symbol { id: _, params: _ } = ty {
206 log::debug!("convert {:?} -> {:?}", vt, ty);
207 return Ok(vt.0); }
209 if vt.1.is_bool() {
210 let v = ctx.builder.ins().sextend(types::I64, vt.0);
211 return self.call(ctx, self.get_method(&Type::Any, "from_i64")?, vec![v]).map(|(v, _)| v);
212 }
213 log::error!("未实现 {:?} {:?}", vt, ty); Ok(vt.0)
215 } else {
216 Ok(vt.0)
217 }
218 }
219
220 pub(crate) fn binary_with_expected(&mut self, ctx: &mut BuildContext, left: (Value, Type), op: BinaryOp, right: &Expr, expected: Option<&Type>) -> Result<(Value, Type)> {
221 if matches!(op, BinaryOp::And | BinaryOp::Or) {
223 return self.short_circuit_logic(ctx, left, op, right);
224 }
225 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()) };
226 let right = if right.is_value() {
227 let right = right.clone().value()?;
228 if right.is_f32() {
229 (ctx.builder.ins().f32const(right.as_float().unwrap() as f32), Type::F32)
230 } else if right.is_f64() {
231 (ctx.builder.ins().f64const(right.as_float().unwrap() as f64), Type::F64)
232 } else if left.1.is_any() {
233 if right.is_int() {
234 (ctx.builder.ins().iconst(types::I64, right.as_int().unwrap()), Type::I64)
235 } else if right.is_null() {
236 self.call(ctx, self.get_method(&Type::Any, "null")?, vec![])?
237 } else {
238 ctx.get_const(&right)?
239 }
240 } else {
241 return self.binary_imm(ctx, left, op, right);
242 }
243 } else {
244 self.eval(ctx, right)?.get(ctx).ok_or_else(|| anyhow!("没有返回值: {:?}", right))?
245 };
246 let right_ty = right_ty_hint.as_ref().unwrap_or(&right.1);
247 let numeric_expected = expected.filter(|ty| (ty.is_int() || ty.is_uint() || ty.is_float()) && (left.1.is_any() || right.1.is_any()));
248 let ty = if (op.is_add() || op.is_logic()) && (left.1.is_str() || right.1.is_str() || right_ty.is_str()) {
249 Type::Str
250 } else if !op.is_logic()
251 && let Some(expected) = numeric_expected
252 {
253 expected.clone()
254 } else if (op.is_add() || op.is_logic()) && (left.1.is_any() || right.1.is_any()) {
255 Type::Any
256 } else {
257 left.1.clone() + right.1.clone()
258 }; if ty.is_str() && op.is_add() {
260 if op == BinaryOp::AddAssign {
261 let left = self.convert(ctx, left, Type::Any)?;
262 let right = self.convert(ctx, right, Type::Any)?;
263 return Ok((self.strcat_assign(ctx, left, right)?, ty));
264 }
265 if left.1.is_str() && right.1.is_str() {
266 return Ok((self.strcat(ctx, left.0, right.0)?, Type::Str));
267 }
268 if left.1.is_str() && right.1.is_int() {
269 let right = self.convert(ctx, right, Type::I64)?;
270 return Ok((self.strcat_i64(ctx, left.0, right)?, Type::Str));
271 }
272 let left = self.convert(ctx, left, Type::Any)?;
273 let right = self.convert(ctx, right, Type::Any)?;
274 let result = self.any_binary(ctx, left, op, right)?.0;
275 return Ok((result, ty));
276 }
277 let left = self.convert(ctx, left, ty.clone())?;
278 let right = self.convert(ctx, right, ty.clone())?;
279 if ty.is_any() {
280 if op.is_logic() {
281 return self.any_logic(ctx, left, op, right);
282 } else {
283 return self.any_binary(ctx, left, op, right);
284 }
285 }
286 if ty.is_str() && op.is_logic() {
287 return self.any_logic(ctx, left, op, right);
288 }
289 match op {
290 BinaryOp::Add | BinaryOp::AddAssign => {
291 if ty.is_int() || ty.is_uint() {
292 return Ok((ctx.builder.ins().iadd(left, right), ty));
293 } else if ty.is_float() {
294 return Ok((ctx.builder.ins().fadd(left, right), ty));
295 } else if ty.is_str() {
296 let result = self.any_binary(ctx, left, op, right)?.0;
297 return Ok((result, ty));
298 }
299 }
300 BinaryOp::Sub | BinaryOp::SubAssign => {
301 if ty.is_int() || ty.is_uint() {
302 return Ok((ctx.builder.ins().isub(left, right), ty));
303 } else if ty.is_float() {
304 return Ok((ctx.builder.ins().fsub(left, right), ty));
305 }
306 }
307 BinaryOp::Mul | BinaryOp::MulAssign => {
308 if ty.is_int() || ty.is_uint() {
309 return Ok((ctx.builder.ins().imul(left, right), ty));
310 } else if ty.is_float() {
311 return Ok((ctx.builder.ins().fmul(left, right), ty));
312 }
313 }
314 BinaryOp::Div | BinaryOp::DivAssign => {
315 if ty.is_int() {
316 return Ok((ctx.builder.ins().sdiv(left, right), ty));
317 } else if ty.is_uint() {
318 return Ok((ctx.builder.ins().udiv(left, right), ty));
319 } else if ty.is_float() {
320 return Ok((ctx.builder.ins().fdiv(left, right), ty));
321 }
322 }
323 BinaryOp::Mod | BinaryOp::ModAssign => {
324 if ty.is_int() {
325 return Ok((ctx.builder.ins().srem(left, right), ty));
326 } else if ty.is_uint() {
327 return Ok((ctx.builder.ins().urem(left, right), ty));
328 }
329 }
330 BinaryOp::Shl | BinaryOp::ShlAssign => {
331 if ty.is_int() || ty.is_uint() {
332 return Ok((ctx.builder.ins().ishl(left, right), ty));
333 }
334 }
335 BinaryOp::Shr | BinaryOp::ShrAssign => {
336 if ty.is_int() {
337 return Ok((ctx.builder.ins().sshr(left, right), ty));
338 } else if ty.is_uint() {
339 return Ok((ctx.builder.ins().ushr(left, right), ty));
340 }
341 }
342 BinaryOp::BitAnd | BinaryOp::BitAndAssign => {
343 return Ok((ctx.builder.ins().band(left, right), ty));
344 }
345 BinaryOp::BitOr | BinaryOp::BitOrAssign => {
346 return Ok((ctx.builder.ins().bor(left, right), ty));
347 }
348 BinaryOp::BitXor | BinaryOp::BitXorAssign => {
349 return Ok((ctx.builder.ins().bxor(left, right), ty));
350 }
351 BinaryOp::Eq => {
352 if ty.is_int() | ty.is_uint() || ty.is_bool() {
353 return Ok((ctx.builder.ins().icmp(IntCC::Equal, left, right), Type::Bool));
354 } else if ty.is_float() {
355 return Ok((ctx.builder.ins().fcmp(FloatCC::Equal, left, right), Type::Bool));
356 }
357 }
358 BinaryOp::Ne => {
359 if ty.is_int() | ty.is_uint() || ty.is_bool() {
360 return Ok((ctx.builder.ins().icmp(IntCC::NotEqual, left, right), Type::Bool));
361 } else if ty.is_float() {
362 return Ok((ctx.builder.ins().fcmp(FloatCC::NotEqual, left, right), Type::Bool));
363 }
364 }
365 BinaryOp::Lt => {
366 if ty.is_int() {
367 return Ok((ctx.builder.ins().icmp(IntCC::SignedLessThan, left, right), Type::Bool));
368 } else if ty.is_uint() {
369 return Ok((ctx.builder.ins().icmp(IntCC::UnsignedLessThan, left, right), Type::Bool));
370 } else if ty.is_float() {
371 return Ok((ctx.builder.ins().fcmp(FloatCC::LessThan, left, right), Type::Bool));
372 }
373 }
374 BinaryOp::Le => {
375 if ty.is_int() {
376 return Ok((ctx.builder.ins().icmp(IntCC::SignedLessThanOrEqual, left, right), Type::Bool));
377 } else if ty.is_uint() {
378 return Ok((ctx.builder.ins().icmp(IntCC::UnsignedLessThanOrEqual, left, right), Type::Bool));
379 } else if ty.is_float() {
380 return Ok((ctx.builder.ins().fcmp(FloatCC::LessThanOrEqual, left, right), Type::Bool));
381 }
382 }
383 BinaryOp::Gt => {
384 if ty.is_int() {
385 return Ok((ctx.builder.ins().icmp(IntCC::SignedGreaterThan, left, right), Type::Bool));
386 } else if ty.is_uint() {
387 return Ok((ctx.builder.ins().icmp(IntCC::UnsignedGreaterThan, left, right), Type::Bool));
388 } else if ty.is_float() {
389 return Ok((ctx.builder.ins().fcmp(FloatCC::GreaterThan, left, right), Type::Bool));
390 }
391 }
392 BinaryOp::Ge => {
393 if ty.is_int() {
394 return Ok((ctx.builder.ins().icmp(IntCC::SignedGreaterThanOrEqual, left, right), Type::Bool));
395 } else if ty.is_uint() {
396 return Ok((ctx.builder.ins().icmp(IntCC::UnsignedGreaterThanOrEqual, left, right), Type::Bool));
397 } else if ty.is_float() {
398 return Ok((ctx.builder.ins().fcmp(FloatCC::GreaterThanOrEqual, left, right), Type::Bool));
399 }
400 }
401 _ => {}
402 }
403 log::debug!("binary_with_expected fallback to dynamic: {:?} {:?} {:?}", ty, op, right);
405 let left_any = self.convert(ctx, (left, ty.clone()), Type::Any)?;
406 let right_any = self.convert(ctx, (right, ty.clone()), Type::Any)?;
407 if op.is_logic() {
408 self.any_logic(ctx, left_any, op, right_any)
409 } else {
410 self.any_binary(ctx, left_any, op, right_any)
411 }
412 }
413
414 pub(crate) fn binary_imm<'a>(&mut self, ctx: &'a mut BuildContext, left: (Value, Type), op: BinaryOp, right: Dynamic) -> Result<(Value, Type)> {
415 let ty = left.1.clone() + right.get_type();
416 let bool_imm = || right.as_bool().map(|value| if value { 1 } else { 0 });
417 if ty.is_str() && op.is_add() {
418 if op == BinaryOp::AddAssign {
419 let left = self.convert(ctx, left, Type::Any)?;
420 let right_vt = ctx.get_const(&right).or_else(|_| {
421 let idx = self.compiler.get_const(right.clone());
422 self.get_const_value(ctx, idx)
423 })?;
424 let right = self.convert(ctx, right_vt, Type::Any)?;
425 return Ok((self.strcat_assign(ctx, left, right)?, ty));
426 }
427 if left.1.is_str() && right.is_str() {
428 let right_vt = ctx.get_const(&right).or_else(|_| {
429 let idx = self.compiler.get_const(right.clone());
430 self.get_const_value(ctx, idx)
431 })?;
432 let right = self.convert(ctx, right_vt, Type::Str)?;
433 return Ok((self.strcat(ctx, left.0, right)?, Type::Str));
434 }
435 if left.1.is_str() && right.is_int() {
436 let right = ctx.get_const(&right)?;
437 let right = self.convert(ctx, right, Type::I64)?;
438 return Ok((self.strcat_i64(ctx, left.0, right)?, Type::Str));
439 }
440 let left = self.convert(ctx, left, Type::Any)?;
441 let right_vt = ctx.get_const(&right).or_else(|_| {
442 let idx = self.compiler.get_const(right.clone());
443 self.get_const_value(ctx, idx)
444 })?;
445 let right = self.convert(ctx, right_vt, Type::Any)?;
446 let result = self.any_binary(ctx, left, op, right)?.0;
447 return Ok((result, ty));
448 }
449 let left = self.convert(ctx, left, ty.clone())?;
450 if ty.is_str() && op.is_logic() {
451 let right_vt = ctx.get_const(&right).or_else(|_| {
452 let idx = self.compiler.get_const(right.clone());
453 self.get_const_value(ctx, idx)
454 })?;
455 let right = self.convert(ctx, right_vt, Type::Str)?;
456 return self.any_logic(ctx, left, op, right);
457 }
458 let right_float = if ty.is_float() {
459 let right = right.as_float().ok_or(anyhow!("非数字"))?;
460 Some(if ty.is_f32() { ctx.builder.ins().f32const(right as f32) } else { ctx.builder.ins().f64const(right) })
461 } else {
462 None
463 };
464 match op {
465 BinaryOp::Add | BinaryOp::AddAssign => {
466 if ty.is_str() {
467 let right_vt = ctx.get_const(&right).or_else(|_| {
468 let idx = self.compiler.get_const(right.clone());
469 self.get_const_value(ctx, idx)
470 })?;
471 let right = self.convert(ctx, right_vt, Type::Str)?;
472 let result = self.any_binary(ctx, left, op, right)?.0;
473 return Ok((result, ty));
474 }
475 if ty.is_int() | ty.is_uint() {
476 return Ok((ctx.builder.ins().iadd_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
477 } else if ty.is_float() {
478 return Ok((ctx.builder.ins().fadd(left, right_float.unwrap()), ty));
479 }
480 }
481 BinaryOp::Sub | BinaryOp::SubAssign => {
482 if ty.is_int() | ty.is_uint() {
483 return Ok((ctx.builder.ins().iadd_imm(left, -right.as_int().ok_or(anyhow!("非整数"))?), ty));
484 } else if ty.is_float() {
485 return Ok((ctx.builder.ins().fsub(left, right_float.unwrap()), ty));
486 }
487 }
488 BinaryOp::Mul | BinaryOp::MulAssign => {
489 if ty.is_int() | ty.is_uint() {
490 return Ok((ctx.builder.ins().imul_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
491 } else if ty.is_float() {
492 return Ok((ctx.builder.ins().fmul(left, right_float.unwrap()), ty));
493 }
494 }
495 BinaryOp::Div | BinaryOp::DivAssign => {
496 if ty.is_int() {
497 return Ok((ctx.builder.ins().sdiv_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
498 } else if ty.is_uint() {
499 return Ok((ctx.builder.ins().udiv_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
500 } else if ty.is_float() {
501 return Ok((ctx.builder.ins().fdiv(left, right_float.unwrap()), ty));
502 }
503 }
504 BinaryOp::Shl | BinaryOp::ShlAssign => {
505 if ty.is_int() || ty.is_uint() {
506 return Ok((ctx.builder.ins().ishl_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
507 }
508 }
509 BinaryOp::Shr | BinaryOp::ShrAssign => {
510 if ty.is_int() {
511 return Ok((ctx.builder.ins().sshr_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
512 } else if ty.is_uint() {
513 return Ok((ctx.builder.ins().ushr_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
514 }
515 }
516 BinaryOp::BitAnd | BinaryOp::BitAndAssign => {
517 return Ok((ctx.builder.ins().band_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
518 }
519 BinaryOp::BitOr | BinaryOp::BitOrAssign => {
520 return Ok((ctx.builder.ins().bor_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
521 }
522 BinaryOp::BitXor | BinaryOp::BitXorAssign => {
523 return Ok((ctx.builder.ins().bxor_imm(left, right.as_int().ok_or(anyhow!("非整数"))?), ty));
524 }
525 BinaryOp::Eq => {
526 if ty.is_int() | ty.is_uint() {
527 return Ok((ctx.builder.ins().icmp_imm(IntCC::Equal, left, right.as_int().unwrap()), Type::Bool));
528 } else if ty.is_bool() {
529 return Ok((ctx.builder.ins().icmp_imm(IntCC::Equal, left, bool_imm().unwrap()), Type::Bool));
530 } else if ty.is_float() {
531 return Ok((ctx.builder.ins().fcmp(FloatCC::Equal, left, right_float.unwrap()), Type::Bool));
532 }
533 }
534 BinaryOp::Ne => {
535 if ty.is_int() | ty.is_uint() {
536 return Ok((ctx.builder.ins().icmp_imm(IntCC::NotEqual, left, right.as_int().unwrap()), Type::Bool));
537 } else if ty.is_bool() {
538 return Ok((ctx.builder.ins().icmp_imm(IntCC::NotEqual, left, bool_imm().unwrap()), Type::Bool));
539 } else if ty.is_float() {
540 return Ok((ctx.builder.ins().fcmp(FloatCC::NotEqual, left, right_float.unwrap()), Type::Bool));
541 }
542 }
543 BinaryOp::Le => {
544 if ty.is_int() {
545 return Ok((ctx.builder.ins().icmp_imm(IntCC::SignedLessThanOrEqual, left, right.as_int().unwrap()), Type::Bool));
546 } else if ty.is_uint() {
547 return Ok((ctx.builder.ins().icmp_imm(IntCC::UnsignedLessThanOrEqual, left, right.as_int().unwrap()), Type::Bool));
548 } else if ty.is_float() {
549 return Ok((ctx.builder.ins().fcmp(FloatCC::LessThanOrEqual, left, right_float.unwrap()), Type::Bool));
550 }
551 }
552 BinaryOp::Lt => {
553 if ty.is_int() {
554 return Ok((ctx.builder.ins().icmp_imm(IntCC::SignedLessThan, left, right.as_int().unwrap()), Type::Bool));
555 } else if ty.is_uint() {
556 return Ok((ctx.builder.ins().icmp_imm(IntCC::UnsignedLessThan, left, right.as_int().unwrap()), Type::Bool));
557 } else if ty.is_float() {
558 return Ok((ctx.builder.ins().fcmp(FloatCC::LessThan, left, right_float.unwrap()), Type::Bool));
559 }
560 }
561 BinaryOp::Ge => {
562 if ty.is_int() {
563 return Ok((ctx.builder.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, left, right.as_int().unwrap()), Type::Bool));
564 } else if ty.is_uint() {
565 return Ok((ctx.builder.ins().icmp_imm(IntCC::UnsignedGreaterThanOrEqual, left, right.as_int().unwrap()), Type::Bool));
566 } else if ty.is_float() {
567 return Ok((ctx.builder.ins().fcmp(FloatCC::GreaterThanOrEqual, left, right_float.unwrap()), Type::Bool));
568 }
569 }
570 BinaryOp::Gt => {
571 if ty.is_int() {
572 return Ok((ctx.builder.ins().icmp_imm(IntCC::SignedGreaterThan, left, right.as_int().unwrap()), Type::Bool));
573 } else if ty.is_uint() {
574 return Ok((ctx.builder.ins().icmp_imm(IntCC::UnsignedGreaterThan, left, right.as_int().unwrap()), Type::Bool));
575 } else if ty.is_float() {
576 return Ok((ctx.builder.ins().fcmp(FloatCC::GreaterThan, left, right_float.unwrap()), Type::Bool));
577 }
578 }
579 BinaryOp::Mod | BinaryOp::ModAssign => {
580 if ty.is_int() {
581 return Ok((ctx.builder.ins().srem_imm(left, right.as_int().unwrap()), ty));
582 } else if ty.is_uint() {
583 return Ok((ctx.builder.ins().urem_imm(left, right.as_int().unwrap()), ty));
584 }
585 }
586 exp => {
587 log::debug!("binary_imm fallback to dynamic (unsupported op): {:?} {:?}", ty, exp);
589 let left_any = self.convert(ctx, (left, ty.clone()), Type::Any)?;
590 let right_vt = ctx.get_const(&right).or_else(|_| {
591 let idx = self.compiler.get_const(right.clone());
592 self.get_const_value(ctx, idx)
593 })?;
594 let right_any = self.convert(ctx, right_vt, Type::Any)?;
595 if exp.is_logic() {
596 return self.any_logic(ctx, left_any, exp, right_any);
597 }
598 return self.any_binary(ctx, left_any, exp, right_any);
599 }
600 }
601 log::debug!("binary_imm fallback to dynamic (unsupported type combo): {:?} {:?} {:?}", ty, op, right.get_type());
603 let left_any = self.convert(ctx, (left, ty.clone()), Type::Any)?;
604 let right_vt = ctx.get_const(&right).or_else(|_| {
605 let idx = self.compiler.get_const(right.clone());
606 self.get_const_value(ctx, idx)
607 })?;
608 let right_any = self.convert(ctx, right_vt, Type::Any)?;
609 if op.is_logic() {
610 self.any_logic(ctx, left_any, op, right_any)
611 } else {
612 self.any_binary(ctx, left_any, op, right_any)
613 }
614 }
615}