From 0902d8adf4df565b25df9554a96577107910d21b Mon Sep 17 00:00:00 2001 From: pca006132 Date: Wed, 22 Dec 2021 16:49:03 +0800 Subject: [PATCH] nac3core: fix #84 --- nac3artiq/src/codegen.rs | 52 +++++--- nac3artiq/src/lib.rs | 7 +- nac3artiq/src/symbol_resolver.rs | 20 ++-- nac3core/src/codegen/expr.rs | 192 +++++++++++++++++------------- nac3core/src/codegen/generator.rs | 75 +++++++++--- nac3core/src/codegen/mod.rs | 17 +-- nac3core/src/codegen/stmt.rs | 79 +++++++----- nac3core/src/codegen/test.rs | 6 +- nac3core/src/symbol_resolver.rs | 8 +- nac3standalone/src/main.rs | 2 +- 10 files changed, 288 insertions(+), 170 deletions(-) diff --git a/nac3artiq/src/codegen.rs b/nac3artiq/src/codegen.rs index 62dae23d..0b2bc784 100644 --- a/nac3artiq/src/codegen.rs +++ b/nac3artiq/src/codegen.rs @@ -1,18 +1,19 @@ use nac3core::{ codegen::{expr::gen_call, stmt::gen_with, CodeGenContext, CodeGenerator}, + symbol_resolver::ValueEnum, toplevel::DefinitionId, typecheck::typedef::{FunSignature, Type}, - symbol_resolver::ValueEnum, }; use nac3parser::ast::{Expr, ExprKind, Located, Stmt, StmtKind, StrRef}; -use inkwell::values::BasicValueEnum; +use inkwell::{context::Context, types::IntType, values::BasicValueEnum}; use crate::timeline::TimeFns; pub struct ArtiqCodeGenerator<'a> { name: String, + size_t: u32, name_counter: u32, start: Option>>, end: Option>>, @@ -20,9 +21,11 @@ pub struct ArtiqCodeGenerator<'a> { } impl<'a> ArtiqCodeGenerator<'a> { - pub fn new(name: String, timeline: &'a (dyn TimeFns + Sync)) -> ArtiqCodeGenerator<'a> { + pub fn new(name: String, size_t: u32, timeline: &'a (dyn TimeFns + Sync)) -> ArtiqCodeGenerator<'a> { + assert!(size_t == 32 || size_t == 64); ArtiqCodeGenerator { name, + size_t, name_counter: 0, start: None, end: None, @@ -36,6 +39,14 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> { &self.name } + fn get_size_type<'ctx>(&self, ctx: &'ctx Context) -> IntType<'ctx> { + if self.size_t == 32 { + ctx.i32_type() + } else { + ctx.i64_type() + } + } + fn gen_call<'ctx, 'a>( &mut self, ctx: &mut CodeGenContext<'ctx, 'a>, @@ -45,7 +56,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> { ) -> Option> { 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); + let old_end = self.gen_expr(ctx, &end).unwrap().to_basic_value_enum(ctx, self); 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(); @@ -65,7 +76,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); + let start_val = self.gen_expr(ctx, &start).unwrap().to_basic_value_enum(ctx, self); self.timeline.emit_at_mu(ctx, start_val); } result @@ -97,7 +108,9 @@ 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.gen_expr(ctx, old_start) + .unwrap() + .to_basic_value_enum(ctx, self) } else { self.timeline.emit_now_mu(ctx) }; @@ -146,7 +159,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); + let end_val = self + .gen_expr(ctx, &end_expr) + .unwrap() + .to_basic_value_enum(ctx, self); // inside an sequential block if old_start.is_none() { @@ -154,15 +170,19 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> { } // inside a parallel block, should update the outer max now_mu if let Some(old_end) = &old_end { - let outer_end_val = self.gen_expr(ctx, old_end).unwrap().to_basic_value_enum(ctx); - let smax = ctx.module.get_function("llvm.smax.i64").unwrap_or_else(|| { - let i64 = ctx.ctx.i64_type(); - ctx.module.add_function( - "llvm.smax.i64", - i64.fn_type(&[i64.into(), i64.into()], false), - None, - ) - }); + let outer_end_val = self + .gen_expr(ctx, old_end) + .unwrap() + .to_basic_value_enum(ctx, self); + let smax = + ctx.module.get_function("llvm.smax.i64").unwrap_or_else(|| { + let i64 = ctx.ctx.i64_type(); + ctx.module.add_function( + "llvm.smax.i64", + i64.fn_type(&[i64.into(), i64.into()], false), + None, + ) + }); let max = ctx .builder .build_call(smax, &[end_val, outer_end_val], "smax") diff --git a/nac3artiq/src/lib.rs b/nac3artiq/src/lib.rs index 91d766b5..e206facb 100644 --- a/nac3artiq/src/lib.rs +++ b/nac3artiq/src/lib.rs @@ -558,10 +558,15 @@ impl Nac3 { let buffer = buffer.as_slice().into(); membuffer.lock().push(buffer); }))); + let size_t = if self.isa == Isa::Host { + 64 + } else { + 32 + }; let thread_names: Vec = (0..4).map(|_| "main".to_string()).collect(); let threads: Vec<_> = thread_names .iter() - .map(|s| Box::new(ArtiqCodeGenerator::new(s.to_string(), self.time_fns))) + .map(|s| Box::new(ArtiqCodeGenerator::new(s.to_string(), size_t, self.time_fns))) .collect(); py.allow_threads(|| { diff --git a/nac3artiq/src/symbol_resolver.rs b/nac3artiq/src/symbol_resolver.rs index e42db752..30386070 100644 --- a/nac3artiq/src/symbol_resolver.rs +++ b/nac3artiq/src/symbol_resolver.rs @@ -1,6 +1,6 @@ use inkwell::{types::BasicType, values::BasicValueEnum, AddressSpace}; use nac3core::{ - codegen::CodeGenContext, + codegen::{CodeGenContext, CodeGenerator}, location::Location, symbol_resolver::{StaticValue, SymbolResolver, SymbolValue, ValueEnum}, toplevel::{DefinitionId, TopLevelDef}, @@ -72,6 +72,7 @@ impl StaticValue for PythonValue { fn to_basic_value_enum<'ctx, 'a>( &self, ctx: &mut CodeGenContext<'ctx, 'a>, + generator: &mut dyn CodeGenerator, ) -> BasicValueEnum<'ctx> { if let Some(val) = self.resolver.id_to_primitive.read().get(&self.id) { return match val { @@ -89,7 +90,7 @@ impl StaticValue for PythonValue { Python::with_gil(|py| -> PyResult> { self.resolver - .get_obj_value(py, self.value.as_ref(py), ctx) + .get_obj_value(py, self.value.as_ref(py), ctx, generator) .map(Option::unwrap) }) .unwrap() @@ -540,6 +541,7 @@ impl InnerResolver { py: Python, obj: &PyAny, ctx: &mut CodeGenContext<'ctx, 'a>, + generator: &mut dyn CodeGenerator, ) -> PyResult>> { let ty_id: u64 = self .helper @@ -595,11 +597,9 @@ impl InnerResolver { .unwrap() }; let ty = ctx.get_llvm_type(ty); + let size_t = generator.get_size_type(ctx.ctx); let arr_ty = ctx.ctx.struct_type( - &[ - ctx.ctx.i32_type().into(), - ty.ptr_type(AddressSpace::Generic).into(), - ], + &[ty.ptr_type(AddressSpace::Generic).into(), size_t.into()], false, ); @@ -618,7 +618,7 @@ impl InnerResolver { let arr: Result>, _> = (0..len) .map(|i| { obj.get_item(i) - .and_then(|elem| self.get_obj_value(py, elem, ctx)) + .and_then(|elem| self.get_obj_value(py, elem, ctx, generator)) }) .collect(); let arr = arr?.unwrap(); @@ -665,11 +665,11 @@ impl InnerResolver { arr_global.set_initializer(&arr); let val = arr_ty.const_named_struct(&[ - ctx.ctx.i32_type().const_int(len as u64, false).into(), 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 @@ -716,7 +716,7 @@ impl InnerResolver { let val: Result>, _> = elements .iter() - .map(|elem| self.get_obj_value(py, elem, ctx)) + .map(|elem| self.get_obj_value(py, elem, ctx, generator)) .collect(); let val = val?.unwrap(); let val = ctx.ctx.const_struct(&val, false); @@ -763,7 +763,7 @@ impl InnerResolver { let values: Result>, _> = fields .iter() .map(|(name, _, _)| { - self.get_obj_value(py, obj.getattr(&name.to_string())?, ctx) + self.get_obj_value(py, obj.getattr(&name.to_string())?, ctx, generator) }) .collect(); let values = values?; diff --git a/nac3core/src/codegen/expr.rs b/nac3core/src/codegen/expr.rs index dd46673e..9f2cd93f 100644 --- a/nac3core/src/codegen/expr.rs +++ b/nac3core/src/codegen/expr.rs @@ -35,12 +35,9 @@ pub fn get_subst_key( }) .unwrap_or_default(); vars.extend(fun_vars.iter()); - let sorted = - vars.keys().filter(|id| filter.map(|v| v.contains(id)).unwrap_or(true)).sorted(); + let sorted = vars.keys().filter(|id| filter.map(|v| v.contains(id)).unwrap_or(true)).sorted(); sorted - .map(|id| { - unifier.stringify(vars[id], &mut |id| id.to_string(), &mut |id| id.to_string()) - }) + .map(|id| unifier.stringify(vars[id], &mut |id| id.to_string(), &mut |id| id.to_string())) .join(", ") } @@ -104,8 +101,19 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> { } } - pub fn get_llvm_type(&mut self, ty: Type) -> BasicTypeEnum<'ctx> { - get_llvm_type(self.ctx, &mut self.unifier, self.top_level, &mut self.type_cache, ty) + pub fn get_llvm_type( + &mut self, + generator: &mut dyn CodeGenerator, + ty: Type, + ) -> BasicTypeEnum<'ctx> { + get_llvm_type( + self.ctx, + generator, + &mut self.unifier, + self.top_level, + &mut self.type_cache, + ty, + ) } fn gen_const(&mut self, value: &Constant, ty: Type) -> BasicValueEnum<'ctx> { @@ -224,7 +232,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> { } } -pub fn gen_constructor<'ctx, 'a, G: CodeGenerator + ?Sized>( +pub fn gen_constructor<'ctx, 'a, G: CodeGenerator>( generator: &mut G, ctx: &mut CodeGenContext<'ctx, 'a>, signature: &FunSignature, @@ -240,7 +248,7 @@ pub fn gen_constructor<'ctx, 'a, G: CodeGenerator + ?Sized>( fun_id = Some(*id); } } - let ty = ctx.get_llvm_type(signature.ret).into_pointer_type(); + let ty = ctx.get_llvm_type(generator, signature.ret).into_pointer_type(); let zelf_ty: BasicTypeEnum = ty.get_element_type().try_into().unwrap(); let zelf: BasicValueEnum<'ctx> = ctx.builder.build_alloca(zelf_ty, "alloca").into(); // call `__init__` if there is one @@ -329,7 +337,7 @@ pub fn gen_func_instance<'ctx, 'a>( } } -pub fn gen_call<'ctx, 'a, G: CodeGenerator + ?Sized>( +pub fn gen_call<'ctx, 'a, G: CodeGenerator>( generator: &mut G, ctx: &mut CodeGenContext<'ctx, 'a>, obj: Option<(Type, ValueEnum<'ctx>)>, @@ -353,10 +361,10 @@ pub fn gen_call<'ctx, 'a, G: CodeGenerator + ?Sized>( } => { if let Some(callback) = codegen_callback { // TODO: Change signature - let obj = obj.map(|(t, v)| (t, v.to_basic_value_enum(ctx))); + let obj = obj.map(|(t, v)| (t, v.to_basic_value_enum(ctx, generator))); let params = params .into_iter() - .map(|(name, val)| (name, val.to_basic_value_enum(ctx))) + .map(|(name, val)| (name, val.to_basic_value_enum(ctx, generator))) .collect(); return callback.run(ctx, obj, fun, params); } @@ -410,8 +418,10 @@ pub fn gen_call<'ctx, 'a, G: CodeGenerator + ?Sized>( } else { format!("{}:{}", id, old_key) }; - param_vals = - real_params.into_iter().map(|p| p.to_basic_value_enum(ctx)).collect_vec(); + param_vals = real_params + .into_iter() + .map(|p| p.to_basic_value_enum(ctx, generator)) + .collect_vec(); instance_to_symbol.get(&key).cloned() } TopLevelDef::Class { .. } => { @@ -427,11 +437,11 @@ pub fn gen_call<'ctx, 'a, G: CodeGenerator + ?Sized>( if let Some(obj) = &obj { args.insert(0, FuncArg { name: "self".into(), ty: obj.0, default_value: None }); } - let params = args.iter().map(|arg| ctx.get_llvm_type(arg.ty)).collect_vec(); + let params = args.iter().map(|arg| ctx.get_llvm_type(generator, arg.ty)).collect_vec(); let fun_ty = if ctx.unifier.unioned(fun.0.ret, ctx.primitives.none) { ctx.ctx.void_type().fn_type(¶ms, false) } else { - ctx.get_llvm_type(fun.0.ret).fn_type(¶ms, false) + ctx.get_llvm_type(generator, fun.0.ret).fn_type(¶ms, false) }; ctx.module.add_function(&symbol, fun_ty, None) }); @@ -455,32 +465,36 @@ pub fn destructure_range<'ctx, 'a>( (start, end, step) } -pub fn allocate_list<'ctx, 'a>( +pub fn allocate_list<'ctx, 'a, G: CodeGenerator>( + generator: &mut G, ctx: &mut CodeGenContext<'ctx, 'a>, ty: BasicTypeEnum<'ctx>, length: IntValue<'ctx>, ) -> PointerValue<'ctx> { let arr_ptr = ctx.builder.build_array_alloca(ty, length, "tmparr"); - let arr_ty = ctx.ctx.struct_type( - &[ctx.ctx.i32_type().into(), ty.ptr_type(AddressSpace::Generic).into()], - false, - ); + let size_t = generator.get_size_type(ctx.ctx); + let i32_t = ctx.ctx.i32_type(); + let arr_ty = + ctx.ctx.struct_type(&[ty.ptr_type(AddressSpace::Generic).into(), size_t.into()], false); let zero = ctx.ctx.i32_type().const_zero(); let arr_str_ptr = ctx.builder.build_alloca(arr_ty, "tmparrstr"); unsafe { - let len_ptr = ctx.builder.build_in_bounds_gep(arr_str_ptr, &[zero, zero], "len_ptr"); - ctx.builder.build_store(len_ptr, length); - let ptr_to_arr = ctx.builder.build_in_bounds_gep( + let len_ptr = ctx.builder.build_in_bounds_gep( arr_str_ptr, - &[zero, ctx.ctx.i32_type().const_int(1, false)], - "ptr_to_arr", + &[zero, i32_t.const_int(1, false)], + "len_ptr", ); + let length = ctx.builder.build_int_z_extend(length, size_t, "zext"); + ctx.builder.build_store(len_ptr, length); + let ptr_to_arr = + ctx.builder.build_in_bounds_gep(arr_str_ptr, &[zero, i32_t.const_zero()], "ptr_to_arr"); ctx.builder.build_store(ptr_to_arr, arr_ptr); + println!("arr_str_ptr: {:?}", arr_str_ptr); arr_str_ptr } } -pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator + ?Sized>( +pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>( generator: &mut G, ctx: &mut CodeGenContext<'ctx, 'a>, expr: &Expr>, @@ -492,15 +506,16 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator + ?Sized>( 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); + let iter_val = generator.gen_expr(ctx, iter).unwrap().to_basic_value_enum(ctx, generator); let int32 = ctx.ctx.i32_type(); - let zero = int32.const_zero(); + let size_t = generator.get_size_type(ctx.ctx); + let zero = size_t.const_zero(); - let index = generator.gen_var_alloc(ctx, ctx.primitives.int32); + let index = generator.gen_var_alloc(ctx, size_t.into()); // counter = -1 - ctx.builder.build_store(index, ctx.ctx.i32_type().const_zero()); + ctx.builder.build_store(index, size_t.const_zero()); - let elem_ty = ctx.get_llvm_type(elt.custom.unwrap()); + let elem_ty = ctx.get_llvm_type(generator, elt.custom.unwrap()); let is_range = ctx.unifier.unioned(iter.custom.unwrap(), ctx.primitives.range); let list; let list_content; @@ -523,18 +538,16 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator + ?Sized>( ctx.builder.build_conditional_branch(is_valid, normal, empty); // normal: allocate a list ctx.builder.position_at_end(normal); - let list_a = allocate_list(ctx, elem_ty, length); + let list_a = allocate_list(generator, ctx, elem_ty, length); ctx.builder.build_unconditional_branch(list_init); ctx.builder.position_at_end(empty); - let list_b = allocate_list(ctx, elem_ty, zero); + let list_b = allocate_list(generator, ctx, elem_ty, zero); ctx.builder.build_unconditional_branch(list_init); ctx.builder.position_at_end(list_init); let phi = ctx.builder.build_phi(list_a.get_type(), "phi"); phi.add_incoming(&[(&list_a, normal), (&list_b, empty)]); list = phi.as_basic_value().into_pointer_value(); - list_content = ctx - .build_gep_and_load(list, &[zero, int32.const_int(1, false)]) - .into_pointer_value(); + list_content = ctx.build_gep_and_load(list, &[zero, zero]).into_pointer_value(); let i = generator.gen_store_target(ctx, target); ctx.builder.build_store(i, ctx.builder.build_int_sub(start, step, "start_init")); @@ -567,35 +580,36 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator + ?Sized>( ctx.builder.position_at_end(body_bb); } else { let length = ctx - .build_gep_and_load(iter_val.into_pointer_value(), &[zero, zero]) + .build_gep_and_load( + iter_val.into_pointer_value(), + &[zero, int32.const_int(1, false)], + ) .into_int_value(); - list = allocate_list(ctx, elem_ty, length); - list_content = ctx - .build_gep_and_load(list, &[zero, int32.const_int(1, false)]) - .into_pointer_value(); - let counter = generator.gen_var_alloc(ctx, ctx.primitives.int32); + list = allocate_list(generator, ctx, elem_ty, length); + list_content = ctx.build_gep_and_load(list, &[zero, zero]).into_pointer_value(); + let counter = generator.gen_var_alloc(ctx, size_t.into()); // counter = -1 ctx.builder.build_store(counter, ctx.ctx.i32_type().const_int(u64::max_value(), true)); ctx.builder.build_unconditional_branch(test_bb); ctx.builder.position_at_end(test_bb); let tmp = ctx.builder.build_load(counter, "i").into_int_value(); - let tmp = ctx.builder.build_int_add(tmp, int32.const_int(1, false), "inc"); + let tmp = ctx.builder.build_int_add(tmp, size_t.const_int(1, false), "inc"); ctx.builder.build_store(counter, tmp); let cmp = ctx.builder.build_int_compare(inkwell::IntPredicate::SLT, tmp, length, "cmp"); ctx.builder.build_conditional_branch(cmp, body_bb, cont_bb); ctx.builder.position_at_end(body_bb); let arr_ptr = ctx - .build_gep_and_load( - iter_val.into_pointer_value(), - &[zero, int32.const_int(1, false)], - ) + .build_gep_and_load(iter_val.into_pointer_value(), &[zero, zero]) .into_pointer_value(); let val = ctx.build_gep_and_load(arr_ptr, &[tmp]); generator.gen_assign(ctx, target, val.into()); } for cond in ifs.iter() { - let result = - generator.gen_expr(ctx, cond).unwrap().to_basic_value_enum(ctx).into_int_value(); + let result = generator + .gen_expr(ctx, cond) + .unwrap() + .to_basic_value_enum(ctx, generator) + .into_int_value(); let succ = ctx.ctx.append_basic_block(current, "then"); ctx.builder.build_conditional_branch(result, succ, test_bb); ctx.builder.position_at_end(succ); @@ -603,13 +617,14 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator + ?Sized>( 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); + let val = elem.to_basic_value_enum(ctx, generator); ctx.builder.build_store(elem_ptr, val); ctx.builder - .build_store(index, ctx.builder.build_int_add(i, int32.const_int(1, false), "inc")); + .build_store(index, ctx.builder.build_int_add(i, size_t.const_int(1, false), "inc")); ctx.builder.build_unconditional_branch(test_bb); ctx.builder.position_at_end(cont_bb); - let len_ptr = unsafe { ctx.builder.build_gep(list, &[zero, zero], "length") }; + let len_ptr = + unsafe { ctx.builder.build_gep(list, &[zero, int32.const_int(1, false)], "length") }; ctx.builder.build_store(len_ptr, ctx.builder.build_load(index, "index")); list.into() } else { @@ -617,7 +632,7 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator + ?Sized>( } } -pub fn gen_expr<'ctx, 'a, G: CodeGenerator + ?Sized>( +pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( generator: &mut G, ctx: &mut CodeGenContext<'ctx, 'a>, expr: &Expr>, @@ -642,14 +657,12 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator + ?Sized>( // we should use memcpy for that instead of generating thousands of stores let elements = elts .iter() - .map(|x| generator.gen_expr(ctx, x).unwrap().to_basic_value_enum(ctx)) + .map(|x| generator.gen_expr(ctx, x).unwrap().to_basic_value_enum(ctx, generator)) .collect_vec(); let ty = if elements.is_empty() { int32.into() } else { elements[0].get_type() }; - let length = int32.const_int(elements.len() as u64, false); - let arr_str_ptr = allocate_list(ctx, ty, length); - let arr_ptr = ctx - .build_gep_and_load(arr_str_ptr, &[zero, int32.const_int(1, false)]) - .into_pointer_value(); + let length = generator.get_size_type(ctx.ctx).const_int(elements.len() as u64, false); + let arr_str_ptr = allocate_list(generator, ctx, ty, length); + let arr_ptr = ctx.build_gep_and_load(arr_str_ptr, &[zero, zero]).into_pointer_value(); unsafe { for (i, v) in elements.iter().enumerate() { let elem_ptr = ctx.builder.build_gep( @@ -665,7 +678,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator + ?Sized>( ExprKind::Tuple { elts, .. } => { let element_val = elts .iter() - .map(|x| generator.gen_expr(ctx, x).unwrap().to_basic_value_enum(ctx)) + .map(|x| generator.gen_expr(ctx, x).unwrap().to_basic_value_enum(ctx, generator)) .collect_vec(); let element_ty = element_val.iter().map(BasicValueEnum::get_type).collect_vec(); let tuple_ty = ctx.ctx.struct_type(&element_ty, false); @@ -686,7 +699,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator + ?Sized>( // 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).unwrap_or_else(|| { - let v = v.to_basic_value_enum(ctx); + let v = v.to_basic_value_enum(ctx, generator); let index = ctx.get_attr_index(value.custom.unwrap(), *attr); ValueEnum::Dynamic(ctx.build_gep_and_load( v.into_pointer_value(), @@ -707,7 +720,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator + ?Sized>( let left = generator .gen_expr(ctx, &values[0]) .unwrap() - .to_basic_value_enum(ctx) + .to_basic_value_enum(ctx, generator) .into_int_value(); let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap(); let a_bb = ctx.ctx.append_basic_block(current, "a"); @@ -723,7 +736,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator + ?Sized>( let b = generator .gen_expr(ctx, &values[1]) .unwrap() - .to_basic_value_enum(ctx) + .to_basic_value_enum(ctx, generator) .into_int_value(); ctx.builder.build_unconditional_branch(cont_bb); (a, b) @@ -733,7 +746,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator + ?Sized>( let a = generator .gen_expr(ctx, &values[1]) .unwrap() - .to_basic_value_enum(ctx) + .to_basic_value_enum(ctx, generator) .into_int_value(); ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.position_at_end(b_bb); @@ -750,8 +763,8 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator + ?Sized>( ExprKind::BinOp { op, left, right } => { 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); - let right = generator.gen_expr(ctx, right).unwrap().to_basic_value_enum(ctx); + 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); // we can directly compare the types, because we've got their representatives // which would be unchanged until further unification, which we would never do @@ -767,7 +780,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator + ?Sized>( } 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); + let val = generator.gen_expr(ctx, operand).unwrap().to_basic_value_enum(ctx, generator); if ty == ctx.primitives.bool { let val = val.into_int_value(); match op { @@ -824,8 +837,14 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator + ?Sized>( BasicValueEnum::IntValue(lhs), BasicValueEnum::IntValue(rhs), ) = ( - generator.gen_expr(ctx, lhs).unwrap().to_basic_value_enum(ctx), - generator.gen_expr(ctx, rhs).unwrap().to_basic_value_enum(ctx), + generator + .gen_expr(ctx, lhs) + .unwrap() + .to_basic_value_enum(ctx, generator), + generator + .gen_expr(ctx, rhs) + .unwrap() + .to_basic_value_enum(ctx, generator), ) { (lhs, rhs) } else { @@ -846,8 +865,14 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator + ?Sized>( BasicValueEnum::FloatValue(lhs), BasicValueEnum::FloatValue(rhs), ) = ( - generator.gen_expr(ctx, lhs).unwrap().to_basic_value_enum(ctx), - generator.gen_expr(ctx, rhs).unwrap().to_basic_value_enum(ctx), + generator + .gen_expr(ctx, lhs) + .unwrap() + .to_basic_value_enum(ctx, generator), + generator + .gen_expr(ctx, rhs) + .unwrap() + .to_basic_value_enum(ctx, generator), ) { (lhs, rhs) } else { @@ -872,18 +897,21 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator + ?Sized>( .into() // as there should be at least 1 element, it should never be none } ExprKind::IfExp { test, body, orelse } => { - let test = - generator.gen_expr(ctx, test).unwrap().to_basic_value_enum(ctx).into_int_value(); + let test = generator + .gen_expr(ctx, test) + .unwrap() + .to_basic_value_enum(ctx, generator) + .into_int_value(); let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap(); let then_bb = ctx.ctx.append_basic_block(current, "then"); let else_bb = ctx.ctx.append_basic_block(current, "else"); let cont_bb = ctx.ctx.append_basic_block(current, "cont"); ctx.builder.build_conditional_branch(test, then_bb, else_bb); ctx.builder.position_at_end(then_bb); - let a = generator.gen_expr(ctx, body).unwrap().to_basic_value_enum(ctx); + let a = generator.gen_expr(ctx, body).unwrap().to_basic_value_enum(ctx, generator); ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.position_at_end(else_bb); - let b = generator.gen_expr(ctx, orelse).unwrap().to_basic_value_enum(ctx); + let b = generator.gen_expr(ctx, orelse).unwrap().to_basic_value_enum(ctx, generator); ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.position_at_end(cont_bb); let phi = ctx.builder.build_phi(a.get_type(), "ifexpr"); @@ -965,27 +993,27 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator + ?Sized>( let v = generator .gen_expr(ctx, value) .unwrap() - .to_basic_value_enum(ctx) + .to_basic_value_enum(ctx, generator) .into_pointer_value(); let index = generator .gen_expr(ctx, slice) .unwrap() - .to_basic_value_enum(ctx) + .to_basic_value_enum(ctx, generator) .into_int_value(); - let arr_ptr = - ctx.build_gep_and_load(v, &[int32.const_zero(), int32.const_int(1, false)]); + let zero = int32.const_zero(); + let arr_ptr = ctx.build_gep_and_load(v, &[zero, zero]); ctx.build_gep_and_load(arr_ptr.into_pointer_value(), &[index]) } } else { let v = generator .gen_expr(ctx, value) .unwrap() - .to_basic_value_enum(ctx) + .to_basic_value_enum(ctx, generator) .into_pointer_value(); let index = generator .gen_expr(ctx, slice) .unwrap() - .to_basic_value_enum(ctx) + .to_basic_value_enum(ctx, generator) .into_int_value(); ctx.build_gep_and_load(v, &[int32.const_zero(), index]) } diff --git a/nac3core/src/codegen/generator.rs b/nac3core/src/codegen/generator.rs index cf66967e..6d897b97 100644 --- a/nac3core/src/codegen/generator.rs +++ b/nac3core/src/codegen/generator.rs @@ -4,13 +4,19 @@ use crate::{ toplevel::{DefinitionId, TopLevelDef}, typecheck::typedef::{FunSignature, Type}, }; -use inkwell::values::{BasicValueEnum, PointerValue}; +use inkwell::{ + context::Context, + types::{BasicTypeEnum, IntType}, + values::{BasicValueEnum, PointerValue}, +}; use nac3parser::ast::{Expr, Stmt, StrRef}; pub trait CodeGenerator { /// Return the module name for the code generator. fn get_name(&self) -> &str; + fn get_size_type<'ctx>(&self, ctx: &'ctx Context) -> IntType<'ctx>; + /// Generate function call and returns the function return value. /// - obj: Optional object for method call. /// - fun: Function signature and definition ID. @@ -22,7 +28,10 @@ pub trait CodeGenerator { obj: Option<(Type, ValueEnum<'ctx>)>, fun: (&FunSignature, DefinitionId), params: Vec<(Option, ValueEnum<'ctx>)>, - ) -> Option> { + ) -> Option> + where + Self: Sized, + { gen_call(self, ctx, obj, fun, params) } @@ -36,7 +45,10 @@ pub trait CodeGenerator { signature: &FunSignature, def: &TopLevelDef, params: Vec<(Option, ValueEnum<'ctx>)>, - ) -> BasicValueEnum<'ctx> { + ) -> BasicValueEnum<'ctx> + where + Self: Sized, + { gen_constructor(self, ctx, signature, def, params) } @@ -62,7 +74,10 @@ pub trait CodeGenerator { &mut self, ctx: &mut CodeGenContext<'ctx, 'a>, expr: &Expr>, - ) -> Option> { + ) -> Option> + where + Self: Sized, + { gen_expr(self, ctx, expr) } @@ -71,7 +86,7 @@ pub trait CodeGenerator { fn gen_var_alloc<'ctx, 'a>( &mut self, ctx: &mut CodeGenContext<'ctx, 'a>, - ty: Type, + ty: BasicTypeEnum<'ctx>, ) -> PointerValue<'ctx> { gen_var(ctx, ty) } @@ -81,7 +96,10 @@ pub trait CodeGenerator { &mut self, ctx: &mut CodeGenContext<'ctx, 'a>, pattern: &Expr>, - ) -> PointerValue<'ctx> { + ) -> PointerValue<'ctx> + where + Self: Sized, + { gen_store_target(self, ctx, pattern) } @@ -91,7 +109,9 @@ pub trait CodeGenerator { ctx: &mut CodeGenContext<'ctx, 'a>, target: &Expr>, value: ValueEnum<'ctx>, - ) { + ) where + Self: Sized, + { gen_assign(self, ctx, target, value) } @@ -101,7 +121,10 @@ pub trait CodeGenerator { &mut self, ctx: &mut CodeGenContext<'ctx, 'a>, stmt: &Stmt>, - ) -> bool { + ) -> bool + where + Self: Sized, + { gen_while(self, ctx, stmt); false } @@ -112,7 +135,10 @@ pub trait CodeGenerator { &mut self, ctx: &mut CodeGenContext<'ctx, 'a>, stmt: &Stmt>, - ) -> bool { + ) -> bool + where + Self: Sized, + { gen_for(self, ctx, stmt); false } @@ -123,7 +149,10 @@ pub trait CodeGenerator { &mut self, ctx: &mut CodeGenContext<'ctx, 'a>, stmt: &Stmt>, - ) -> bool { + ) -> bool + where + Self: Sized, + { gen_if(self, ctx, stmt) } @@ -131,7 +160,10 @@ pub trait CodeGenerator { &mut self, ctx: &mut CodeGenContext<'ctx, 'a>, stmt: &Stmt>, - ) -> bool { + ) -> bool + where + Self: Sized, + { gen_with(self, ctx, stmt) } @@ -141,18 +173,23 @@ pub trait CodeGenerator { &mut self, ctx: &mut CodeGenContext<'ctx, 'a>, stmt: &Stmt>, - ) -> bool { + ) -> bool + where + Self: Sized, + { gen_stmt(self, ctx, stmt) } } pub struct DefaultCodeGenerator { name: String, + size_t: u32, } impl DefaultCodeGenerator { - pub fn new(name: String) -> DefaultCodeGenerator { - DefaultCodeGenerator { name } + pub fn new(name: String, size_t: u32) -> DefaultCodeGenerator { + assert!(size_t == 32 || size_t == 64); + DefaultCodeGenerator { name, size_t } } } @@ -160,4 +197,14 @@ impl CodeGenerator for DefaultCodeGenerator { fn get_name(&self) -> &str { &self.name } + + fn get_size_type<'ctx>(&self, ctx: &'ctx Context) -> IntType<'ctx> { + // it should be unsigned, but we don't really need unsigned and this could save us from + // having to do a bit cast... + if self.size_t == 32 { + ctx.i32_type() + } else { + ctx.i64_type() + } + } } diff --git a/nac3core/src/codegen/mod.rs b/nac3core/src/codegen/mod.rs index 3f60baf2..4d2583e1 100644 --- a/nac3core/src/codegen/mod.rs +++ b/nac3core/src/codegen/mod.rs @@ -224,6 +224,7 @@ pub struct CodeGenTask { fn get_llvm_type<'ctx>( ctx: &'ctx Context, + generator: &mut dyn CodeGenerator, unifier: &mut Unifier, top_level: &TopLevelContext, type_cache: &mut HashMap>, @@ -244,7 +245,7 @@ fn get_llvm_type<'ctx>( let fields = fields.borrow(); let fields = fields_list .iter() - .map(|f| get_llvm_type(ctx, unifier, top_level, type_cache, fields[&f.0].0)) + .map(|f| get_llvm_type(ctx, generator, unifier, top_level, type_cache, fields[&f.0].0)) .collect_vec(); ctx.struct_type(&fields, false).ptr_type(AddressSpace::Generic).into() } else { @@ -256,15 +257,15 @@ fn get_llvm_type<'ctx>( // a struct with fields in the order present in the tuple let fields = ty .iter() - .map(|ty| get_llvm_type(ctx, unifier, top_level, type_cache, *ty)) + .map(|ty| get_llvm_type(ctx, generator, unifier, top_level, type_cache, *ty)) .collect_vec(); ctx.struct_type(&fields, false).ptr_type(AddressSpace::Generic).into() } TList { ty } => { // a struct with an integer and a pointer to an array - let element_type = get_llvm_type(ctx, unifier, top_level, type_cache, *ty); + let element_type = get_llvm_type(ctx, generator, unifier, top_level, type_cache, *ty); let fields = - [ctx.i32_type().into(), element_type.ptr_type(AddressSpace::Generic).into()]; + [element_type.ptr_type(AddressSpace::Generic).into(), generator.get_size_type(ctx).into()]; ctx.struct_type(&fields, false).ptr_type(AddressSpace::Generic).into() } TVirtual { .. } => unimplemented!(), @@ -273,7 +274,7 @@ fn get_llvm_type<'ctx>( }) } -pub fn gen_func<'ctx, G: CodeGenerator + ?Sized>( +pub fn gen_func<'ctx, G: CodeGenerator>( context: &'ctx Context, generator: &mut G, registry: &WorkerRegistry, @@ -351,14 +352,14 @@ pub fn gen_func<'ctx, G: CodeGenerator + ?Sized>( let params = args .iter() .map(|arg| { - get_llvm_type(context, &mut unifier, top_level_ctx.as_ref(), &mut type_cache, arg.ty) + get_llvm_type(context, generator, &mut unifier, top_level_ctx.as_ref(), &mut type_cache, arg.ty) }) .collect_vec(); let fn_type = if unifier.unioned(ret, primitives.none) { context.void_type().fn_type(¶ms, false) } else { - get_llvm_type(context, &mut unifier, top_level_ctx.as_ref(), &mut type_cache, ret) + get_llvm_type(context, generator, &mut unifier, top_level_ctx.as_ref(), &mut type_cache, ret) .fn_type(¶ms, false) }; @@ -382,7 +383,7 @@ pub fn gen_func<'ctx, G: CodeGenerator + ?Sized>( for (n, arg) in args.iter().enumerate() { let param = fn_val.get_nth_param(n as u32).unwrap(); let alloca = builder.build_alloca( - get_llvm_type(context, &mut unifier, top_level_ctx.as_ref(), &mut type_cache, arg.ty), + get_llvm_type(context, generator, &mut unifier, top_level_ctx.as_ref(), &mut type_cache, arg.ty), &arg.name.to_string(), ); builder.build_store(alloca, param); diff --git a/nac3core/src/codegen/stmt.rs b/nac3core/src/codegen/stmt.rs index cbad16d7..9acac3d6 100644 --- a/nac3core/src/codegen/stmt.rs +++ b/nac3core/src/codegen/stmt.rs @@ -1,20 +1,27 @@ -use super::{expr::destructure_range, CodeGenContext, CodeGenerator, super::symbol_resolver::ValueEnum}; +use super::{ + super::symbol_resolver::ValueEnum, expr::destructure_range, CodeGenContext, CodeGenerator, +}; use crate::typecheck::typedef::Type; -use inkwell::values::{BasicValue, BasicValueEnum, PointerValue}; +use inkwell::{ + types::BasicTypeEnum, + values::{BasicValue, BasicValueEnum, PointerValue}, +}; use nac3parser::ast::{Expr, ExprKind, Stmt, StmtKind}; -pub fn gen_var<'ctx, 'a>(ctx: &mut CodeGenContext<'ctx, 'a>, ty: Type) -> PointerValue<'ctx> { +pub fn gen_var<'ctx, 'a>( + ctx: &mut CodeGenContext<'ctx, 'a>, + ty: BasicTypeEnum<'ctx>, +) -> PointerValue<'ctx> { // put the alloca in init block let current = ctx.builder.get_insert_block().unwrap(); // position before the last branching instruction... ctx.builder.position_before(&ctx.init_bb.get_last_instruction().unwrap()); - let ty = ctx.get_llvm_type(ty); let ptr = ctx.builder.build_alloca(ty, "tmp"); ctx.builder.position_at_end(current); ptr } -pub fn gen_store_target<'ctx, 'a, G: CodeGenerator + ?Sized>( +pub fn gen_store_target<'ctx, 'a, G: CodeGenerator>( generator: &mut G, ctx: &mut CodeGenContext<'ctx, 'a>, pattern: &Expr>, @@ -23,13 +30,14 @@ pub fn gen_store_target<'ctx, 'a, G: CodeGenerator + ?Sized>( // and we flatten nested tuples match &pattern.node { ExprKind::Name { id, .. } => ctx.var_assignment.get(id).map(|v| v.0).unwrap_or_else(|| { - let ptr = generator.gen_var_alloc(ctx, pattern.custom.unwrap()); + let ptr_ty = ctx.get_llvm_type(generator, pattern.custom.unwrap()); + let ptr = generator.gen_var_alloc(ctx, ptr_ty); ctx.var_assignment.insert(*id, (ptr, None, 0)); ptr }), 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); + let val = generator.gen_expr(ctx, value).unwrap().to_basic_value_enum(ctx, generator); let ptr = if let BasicValueEnum::PointerValue(v) = val { v } else { @@ -51,10 +59,13 @@ pub fn gen_store_target<'ctx, 'a, G: CodeGenerator + ?Sized>( let v = generator .gen_expr(ctx, value) .unwrap() - .to_basic_value_enum(ctx) + .to_basic_value_enum(ctx, generator) .into_pointer_value(); - let index = - generator.gen_expr(ctx, slice).unwrap().to_basic_value_enum(ctx).into_int_value(); + let index = generator + .gen_expr(ctx, slice) + .unwrap() + .to_basic_value_enum(ctx, generator) + .into_int_value(); unsafe { let arr_ptr = ctx .build_gep_and_load(v, &[i32_type.const_zero(), i32_type.const_int(1, false)]) @@ -66,14 +77,14 @@ pub fn gen_store_target<'ctx, 'a, G: CodeGenerator + ?Sized>( } } -pub fn gen_assign<'ctx, 'a, G: CodeGenerator + ?Sized>( +pub fn gen_assign<'ctx, 'a, G: CodeGenerator>( generator: &mut G, ctx: &mut CodeGenContext<'ctx, 'a>, target: &Expr>, value: ValueEnum<'ctx>, ) { if let ExprKind::Tuple { elts, .. } = &target.node { - if let BasicValueEnum::PointerValue(ptr) = value.to_basic_value_enum(ctx) { + if let BasicValueEnum::PointerValue(ptr) = value.to_basic_value_enum(ctx, generator) { let i32_type = ctx.ctx.i32_type(); for (i, elt) in elts.iter().enumerate() { let v = ctx.build_gep_and_load( @@ -94,12 +105,12 @@ pub fn gen_assign<'ctx, 'a, G: CodeGenerator + ?Sized>( *static_value = Some(s.clone()); } } - let val = value.to_basic_value_enum(ctx); + let val = value.to_basic_value_enum(ctx, generator); ctx.builder.build_store(ptr, val); } } -pub fn gen_for<'ctx, 'a, G: CodeGenerator + ?Sized>( +pub fn gen_for<'ctx, 'a, G: CodeGenerator>( generator: &mut G, ctx: &mut CodeGenContext<'ctx, 'a>, stmt: &Stmt>, @@ -110,6 +121,7 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator + ?Sized>( let var_assignment = ctx.var_assignment.clone(); let int32 = ctx.ctx.i32_type(); + let size_t = generator.get_size_type(ctx.ctx); let zero = int32.const_zero(); let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap(); let test_bb = ctx.ctx.append_basic_block(current, "test"); @@ -121,7 +133,7 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator + ?Sized>( // store loop bb information and restore it later let loop_bb = ctx.loop_bb.replace((test_bb, cont_bb)); - let iter_val = generator.gen_expr(ctx, iter).unwrap().to_basic_value_enum(ctx); + let iter_val = generator.gen_expr(ctx, iter).unwrap().to_basic_value_enum(ctx, generator); if ctx.unifier.unioned(iter.custom.unwrap(), ctx.primitives.range) { // setup let iter_val = iter_val.into_pointer_value(); @@ -156,25 +168,26 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator + ?Sized>( ); ctx.builder.position_at_end(body_bb); } else { - let counter = generator.gen_var_alloc(ctx, ctx.primitives.int32); + println!("{:?}", iter_val); + let counter = generator.gen_var_alloc(ctx, size_t.into()); // counter = -1 - ctx.builder.build_store(counter, ctx.ctx.i32_type().const_int(u64::max_value(), true)); + ctx.builder.build_store(counter, size_t.const_int(u64::max_value(), true)); let len = ctx - .build_gep_and_load(iter_val.into_pointer_value(), &[zero, zero]) + .build_gep_and_load( + iter_val.into_pointer_value(), + &[zero, int32.const_int(1, false)], + ) .into_int_value(); ctx.builder.build_unconditional_branch(test_bb); ctx.builder.position_at_end(test_bb); let tmp = ctx.builder.build_load(counter, "i").into_int_value(); - let tmp = ctx.builder.build_int_add(tmp, int32.const_int(1, false), "inc"); + let tmp = ctx.builder.build_int_add(tmp, size_t.const_int(1, false), "inc"); ctx.builder.build_store(counter, tmp); let cmp = ctx.builder.build_int_compare(inkwell::IntPredicate::SLT, tmp, len, "cmp"); ctx.builder.build_conditional_branch(cmp, body_bb, orelse_bb); ctx.builder.position_at_end(body_bb); let arr_ptr = ctx - .build_gep_and_load( - iter_val.into_pointer_value(), - &[zero, int32.const_int(1, false)], - ) + .build_gep_and_load(iter_val.into_pointer_value(), &[zero, zero]) .into_pointer_value(); let val = ctx.build_gep_and_load(arr_ptr, &[tmp]); generator.gen_assign(ctx, target, val.into()); @@ -210,7 +223,7 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator + ?Sized>( } } -pub fn gen_while<'ctx, 'a, G: CodeGenerator + ?Sized>( +pub fn gen_while<'ctx, 'a, G: CodeGenerator>( generator: &mut G, ctx: &mut CodeGenContext<'ctx, 'a>, stmt: &Stmt>, @@ -231,7 +244,7 @@ pub fn gen_while<'ctx, 'a, G: CodeGenerator + ?Sized>( let loop_bb = ctx.loop_bb.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); + let test = generator.gen_expr(ctx, test).unwrap().to_basic_value_enum(ctx, generator); if let BasicValueEnum::IntValue(test) = test { ctx.builder.build_conditional_branch(test, body_bb, orelse_bb); } else { @@ -268,7 +281,7 @@ pub fn gen_while<'ctx, 'a, G: CodeGenerator + ?Sized>( } } -pub fn gen_if<'ctx, 'a, G: CodeGenerator + ?Sized>( +pub fn gen_if<'ctx, 'a, G: CodeGenerator>( generator: &mut G, ctx: &mut CodeGenContext<'ctx, 'a>, stmt: &Stmt>, @@ -291,7 +304,7 @@ pub fn gen_if<'ctx, 'a, G: CodeGenerator + ?Sized>( }; 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); + let test = generator.gen_expr(ctx, test).unwrap().to_basic_value_enum(ctx, generator); if let BasicValueEnum::IntValue(test) = test { ctx.builder.build_conditional_branch(test, body_bb, orelse_bb); } else { @@ -353,7 +366,7 @@ pub fn gen_if<'ctx, 'a, G: CodeGenerator + ?Sized>( } } -pub fn gen_with<'ctx, 'a, G: CodeGenerator + ?Sized>( +pub fn gen_with<'ctx, 'a, G: CodeGenerator>( _: &mut G, _: &mut CodeGenContext<'ctx, 'a>, _: &Stmt>, @@ -362,7 +375,7 @@ pub fn gen_with<'ctx, 'a, G: CodeGenerator + ?Sized>( unimplemented!() } -pub fn gen_stmt<'ctx, 'a, G: CodeGenerator + ?Sized>( +pub fn gen_stmt<'ctx, 'a, G: CodeGenerator>( generator: &mut G, ctx: &mut CodeGenContext<'ctx, 'a>, stmt: &Stmt>, @@ -375,7 +388,7 @@ pub fn gen_stmt<'ctx, 'a, G: CodeGenerator + ?Sized>( StmtKind::Return { value, .. } => { let value = value .as_ref() - .map(|v| generator.gen_expr(ctx, v).unwrap().to_basic_value_enum(ctx)); + .map(|v| generator.gen_expr(ctx, v).unwrap().to_basic_value_enum(ctx, generator)); let value = value.as_ref().map(|v| v as &dyn BasicValue); ctx.builder.build_return(value); return true; @@ -408,8 +421,10 @@ pub fn gen_stmt<'ctx, 'a, G: CodeGenerator + ?Sized>( let value = { let ty1 = ctx.unifier.get_representative(target.custom.unwrap()); let ty2 = ctx.unifier.get_representative(value.custom.unwrap()); - let left = generator.gen_expr(ctx, target).unwrap().to_basic_value_enum(ctx); - let right = generator.gen_expr(ctx, value).unwrap().to_basic_value_enum(ctx); + let left = + generator.gen_expr(ctx, target).unwrap().to_basic_value_enum(ctx, generator); + let right = + generator.gen_expr(ctx, value).unwrap().to_basic_value_enum(ctx, generator); // we can directly compare the types, because we've got their representatives // which would be unchanged until further unification, which we would never do diff --git a/nac3core/src/codegen/test.rs b/nac3core/src/codegen/test.rs index 2bbc75ed..34fcf3f4 100644 --- a/nac3core/src/codegen/test.rs +++ b/nac3core/src/codegen/test.rs @@ -39,7 +39,7 @@ impl SymbolResolver for Resolver { fn get_default_param_value(&self, _: &nac3parser::ast::Expr) -> Option { unimplemented!() } - + fn get_symbol_type( &self, _: &mut Unifier, @@ -88,7 +88,7 @@ fn test_primitives() { class_names: Default::default(), }) as Arc; - let threads = vec![DefaultCodeGenerator::new("test".into()).into()]; + let threads = vec![DefaultCodeGenerator::new("test".into(), 32).into()]; let signature = FunSignature { args: vec![ FuncArg { name: "a".into(), ty: primitives.int32, default_value: None }, @@ -245,7 +245,7 @@ fn test_simple_call() { unreachable!() } - let threads = vec![DefaultCodeGenerator::new("test".into()).into()]; + let threads = vec![DefaultCodeGenerator::new("test".into(), 32).into()]; let mut function_data = FunctionData { resolver: resolver.clone(), bound_variables: Vec::new(), diff --git a/nac3core/src/symbol_resolver.rs b/nac3core/src/symbol_resolver.rs index 742bfafa..c5dbe54f 100644 --- a/nac3core/src/symbol_resolver.rs +++ b/nac3core/src/symbol_resolver.rs @@ -2,10 +2,10 @@ use std::collections::HashMap; use std::fmt::Debug; use std::{cell::RefCell, sync::Arc}; -use crate::typecheck::{ +use crate::{codegen::CodeGenerator, typecheck::{ type_inferencer::PrimitiveStore, typedef::{Type, Unifier}, -}; +}}; use crate::{ codegen::CodeGenContext, toplevel::{DefinitionId, TopLevelDef}, @@ -31,6 +31,7 @@ pub trait StaticValue { fn to_basic_value_enum<'ctx, 'a>( &self, ctx: &mut CodeGenContext<'ctx, 'a>, + generator: &mut dyn CodeGenerator ) -> BasicValueEnum<'ctx>; fn get_field<'ctx, 'a>( @@ -74,9 +75,10 @@ impl<'ctx> ValueEnum<'ctx> { pub fn to_basic_value_enum<'a>( self, ctx: &mut CodeGenContext<'ctx, 'a>, + generator: &mut dyn CodeGenerator, ) -> BasicValueEnum<'ctx> { match self { - ValueEnum::Static(v) => v.to_basic_value_enum(ctx), + ValueEnum::Static(v) => v.to_basic_value_enum(ctx, generator), ValueEnum::Dynamic(v) => v, } } diff --git a/nac3standalone/src/main.rs b/nac3standalone/src/main.rs index d5007129..f3a6b307 100644 --- a/nac3standalone/src/main.rs +++ b/nac3standalone/src/main.rs @@ -295,7 +295,7 @@ fn main() { // println!("IR:\n{}", module.print_to_string().to_str().unwrap()); }))); let threads = (0..threads) - .map(|i| Box::new(DefaultCodeGenerator::new(format!("module{}", i)))) + .map(|i| Box::new(DefaultCodeGenerator::new(format!("module{}", i), 64))) .collect(); let (registry, handles) = WorkerRegistry::create_workers(threads, top_level, f); registry.add_task(task);