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); }
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); 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 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 }; 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}