Add codegen for assoc functions
This commit is contained in:
		
							parent
							
								
									4d7c17a854
								
							
						
					
					
						commit
						24f11a77d2
					
				| @ -15,8 +15,11 @@ use scope::*; | ||||
| 
 | ||||
| use crate::{ | ||||
|     mir::{ | ||||
|         self, implement::TypeCategory, pass::BinopKey, CustomTypeKey, FunctionDefinitionKind, NamedVariableRef, | ||||
|         SourceModuleId, StructField, StructType, TypeDefinition, TypeDefinitionKind, TypeKind, WhileStatement, | ||||
|         self, | ||||
|         implement::TypeCategory, | ||||
|         pass::{AssociatedFunctionKey, BinopKey}, | ||||
|         CustomTypeKey, FunctionDefinitionKind, NamedVariableRef, SourceModuleId, StructField, StructType, | ||||
|         TypeDefinition, TypeDefinitionKind, TypeKind, WhileStatement, | ||||
|     }, | ||||
|     util::try_all, | ||||
| }; | ||||
| @ -212,6 +215,46 @@ impl mir::Module { | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         let mut associated_functions = HashMap::new(); | ||||
| 
 | ||||
|         for (ty, function) in &self.associated_functions { | ||||
|             let param_types: Vec<Type> = function | ||||
|                 .parameters | ||||
|                 .iter() | ||||
|                 .map(|(_, p)| p.get_type(&type_values)) | ||||
|                 .collect(); | ||||
| 
 | ||||
|             let is_main = self.is_main && function.name == "main"; | ||||
|             let func = match &function.kind { | ||||
|                 mir::FunctionDefinitionKind::Local(_, _) => Some(module.function( | ||||
|                     &format!("{}::{}", ty, function.name), | ||||
|                     function.return_type.get_type(&type_values), | ||||
|                     param_types, | ||||
|                     FunctionFlags { | ||||
|                         is_pub: function.is_pub || is_main, | ||||
|                         is_main, | ||||
|                         is_imported: function.is_imported, | ||||
|                         ..FunctionFlags::default() | ||||
|                     }, | ||||
|                 )), | ||||
|                 mir::FunctionDefinitionKind::Extern(imported) => Some(module.function( | ||||
|                     &function.name, | ||||
|                     function.return_type.get_type(&type_values), | ||||
|                     param_types, | ||||
|                     FunctionFlags { | ||||
|                         is_extern: true, | ||||
|                         is_imported: *imported, | ||||
|                         ..FunctionFlags::default() | ||||
|                     }, | ||||
|                 )), | ||||
|                 mir::FunctionDefinitionKind::Intrinsic(_) => None, | ||||
|             }; | ||||
| 
 | ||||
|             if let Some(func) = func { | ||||
|                 associated_functions.insert(AssociatedFunctionKey(ty.clone(), function.name.clone()), func); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         let mut binops = HashMap::new(); | ||||
|         for binop in &self.binop_defs { | ||||
|             let binop_fn_name = format!( | ||||
| @ -258,6 +301,7 @@ impl mir::Module { | ||||
|                                 module_id: self.module_id, | ||||
|                                 function: &ir_function, | ||||
|                                 block: entry, | ||||
|                                 assoc_functions: &associated_functions, | ||||
|                                 functions: &functions, | ||||
|                                 types: &types, | ||||
|                                 type_values: &type_values, | ||||
| @ -331,6 +375,62 @@ impl mir::Module { | ||||
|                 module_id: self.module_id, | ||||
|                 function, | ||||
|                 block: entry, | ||||
|                 assoc_functions: &associated_functions, | ||||
|                 functions: &functions, | ||||
|                 types: &types, | ||||
|                 type_values: &type_values, | ||||
|                 stack_values: HashMap::new(), | ||||
|                 debug: Some(Debug { | ||||
|                     info: &debug, | ||||
|                     scope: compile_unit, | ||||
|                     types: &debug_types, | ||||
|                 }), | ||||
|                 binops: &binops, | ||||
|                 allocator: Rc::new(RefCell::new(allocator)), | ||||
|             }; | ||||
| 
 | ||||
|             mir_function | ||||
|                 .kind | ||||
|                 .codegen( | ||||
|                     mir_function.name.clone(), | ||||
|                     mir_function.is_pub, | ||||
|                     &mut scope, | ||||
|                     &mir_function.parameters, | ||||
|                     &mir_function.return_type, | ||||
|                     &function, | ||||
|                     match &mir_function.kind { | ||||
|                         FunctionDefinitionKind::Local(..) => mir_function.signature().into_debug(tokens, compile_unit), | ||||
|                         FunctionDefinitionKind::Extern(_) => None, | ||||
|                         FunctionDefinitionKind::Intrinsic(_) => None, | ||||
|                     }, | ||||
|                 ) | ||||
|                 .unwrap(); | ||||
|         } | ||||
| 
 | ||||
|         for (ty, mir_function) in &self.associated_functions { | ||||
|             let function = associated_functions | ||||
|                 .get(&AssociatedFunctionKey(ty.clone(), mir_function.name.clone())) | ||||
|                 .unwrap(); | ||||
|             let mut entry = function.block("entry"); | ||||
| 
 | ||||
|             let allocator = Allocator::from( | ||||
|                 &mir_function.kind, | ||||
|                 &mir_function.parameters, | ||||
|                 &mut AllocatorScope { | ||||
|                     block: &mut entry, | ||||
|                     type_values: &type_values, | ||||
|                 }, | ||||
|             ); | ||||
| 
 | ||||
|             let mut scope = Scope { | ||||
|                 context, | ||||
|                 modules: &modules, | ||||
|                 tokens, | ||||
|                 module: &module, | ||||
|                 module_id: self.module_id, | ||||
|                 function, | ||||
|                 block: entry, | ||||
|                 assoc_functions: &associated_functions, | ||||
|                 functions: &functions, | ||||
|                 types: &types, | ||||
|                 type_values: &type_values, | ||||
| @ -1215,7 +1315,76 @@ impl mir::Expression { | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             mir::ExprKind::AssociatedFunctionCall(..) => todo!(), | ||||
|             mir::ExprKind::AssociatedFunctionCall(ty, call) => { | ||||
|                 let ret_type_kind = call.return_type.known().expect("function return type unknown"); | ||||
|                 let call_name = format!("{}::{}", ty, call.name); | ||||
| 
 | ||||
|                 let ret_type = ret_type_kind.get_type(scope.type_values); | ||||
| 
 | ||||
|                 let params = try_all( | ||||
|                     call.parameters | ||||
|                         .iter() | ||||
|                         .map(|e| e.codegen(scope, state)) | ||||
|                         .collect::<Vec<_>>(), | ||||
|                 ) | ||||
|                 .map_err(|e| e.first().cloned().unwrap())? | ||||
|                 .into_iter() | ||||
|                 .map(|v| v.unwrap()) | ||||
|                 .collect::<Vec<_>>(); | ||||
| 
 | ||||
|                 let param_instrs = params.iter().map(|e| e.instr()).collect(); | ||||
|                 let callee = scope | ||||
|                     .assoc_functions | ||||
|                     .get(&AssociatedFunctionKey(ty.clone(), call.name.clone())) | ||||
|                     .expect("function not found!"); | ||||
| 
 | ||||
|                 let val = scope | ||||
|                     .block | ||||
|                     .build_named(&call_name, Instr::FunctionCall(callee.value(), param_instrs)) | ||||
|                     .unwrap(); | ||||
| 
 | ||||
|                 if let Some(debug) = &scope.debug { | ||||
|                     let location = call.meta.into_debug(scope.tokens, debug.scope).unwrap(); | ||||
|                     let location_val = debug.info.location(&debug.scope, location); | ||||
|                     val.with_location(&mut scope.block, location_val); | ||||
|                 } | ||||
| 
 | ||||
|                 let ptr = if ret_type_kind != TypeKind::Void { | ||||
|                     let ptr = scope | ||||
|                         .block | ||||
|                         .build_named(&call_name, Instr::Alloca(ret_type.clone())) | ||||
|                         .unwrap(); | ||||
|                     scope | ||||
|                         .block | ||||
|                         .build_named(format!("{}.store", call_name), Instr::Store(ptr, val)) | ||||
|                         .unwrap(); | ||||
| 
 | ||||
|                     Some(ptr) | ||||
|                 } else { | ||||
|                     None | ||||
|                 }; | ||||
| 
 | ||||
|                 if let Some(ptr) = ptr { | ||||
|                     if state.should_load { | ||||
|                         Some(StackValue( | ||||
|                             StackValueKind::Immutable( | ||||
|                                 scope | ||||
|                                     .block | ||||
|                                     .build_named(call.name.clone(), Instr::Load(ptr, ret_type)) | ||||
|                                     .unwrap(), | ||||
|                             ), | ||||
|                             ret_type_kind, | ||||
|                         )) | ||||
|                     } else { | ||||
|                         Some(StackValue( | ||||
|                             StackValueKind::Immutable(ptr), | ||||
|                             TypeKind::CodegenPtr(Box::new(ret_type_kind)), | ||||
|                         )) | ||||
|                     } | ||||
|                 } else { | ||||
|                     None | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|         if let Some(value) = &value { | ||||
|             value.instr().maybe_location(&mut scope.block, location); | ||||
|  | ||||
| @ -8,7 +8,10 @@ use reid_lib::{ | ||||
| 
 | ||||
| use crate::{ | ||||
|     lexer::FullToken, | ||||
|     mir::{pass::BinopKey, CustomTypeKey, SourceModuleId, TypeDefinition, TypeKind}, | ||||
|     mir::{ | ||||
|         pass::{AssociatedFunctionKey, BinopKey}, | ||||
|         CustomTypeKey, SourceModuleId, TypeDefinition, TypeKind, | ||||
|     }, | ||||
| }; | ||||
| 
 | ||||
| use super::{allocator::Allocator, ErrorKind, IntrinsicFunction, ModuleCodegen}; | ||||
| @ -23,6 +26,7 @@ pub struct Scope<'ctx, 'scope> { | ||||
|     pub(super) block: Block<'ctx>, | ||||
|     pub(super) types: &'scope HashMap<TypeValue, TypeDefinition>, | ||||
|     pub(super) type_values: &'scope HashMap<CustomTypeKey, TypeValue>, | ||||
|     pub(super) assoc_functions: &'scope HashMap<AssociatedFunctionKey, Function<'ctx>>, | ||||
|     pub(super) functions: &'scope HashMap<String, Function<'ctx>>, | ||||
|     pub(super) binops: &'scope HashMap<BinopKey, StackBinopDefinition<'ctx>>, | ||||
|     pub(super) stack_values: HashMap<String, StackValue>, | ||||
| @ -40,6 +44,7 @@ impl<'ctx, 'a> Scope<'ctx, 'a> { | ||||
|             context: self.context, | ||||
|             module: self.module, | ||||
|             module_id: self.module_id, | ||||
|             assoc_functions: self.assoc_functions, | ||||
|             functions: self.functions, | ||||
|             types: self.types, | ||||
|             type_values: self.type_values, | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user