From 0e0871bc38959fa37ae67bde171004894ebbbba5 Mon Sep 17 00:00:00 2001 From: ychenfo Date: Fri, 8 Apr 2022 03:26:42 +0800 Subject: [PATCH] nac3core, artiq: to_basic_value_enum takes an argument indicating the expected type --- nac3artiq/src/codegen.rs | 16 +++--- nac3artiq/src/lib.rs | 10 ++-- nac3artiq/src/symbol_resolver.rs | 13 +---- nac3core/src/codegen/expr.rs | 79 ++++++++++++----------------- nac3core/src/codegen/irrt/mod.rs | 4 +- nac3core/src/codegen/stmt.rs | 84 ++++++++++++++++++++----------- nac3core/src/symbol_resolver.rs | 4 +- nac3core/src/toplevel/builtins.rs | 73 ++++++++++++++++----------- 8 files changed, 152 insertions(+), 131 deletions(-) diff --git a/nac3artiq/src/codegen.rs b/nac3artiq/src/codegen.rs index 51380fad..47b3bc1c 100644 --- a/nac3artiq/src/codegen.rs +++ b/nac3artiq/src/codegen.rs @@ -68,7 +68,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> { ) -> Result>, String> { let result = gen_call(self, ctx, obj, fun, params)?; if let Some(end) = self.end.clone() { - let old_end = self.gen_expr(ctx, &end)?.unwrap().to_basic_value_enum(ctx, self)?; + let old_end = self.gen_expr(ctx, &end)?.unwrap().to_basic_value_enum(ctx, self, end.custom.unwrap())?; let now = self.timeline.emit_now_mu(ctx); let smax = ctx.module.get_function("llvm.smax.i64").unwrap_or_else(|| { let i64 = ctx.ctx.i64_type(); @@ -88,7 +88,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> { ctx.builder.build_store(end_store, max); } if let Some(start) = self.start.clone() { - let start_val = self.gen_expr(ctx, &start)?.unwrap().to_basic_value_enum(ctx, self)?; + let start_val = self.gen_expr(ctx, &start)?.unwrap().to_basic_value_enum(ctx, self, start.custom.unwrap())?; self.timeline.emit_at_mu(ctx, start_val); } Ok(result) @@ -120,7 +120,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> { let old_start = self.start.take(); let old_end = self.end.take(); let now = if let Some(old_start) = &old_start { - self.gen_expr(ctx, old_start)?.unwrap().to_basic_value_enum(ctx, self)? + self.gen_expr(ctx, old_start)?.unwrap().to_basic_value_enum(ctx, self, old_start.custom.unwrap())? } else { self.timeline.emit_now_mu(ctx) }; @@ -174,8 +174,10 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> { }; // set duration let end_expr = self.end.take().unwrap(); - let end_val = - self.gen_expr(ctx, &end_expr)?.unwrap().to_basic_value_enum(ctx, self)?; + let end_val = self + .gen_expr(ctx, &end_expr)? + .unwrap() + .to_basic_value_enum(ctx, self, end_expr.custom.unwrap())?; // inside a sequential block if old_start.is_none() { @@ -186,7 +188,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> { let outer_end_val = self .gen_expr(ctx, old_end)? .unwrap() - .to_basic_value_enum(ctx, self)?; + .to_basic_value_enum(ctx, self, old_end.custom.unwrap())?; let smax = ctx.module.get_function("llvm.smax.i64").unwrap_or_else(|| { let i64 = ctx.ctx.i64_type(); @@ -371,7 +373,7 @@ fn rpc_codegen_callback_fn<'ctx, 'a>( .0 .args .iter() - .map(|arg| mapping.remove(&arg.name).unwrap().to_basic_value_enum(ctx, generator)) + .map(|arg| mapping.remove(&arg.name).unwrap().to_basic_value_enum(ctx, generator, arg.ty)) .collect::, _>>()?; if let Some(obj) = obj { if let ValueEnum::Static(obj) = obj.1 { diff --git a/nac3artiq/src/lib.rs b/nac3artiq/src/lib.rs index f12dc81c..bf5aad1d 100644 --- a/nac3artiq/src/lib.rs +++ b/nac3artiq/src/lib.rs @@ -328,8 +328,9 @@ impl Nac3 { ret: primitive.none, vars: HashMap::new(), }, - Arc::new(GenCall::new(Box::new(move |ctx, _, _, args, generator| { - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator).unwrap(); + Arc::new(GenCall::new(Box::new(move |ctx, _, fun, args, generator| { + let arg_ty = fun.0.args[0].ty; + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty).unwrap(); time_fns.emit_at_mu(ctx, arg); Ok(None) }))), @@ -345,8 +346,9 @@ impl Nac3 { ret: primitive.none, vars: HashMap::new(), }, - Arc::new(GenCall::new(Box::new(move |ctx, _, _, args, generator| { - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator).unwrap(); + Arc::new(GenCall::new(Box::new(move |ctx, _, fun, args, generator| { + let arg_ty = fun.0.args[0].ty; + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty).unwrap(); time_fns.emit_delay_mu(ctx, arg); Ok(None) }))), diff --git a/nac3artiq/src/symbol_resolver.rs b/nac3artiq/src/symbol_resolver.rs index b77957a6..284f06b3 100644 --- a/nac3artiq/src/symbol_resolver.rs +++ b/nac3artiq/src/symbol_resolver.rs @@ -131,6 +131,7 @@ impl StaticValue for PythonValue { &self, ctx: &mut CodeGenContext<'ctx, 'a>, generator: &mut dyn CodeGenerator, + _expected_ty: Type, ) -> Result, String> { if let Some(val) = self.resolver.id_to_primitive.read().get(&self.id) { return Ok(match val { @@ -544,7 +545,7 @@ impl InnerResolver { let len: usize = self.helper.len_fn.call1(py, (obj,))?.extract(py)?; if len == 0 { assert!(matches!( - &*unifier.get_ty(extracted_ty), + &*unifier.get_ty(*ty), TypeEnum::TVar { fields: None, range, .. } if range.is_empty() )); @@ -728,11 +729,9 @@ impl InnerResolver { Ok(Some(ctx.ctx.f64_type().const_float(val).into())) } else if ty_id == self.primitive_ids.list { let id_str = id.to_string(); - if let Some(global) = ctx.module.get_global(&id_str) { return Ok(Some(global.as_pointer_value().into())); } - let len: usize = self.helper.len_fn.call1(py, (obj,))?.extract(py)?; let ty = if len == 0 { ctx.primitives.int32 @@ -752,7 +751,6 @@ impl InnerResolver { let arr_ty = ctx .ctx .struct_type(&[ty.ptr_type(AddressSpace::Generic).into(), size_t.into()], false); - { if self.global_value_ids.read().contains_key(&id) { let global = ctx.module.get_global(&id_str).unwrap_or_else(|| { @@ -763,7 +761,6 @@ impl InnerResolver { self.global_value_ids.write().insert(id, obj.into()); } } - let arr: Result>, _> = (0..len) .map(|i| { obj.get_item(i).and_then(|elem| self.get_obj_value(py, elem, ctx, generator).map_err( @@ -771,7 +768,6 @@ impl InnerResolver { }) .collect(); let arr = arr?.unwrap(); - let arr_global = ctx.module.add_global( ty.array_type(len as u32), Some(AddressSpace::Generic), @@ -797,15 +793,12 @@ impl InnerResolver { } .into(); arr_global.set_initializer(&arr); - let val = arr_ty.const_named_struct(&[ arr_global.as_pointer_value().const_cast(ty.ptr_type(AddressSpace::Generic)).into(), size_t.const_int(len as u64, false).into(), ]); - let global = ctx.module.add_global(arr_ty, Some(AddressSpace::Generic), &id_str); global.set_initializer(&val); - Ok(Some(global.as_pointer_value().into())) } else if ty_id == self.primitive_ids.tuple { let elements: &PyTuple = obj.cast_as()?; @@ -850,11 +843,9 @@ impl InnerResolver { } } else { let id_str = id.to_string(); - if let Some(global) = ctx.module.get_global(&id_str) { return Ok(Some(global.as_pointer_value().into())); } - let top_level_defs = ctx.top_level.definitions.read(); let ty = self .get_obj_type(py, obj, &mut ctx.unifier, &top_level_defs, &ctx.primitives)? diff --git a/nac3core/src/codegen/expr.rs b/nac3core/src/codegen/expr.rs index 2865ba07..8c01e89d 100644 --- a/nac3core/src/codegen/expr.rs +++ b/nac3core/src/codegen/expr.rs @@ -643,14 +643,14 @@ pub fn gen_call<'ctx, 'a, G: CodeGenerator>( } // reorder the parameters let mut real_params = - fun.0.args.iter().map(|arg| mapping.remove(&arg.name).unwrap()).collect_vec(); + fun.0.args.iter().map(|arg| (mapping.remove(&arg.name).unwrap(), arg.ty)).collect_vec(); if let Some(obj) = &obj { - real_params.insert(0, obj.1.clone()); + real_params.insert(0, (obj.1.clone(), obj.0)); } let static_params = real_params .iter() .enumerate() - .filter_map(|(i, v)| { + .filter_map(|(i, (v, _))| { if let ValueEnum::Static(s) = v { Some((i, s.clone())) } else { @@ -682,7 +682,7 @@ pub fn gen_call<'ctx, 'a, G: CodeGenerator>( }; param_vals = real_params .into_iter() - .map(|p| p.to_basic_value_enum(ctx, generator)) + .map(|(p, t)| p.to_basic_value_enum(ctx, generator, t)) .collect::, String>>()?; instance_to_symbol.get(&key).cloned().ok_or_else(|| "".into()) } @@ -795,7 +795,7 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>( let cont_bb = ctx.ctx.append_basic_block(current, "cont"); let Comprehension { target, iter, ifs, .. } = &generators[0]; - let iter_val = generator.gen_expr(ctx, iter)?.unwrap().to_basic_value_enum(ctx, generator)?; + let iter_val = generator.gen_expr(ctx, iter)?.unwrap().to_basic_value_enum(ctx, generator, iter.custom.unwrap())?; let int32 = ctx.ctx.i32_type(); let size_t = generator.get_size_type(ctx.ctx); let zero_size_t = size_t.const_zero(); @@ -900,7 +900,7 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>( let result = generator .gen_expr(ctx, cond)? .unwrap() - .to_basic_value_enum(ctx, generator)? + .to_basic_value_enum(ctx, generator, cond.custom.unwrap())? .into_int_value(); let succ = ctx.ctx.append_basic_block(current, "then"); ctx.builder.build_conditional_branch(result, succ, test_bb); @@ -909,7 +909,7 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>( let elem = generator.gen_expr(ctx, elt)?.unwrap(); let i = ctx.builder.build_load(index, "i").into_int_value(); let elem_ptr = unsafe { ctx.builder.build_gep(list_content, &[i], "elem_ptr") }; - let val = elem.to_basic_value_enum(ctx, generator)?; + let val = elem.to_basic_value_enum(ctx, generator, elt.custom.unwrap())?; ctx.builder.build_store(elem_ptr, val); ctx.builder .build_store(index, ctx.builder.build_int_add(i, size_t.const_int(1, false), "inc")); @@ -934,8 +934,8 @@ pub fn gen_binop_expr<'ctx, 'a, G: CodeGenerator>( ) -> Result, String> { let ty1 = ctx.unifier.get_representative(left.custom.unwrap()); let ty2 = ctx.unifier.get_representative(right.custom.unwrap()); - let left = generator.gen_expr(ctx, left)?.unwrap().to_basic_value_enum(ctx, generator)?; - let right = generator.gen_expr(ctx, right)?.unwrap().to_basic_value_enum(ctx, generator)?; + let left = generator.gen_expr(ctx, left)?.unwrap().to_basic_value_enum(ctx, generator, left.custom.unwrap())?; + let right = generator.gen_expr(ctx, right)?.unwrap().to_basic_value_enum(ctx, generator, right.custom.unwrap())?; // we can directly compare the types, because we've got their representatives // which would be unchanged until further unification, which we would never do @@ -999,25 +999,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( Some((_, Some(static_value), _)) => ValueEnum::Static(static_value.clone()), None => { let resolver = ctx.resolver.clone(); - let val = resolver.get_symbol_value(*id, ctx).unwrap(); - // if is option, need to cast pointer to handle None - match &*ctx.unifier.get_ty(expr.custom.unwrap()) { - TypeEnum::TObj { obj_id, params, .. } - if *obj_id == ctx.primitives.option.get_obj_id(&ctx.unifier) => - { - if let BasicValueEnum::PointerValue(ptr) = val.to_basic_value_enum(ctx, generator)? { - let actual_ptr_ty = ctx.get_llvm_type( - generator, - *params.iter().next().unwrap().1, - ) - .ptr_type(AddressSpace::Generic); - ctx.builder.build_bitcast(ptr, actual_ptr_ty, "option_ptr_cast").into() - } else { - unreachable!("option obj must be ptr") - } - } - _ => val, - } + resolver.get_symbol_value(*id, ctx).unwrap() } }, ExprKind::List { elts, .. } => { @@ -1028,7 +1010,10 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( .map(|x| { generator .gen_expr(ctx, x) - .map_or_else(Err, |v| v.unwrap().to_basic_value_enum(ctx, generator)) + .map_or_else( + Err, + |v| v.unwrap().to_basic_value_enum(ctx, generator, x.custom.unwrap()) + ) }) .collect::, _>>()?; let ty = if elements.is_empty() { @@ -1061,7 +1046,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( .map(|x| { generator .gen_expr(ctx, x) - .map_or_else(Err, |v| v.unwrap().to_basic_value_enum(ctx, generator)) + .map_or_else(Err, |v| v.unwrap().to_basic_value_enum(ctx, generator, x.custom.unwrap())) }) .collect::, _>>()?; let element_ty = element_val.iter().map(BasicValueEnum::get_type).collect_vec(); @@ -1083,7 +1068,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( // note that we would handle class methods directly in calls match generator.gen_expr(ctx, value)?.unwrap() { ValueEnum::Static(v) => v.get_field(*attr, ctx).map_or_else(|| { - let v = v.to_basic_value_enum(ctx, generator)?; + let v = v.to_basic_value_enum(ctx, generator, value.custom.unwrap())?; let index = ctx.get_attr_index(value.custom.unwrap(), *attr); Ok(ValueEnum::Dynamic(ctx.build_gep_and_load( v.into_pointer_value(), @@ -1104,7 +1089,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( let left = generator .gen_expr(ctx, &values[0])? .unwrap() - .to_basic_value_enum(ctx, generator)? + .to_basic_value_enum(ctx, generator, values[0].custom.unwrap())? .into_int_value(); let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap(); let a_bb = ctx.ctx.append_basic_block(current, "a"); @@ -1120,7 +1105,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( let b = generator .gen_expr(ctx, &values[1])? .unwrap() - .to_basic_value_enum(ctx, generator)? + .to_basic_value_enum(ctx, generator, values[1].custom.unwrap())? .into_int_value(); ctx.builder.build_unconditional_branch(cont_bb); (a, b) @@ -1130,7 +1115,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( let a = generator .gen_expr(ctx, &values[1])? .unwrap() - .to_basic_value_enum(ctx, generator)? + .to_basic_value_enum(ctx, generator, values[1].custom.unwrap())? .into_int_value(); ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.position_at_end(b_bb); @@ -1148,7 +1133,9 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( ExprKind::UnaryOp { op, operand } => { let ty = ctx.unifier.get_representative(operand.custom.unwrap()); let val = - generator.gen_expr(ctx, operand)?.unwrap().to_basic_value_enum(ctx, generator)?; + generator.gen_expr(ctx, operand)? + .unwrap() + .to_basic_value_enum(ctx, generator, operand.custom.unwrap())?; if ty == ctx.primitives.bool { let val = val.into_int_value(); match op { @@ -1208,11 +1195,11 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( generator .gen_expr(ctx, lhs)? .unwrap() - .to_basic_value_enum(ctx, generator)?, + .to_basic_value_enum(ctx, generator, lhs.custom.unwrap())?, generator .gen_expr(ctx, rhs)? .unwrap() - .to_basic_value_enum(ctx, generator)?, + .to_basic_value_enum(ctx, generator, rhs.custom.unwrap())?, ) { (lhs, rhs) } else { @@ -1236,11 +1223,11 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( generator .gen_expr(ctx, lhs)? .unwrap() - .to_basic_value_enum(ctx, generator)?, + .to_basic_value_enum(ctx, generator, lhs.custom.unwrap())?, generator .gen_expr(ctx, rhs)? .unwrap() - .to_basic_value_enum(ctx, generator)?, + .to_basic_value_enum(ctx, generator, rhs.custom.unwrap())?, ) { (lhs, rhs) } else { @@ -1268,7 +1255,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( let test = generator .gen_expr(ctx, test)? .unwrap() - .to_basic_value_enum(ctx, generator)? + .to_basic_value_enum(ctx, generator, test.custom.unwrap())? .into_int_value(); let body_ty = body.custom.unwrap(); let is_none = ctx.unifier.get_representative(body_ty) == ctx.primitives.none; @@ -1288,7 +1275,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( match result { None => None, Some(v) => { - let a = a.unwrap().to_basic_value_enum(ctx, generator)?; + let a = a.unwrap().to_basic_value_enum(ctx, generator, body.custom.unwrap())?; Some(ctx.builder.build_store(v, a)) } }; @@ -1298,7 +1285,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( match result { None => None, Some(v) => { - let b = b.unwrap().to_basic_value_enum(ctx, generator)?; + let b = b.unwrap().to_basic_value_enum(ctx, generator, orelse.custom.unwrap())?; Some(ctx.builder.build_store(v, b)) } }; @@ -1375,7 +1362,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( if attr == &"unwrap".into() && id == ctx.primitives.option.get_obj_id(&ctx.unifier) { - if let BasicValueEnum::PointerValue(ptr) = val.to_basic_value_enum(ctx, generator)? { + if let BasicValueEnum::PointerValue(ptr) = val.to_basic_value_enum(ctx, generator, value.custom.unwrap())? { let not_null = ctx.builder.build_is_not_null(ptr, "unwrap_not_null"); ctx.make_assert( generator, @@ -1407,7 +1394,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( let v = generator .gen_expr(ctx, value)? .unwrap() - .to_basic_value_enum(ctx, generator)? + .to_basic_value_enum(ctx, generator, value.custom.unwrap())? .into_pointer_value(); let ty = ctx.get_llvm_type(generator, *ty); let arr_ptr = ctx.build_gep_and_load(v, &[zero, zero]).into_pointer_value(); @@ -1454,7 +1441,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( let raw_index = generator .gen_expr(ctx, slice)? .unwrap() - .to_basic_value_enum(ctx, generator)? + .to_basic_value_enum(ctx, generator, slice.custom.unwrap())? .into_int_value(); let raw_index = ctx.builder.build_int_s_extend( raw_index, @@ -1495,7 +1482,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( let v = generator .gen_expr(ctx, value)? .unwrap() - .to_basic_value_enum(ctx, generator)? + .to_basic_value_enum(ctx, generator, value.custom.unwrap())? .into_struct_value(); let index: u32 = if let ExprKind::Constant { value: ast::Constant::Int(v), .. } = &slice.node { diff --git a/nac3core/src/codegen/irrt/mod.rs b/nac3core/src/codegen/irrt/mod.rs index 923ae9c6..95f6e52f 100644 --- a/nac3core/src/codegen/irrt/mod.rs +++ b/nac3core/src/codegen/irrt/mod.rs @@ -183,7 +183,7 @@ pub fn handle_slice_indices<'a, 'ctx, G: CodeGenerator>( let step = generator .gen_expr(ctx, step)? .unwrap() - .to_basic_value_enum(ctx, generator)? + .to_basic_value_enum(ctx, generator, ctx.primitives.int32)? .into_int_value(); // assert step != 0, throw exception if not let not_zero = ctx.builder.build_int_compare( @@ -261,7 +261,7 @@ pub fn handle_slice_index_bound<'a, 'ctx, G: CodeGenerator>( ctx.module.add_function(SYMBOL, fn_t, None) }); - let i = generator.gen_expr(ctx, i)?.unwrap().to_basic_value_enum(ctx, generator)?; + let i = generator.gen_expr(ctx, i)?.unwrap().to_basic_value_enum(ctx, generator, i.custom.unwrap())?; Ok(ctx .builder .build_call(func, &[i.into(), length.into()], "bounded_ind") diff --git a/nac3core/src/codegen/stmt.rs b/nac3core/src/codegen/stmt.rs index 6699201f..9209440d 100644 --- a/nac3core/src/codegen/stmt.rs +++ b/nac3core/src/codegen/stmt.rs @@ -54,7 +54,11 @@ pub fn gen_store_target<'ctx, 'a, G: CodeGenerator>( } ExprKind::Attribute { value, attr, .. } => { let index = ctx.get_attr_index(value.custom.unwrap(), *attr); - let val = generator.gen_expr(ctx, value)?.unwrap().to_basic_value_enum(ctx, generator)?; + let val = generator.gen_expr(ctx, value)?.unwrap().to_basic_value_enum( + ctx, + generator, + value.custom.unwrap(), + )?; let ptr = if let BasicValueEnum::PointerValue(v) = val { v } else { @@ -81,7 +85,7 @@ pub fn gen_store_target<'ctx, 'a, G: CodeGenerator>( let v = generator .gen_expr(ctx, value)? .unwrap() - .to_basic_value_enum(ctx, generator)? + .to_basic_value_enum(ctx, generator, value.custom.unwrap())? .into_pointer_value(); let len = ctx .build_gep_and_load(v, &[zero, i32_type.const_int(1, false)]) @@ -89,7 +93,7 @@ pub fn gen_store_target<'ctx, 'a, G: CodeGenerator>( let raw_index = generator .gen_expr(ctx, slice)? .unwrap() - .to_basic_value_enum(ctx, generator)? + .to_basic_value_enum(ctx, generator, slice.custom.unwrap())? .into_int_value(); let raw_index = ctx.builder.build_int_s_extend( raw_index, @@ -143,7 +147,9 @@ pub fn gen_assign<'ctx, 'a, G: CodeGenerator>( ) -> Result<(), String> { match &target.node { ExprKind::Tuple { elts, .. } => { - if let BasicValueEnum::StructValue(v) = value.to_basic_value_enum(ctx, generator)? { + if let BasicValueEnum::StructValue(v) = + value.to_basic_value_enum(ctx, generator, target.custom.unwrap())? + { for (i, elt) in elts.iter().enumerate() { let v = ctx .builder @@ -162,11 +168,13 @@ pub fn gen_assign<'ctx, 'a, G: CodeGenerator>( let ls = generator .gen_expr(ctx, ls)? .unwrap() - .to_basic_value_enum(ctx, generator)? + .to_basic_value_enum(ctx, generator, ls.custom.unwrap())? .into_pointer_value(); let (start, end, step) = handle_slice_indices(lower, upper, step, ctx, generator, ls)?; - let value = value.to_basic_value_enum(ctx, generator)?.into_pointer_value(); + let value = value + .to_basic_value_enum(ctx, generator, target.custom.unwrap())? + .into_pointer_value(); let ty = if let TypeEnum::TList { ty } = &*ctx.unifier.get_ty(target.custom.unwrap()) { ctx.get_llvm_type(generator, *ty) @@ -174,15 +182,7 @@ pub fn gen_assign<'ctx, 'a, G: CodeGenerator>( unreachable!() }; let src_ind = handle_slice_indices(&None, &None, &None, ctx, generator, value)?; - list_slice_assignment( - generator, - ctx, - ty, - ls, - (start, end, step), - value, - src_ind, - ) + list_slice_assignment(generator, ctx, ty, ls, (start, end, step), value, src_ind) } else { unreachable!() } @@ -196,7 +196,7 @@ pub fn gen_assign<'ctx, 'a, G: CodeGenerator>( *static_value = Some(s.clone()); } } - let val = value.to_basic_value_enum(ctx, generator)?; + let val = value.to_basic_value_enum(ctx, generator, target.custom.unwrap())?; ctx.builder.build_store(ptr, val); } }; @@ -226,7 +226,11 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator>( // store loop bb information and restore it later let loop_bb = ctx.loop_target.replace((test_bb, cont_bb)); - let iter_val = generator.gen_expr(ctx, iter)?.unwrap().to_basic_value_enum(ctx, generator)?; + let iter_val = generator.gen_expr(ctx, iter)?.unwrap().to_basic_value_enum( + ctx, + generator, + iter.custom.unwrap(), + )?; if ctx.unifier.unioned(iter.custom.unwrap(), ctx.primitives.range) { // setup let iter_val = iter_val.into_pointer_value(); @@ -339,7 +343,11 @@ pub fn gen_while<'ctx, 'a, G: CodeGenerator>( let loop_bb = ctx.loop_target.replace((test_bb, cont_bb)); ctx.builder.build_unconditional_branch(test_bb); ctx.builder.position_at_end(test_bb); - let test = generator.gen_expr(ctx, test)?.unwrap().to_basic_value_enum(ctx, generator)?; + let test = generator.gen_expr(ctx, test)?.unwrap().to_basic_value_enum( + ctx, + generator, + test.custom.unwrap(), + )?; if let BasicValueEnum::IntValue(test) = test { ctx.builder.build_conditional_branch(test, body_bb, orelse_bb); } else { @@ -400,7 +408,11 @@ pub fn gen_if<'ctx, 'a, G: CodeGenerator>( }; ctx.builder.build_unconditional_branch(test_bb); ctx.builder.position_at_end(test_bb); - let test = generator.gen_expr(ctx, test)?.unwrap().to_basic_value_enum(ctx, generator)?; + let test = generator.gen_expr(ctx, test)?.unwrap().to_basic_value_enum( + ctx, + generator, + test.custom.unwrap(), + )?; if let BasicValueEnum::IntValue(test) = test { ctx.builder.build_conditional_branch(test, body_bb, orelse_bb); } else { @@ -497,7 +509,7 @@ pub fn exn_constructor<'ctx, 'a>( generator: &mut dyn CodeGenerator, ) -> Result>, String> { let (zelf_ty, zelf) = obj.unwrap(); - let zelf = zelf.to_basic_value_enum(ctx, generator)?.into_pointer_value(); + let zelf = zelf.to_basic_value_enum(ctx, generator, zelf_ty)?.into_pointer_value(); let int32 = ctx.ctx.i32_type(); let zero = int32.const_zero(); let zelf_id = { @@ -520,14 +532,14 @@ pub fn exn_constructor<'ctx, 'a>( let ptr = ctx.builder.build_in_bounds_gep(zelf, &[zero, int32.const_int(5, false)], "exn.msg"); let msg = if !args.is_empty() { - args.remove(0).1.to_basic_value_enum(ctx, generator)? + args.remove(0).1.to_basic_value_enum(ctx, generator, ctx.primitives.str)? } else { empty_string }; ctx.builder.build_store(ptr, msg); for i in [6, 7, 8].iter() { let value = if !args.is_empty() { - args.remove(0).1.to_basic_value_enum(ctx, generator)? + args.remove(0).1.to_basic_value_enum(ctx, generator, ctx.primitives.int64)? } else { ctx.ctx.i64_type().const_zero().into() }; @@ -949,7 +961,11 @@ pub fn gen_return<'ctx, 'a, G: CodeGenerator>( ) -> Result<(), String> { let value = value .as_ref() - .map(|v| generator.gen_expr(ctx, v).and_then(|v| v.unwrap().to_basic_value_enum(ctx, generator))) + .map(|v_expr| { + generator.gen_expr(ctx, v_expr).and_then(|v| { + v.unwrap().to_basic_value_enum(ctx, generator, v_expr.custom.unwrap()) + }) + }) .transpose()?; if let Some(return_target) = ctx.return_target { if let Some(value) = value { @@ -1010,20 +1026,28 @@ pub fn gen_stmt<'ctx, 'a, G: CodeGenerator>( StmtKind::Try { .. } => gen_try(generator, ctx, stmt)?, StmtKind::Raise { exc, .. } => { if let Some(exc) = exc { - let exc = - generator.gen_expr(ctx, exc)?.unwrap().to_basic_value_enum(ctx, generator)?; + let exc = generator.gen_expr(ctx, exc)?.unwrap().to_basic_value_enum( + ctx, + generator, + exc.custom.unwrap(), + )?; gen_raise(generator, ctx, Some(&exc), stmt.location); } else { gen_raise(generator, ctx, None, stmt.location); } } StmtKind::Assert { test, msg, .. } => { - let test = - generator.gen_expr(ctx, test)?.unwrap().to_basic_value_enum(ctx, generator)?; + let test = generator.gen_expr(ctx, test)?.unwrap().to_basic_value_enum( + ctx, + generator, + test.custom.unwrap(), + )?; let err_msg = match msg { - Some(msg) => { - generator.gen_expr(ctx, msg)?.unwrap().to_basic_value_enum(ctx, generator)? - } + Some(msg) => generator.gen_expr(ctx, msg)?.unwrap().to_basic_value_enum( + ctx, + generator, + msg.custom.unwrap(), + )?, None => ctx.gen_string(generator, ""), }; ctx.make_assert_impl( diff --git a/nac3core/src/symbol_resolver.rs b/nac3core/src/symbol_resolver.rs index 18d5f699..acdd0d90 100644 --- a/nac3core/src/symbol_resolver.rs +++ b/nac3core/src/symbol_resolver.rs @@ -71,6 +71,7 @@ pub trait StaticValue { &self, ctx: &mut CodeGenContext<'ctx, 'a>, generator: &mut dyn CodeGenerator, + expected_ty: Type, ) -> Result, String>; fn get_field<'ctx, 'a>( @@ -121,9 +122,10 @@ impl<'ctx> ValueEnum<'ctx> { self, ctx: &mut CodeGenContext<'ctx, 'a>, generator: &mut dyn CodeGenerator, + expected_ty: Type, ) -> Result, String> { match self { - ValueEnum::Static(v) => v.to_basic_value_enum(ctx, generator), + ValueEnum::Static(v) => v.to_basic_value_enum(ctx, generator, expected_ty), ValueEnum::Dynamic(v) => Ok(v), } } diff --git a/nac3core/src/toplevel/builtins.rs b/nac3core/src/toplevel/builtins.rs index 85c2532b..15fa2e07 100644 --- a/nac3core/src/toplevel/builtins.rs +++ b/nac3core/src/toplevel/builtins.rs @@ -224,7 +224,12 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { resolver: None, codegen_callback: Some(Arc::new(GenCall::new(Box::new( |ctx, obj, _, _, generator| { - let obj_val = obj.unwrap().1.clone().to_basic_value_enum(ctx, generator)?; + let expect_ty = obj.clone().unwrap().0; + let obj_val = obj.unwrap().1.clone().to_basic_value_enum( + ctx, + generator, + expect_ty, + )?; if let BasicValueEnum::PointerValue(ptr) = obj_val { Ok(Some(ctx.builder.build_is_not_null(ptr, "is_some").into())) } else { @@ -244,7 +249,12 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { resolver: None, codegen_callback: Some(Arc::new(GenCall::new(Box::new( |ctx, obj, _, _, generator| { - let obj_val = obj.unwrap().1.clone().to_basic_value_enum(ctx, generator)?; + let expect_ty = obj.clone().unwrap().0; + let obj_val = obj.unwrap().1.clone().to_basic_value_enum( + ctx, + generator, + expect_ty, + )?; if let BasicValueEnum::PointerValue(ptr) = obj_val { Ok(Some(ctx.builder.build_is_null(ptr, "is_none").into())) } else { @@ -290,7 +300,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { let float = ctx.primitives.float; let boolean = ctx.primitives.bool; let arg_ty = fun.0.args[0].ty; - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?; + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty)?; Ok(if ctx.unifier.unioned(arg_ty, boolean) { Some( ctx.builder @@ -355,7 +365,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { let float = ctx.primitives.float; let boolean = ctx.primitives.bool; let arg_ty = fun.0.args[0].ty; - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?; + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty)?; Ok( if ctx.unifier.unioned(arg_ty, boolean) || ctx.unifier.unioned(arg_ty, uint32) @@ -422,7 +432,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { let float = ctx.primitives.float; let boolean = ctx.primitives.bool; let arg_ty = fun.0.args[0].ty; - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?; + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty)?; let res = if ctx.unifier.unioned(arg_ty, boolean) { ctx.builder .build_int_z_extend(arg.into_int_value(), ctx.ctx.i64_type(), "zext") @@ -474,7 +484,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { let float = ctx.primitives.float; let boolean = ctx.primitives.bool; let arg_ty = fun.0.args[0].ty; - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?; + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty)?; let res = if ctx.unifier.unioned(arg_ty, int32) || ctx.unifier.unioned(arg_ty, uint32) || ctx.unifier.unioned(arg_ty, boolean) @@ -521,7 +531,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { let boolean = ctx.primitives.bool; let float = ctx.primitives.float; let arg_ty = fun.0.args[0].ty; - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?; + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty)?; Ok( if ctx.unifier.unioned(arg_ty, boolean) || ctx.unifier.unioned(arg_ty, int32) @@ -557,7 +567,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { resolver: None, codegen_callback: Some(Arc::new(GenCall::new(Box::new( |ctx, _, _, args, generator| { - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?; + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, ctx.primitives.float)?; let round_intrinsic = ctx.module.get_function("llvm.round.f64").unwrap_or_else(|| { let float = ctx.ctx.f64_type(); @@ -597,7 +607,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { resolver: None, codegen_callback: Some(Arc::new(GenCall::new(Box::new( |ctx, _, _, args, generator| { - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?; + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, ctx.primitives.float)?; let round_intrinsic = ctx.module.get_function("llvm.round.f64").unwrap_or_else(|| { let float = ctx.ctx.f64_type(); @@ -655,19 +665,20 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { let mut step = None; let int32 = ctx.ctx.i32_type(); let zero = int32.const_zero(); + let ty_i32 = ctx.primitives.int32; for (i, arg) in args.iter().enumerate() { if arg.0 == Some("start".into()) { - start = Some(arg.1.clone().to_basic_value_enum(ctx, generator)?); + start = Some(arg.1.clone().to_basic_value_enum(ctx, generator, ty_i32)?); } else if arg.0 == Some("stop".into()) { - stop = Some(arg.1.clone().to_basic_value_enum(ctx, generator)?); + stop = Some(arg.1.clone().to_basic_value_enum(ctx, generator, ty_i32)?); } else if arg.0 == Some("step".into()) { - step = Some(arg.1.clone().to_basic_value_enum(ctx, generator)?); + step = Some(arg.1.clone().to_basic_value_enum(ctx, generator, ty_i32)?); } else if i == 0 { - start = Some(arg.1.clone().to_basic_value_enum(ctx, generator)?); + start = Some(arg.1.clone().to_basic_value_enum(ctx, generator, ty_i32)?); } else if i == 1 { - stop = Some(arg.1.clone().to_basic_value_enum(ctx, generator)?); + stop = Some(arg.1.clone().to_basic_value_enum(ctx, generator, ty_i32)?); } else if i == 2 { - step = Some(arg.1.clone().to_basic_value_enum(ctx, generator)?); + step = Some(arg.1.clone().to_basic_value_enum(ctx, generator, ty_i32)?); } } let step = match step { @@ -734,8 +745,9 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { instance_to_stmt: Default::default(), resolver: None, codegen_callback: Some(Arc::new(GenCall::new(Box::new( - |ctx, _, _, args, generator| { - Ok(Some(args[0].1.clone().to_basic_value_enum(ctx, generator)?)) + |ctx, _, fun, args, generator| { + let arg_ty = fun.0.args[0].ty; + Ok(Some(args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty)?)) }, )))), loc: None, @@ -759,7 +771,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { let float = ctx.primitives.float; let boolean = ctx.primitives.bool; let arg_ty = fun.0.args[0].ty; - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?; + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty)?; Ok(if ctx.unifier.unioned(arg_ty, boolean) { Some(arg) } else if ctx.unifier.unioned(arg_ty, int32) { @@ -817,7 +829,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { resolver: None, codegen_callback: Some(Arc::new(GenCall::new(Box::new( |ctx, _, _, args, generator| { - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?; + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, ctx.primitives.float)?; let floor_intrinsic = ctx.module.get_function("llvm.floor.f64").unwrap_or_else(|| { let float = ctx.ctx.f64_type(); @@ -857,7 +869,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { resolver: None, codegen_callback: Some(Arc::new(GenCall::new(Box::new( |ctx, _, _, args, generator| { - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?; + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, ctx.primitives.float)?; let floor_intrinsic = ctx.module.get_function("llvm.floor.f64").unwrap_or_else(|| { let float = ctx.ctx.f64_type(); @@ -897,7 +909,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { resolver: None, codegen_callback: Some(Arc::new(GenCall::new(Box::new( |ctx, _, _, args, generator| { - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?; + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, ctx.primitives.float)?; let ceil_intrinsic = ctx.module.get_function("llvm.ceil.f64").unwrap_or_else(|| { let float = ctx.ctx.f64_type(); @@ -937,7 +949,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { resolver: None, codegen_callback: Some(Arc::new(GenCall::new(Box::new( |ctx, _, _, args, generator| { - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?; + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, ctx.primitives.float)?; let ceil_intrinsic = ctx.module.get_function("llvm.ceil.f64").unwrap_or_else(|| { let float = ctx.ctx.f64_type(); @@ -989,7 +1001,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { |ctx, _, fun, args, generator| { let range_ty = ctx.primitives.range; let arg_ty = fun.0.args[0].ty; - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?; + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty)?; Ok(if ctx.unifier.unioned(arg_ty, range_ty) { let arg = arg.into_pointer_value(); let (start, end, step) = destructure_range(ctx, arg); @@ -1043,8 +1055,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { let llvm_f64 = ctx.ctx.f64_type().as_basic_type_enum(); let m_ty = fun.0.args[0].ty; let n_ty = fun.0.args[1].ty; - let m_val = args[0].1.clone().to_basic_value_enum(ctx, generator)?; - let n_val = args[1].1.clone().to_basic_value_enum(ctx, generator)?; + let m_val = args[0].1.clone().to_basic_value_enum(ctx, generator, m_ty)?; + let n_val = args[1].1.clone().to_basic_value_enum(ctx, generator, n_ty)?; let mut is_type = |a: Type, b: Type| ctx.unifier.unioned(a, b); let (fun_name, arg_ty) = if is_type(m_ty, n_ty) && is_type(n_ty, boolean) { ("llvm.umin.i1", llvm_i1) @@ -1105,8 +1117,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { let llvm_f64 = ctx.ctx.f64_type().as_basic_type_enum(); let m_ty = fun.0.args[0].ty; let n_ty = fun.0.args[1].ty; - let m_val = args[0].1.clone().to_basic_value_enum(ctx, generator)?; - let n_val = args[1].1.clone().to_basic_value_enum(ctx, generator)?; + let m_val = args[0].1.clone().to_basic_value_enum(ctx, generator, m_ty)?; + let n_val = args[1].1.clone().to_basic_value_enum(ctx, generator, n_ty)?; let mut is_type = |a: Type, b: Type| ctx.unifier.unioned(a, b); let (fun_name, arg_ty) = if is_type(m_ty, n_ty) && is_type(n_ty, boolean) { ("llvm.umax.i1", llvm_i1) @@ -1163,7 +1175,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { let llvm_i64 = ctx.ctx.i64_type().as_basic_type_enum(); let llvm_f64 = ctx.ctx.f64_type().as_basic_type_enum(); let n_ty = fun.0.args[0].ty; - let n_val = args[0].1.clone().to_basic_value_enum(ctx, generator)?; + let n_val = args[0].1.clone().to_basic_value_enum(ctx, generator, n_ty)?; let mut is_type = |a: Type, b: Type| ctx.unifier.unioned(a, b); let mut is_float = false; let (fun_name, arg_ty) = @@ -1220,8 +1232,9 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { instance_to_stmt: Default::default(), resolver: None, codegen_callback: Some(Arc::new(GenCall::new(Box::new( - |ctx, _, _fun, args, generator| { - let arg_val = args[0].1.clone().to_basic_value_enum(ctx, generator)?; + |ctx, _, fun, args, generator| { + let arg_ty = fun.0.args[0].ty; + let arg_val = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty)?; let alloca = ctx.builder.build_alloca(arg_val.get_type(), "alloca_some"); ctx.builder.build_store(alloca, arg_val); Ok(Some(alloca.into()))