Skip to main content

vm/
binary.rs

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