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