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