Skip to main content

vm/
binary.rs

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