Add intrinsic associated functions
This commit is contained in:
		
							parent
							
								
									0613fc5c53
								
							
						
					
					
						commit
						537167fe4f
					
				| @ -22,6 +22,7 @@ fn main() -> u32 { | |||||||
|     let otus = Otus { field: 17 }; |     let otus = Otus { field: 17 }; | ||||||
|     print(from_str("otus: ") + Otus::test(&otus) as u64); |     print(from_str("otus: ") + Otus::test(&otus) as u64); | ||||||
|     print(from_str("i32: ") + i32::test(54) as u64); |     print(from_str("i32: ") + i32::test(54) as u64); | ||||||
|  |     print(from_str("sizeof i32: ") + i32::sizeof()); | ||||||
| 
 | 
 | ||||||
|     return Otus::test(&otus); |     return Otus::test(&otus); | ||||||
| } | } | ||||||
|  | |||||||
| @ -36,6 +36,20 @@ pub fn form_intrinsics() -> Vec<FunctionDefinition> { | |||||||
|     intrinsics |     intrinsics | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | pub fn get_intrinsic_assoc_func(ty: &TypeKind, name: &str) -> Option<FunctionDefinition> { | ||||||
|  |     match name { | ||||||
|  |         "sizeof" => Some(FunctionDefinition { | ||||||
|  |             name: "sizeof".to_owned(), | ||||||
|  |             is_pub: true, | ||||||
|  |             is_imported: false, | ||||||
|  |             return_type: TypeKind::U64, | ||||||
|  |             parameters: Vec::new(), | ||||||
|  |             kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSizeOf(ty.clone()))), | ||||||
|  |         }), | ||||||
|  |         _ => None, | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| fn simple_binop_def<T: Clone + 'static>(op: BinaryOperator, ty: &TypeKind, fun: T) -> BinopDefinition | fn simple_binop_def<T: Clone + 'static>(op: BinaryOperator, ty: &TypeKind, fun: T) -> BinopDefinition | ||||||
| where | where | ||||||
|     T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue, |     T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue, | ||||||
| @ -167,28 +181,33 @@ pub fn form_intrinsic_binops() -> Vec<BinopDefinition> { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub trait IntrinsicFunction: std::fmt::Debug { | pub trait IntrinsicFunction: std::fmt::Debug { | ||||||
|     fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, params: &[&StackValue]) -> Result<StackValue, ErrorKind>; |     fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, params: &[StackValue]) -> Result<StackValue, ErrorKind>; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | macro_rules! intrinsic_debug { | ||||||
|  |     ($kind:ty, $name:literal) => { | ||||||
|  |         impl<T> std::fmt::Debug for $kind | ||||||
|  |         where | ||||||
|  |             T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue, | ||||||
|  |         { | ||||||
|  |             fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||||
|  |                 f.debug_tuple($name).finish() | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Clone)] | #[derive(Clone)] | ||||||
| pub struct IntrinsicSimpleInstr<T>(T) | pub struct IntrinsicSimpleInstr<T>(T) | ||||||
| where | where | ||||||
|     T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue; |     T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue; | ||||||
| 
 | intrinsic_debug!(IntrinsicSimpleInstr<T>, "IntrinsicSimpleInstr"); | ||||||
| impl<T> std::fmt::Debug for IntrinsicSimpleInstr<T> |  | ||||||
| where |  | ||||||
|     T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue, |  | ||||||
| { |  | ||||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |  | ||||||
|         f.debug_tuple("IntrinsicSimpleInstr").finish() |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| impl<T: Clone> IntrinsicFunction for IntrinsicSimpleInstr<T> | impl<T: Clone> IntrinsicFunction for IntrinsicSimpleInstr<T> | ||||||
| where | where | ||||||
|     T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue, |     T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue, | ||||||
| { | { | ||||||
|     fn codegen<'b, 'c>(&self, scope: &mut Scope<'b, 'c>, params: &[&StackValue]) -> Result<StackValue, ErrorKind> { |     fn codegen<'b, 'c>(&self, scope: &mut Scope<'b, 'c>, params: &[StackValue]) -> Result<StackValue, ErrorKind> { | ||||||
|         let lhs = params.get(0).unwrap(); |         let lhs = params.get(0).unwrap(); | ||||||
|         let rhs = params.get(1).unwrap(); |         let rhs = params.get(1).unwrap(); | ||||||
|         let instr = self.clone().0(scope, lhs.instr(), rhs.instr()); |         let instr = self.clone().0(scope, lhs.instr(), rhs.instr()); | ||||||
| @ -200,21 +219,13 @@ where | |||||||
| pub struct IntrinsicBooleanInstr<T>(T) | pub struct IntrinsicBooleanInstr<T>(T) | ||||||
| where | where | ||||||
|     T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue; |     T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue; | ||||||
| 
 | intrinsic_debug!(IntrinsicBooleanInstr<T>, "IntrinsicBooleanInstr"); | ||||||
| impl<T> std::fmt::Debug for IntrinsicBooleanInstr<T> |  | ||||||
| where |  | ||||||
|     T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue, |  | ||||||
| { |  | ||||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |  | ||||||
|         f.debug_tuple("IntrinsicBooleanInstr").finish() |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| impl<T: Clone> IntrinsicFunction for IntrinsicBooleanInstr<T> | impl<T: Clone> IntrinsicFunction for IntrinsicBooleanInstr<T> | ||||||
| where | where | ||||||
|     T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue, |     T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue, | ||||||
| { | { | ||||||
|     fn codegen<'b, 'c>(&self, scope: &mut Scope<'b, 'c>, params: &[&StackValue]) -> Result<StackValue, ErrorKind> { |     fn codegen<'b, 'c>(&self, scope: &mut Scope<'b, 'c>, params: &[StackValue]) -> Result<StackValue, ErrorKind> { | ||||||
|         let lhs = params.get(0).unwrap(); |         let lhs = params.get(0).unwrap(); | ||||||
|         let rhs = params.get(1).unwrap(); |         let rhs = params.get(1).unwrap(); | ||||||
|         let instr = self.clone().0(scope, lhs.instr(), rhs.instr()); |         let instr = self.clone().0(scope, lhs.instr(), rhs.instr()); | ||||||
| @ -222,6 +233,24 @@ where | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #[derive(Clone)] | ||||||
|  | pub struct IntrinsicSizeOf(TypeKind); | ||||||
|  | impl std::fmt::Debug for IntrinsicSizeOf { | ||||||
|  |     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||||
|  |         f.debug_tuple("IntrinsicSizeOf").finish() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl IntrinsicFunction for IntrinsicSizeOf { | ||||||
|  |     fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, _: &[StackValue]) -> Result<StackValue, ErrorKind> { | ||||||
|  |         let instr = scope | ||||||
|  |             .block | ||||||
|  |             .build(Instr::Constant(reid_lib::ConstValue::U64(self.0.size_of()))) | ||||||
|  |             .unwrap(); | ||||||
|  |         Ok(StackValue(StackValueKind::Literal(instr), self.0.clone())) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // impl IntrinsicFunction for IntrinsicIAdd {
 | // impl IntrinsicFunction for IntrinsicIAdd {
 | ||||||
| //     fn codegen<'ctx, 'a>(
 | //     fn codegen<'ctx, 'a>(
 | ||||||
| //         &self,
 | //         &self,
 | ||||||
|  | |||||||
| @ -211,7 +211,7 @@ impl mir::Module { | |||||||
|             }; |             }; | ||||||
| 
 | 
 | ||||||
|             if let Some(func) = func { |             if let Some(func) = func { | ||||||
|                 functions.insert(function.name.clone(), func); |                 functions.insert(function.name.clone(), ScopeFunctionKind::UserGenerated(func)); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -251,7 +251,10 @@ impl mir::Module { | |||||||
|             }; |             }; | ||||||
| 
 | 
 | ||||||
|             if let Some(func) = func { |             if let Some(func) = func { | ||||||
|                 associated_functions.insert(AssociatedFunctionKey(ty.clone(), function.name.clone()), func); |                 associated_functions.insert( | ||||||
|  |                     AssociatedFunctionKey(ty.clone(), function.name.clone()), | ||||||
|  |                     ScopeFunctionKind::UserGenerated(func), | ||||||
|  |                 ); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -332,22 +335,20 @@ impl mir::Module { | |||||||
|                                 ) |                                 ) | ||||||
|                                 .unwrap(); |                                 .unwrap(); | ||||||
| 
 | 
 | ||||||
|                             StackBinopFunctionKind::UserGenerated(ir_function) |                             ScopeFunctionKind::UserGenerated(ir_function) | ||||||
|                         } |  | ||||||
|                         FunctionDefinitionKind::Extern(imported) => { |  | ||||||
|                             StackBinopFunctionKind::UserGenerated(module.function( |  | ||||||
|                                 &binop_fn_name, |  | ||||||
|                                 binop.return_type.get_type(&type_values), |  | ||||||
|                                 vec![binop.lhs.1.get_type(&type_values), binop.rhs.1.get_type(&type_values)], |  | ||||||
|                                 FunctionFlags { |  | ||||||
|                                     is_extern: true, |  | ||||||
|                                     is_imported: *imported, |  | ||||||
|                                     ..FunctionFlags::default() |  | ||||||
|                                 }, |  | ||||||
|                             )) |  | ||||||
|                         } |                         } | ||||||
|  |                         FunctionDefinitionKind::Extern(imported) => ScopeFunctionKind::UserGenerated(module.function( | ||||||
|  |                             &binop_fn_name, | ||||||
|  |                             binop.return_type.get_type(&type_values), | ||||||
|  |                             vec![binop.lhs.1.get_type(&type_values), binop.rhs.1.get_type(&type_values)], | ||||||
|  |                             FunctionFlags { | ||||||
|  |                                 is_extern: true, | ||||||
|  |                                 is_imported: *imported, | ||||||
|  |                                 ..FunctionFlags::default() | ||||||
|  |                             }, | ||||||
|  |                         )), | ||||||
|                         FunctionDefinitionKind::Intrinsic(intrinsic_function) => { |                         FunctionDefinitionKind::Intrinsic(intrinsic_function) => { | ||||||
|                             StackBinopFunctionKind::Intrinsic(intrinsic_function) |                             ScopeFunctionKind::Intrinsic(intrinsic_function) | ||||||
|                         } |                         } | ||||||
|                     }, |                     }, | ||||||
|                 }, |                 }, | ||||||
| @ -355,111 +356,118 @@ impl mir::Module { | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         for mir_function in &self.functions { |         for mir_function in &self.functions { | ||||||
|             let function = functions.get(&mir_function.name).unwrap(); |             if let ScopeFunctionKind::UserGenerated(function) = functions.get(&mir_function.name).unwrap() { | ||||||
|             let mut entry = function.block("entry"); |                 let mut entry = function.block("entry"); | ||||||
| 
 | 
 | ||||||
|             let allocator = Allocator::from( |                 let allocator = Allocator::from( | ||||||
|                 &mir_function.kind, |                     &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, |  | ||||||
|                 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.parameters, | ||||||
|                     &mir_function.return_type, |                     &mut AllocatorScope { | ||||||
|                     &function, |                         block: &mut entry, | ||||||
|                     match &mir_function.kind { |                         type_values: &type_values, | ||||||
|                         FunctionDefinitionKind::Local(..) => mir_function.signature().into_debug(tokens, compile_unit), |  | ||||||
|                         FunctionDefinitionKind::Extern(_) => None, |  | ||||||
|                         FunctionDefinitionKind::Intrinsic(_) => None, |  | ||||||
|                     }, |                     }, | ||||||
|                 ) |                 ); | ||||||
|                 .unwrap(); | 
 | ||||||
|  |                 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, | ||||||
|  |                     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 { |         for (ty, mir_function) in &self.associated_functions { | ||||||
|             let function = associated_functions |             if let ScopeFunctionKind::UserGenerated(function) = associated_functions | ||||||
|                 .get(&AssociatedFunctionKey(ty.clone(), mir_function.name.clone())) |                 .get(&AssociatedFunctionKey(ty.clone(), mir_function.name.clone())) | ||||||
|                 .unwrap(); |                 .unwrap() | ||||||
|             let mut entry = function.block("entry"); |             { | ||||||
|  |                 let mut entry = function.block("entry"); | ||||||
| 
 | 
 | ||||||
|             let allocator = Allocator::from( |                 let allocator = Allocator::from( | ||||||
|                 &mir_function.kind, |                     &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, |  | ||||||
|                 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.parameters, | ||||||
|                     &mir_function.return_type, |                     &mut AllocatorScope { | ||||||
|                     &function, |                         block: &mut entry, | ||||||
|                     match &mir_function.kind { |                         type_values: &type_values, | ||||||
|                         FunctionDefinitionKind::Local(..) => mir_function.signature().into_debug(tokens, compile_unit), |  | ||||||
|                         FunctionDefinitionKind::Extern(_) => None, |  | ||||||
|                         FunctionDefinitionKind::Intrinsic(_) => None, |  | ||||||
|                     }, |                     }, | ||||||
|                 ) |                 ); | ||||||
|                 .unwrap(); | 
 | ||||||
|  |                 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, | ||||||
|  |                     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(); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         Ok(ModuleCodegen { module }) |         Ok(ModuleCodegen { module }) | ||||||
| @ -821,7 +829,7 @@ impl mir::Expression { | |||||||
|                 }); |                 }); | ||||||
| 
 | 
 | ||||||
|                 if let Some(operation) = operation { |                 if let Some(operation) = operation { | ||||||
|                     let a = operation.codegen(&lhs_val, &rhs_val, scope)?; |                     let a = operation.codegen(lhs_val.clone(), rhs_val.clone(), scope)?; | ||||||
|                     Some(a) |                     Some(a) | ||||||
|                 } else { |                 } else { | ||||||
|                     let lhs_type = lhs_exp.return_type(&Default::default(), scope.module_id).unwrap().1; |                     let lhs_type = lhs_exp.return_type(&Default::default(), scope.module_id).unwrap().1; | ||||||
| @ -906,19 +914,19 @@ impl mir::Expression { | |||||||
|                 .map(|v| v.unwrap()) |                 .map(|v| v.unwrap()) | ||||||
|                 .collect::<Vec<_>>(); |                 .collect::<Vec<_>>(); | ||||||
| 
 | 
 | ||||||
|                 let param_instrs = params.iter().map(|e| e.instr()).collect(); |  | ||||||
|                 let callee = scope.functions.get(&call.name).expect("function not found!"); |                 let callee = scope.functions.get(&call.name).expect("function not found!"); | ||||||
| 
 | 
 | ||||||
|                 let val = scope |                 let val = callee.codegen( | ||||||
|                     .block |                     &call.name, | ||||||
|                     .build_named(call.name.clone(), Instr::FunctionCall(callee.value(), param_instrs)) |                     params.as_slice(), | ||||||
|                     .unwrap(); |                     &call.return_type, | ||||||
| 
 |                     if let Some(debug) = &scope.debug { | ||||||
|                 if let Some(debug) = &scope.debug { |                         call.meta.into_debug(scope.tokens, debug.scope) | ||||||
|                     let location = call.meta.into_debug(scope.tokens, debug.scope).unwrap(); |                     } else { | ||||||
|                     let location_val = debug.info.location(&debug.scope, location); |                         None | ||||||
|                     val.with_location(&mut scope.block, location_val); |                     }, | ||||||
|                 } |                     scope, | ||||||
|  |                 )?; | ||||||
| 
 | 
 | ||||||
|                 let ptr = if ret_type_kind != TypeKind::Void { |                 let ptr = if ret_type_kind != TypeKind::Void { | ||||||
|                     let ptr = scope |                     let ptr = scope | ||||||
| @ -927,7 +935,7 @@ impl mir::Expression { | |||||||
|                         .unwrap(); |                         .unwrap(); | ||||||
|                     scope |                     scope | ||||||
|                         .block |                         .block | ||||||
|                         .build_named(format!("{}.store", call.name), Instr::Store(ptr, val)) |                         .build_named(format!("{}.store", call.name), Instr::Store(ptr, val.instr())) | ||||||
|                         .unwrap(); |                         .unwrap(); | ||||||
| 
 | 
 | ||||||
|                     Some(ptr) |                     Some(ptr) | ||||||
| @ -1332,31 +1340,38 @@ impl mir::Expression { | |||||||
|                 .map(|v| v.unwrap()) |                 .map(|v| v.unwrap()) | ||||||
|                 .collect::<Vec<_>>(); |                 .collect::<Vec<_>>(); | ||||||
| 
 | 
 | ||||||
|                 let param_instrs = params.iter().map(|e| e.instr()).collect(); |                 let assoc_key = AssociatedFunctionKey(ty.clone(), call.name.clone()); | ||||||
|  |                 let intrinsic = get_intrinsic_assoc_func(&ty, &call.name); | ||||||
|  |                 let intrinsic_owned = intrinsic.map(|func_def| { | ||||||
|  |                     let FunctionDefinitionKind::Intrinsic(intrinsic) = func_def.kind else { | ||||||
|  |                         panic!(); | ||||||
|  |                     }; | ||||||
|  |                     ScopeFunctionKind::IntrinsicOwned(intrinsic) | ||||||
|  |                 }); | ||||||
|                 let callee = scope |                 let callee = scope | ||||||
|                     .assoc_functions |                     .assoc_functions | ||||||
|                     .get(&AssociatedFunctionKey(ty.clone(), call.name.clone())) |                     .get(&assoc_key) | ||||||
|                     .expect("function not found!"); |                     .or(intrinsic_owned.as_ref()) | ||||||
|  |                     .expect(&format!("Function {} does not exist!", call_name)); | ||||||
| 
 | 
 | ||||||
|                 let val = scope |                 let location = if let Some(debug) = &scope.debug { | ||||||
|                     .block |                     call.meta.into_debug(scope.tokens, debug.scope) | ||||||
|                     .build_named(&call_name, Instr::FunctionCall(callee.value(), param_instrs)) |                 } else { | ||||||
|  |                     None | ||||||
|  |                 }; | ||||||
|  | 
 | ||||||
|  |                 let val = callee | ||||||
|  |                     .codegen(&call_name, params.as_slice(), &call.return_type, location, scope) | ||||||
|                     .unwrap(); |                     .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 = if ret_type_kind != TypeKind::Void { | ||||||
|                     let ptr = scope |                     let ptr = scope | ||||||
|                         .block |                         .block | ||||||
|                         .build_named(&call_name, Instr::Alloca(ret_type.clone())) |                         .build_named(&call.name, Instr::Alloca(ret_type.clone())) | ||||||
|                         .unwrap(); |                         .unwrap(); | ||||||
|                     scope |                     scope | ||||||
|                         .block |                         .block | ||||||
|                         .build_named(format!("{}.store", call_name), Instr::Store(ptr, val)) |                         .build_named(format!("{}.store", call_name), Instr::Store(ptr, val.instr())) | ||||||
|                         .unwrap(); |                         .unwrap(); | ||||||
| 
 | 
 | ||||||
|                     Some(ptr) |                     Some(ptr) | ||||||
|  | |||||||
| @ -2,7 +2,7 @@ use std::{cell::RefCell, collections::HashMap, mem, rc::Rc}; | |||||||
| 
 | 
 | ||||||
| use reid_lib::{ | use reid_lib::{ | ||||||
|     builder::{InstructionValue, TypeValue}, |     builder::{InstructionValue, TypeValue}, | ||||||
|     debug_information::{DebugInformation, DebugProgramValue, DebugTypeValue}, |     debug_information::{DebugInformation, DebugLocation, DebugProgramValue, DebugTypeValue}, | ||||||
|     Block, Context, Function, Instr, Module, |     Block, Context, Function, Instr, Module, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -26,8 +26,8 @@ pub struct Scope<'ctx, 'scope> { | |||||||
|     pub(super) block: Block<'ctx>, |     pub(super) block: Block<'ctx>, | ||||||
|     pub(super) types: &'scope HashMap<TypeValue, TypeDefinition>, |     pub(super) types: &'scope HashMap<TypeValue, TypeDefinition>, | ||||||
|     pub(super) type_values: &'scope HashMap<CustomTypeKey, TypeValue>, |     pub(super) type_values: &'scope HashMap<CustomTypeKey, TypeValue>, | ||||||
|     pub(super) assoc_functions: &'scope HashMap<AssociatedFunctionKey, Function<'ctx>>, |     pub(super) assoc_functions: &'scope HashMap<AssociatedFunctionKey, ScopeFunctionKind<'ctx>>, | ||||||
|     pub(super) functions: &'scope HashMap<String, Function<'ctx>>, |     pub(super) functions: &'scope HashMap<String, ScopeFunctionKind<'ctx>>, | ||||||
|     pub(super) binops: &'scope HashMap<BinopKey, StackBinopDefinition<'ctx>>, |     pub(super) binops: &'scope HashMap<BinopKey, StackBinopDefinition<'ctx>>, | ||||||
|     pub(super) stack_values: HashMap<String, StackValue>, |     pub(super) stack_values: HashMap<String, StackValue>, | ||||||
|     pub(super) debug: Option<Debug<'ctx>>, |     pub(super) debug: Option<Debug<'ctx>>, | ||||||
| @ -131,19 +131,20 @@ impl StackValueKind { | |||||||
| pub struct StackBinopDefinition<'ctx> { | pub struct StackBinopDefinition<'ctx> { | ||||||
|     pub(super) parameters: ((String, TypeKind), (String, TypeKind)), |     pub(super) parameters: ((String, TypeKind), (String, TypeKind)), | ||||||
|     pub(super) return_ty: TypeKind, |     pub(super) return_ty: TypeKind, | ||||||
|     pub(super) kind: StackBinopFunctionKind<'ctx>, |     pub(super) kind: ScopeFunctionKind<'ctx>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub enum StackBinopFunctionKind<'ctx> { | pub enum ScopeFunctionKind<'ctx> { | ||||||
|     UserGenerated(Function<'ctx>), |     UserGenerated(Function<'ctx>), | ||||||
|     Intrinsic(&'ctx Box<dyn IntrinsicFunction>), |     Intrinsic(&'ctx Box<dyn IntrinsicFunction>), | ||||||
|  |     IntrinsicOwned(Box<dyn IntrinsicFunction>), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<'ctx> StackBinopDefinition<'ctx> { | impl<'ctx> StackBinopDefinition<'ctx> { | ||||||
|     pub fn codegen<'a>( |     pub fn codegen<'a>( | ||||||
|         &self, |         &self, | ||||||
|         lhs: &StackValue, |         lhs: StackValue, | ||||||
|         rhs: &StackValue, |         rhs: StackValue, | ||||||
|         scope: &mut Scope<'ctx, 'a>, |         scope: &mut Scope<'ctx, 'a>, | ||||||
|     ) -> Result<StackValue, ErrorKind> { |     ) -> Result<StackValue, ErrorKind> { | ||||||
|         let (lhs, rhs) = if lhs.1 == self.parameters.0 .1 && rhs.1 == self.parameters.1 .1 { |         let (lhs, rhs) = if lhs.1 == self.parameters.0 .1 && rhs.1 == self.parameters.1 .1 { | ||||||
| @ -151,15 +152,43 @@ impl<'ctx> StackBinopDefinition<'ctx> { | |||||||
|         } else { |         } else { | ||||||
|             (rhs, lhs) |             (rhs, lhs) | ||||||
|         }; |         }; | ||||||
|         match &self.kind { |         let name = format!( | ||||||
|             StackBinopFunctionKind::UserGenerated(ir) => { |             "binop.{}.{}.{}.call", | ||||||
|                 let instr = scope |             self.parameters.0 .1, self.parameters.1 .1, self.return_ty | ||||||
|  |         ); | ||||||
|  |         self.kind.codegen(&name, &[lhs, rhs], &self.return_ty, None, scope) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<'ctx> ScopeFunctionKind<'ctx> { | ||||||
|  |     pub fn codegen<'a>( | ||||||
|  |         &self, | ||||||
|  |         name: &str, | ||||||
|  |         params: &[StackValue], | ||||||
|  |         return_ty: &TypeKind, | ||||||
|  |         location: Option<DebugLocation>, | ||||||
|  |         scope: &mut Scope<'ctx, 'a>, | ||||||
|  |     ) -> Result<StackValue, ErrorKind> { | ||||||
|  |         match self { | ||||||
|  |             ScopeFunctionKind::UserGenerated(function) => { | ||||||
|  |                 let val = scope | ||||||
|                     .block |                     .block | ||||||
|                     .build(Instr::FunctionCall(ir.value(), vec![lhs.instr(), rhs.instr()])) |                     .build_named( | ||||||
|  |                         name, | ||||||
|  |                         Instr::FunctionCall(function.value(), params.iter().map(|p| p.instr()).collect()), | ||||||
|  |                     ) | ||||||
|                     .unwrap(); |                     .unwrap(); | ||||||
|                 Ok(StackValue(StackValueKind::Immutable(instr), self.return_ty.clone())) | 
 | ||||||
|  |                 if let Some(debug) = &scope.debug { | ||||||
|  |                     if let Some(location) = location { | ||||||
|  |                         let location_val = debug.info.location(&debug.scope, location); | ||||||
|  |                         val.with_location(&mut scope.block, location_val); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 Ok(StackValue(StackValueKind::Immutable(val), return_ty.clone())) | ||||||
|             } |             } | ||||||
|             StackBinopFunctionKind::Intrinsic(fun) => fun.codegen(scope, &[&lhs, &rhs]), |             ScopeFunctionKind::Intrinsic(fun) => fun.codegen(scope, params), | ||||||
|  |             ScopeFunctionKind::IntrinsicOwned(fun) => fun.codegen(scope, params), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -5,7 +5,7 @@ use std::collections::HashMap; | |||||||
| use std::convert::Infallible; | use std::convert::Infallible; | ||||||
| use std::error::Error as STDError; | use std::error::Error as STDError; | ||||||
| 
 | 
 | ||||||
| use crate::codegen::intrinsics::form_intrinsic_binops; | use crate::codegen::intrinsics::{form_intrinsic_binops, get_intrinsic_assoc_func}; | ||||||
| use crate::error_raporting::ReidError; | use crate::error_raporting::ReidError; | ||||||
| 
 | 
 | ||||||
| use super::*; | use super::*; | ||||||
| @ -169,6 +169,24 @@ impl<Data: Clone + Default> Scope<Data> { | |||||||
|             .find(|(key, def)| key.0 == typekey.0 && def.importer == Some(typekey.1)) |             .find(|(key, def)| key.0 == typekey.0 && def.importer == Some(typekey.1)) | ||||||
|             .map(|(_, v)| v)) |             .map(|(_, v)| v)) | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     pub fn get_associated_function(&mut self, key: &AssociatedFunctionKey) -> Option<ScopeFunction> { | ||||||
|  |         let func = self.associated_functions.get(key); | ||||||
|  |         if let Some(func) = func { | ||||||
|  |             Some(func.clone()) | ||||||
|  |         } else if let Some(func) = get_intrinsic_assoc_func(&key.0, &key.1) { | ||||||
|  |             self.associated_functions.set( | ||||||
|  |                 key.clone(), | ||||||
|  |                 ScopeFunction { | ||||||
|  |                     ret: func.return_type, | ||||||
|  |                     params: func.parameters.iter().map(|(_, p)| p.clone()).collect(), | ||||||
|  |                 }, | ||||||
|  |             ); | ||||||
|  |             self.associated_functions.get(key).cloned() | ||||||
|  |         } else { | ||||||
|  |             None | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Clone, Debug)] | #[derive(Clone, Debug)] | ||||||
|  | |||||||
| @ -732,12 +732,10 @@ impl Expression { | |||||||
|             ExprKind::AssociatedFunctionCall(type_kind, function_call) => { |             ExprKind::AssociatedFunctionCall(type_kind, function_call) => { | ||||||
|                 let true_function = state |                 let true_function = state | ||||||
|                     .scope |                     .scope | ||||||
|                     .associated_functions |                     .get_associated_function(&pass::AssociatedFunctionKey( | ||||||
|                     .get(&pass::AssociatedFunctionKey( |  | ||||||
|                         type_kind.clone(), |                         type_kind.clone(), | ||||||
|                         function_call.name.clone(), |                         function_call.name.clone(), | ||||||
|                     )) |                     )) | ||||||
|                     .cloned() |  | ||||||
|                     .ok_or(ErrorKind::FunctionNotDefined(function_call.name.clone())); |                     .ok_or(ErrorKind::FunctionNotDefined(function_call.name.clone())); | ||||||
| 
 | 
 | ||||||
|                 if let Some(f) = state.ok(true_function, self.1) { |                 if let Some(f) = state.ok(true_function, self.1) { | ||||||
|  | |||||||
| @ -598,8 +598,7 @@ impl Expression { | |||||||
|                 // Get function definition and types
 |                 // Get function definition and types
 | ||||||
|                 let fn_call = state |                 let fn_call = state | ||||||
|                     .scope |                     .scope | ||||||
|                     .associated_functions |                     .get_associated_function(&AssociatedFunctionKey(type_kind.clone(), function_call.name.clone())) | ||||||
|                     .get(&AssociatedFunctionKey(type_kind.clone(), function_call.name.clone())) |  | ||||||
|                     .ok_or(ErrorKind::AssocFunctionNotDefined( |                     .ok_or(ErrorKind::AssocFunctionNotDefined( | ||||||
|                         function_call.name.clone(), |                         function_call.name.clone(), | ||||||
|                         type_kind.clone(), |                         type_kind.clone(), | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user