diff options
| author | Cody <cody@codyq.dev> | 2023-06-26 17:12:55 -0500 |
|---|---|---|
| committer | Cody <cody@codyq.dev> | 2023-06-26 17:12:55 -0500 |
| commit | 00e423d30edf38a5e57c5c1c52cdb323c62850bc (patch) | |
| tree | 0c7c44cd319ee0b1a15c9b3e42813afb2a938fb1 | |
| parent | 4172dc213f88df5025169fa7f43d02f2794fdd70 (diff) | |
| download | sloth-00e423d30edf38a5e57c5c1c52cdb323c62850bc.tar.gz | |
vpop & function args
| -rw-r--r-- | examples/hello.sloth | 15 | ||||
| -rw-r--r-- | sloth/src/codegen/mod.rs | 173 | ||||
| -rw-r--r-- | sloth/src/main.rs | 6 | ||||
| -rw-r--r-- | sloth/src/parser/ast.rs | 1 | ||||
| -rw-r--r-- | sloth/src/parser/mod.rs | 11 | ||||
| -rw-r--r-- | sloth/src/parser/stmt.rs | 4 | ||||
| -rw-r--r-- | sloth/src/symtable.rs | 6 | ||||
| -rw-r--r-- | test.c | 16 | ||||
| -rwxr-xr-x | test.sh | 3 |
9 files changed, 174 insertions, 61 deletions
diff --git a/examples/hello.sloth b/examples/hello.sloth index 1bbdbd4..f4e6692 100644 --- a/examples/hello.sloth +++ b/examples/hello.sloth @@ -1,11 +1,22 @@ -fn test() [Int 3] { - var list: [Int 3] = [500, 5, 7]; +fn test() [Int] { + var list: [Int] = [500, 5, 7]; vpushi(list, 3); vpushi(list, 3); vpushi(list, 3); vpushi(list, 5); + var x: Int = vpopi(list); + vpushi(list, x); + vpushi(list, x * 2); + vpushi(list, x * 3); + return list; } +fn testtwo(list: [Int]) Int { + #vpopi(list); + var x: Int = vpopi(list); + return x; +} + diff --git a/sloth/src/codegen/mod.rs b/sloth/src/codegen/mod.rs index ad6b451..0035802 100644 --- a/sloth/src/codegen/mod.rs +++ b/sloth/src/codegen/mod.rs @@ -7,9 +7,9 @@ use inkwell::module::Module; use inkwell::targets::{ CodeModel, FileType, InitializationConfig, RelocMode, Target, TargetMachine, }; -use inkwell::types::{BasicMetadataTypeEnum, BasicType, BasicTypeEnum}; +use inkwell::types::{BasicMetadataTypeEnum, BasicType, BasicTypeEnum, FunctionType}; use inkwell::values::{ - BasicMetadataValueEnum, BasicValue, BasicValueEnum, FunctionValue, PointerValue, + BasicMetadataValueEnum, BasicValue, BasicValueEnum, FunctionValue, IntValue, PointerValue, }; use inkwell::{AddressSpace, FloatPredicate, IntPredicate, OptimizationLevel}; use itertools::{Either, Itertools}; @@ -46,9 +46,14 @@ impl<'ctx> Codegen<'ctx> { references: Default::default(), }; - this.INTRINSIC_vpush("i", Type::Integer); - this.INTRINSIC_vpush("f", Type::Float); - this.INTRINSIC_vpush("b", Type::Boolean); + for (c, t) in [ + ("i", Type::Integer), + ("f", Type::Float), + ("b", Type::Boolean), + ] { + this.INTRINSIC_vpush(c, t.clone()); + this.INTRINSIC_vpop(c, t); + } this } @@ -164,19 +169,45 @@ impl<'ctx> Codegen<'ctx> { } StmtKind::DefineFunction(function) => { let table = code.symtable.clone(); - self.codegen_function(table, function.clone()); + self.codegen_function( + table, + // if let FunctionKind::Normal { body } = &function.kind { + // Some(body.symtable.clone()) + // } else { + // None + // }, + function.clone(), + ); // If the function is written in sloth (as opposed to an extern one) we generate // the block contents if let FunctionKind::Normal { body } = &function.kind { - if let StmtKind::Block(body) = &body.kind { + if let StmtKind::Block(code) = &body.kind { // Make the block containing the code for the function let func = self.current_func.unwrap(); let block = self.context.append_basic_block(func, "entrypoint"); // Position the builder to be at the block self.builder.position_at_end(block); - self.codegen_block(body); + + // FIXME 🍝 + // This code adds parameters to the body so they're accessible + let body_table = body.symtable.clone(); + for (i, input) in function.inputs.iter().enumerate() { + let symbol = body_table.get_value(&input.identifier).unwrap(); + + let ptr = self.codegen_alloca( + self.type_as_basic_type(symbol.typ), + &input.identifier, + ); + let init_value = func.get_nth_param(i as u32).unwrap(); + + self.builder.build_store(ptr, init_value); + self.references.insert(symbol.id, ptr); + } + + // Codegen the function body + self.codegen_block(code); if self.current_func_void { self.builder.build_return(None); @@ -222,15 +253,9 @@ impl<'ctx> Codegen<'ctx> { .as_basic_type_enum(); let vector_type = self.context.struct_type(&[i32_type, i32_type, typ], false); - let ptr_to_that = vector_type.ptr_type(AddressSpace::default()); ptr_to_that.fn_type(&inputs_typ, false) - - // killll me - // self.type_as_basic_type(*typ.clone()) - // .ptr_type(AddressSpace::default()) - // .fn_type(&inputs_typ, false) } _ => todo!(), }; @@ -478,34 +503,28 @@ impl<'ctx> Codegen<'ctx> { #[allow(non_snake_case)] impl<'ctx> Codegen<'ctx> { - fn INTRINSIC_vpush(&mut self, name: &str, typ: Type) { + fn _setup(&mut self, name: &str, func_type: FunctionType<'ctx>) { // Preparing for function self.references.clear(); - let bruh = self.type_as_basic_type(Type::Array { - typ: Box::new(typ.clone()), - len: 0, - }); - - let inputs = &[bruh.into(), self.type_as_metadata_type(typ.clone())]; - // Making the function - let func_type = self.context.void_type().fn_type(inputs, false); - let func = self - .module - .add_function(&format!("vpush{name}"), func_type, None); + let func = self.module.add_function(name, func_type, None); self.current_func = Some(func); self.current_func_void = true; let block = self.context.append_basic_block(func, "entrypoint"); self.builder.position_at_end(block); + } - // Writing the logic - let element_type = self.type_as_basic_type(typ); - let element_ptr_type = element_type.ptr_type(AddressSpace::default()); - + fn _get_ptrs( + &mut self, + element_type: BasicTypeEnum<'ctx>, + vector_ptr: PointerValue<'ctx>, + ) -> (PointerValue<'ctx>, PointerValue<'ctx>, PointerValue<'ctx>) { + // Types let i32_type = self.context.i32_type(); + let element_ptr_type = element_type.ptr_type(AddressSpace::default()); let vector_type = self.context.struct_type( &[ @@ -516,8 +535,7 @@ impl<'ctx> Codegen<'ctx> { false, ); - let vector_ptr = func.get_nth_param(0).unwrap().into_pointer_value(); - + // Getting pointers let size_ptr = self .builder .build_struct_gep(vector_type, vector_ptr, 0, "sizegep") @@ -531,11 +549,26 @@ impl<'ctx> Codegen<'ctx> { .build_struct_gep(vector_type, vector_ptr, 2, "innergep") .unwrap(); + (size_ptr, cap_ptr, inner_ptr) + } + + fn _get_values( + &mut self, + element_type: BasicTypeEnum<'ctx>, + size_ptr: PointerValue<'ctx>, + cap_ptr: PointerValue<'ctx>, + inner_ptr: PointerValue<'ctx>, + ) -> (IntValue<'ctx>, IntValue<'ctx>, PointerValue<'ctx>) { + // Types + let i32_type = self.context.i32_type(); + let element_ptr_type = element_type.ptr_type(AddressSpace::default()); + + // Getting values let size = self .builder .build_load(i32_type, size_ptr, "size") .into_int_value(); - let _cap = self + let cap = self .builder .build_load(i32_type, cap_ptr, "cap") .into_int_value(); @@ -544,21 +577,85 @@ impl<'ctx> Codegen<'ctx> { .build_load(element_ptr_type, inner_ptr, "inner") .into_pointer_value(); + (size, cap, inner) + } + + fn INTRINSIC_vpush(&mut self, name: &str, typ: Type) { + // Setup function + let array_input = self.type_as_basic_type(Type::Array { + typ: Box::new(typ.clone()), + }); + let inputs = &[array_input.into(), self.type_as_metadata_type(typ.clone())]; + let func_type = self.context.void_type().fn_type(inputs, false); + self._setup(&format!("vpush{name}"), func_type); + let func = self.current_func.unwrap(); + + // Types + let element_type = self.type_as_basic_type(typ); + let i32_type = self.context.i32_type(); + + // Getting the pointers and values needed + let vector_ptr = func.get_nth_param(0).unwrap().into_pointer_value(); + let (size_ptr, cap_ptr, inner_ptr) = self._get_ptrs(element_type, vector_ptr); + let (size, _cap, inner) = self._get_values(element_type, size_ptr, cap_ptr, inner_ptr); + + // FIXME: Array cant grow as of now + // Put the new element into backing array let element = func.get_nth_param(1).unwrap(); let slot_ptr = unsafe { self.builder.build_gep(element_type, inner, &[size], "slot") }; - self.builder.build_store(slot_ptr, element); - // TODO: Handle going over capacity - // Increase size tracker - let new_size = self + let updated_size = self .builder .build_int_add(size, i32_type.const_int(1, false), ""); - self.builder.build_store(size_ptr, new_size); + self.builder.build_store(size_ptr, updated_size); // Function return self.builder.build_return(None); } + + fn INTRINSIC_vpop(&mut self, name: &str, typ: Type) { + // Setup function + let array_input = self.type_as_basic_type(Type::Array { + typ: Box::new(typ.clone()), + }); + let inputs = &[array_input.into(), self.type_as_metadata_type(typ.clone())]; + let func_type = match typ { + Type::Integer => self.context.i32_type().fn_type(inputs, false), + Type::Float => self.context.f32_type().fn_type(inputs, false), + Type::Boolean => self.context.bool_type().fn_type(inputs, false), + _ => panic!(), + }; + self._setup(&format!("vpop{name}"), func_type); + let func = self.current_func.unwrap(); + + // Types + let element_type = self.type_as_basic_type(typ); + let i32_type = self.context.i32_type(); + + // Getting the pointers and values needed + let vector_ptr = func.get_nth_param(0).unwrap().into_pointer_value(); + let (size_ptr, cap_ptr, inner_ptr) = self._get_ptrs(element_type, vector_ptr); + let (size, _cap, inner) = self._get_values(element_type, size_ptr, cap_ptr, inner_ptr); + + // Get the last element in the array + let element_idx = self + .builder + .build_int_sub(size, i32_type.const_int(1, false), ""); + let element_ptr = unsafe { + self.builder + .build_gep(element_type, inner, &[element_idx], "elementptr") + }; + let element = self + .builder + .build_load(element_type, element_ptr, "element"); + + // Decrease the size tracker + self.builder.build_store(size_ptr, element_idx); + + // Return element + self.builder.build_return(Some(&element)); + } } diff --git a/sloth/src/main.rs b/sloth/src/main.rs index dec55de..5522082 100644 --- a/sloth/src/main.rs +++ b/sloth/src/main.rs @@ -59,7 +59,11 @@ fn main() { global_symtable.insert("vpushi".into(), dummy.clone()); global_symtable.insert("vpushf".into(), dummy.clone()); - global_symtable.insert("vpushb".into(), dummy); + global_symtable.insert("vpushb".into(), dummy.clone()); + + global_symtable.insert("vpopi".into(), dummy.clone()); + global_symtable.insert("vpopf".into(), dummy.clone()); + global_symtable.insert("vpopb".into(), dummy); // Parsing let tokens = Lexer::new(&source).collect_vec(); diff --git a/sloth/src/parser/ast.rs b/sloth/src/parser/ast.rs index 66bf851..00719e7 100644 --- a/sloth/src/parser/ast.rs +++ b/sloth/src/parser/ast.rs @@ -255,7 +255,6 @@ pub struct FunctionInput { pub struct TypeIdentifier { pub name: String, pub is_list: bool, - pub list_len: u32, } impl Display for TypeIdentifier { diff --git a/sloth/src/parser/mod.rs b/sloth/src/parser/mod.rs index 6dd534a..a1f251e 100644 --- a/sloth/src/parser/mod.rs +++ b/sloth/src/parser/mod.rs @@ -126,20 +126,11 @@ impl<'a> AstParser<'a> { let name = self.consume_identifier()?; - let mut list_len = 0; if is_list { - if let Literal::Integer(i) = self.consume_literal()? { - list_len = i as u32; - } - self.consume(TokenType::ClosingBracket, "Expected ']'")?; } - Ok(TypeIdentifier { - name, - is_list, - list_len, - }) + Ok(TypeIdentifier { name, is_list }) } pub fn reserve_id(&mut self) -> i32 { diff --git a/sloth/src/parser/stmt.rs b/sloth/src/parser/stmt.rs index d8c091d..d8a0509 100644 --- a/sloth/src/parser/stmt.rs +++ b/sloth/src/parser/stmt.rs @@ -311,7 +311,6 @@ mod tests { typ: TypeIdentifier { name: "Int".to_string(), is_list: false, - list_len: 0, }, })); @@ -346,13 +345,11 @@ mod tests { typ: TypeIdentifier { name: "Int".to_owned(), is_list: false, - list_len: 0, }, }], output: Some(TypeIdentifier { name: "Int".to_owned(), is_list: false, - list_len: 0, }), kind: FunctionKind::Normal { body: Box::new(Stmt::without_table( @@ -374,7 +371,6 @@ mod tests { typ: TypeIdentifier { name: "Int".to_owned(), is_list: false, - list_len: 0, }, }), Stmt::without_table(7, StmtKind::AssignVariable { diff --git a/sloth/src/symtable.rs b/sloth/src/symtable.rs index 5a89c7a..8af1c60 100644 --- a/sloth/src/symtable.rs +++ b/sloth/src/symtable.rs @@ -59,10 +59,7 @@ impl SymbolTable { if let Symbol::Type(ref typ) = *symbol { let mut typ = typ.clone(); if identifier.is_list { - typ = Type::Array { - typ: Box::new(typ), - len: identifier.list_len, - }; + typ = Type::Array { typ: Box::new(typ) }; } return Some(typ); } @@ -160,6 +157,5 @@ pub enum Type { }, Array { typ: Box<Type>, - len: u32, }, } @@ -7,6 +7,7 @@ typedef struct { } IntVec; IntVec* test(); +int testtwo(IntVec*); int main() { IntVec* v = test(); @@ -22,5 +23,20 @@ int main() { int value = inner[i]; printf("%d ", value); } + puts("\n\n"); + + testtwo(v); + + size = (*v).size; + cap = (*v).cap; + inner = (*v).inner; + + printf("%d\n", size); + printf("%d\n", cap); + + for (int i = 0; i < size; ++i) { + int value = inner[i]; + printf("%d ", value); + } puts("\n"); } @@ -0,0 +1,3 @@ +cargo run examples/hello.sloth +clang output.o test.c -o output +./output |
