From 525ff4513046fc7aae185b103ea76c4fd77d5a06 Mon Sep 17 00:00:00 2001 From: Niels Saurer Date: Wed, 10 Nov 2021 02:42:12 +0100 Subject: [PATCH] Add codegen for dynamically sized arrays --- codegen-examples/array.progge | 15 +++++++++++++-- runtime.c | 13 +++++++++++++ src/compiler.rs | 34 ++++++++++++++++++++++++++-------- 3 files changed, 52 insertions(+), 10 deletions(-) diff --git a/codegen-examples/array.progge b/codegen-examples/array.progge index bfce10c..34ac295 100644 --- a/codegen-examples/array.progge +++ b/codegen-examples/array.progge @@ -6,13 +6,24 @@ fn program(_argc: int) -> int { if arr_v[0][0] == 1 { let _ = print_int(_argc); } - let _ = print_int(-1); + let _ = print_int(111111111111111); // prints 100 because Progge's arrays are by-reference let _ = print_int(arr_v[1][1]); + + let _ = print_int(111111111111111); + + let dyn_arr = [42; _argc]; + let i = 0; + while i < _argc { + let _ = print_int(dyn_arr[i]); + i = i + 1; + } + return 0; } fn double_index(barr: [[int]]) -> [int] { - barr[0] = [1]; + let size = 1; + barr[0] = [1; size]; return barr[1]; } \ No newline at end of file diff --git a/runtime.c b/runtime.c index f91ee35..4330459 100644 --- a/runtime.c +++ b/runtime.c @@ -20,6 +20,19 @@ int64_t* alloc_array(int64_t size) { return array; } +int64_t* alloc_array_default(int64_t size, int64_t value) { + int64_t* array = malloc((size + 1) * sizeof(int64_t)); + if (array == NULL) { + printf("Array allocation failed!\n"); + exit(1); + } + array[0] = size; + for (int i = 1; i <= size; i++) { + array[i] = value; + } + return array; +} + int64_t int_arg(int64_t i) { char* arg = argv[i]; int64_t result = 0; diff --git a/src/compiler.rs b/src/compiler.rs index ab00a2a..9ddb460 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -1,3 +1,4 @@ +use std::arch::x86_64::_mm256_undefined_pd; use std::collections::HashMap; use std::process::Command; use inkwell::builder::Builder; @@ -70,15 +71,20 @@ impl<'a, 'ctx> Compiler<'a, 'ctx> { self.context.i64_type().into() } - fn compile_array_alloc(&mut self, size: u64) -> PointerValue<'ctx> { - let size = self.context.i64_type().const_int(size as u64, false); - + fn compile_array_alloc(&mut self, size: IntValue<'ctx>) -> PointerValue<'ctx> { let alloc_array_fn = self.functions.get("alloc_array").unwrap(); let alloc_array_res = self.builder.build_call(*alloc_array_fn, &[size.into()], "alloc_array"); alloc_array_res.try_as_basic_value().left().unwrap().into_pointer_value() } + fn compile_array_alloc_default(&mut self, size: IntValue<'ctx>, default: IntValue<'ctx>) -> PointerValue<'ctx> { + let alloc_array_default_fn = self.functions.get("alloc_array_default").unwrap(); + let alloc_array_default_res = self.builder.build_call(*alloc_array_default_fn, &[size.into(), default.into()], "alloc_array_default"); + + alloc_array_default_res.try_as_basic_value().left().unwrap().into_pointer_value() + } + fn compile_loc_exp(&mut self, lexp: &WithLoc) -> PointerValue<'ctx> { match &lexp.elem { LocExpr::Var(v) => { @@ -193,13 +199,14 @@ impl<'a, 'ctx> Compiler<'a, 'ctx> { // Progge array representation: pointer to array of size+1 elements, element 0 is size // also, arrays are reference types Expr::Array(els) => { - let ty = match &exp.typ { - Type::Array(t) => t.clone(), - _ => panic!("Expected array type") - }; + // let ty = match &exp.typ { + // Type::Array(t) => t.clone(), + // _ => panic!("Expected array type") + // }; let size = els.len(); - let arr_ptr = self.compile_array_alloc(size as u64); + let size = self.context.i64_type().const_int(size as u64, false); + let arr_ptr = self.compile_array_alloc(size); unsafe { for (i, el) in els.iter().enumerate() { @@ -223,6 +230,13 @@ impl<'a, 'ctx> Compiler<'a, 'ctx> { self.builder.build_ptr_to_int(arr_ptr, self.context.i64_type(), "arr_ptr_int").into() } + Expr::DefaultArray { default_value, size } => { + let size = self.compile_exp(size); + let default_value = self.compile_exp(default_value); + let arr_ptr = self.compile_array_alloc_default(size.into_int_value(), default_value.into_int_value()); + + self.builder.build_ptr_to_int(arr_ptr, self.context.i64_type(), "arr_ptr_int").into() + } Expr::Index(arr, idx) => { let ptr = self.compile_loc_exp(&WithLoc::new(LocExpr::Index((**arr).clone(), (**idx).clone()), exp.loc)); self.builder.build_load(ptr, "arr_idx_load").into() @@ -417,6 +431,10 @@ impl<'a, 'ctx> Compiler<'a, 'ctx> { let alloc_array_fn = self.module.add_function("alloc_array", alloc_array, None); self.functions.insert("alloc_array".to_string(), alloc_array_fn); + let alloc_array_default = self.context.i64_type().ptr_type(AddressSpace::Generic).fn_type(&[self.context.i64_type().into(), self.context.i64_type().into()], false); + let alloc_array_default_fn = self.module.add_function("alloc_array_default", alloc_array_default, None); + self.functions.insert("alloc_array_default".to_string(), alloc_array_default_fn); + let funcdefs = self.program.0.clone(); // Build decl map for f in funcdefs.iter() {