Add possibility to call instructions and store functions in values
This commit is contained in:
		
							parent
							
								
									100cd96a6d
								
							
						
					
					
						commit
						17545baa50
					
				| @ -4,10 +4,11 @@ | |||||||
| use std::{cell::RefCell, rc::Rc}; | use std::{cell::RefCell, rc::Rc}; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     Block, BlockData, CompileResult, ConstValueKind, CustomTypeKind, ErrorKind, FunctionData, Instr, InstructionData, |     Block, BlockData, CompileResult, ConstValueKind, CustomTypeKind, ErrorKind, FunctionData, | ||||||
|     ModuleData, NamedStruct, TerminatorKind, Type, TypeCategory, TypeData, |     Instr, InstructionData, ModuleData, NamedStruct, TerminatorKind, Type, TypeCategory, TypeData, | ||||||
|     debug_information::{ |     debug_information::{ | ||||||
|         DebugInformation, DebugLocationValue, DebugMetadataValue, DebugScopeValue, InstructionDebugRecordData, |         DebugInformation, DebugLocationValue, DebugMetadataValue, DebugScopeValue, | ||||||
|  |         InstructionDebugRecordData, | ||||||
|     }, |     }, | ||||||
|     util::match_types, |     util::match_types, | ||||||
| }; | }; | ||||||
| @ -114,7 +115,11 @@ impl Builder { | |||||||
|         value |         value | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub(crate) fn set_debug_information(&self, mod_val: &ModuleValue, debug_info: DebugInformation) { |     pub(crate) fn set_debug_information( | ||||||
|  |         &self, | ||||||
|  |         mod_val: &ModuleValue, | ||||||
|  |         debug_info: DebugInformation, | ||||||
|  |     ) { | ||||||
|         unsafe { |         unsafe { | ||||||
|             let mut modules = self.modules.borrow_mut(); |             let mut modules = self.modules.borrow_mut(); | ||||||
|             let module = modules.get_unchecked_mut(mod_val.0); |             let module = modules.get_unchecked_mut(mod_val.0); | ||||||
| @ -132,7 +137,11 @@ impl Builder { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub(crate) unsafe fn add_function(&self, mod_val: &ModuleValue, data: FunctionData) -> FunctionValue { |     pub(crate) unsafe fn add_function( | ||||||
|  |         &self, | ||||||
|  |         mod_val: &ModuleValue, | ||||||
|  |         data: FunctionData, | ||||||
|  |     ) -> FunctionValue { | ||||||
|         unsafe { |         unsafe { | ||||||
|             let mut modules = self.modules.borrow_mut(); |             let mut modules = self.modules.borrow_mut(); | ||||||
|             let module = modules.get_unchecked_mut(mod_val.0); |             let module = modules.get_unchecked_mut(mod_val.0); | ||||||
| @ -190,7 +199,11 @@ impl Builder { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub(crate) unsafe fn build_constant(&self, module: ModuleValue, kind: ConstValueKind) -> ConstantValue { |     pub(crate) unsafe fn build_constant( | ||||||
|  |         &self, | ||||||
|  |         module: ModuleValue, | ||||||
|  |         kind: ConstValueKind, | ||||||
|  |     ) -> ConstantValue { | ||||||
|         unsafe { |         unsafe { | ||||||
|             let mut modules = self.modules.borrow_mut(); |             let mut modules = self.modules.borrow_mut(); | ||||||
|             let module = modules.get_unchecked_mut(module.0); |             let module = modules.get_unchecked_mut(module.0); | ||||||
| @ -219,15 +232,27 @@ impl Builder { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub(crate) unsafe fn find_function(&self, module: ModuleValue, name: &String) -> Option<FunctionValue> { |     pub(crate) unsafe fn find_function( | ||||||
|  |         &self, | ||||||
|  |         module: ModuleValue, | ||||||
|  |         name: &String, | ||||||
|  |     ) -> Option<FunctionValue> { | ||||||
|         unsafe { |         unsafe { | ||||||
|             let mut modules = self.modules.borrow_mut(); |             let mut modules = self.modules.borrow_mut(); | ||||||
|             let module = modules.get_unchecked_mut(module.0); |             let module = modules.get_unchecked_mut(module.0); | ||||||
|             module.functions.iter().find(|f| f.data.name == *name).map(|f| f.value) |             module | ||||||
|  |                 .functions | ||||||
|  |                 .iter() | ||||||
|  |                 .find(|f| f.data.name == *name) | ||||||
|  |                 .map(|f| f.value) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub(crate) unsafe fn add_instruction_location(&self, value: &InstructionValue, location: DebugLocationValue) { |     pub(crate) unsafe fn add_instruction_location( | ||||||
|  |         &self, | ||||||
|  |         value: &InstructionValue, | ||||||
|  |         location: DebugLocationValue, | ||||||
|  |     ) { | ||||||
|         unsafe { |         unsafe { | ||||||
|             let mut modules = self.modules.borrow_mut(); |             let mut modules = self.modules.borrow_mut(); | ||||||
|             let module = modules.get_unchecked_mut(value.0.0.0.0); |             let module = modules.get_unchecked_mut(value.0.0.0.0); | ||||||
| @ -238,7 +263,11 @@ impl Builder { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub(crate) unsafe fn add_instruction_metadata(&self, value: &InstructionValue, metadata: DebugMetadataValue) { |     pub(crate) unsafe fn add_instruction_metadata( | ||||||
|  |         &self, | ||||||
|  |         value: &InstructionValue, | ||||||
|  |         metadata: DebugMetadataValue, | ||||||
|  |     ) { | ||||||
|         unsafe { |         unsafe { | ||||||
|             let mut modules = self.modules.borrow_mut(); |             let mut modules = self.modules.borrow_mut(); | ||||||
|             let module = modules.get_unchecked_mut(value.0.0.0.0); |             let module = modules.get_unchecked_mut(value.0.0.0.0); | ||||||
| @ -249,7 +278,11 @@ impl Builder { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub(crate) unsafe fn add_instruction_record(&self, value: &InstructionValue, record: InstructionDebugRecordData) { |     pub(crate) unsafe fn add_instruction_record( | ||||||
|  |         &self, | ||||||
|  |         value: &InstructionValue, | ||||||
|  |         record: InstructionDebugRecordData, | ||||||
|  |     ) { | ||||||
|         unsafe { |         unsafe { | ||||||
|             let mut modules = self.modules.borrow_mut(); |             let mut modules = self.modules.borrow_mut(); | ||||||
|             let module = modules.get_unchecked_mut(value.0.0.0.0); |             let module = modules.get_unchecked_mut(value.0.0.0.0); | ||||||
| @ -260,7 +293,11 @@ impl Builder { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub(crate) unsafe fn set_debug_subprogram(&self, value: &FunctionValue, subprogram: DebugScopeValue) { |     pub(crate) unsafe fn set_debug_subprogram( | ||||||
|  |         &self, | ||||||
|  |         value: &FunctionValue, | ||||||
|  |         subprogram: DebugScopeValue, | ||||||
|  |     ) { | ||||||
|         unsafe { |         unsafe { | ||||||
|             let mut modules = self.modules.borrow_mut(); |             let mut modules = self.modules.borrow_mut(); | ||||||
|             let module = modules.get_unchecked_mut(value.0.0); |             let module = modules.get_unchecked_mut(value.0.0); | ||||||
| @ -269,7 +306,11 @@ impl Builder { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub(crate) unsafe fn terminate(&self, block: &BlockValue, value: TerminatorKind) -> CompileResult<()> { |     pub(crate) unsafe fn terminate( | ||||||
|  |         &self, | ||||||
|  |         block: &BlockValue, | ||||||
|  |         value: TerminatorKind, | ||||||
|  |     ) -> CompileResult<()> { | ||||||
|         unsafe { |         unsafe { | ||||||
|             let mut modules = self.modules.borrow_mut(); |             let mut modules = self.modules.borrow_mut(); | ||||||
|             let module = modules.get_unchecked_mut(block.0.0.0); |             let module = modules.get_unchecked_mut(block.0.0.0); | ||||||
| @ -551,7 +592,10 @@ impl Builder { | |||||||
|                     } |                     } | ||||||
|                     for (a, b) in param_types.iter().zip(params) { |                     for (a, b) in param_types.iter().zip(params) { | ||||||
|                         if *a != b.get_type(&self)? { |                         if *a != b.get_type(&self)? { | ||||||
|                             return Err(ErrorKind::TypesIncompatible(a.clone(), b.get_type(&self)?)); |                             return Err(ErrorKind::TypesIncompatible( | ||||||
|  |                                 a.clone(), | ||||||
|  |                                 b.get_type(&self)?, | ||||||
|  |                             )); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                     Ok(()) |                     Ok(()) | ||||||
| @ -662,6 +706,14 @@ impl Builder { | |||||||
|                         Err(ErrorKind::NotPointer(val, val_ty)) |                         Err(ErrorKind::NotPointer(val, val_ty)) | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |                 Instr::Function(_) => Ok(()), | ||||||
|  |                 Instr::DynFunctionCall(instr, _) => { | ||||||
|  |                     let fn_ty = instr.get_type(&self)?; | ||||||
|  |                     let Type::Function(..) = fn_ty else { | ||||||
|  |                         return Err(ErrorKind::NotPointer(instr, fn_ty)); | ||||||
|  |                     }; | ||||||
|  |                     Ok(()) | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -709,7 +761,11 @@ impl InstructionValue { | |||||||
|         self |         self | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn maybe_location(self, block: &mut Block, location: Option<DebugLocationValue>) -> InstructionValue { |     pub fn maybe_location( | ||||||
|  |         self, | ||||||
|  |         block: &mut Block, | ||||||
|  |         location: Option<DebugLocationValue>, | ||||||
|  |     ) -> InstructionValue { | ||||||
|         unsafe { |         unsafe { | ||||||
|             if let Some(location) = location { |             if let Some(location) = location { | ||||||
|                 block.builder.add_instruction_location(&self, location); |                 block.builder.add_instruction_location(&self, location); | ||||||
| @ -822,6 +878,17 @@ impl InstructionValue { | |||||||
|                     Ok(kind.get_type()) |                     Ok(kind.get_type()) | ||||||
|                 } |                 } | ||||||
|                 IsNull(_) => Ok(Type::Bool), |                 IsNull(_) => Ok(Type::Bool), | ||||||
|  |                 Function(fun) => { | ||||||
|  |                     let data = builder.function_data(fun); | ||||||
|  |                     Ok(Type::Function(data.params, Box::new(data.ret))) | ||||||
|  |                 } | ||||||
|  |                 DynFunctionCall(instr, _) => { | ||||||
|  |                     let fn_ty = instr.get_type(builder)?; | ||||||
|  |                     let Type::Function(_, ret_ty) = fn_ty else { | ||||||
|  |                         panic!() | ||||||
|  |                     }; | ||||||
|  |                     Ok(*ret_ty) | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | |||||||
							
								
								
									
										214
									
								
								src/compile.rs
									
									
									
									
									
								
							
							
						
						
									
										214
									
								
								src/compile.rs
									
									
									
									
									
								
							| @ -20,8 +20,8 @@ use llvm_sys::{ | |||||||
|         LLVM_InitializeAllTargetMCs, LLVM_InitializeAllTargets, LLVMSetModuleDataLayout, |         LLVM_InitializeAllTargetMCs, LLVM_InitializeAllTargets, LLVMSetModuleDataLayout, | ||||||
|     }, |     }, | ||||||
|     target_machine::{ |     target_machine::{ | ||||||
|         LLVMCodeGenFileType, LLVMCreateTargetDataLayout, LLVMCreateTargetMachine, LLVMGetDefaultTargetTriple, |         LLVMCodeGenFileType, LLVMCreateTargetDataLayout, LLVMCreateTargetMachine, | ||||||
|         LLVMGetTargetFromTriple, LLVMTargetMachineEmitToMemoryBuffer, |         LLVMGetDefaultTargetTriple, LLVMGetTargetFromTriple, LLVMTargetMachineEmitToMemoryBuffer, | ||||||
|     }, |     }, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -35,8 +35,8 @@ use crate::{ | |||||||
| use super::{ | use super::{ | ||||||
|     CmpPredicate, ConstValueKind, Context, TerminatorKind, Type, |     CmpPredicate, ConstValueKind, Context, TerminatorKind, Type, | ||||||
|     builder::{ |     builder::{ | ||||||
|         BlockHolder, BlockValue, Builder, FunctionHolder, FunctionValue, InstructionHolder, InstructionValue, |         BlockHolder, BlockValue, Builder, FunctionHolder, FunctionValue, InstructionHolder, | ||||||
|         ModuleHolder, |         InstructionValue, ModuleHolder, | ||||||
|     }, |     }, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -120,8 +120,8 @@ impl CompiledModule { | |||||||
|             ); |             ); | ||||||
|             err.into_result().unwrap(); |             err.into_result().unwrap(); | ||||||
| 
 | 
 | ||||||
|             let llvm_ir = |             let llvm_ir = from_cstring(LLVMPrintModuleToString(self.module_ref)) | ||||||
|                 from_cstring(LLVMPrintModuleToString(self.module_ref)).expect("Unable to print LLVM IR to string"); |                 .expect("Unable to print LLVM IR to string"); | ||||||
| 
 | 
 | ||||||
|             let mut err = ErrorMessageHolder::null(); |             let mut err = ErrorMessageHolder::null(); | ||||||
|             LLVMVerifyModule( |             LLVMVerifyModule( | ||||||
| @ -231,8 +231,10 @@ pub struct LLVMValue { | |||||||
| impl ModuleHolder { | impl ModuleHolder { | ||||||
|     fn compile(&self, context: &LLVMContext, builder: &Builder) -> LLVMModuleRef { |     fn compile(&self, context: &LLVMContext, builder: &Builder) -> LLVMModuleRef { | ||||||
|         unsafe { |         unsafe { | ||||||
|             let module_ref = |             let module_ref = LLVMModuleCreateWithNameInContext( | ||||||
|                 LLVMModuleCreateWithNameInContext(into_cstring(&self.data.name).as_ptr(), context.context_ref); |                 into_cstring(&self.data.name).as_ptr(), | ||||||
|  |                 context.context_ref, | ||||||
|  |             ); | ||||||
| 
 | 
 | ||||||
|             // Compile the contents
 |             // Compile the contents
 | ||||||
| 
 | 
 | ||||||
| @ -327,9 +329,12 @@ impl ModuleHolder { | |||||||
|                     constant.value, |                     constant.value, | ||||||
|                     LLVMValue { |                     LLVMValue { | ||||||
|                         ty: constant.kind.get_type(), |                         ty: constant.kind.get_type(), | ||||||
|                         value_ref: constant |                         value_ref: constant.kind.as_llvm( | ||||||
|                             .kind |                             context.context_ref, | ||||||
|                             .as_llvm(context.context_ref, context.builder_ref, &constants, &types), |                             context.builder_ref, | ||||||
|  |                             &constants, | ||||||
|  |                             &types, | ||||||
|  |                         ), | ||||||
|                     }, |                     }, | ||||||
|                 ); |                 ); | ||||||
|             } |             } | ||||||
| @ -357,7 +362,12 @@ impl ModuleHolder { | |||||||
|                         scope = Ref::map(scope, |v| v.inner_scopes.get_unchecked(*i)); |                         scope = Ref::map(scope, |v| v.inner_scopes.get_unchecked(*i)); | ||||||
|                     } |                     } | ||||||
|                     for scope in &scope.inner_scopes { |                     for scope in &scope.inner_scopes { | ||||||
|                         scope.compile_scope(func.metadata.unwrap(), debug.file_ref, debug.scopes, debug.builder); |                         scope.compile_scope( | ||||||
|  |                             func.metadata.unwrap(), | ||||||
|  |                             debug.file_ref, | ||||||
|  |                             debug.scopes, | ||||||
|  |                             debug.builder, | ||||||
|  |                         ); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @ -402,7 +412,11 @@ impl ModuleHolder { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl DebugLocationHolder { | impl DebugLocationHolder { | ||||||
|     unsafe fn compile(&self, context: &LLVMContext, debug: &LLVMDebugInformation) -> LLVMMetadataRef { |     unsafe fn compile( | ||||||
|  |         &self, | ||||||
|  |         context: &LLVMContext, | ||||||
|  |         debug: &LLVMDebugInformation, | ||||||
|  |     ) -> LLVMMetadataRef { | ||||||
|         unsafe { |         unsafe { | ||||||
|             LLVMDIBuilderCreateDebugLocation( |             LLVMDIBuilderCreateDebugLocation( | ||||||
|                 context.context_ref, |                 context.context_ref, | ||||||
| @ -515,7 +529,8 @@ impl DebugTypeHolder { | |||||||
|                     ptr.name.len(), |                     ptr.name.len(), | ||||||
|                 ), |                 ), | ||||||
|                 DebugTypeData::Array(array) => { |                 DebugTypeData::Array(array) => { | ||||||
|                     let subrange = LLVMDIBuilderGetOrCreateSubrange(debug.builder, 0, array.length as i64); |                     let subrange = | ||||||
|  |                         LLVMDIBuilderGetOrCreateSubrange(debug.builder, 0, array.length as i64); | ||||||
|                     let mut elements = vec![subrange]; |                     let mut elements = vec![subrange]; | ||||||
|                     LLVMDIBuilderCreateArrayType( |                     LLVMDIBuilderCreateArrayType( | ||||||
|                         debug.builder, |                         debug.builder, | ||||||
| @ -577,7 +592,11 @@ impl DwarfFlags { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl TypeHolder { | impl TypeHolder { | ||||||
|     unsafe fn compile_type(&self, context: &LLVMContext, types: &HashMap<TypeValue, LLVMTypeRef>) -> LLVMTypeRef { |     unsafe fn compile_type( | ||||||
|  |         &self, | ||||||
|  |         context: &LLVMContext, | ||||||
|  |         types: &HashMap<TypeValue, LLVMTypeRef>, | ||||||
|  |     ) -> LLVMTypeRef { | ||||||
|         unsafe { |         unsafe { | ||||||
|             match &self.data.kind { |             match &self.data.kind { | ||||||
|                 CustomTypeKind::NamedStruct(named_struct) => { |                 CustomTypeKind::NamedStruct(named_struct) => { | ||||||
| @ -585,9 +604,16 @@ impl TypeHolder { | |||||||
|                     for ty in &named_struct.1 { |                     for ty in &named_struct.1 { | ||||||
|                         elem_types.push(ty.as_llvm(context.context_ref, types)); |                         elem_types.push(ty.as_llvm(context.context_ref, types)); | ||||||
|                     } |                     } | ||||||
|                     let struct_ty = |                     let struct_ty = LLVMStructCreateNamed( | ||||||
|                         LLVMStructCreateNamed(context.context_ref, into_cstring(named_struct.0.clone()).as_ptr()); |                         context.context_ref, | ||||||
|                     LLVMStructSetBody(struct_ty, elem_types.as_mut_ptr(), elem_types.len() as u32, 0); |                         into_cstring(named_struct.0.clone()).as_ptr(), | ||||||
|  |                     ); | ||||||
|  |                     LLVMStructSetBody( | ||||||
|  |                         struct_ty, | ||||||
|  |                         elem_types.as_mut_ptr(), | ||||||
|  |                         elem_types.len() as u32, | ||||||
|  |                         0, | ||||||
|  |                     ); | ||||||
|                     struct_ty |                     struct_ty | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @ -617,7 +643,13 @@ impl FunctionHolder { | |||||||
|             let name = if self.data.flags.is_main { |             let name = if self.data.flags.is_main { | ||||||
|                 c"main" |                 c"main" | ||||||
|             } else { |             } else { | ||||||
|                 &into_cstring(&self.data.linkage_name.clone().unwrap_or(self.data.name.clone())) |                 &into_cstring( | ||||||
|  |                     &self | ||||||
|  |                         .data | ||||||
|  |                         .linkage_name | ||||||
|  |                         .clone() | ||||||
|  |                         .unwrap_or(self.data.name.clone()), | ||||||
|  |                 ) | ||||||
|             }; |             }; | ||||||
| 
 | 
 | ||||||
|             let fn_type = LLVMFunctionType(ret_type, param_ptr, param_len as u32, 0); |             let fn_type = LLVMFunctionType(ret_type, param_ptr, param_len as u32, 0); | ||||||
| @ -625,7 +657,11 @@ impl FunctionHolder { | |||||||
|             let function_ref = LLVMAddFunction(module_ref, name.as_ptr(), fn_type); |             let function_ref = LLVMAddFunction(module_ref, name.as_ptr(), fn_type); | ||||||
| 
 | 
 | ||||||
|             if self.data.flags.inline { |             if self.data.flags.inline { | ||||||
|                 let attribute = LLVMCreateEnumAttribute(context.context_ref, LLVMEnumAttribute::AlwaysInline as u32, 0); |                 let attribute = LLVMCreateEnumAttribute( | ||||||
|  |                     context.context_ref, | ||||||
|  |                     LLVMEnumAttribute::AlwaysInline as u32, | ||||||
|  |                     0, | ||||||
|  |                 ); | ||||||
|                 LLVMAddAttributeAtIndex(function_ref, 0, attribute); |                 LLVMAddAttributeAtIndex(function_ref, 0, attribute); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| @ -688,7 +724,10 @@ impl FunctionHolder { | |||||||
| 
 | 
 | ||||||
|             if self.data.flags.is_imported { |             if self.data.flags.is_imported { | ||||||
|                 if self.data.flags.is_extern { |                 if self.data.flags.is_extern { | ||||||
|                     LLVMSetLinkage(own_function.value_ref, LLVMLinkage::LLVMAvailableExternallyLinkage); |                     LLVMSetLinkage( | ||||||
|  |                         own_function.value_ref, | ||||||
|  |                         LLVMLinkage::LLVMAvailableExternallyLinkage, | ||||||
|  |                     ); | ||||||
|                 } else { |                 } else { | ||||||
|                     LLVMSetLinkage(own_function.value_ref, LLVMLinkage::LLVMExternalLinkage); |                     LLVMSetLinkage(own_function.value_ref, LLVMLinkage::LLVMExternalLinkage); | ||||||
|                 } |                 } | ||||||
| @ -705,8 +744,10 @@ impl FunctionHolder { | |||||||
|                     continue; |                     continue; | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 let block_ref = |                 let block_ref = LLVMCreateBasicBlockInContext( | ||||||
|                     LLVMCreateBasicBlockInContext(module.context_ref, into_cstring(&block.data.name).as_ptr()); |                     module.context_ref, | ||||||
|  |                     into_cstring(&block.data.name).as_ptr(), | ||||||
|  |                 ); | ||||||
|                 LLVMAppendExistingBasicBlock(own_function.value_ref, block_ref); |                 LLVMAppendExistingBasicBlock(own_function.value_ref, block_ref); | ||||||
|                 module.blocks.insert(block.value, block_ref); |                 module.blocks.insert(block.value, block_ref); | ||||||
|             } |             } | ||||||
| @ -738,13 +779,22 @@ impl BlockHolder { | |||||||
|                 .data |                 .data | ||||||
|                 .terminator |                 .terminator | ||||||
|                 .clone() |                 .clone() | ||||||
|                 .expect(&format!("Block {} does not have a terminator!", self.data.name)) |                 .expect(&format!( | ||||||
|  |                     "Block {} does not have a terminator!", | ||||||
|  |                     self.data.name | ||||||
|  |                 )) | ||||||
|                 .compile(module, function, block_ref); |                 .compile(module, function, block_ref); | ||||||
| 
 | 
 | ||||||
|             if let Some(location) = &self.data.terminator_location { |             if let Some(location) = &self.data.terminator_location { | ||||||
|                 LLVMInstructionSetDebugLoc( |                 LLVMInstructionSetDebugLoc( | ||||||
|                     term_instr.value_ref, |                     term_instr.value_ref, | ||||||
|                     *module.debug.as_ref().unwrap().locations.get(&location).unwrap(), |                     *module | ||||||
|  |                         .debug | ||||||
|  |                         .as_ref() | ||||||
|  |                         .unwrap() | ||||||
|  |                         .locations | ||||||
|  |                         .get(&location) | ||||||
|  |                         .unwrap(), | ||||||
|                 ); |                 ); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @ -752,14 +802,24 @@ impl BlockHolder { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl InstructionHolder { | impl InstructionHolder { | ||||||
|     unsafe fn compile(&self, module: &LLVMModule, function: &LLVMFunction, _block: LLVMBasicBlockRef) -> LLVMValue { |     unsafe fn compile( | ||||||
|  |         &self, | ||||||
|  |         module: &LLVMModule, | ||||||
|  |         function: &LLVMFunction, | ||||||
|  |         _block: LLVMBasicBlockRef, | ||||||
|  |     ) -> LLVMValue { | ||||||
|         let _ty = self.value.get_type(module.builder).unwrap(); |         let _ty = self.value.get_type(module.builder).unwrap(); | ||||||
|         let name = into_cstring(self.name.clone()); |         let name = into_cstring(self.name.clone()); | ||||||
|         let val = unsafe { |         let val = unsafe { | ||||||
|             use super::Instr::*; |             use super::Instr::*; | ||||||
|             match &self.data.kind { |             match &self.data.kind { | ||||||
|                 Param(nth) => LLVMGetParam(function.value_ref, *nth as u32), |                 Param(nth) => LLVMGetParam(function.value_ref, *nth as u32), | ||||||
|                 Constant(val) => val.as_llvm(module.context_ref, module.builder_ref, &module.constants, &module.types), |                 Constant(val) => val.as_llvm( | ||||||
|  |                     module.context_ref, | ||||||
|  |                     module.builder_ref, | ||||||
|  |                     &module.constants, | ||||||
|  |                     &module.types, | ||||||
|  |                 ), | ||||||
|                 Add(lhs, rhs) => { |                 Add(lhs, rhs) => { | ||||||
|                     let lhs_val = module.values.get(&lhs).unwrap().value_ref; |                     let lhs_val = module.values.get(&lhs).unwrap().value_ref; | ||||||
|                     let rhs_val = module.values.get(&rhs).unwrap().value_ref; |                     let rhs_val = module.values.get(&rhs).unwrap().value_ref; | ||||||
| @ -1055,6 +1115,34 @@ impl InstructionHolder { | |||||||
|                     let val = module.values.get(&*instruction_value).unwrap().value_ref; |                     let val = module.values.get(&*instruction_value).unwrap().value_ref; | ||||||
|                     LLVMBuildIsNull(module.builder_ref, val, name.as_ptr()) |                     LLVMBuildIsNull(module.builder_ref, val, name.as_ptr()) | ||||||
|                 } |                 } | ||||||
|  |                 Function(function_value) => module.functions.get(function_value).unwrap().value_ref, | ||||||
|  |                 DynFunctionCall(function_value, instruction_values) => { | ||||||
|  |                     let fun = module.values.get(&*function_value).unwrap(); | ||||||
|  |                     let ret_ty = | ||||||
|  |                         LLVMGetReturnType(fun.ty.as_llvm(module.context_ref, &module.types)); | ||||||
|  | 
 | ||||||
|  |                     let mut param_list: Vec<LLVMValueRef> = instruction_values | ||||||
|  |                         .iter() | ||||||
|  |                         .map(|i| module.values.get(i).unwrap().value_ref) | ||||||
|  |                         .collect(); | ||||||
|  | 
 | ||||||
|  |                     let is_void = Type::Void.as_llvm(module.context_ref, &module.types) == ret_ty; | ||||||
|  |                     if is_void { | ||||||
|  |                         LLVMContextSetDiscardValueNames(module.context_ref, 1); | ||||||
|  |                     } | ||||||
|  |                     let value = LLVMBuildCall2( | ||||||
|  |                         module.builder_ref, | ||||||
|  |                         fun.ty.as_llvm(module.context_ref, &module.types), | ||||||
|  |                         fun.value_ref, | ||||||
|  |                         param_list.as_mut_ptr(), | ||||||
|  |                         param_list.len() as u32, | ||||||
|  |                         name.as_ptr(), | ||||||
|  |                     ); | ||||||
|  |                     if is_void { | ||||||
|  |                         LLVMContextSetDiscardValueNames(module.context_ref, 0); | ||||||
|  |                     } | ||||||
|  |                     value | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
|         if let Some(record) = &self.record { |         if let Some(record) = &self.record { | ||||||
| @ -1062,7 +1150,8 @@ impl InstructionHolder { | |||||||
| 
 | 
 | ||||||
|             unsafe { |             unsafe { | ||||||
|                 let mut addr = Vec::<u64>::new(); |                 let mut addr = Vec::<u64>::new(); | ||||||
|                 let expr = LLVMDIBuilderCreateExpression(debug.builder, addr.as_mut_ptr(), addr.len()); |                 let expr = | ||||||
|  |                     LLVMDIBuilderCreateExpression(debug.builder, addr.as_mut_ptr(), addr.len()); | ||||||
| 
 | 
 | ||||||
|                 let location = LLVMDIBuilderCreateDebugLocation( |                 let location = LLVMDIBuilderCreateDebugLocation( | ||||||
|                     module.context_ref, |                     module.context_ref, | ||||||
| @ -1073,22 +1162,26 @@ impl InstructionHolder { | |||||||
|                 ); |                 ); | ||||||
| 
 | 
 | ||||||
|                 match record.kind { |                 match record.kind { | ||||||
|                     DebugRecordKind::Declare(instruction_value) => LLVMDIBuilderInsertDeclareRecordBefore( |                     DebugRecordKind::Declare(instruction_value) => { | ||||||
|                         debug.builder, |                         LLVMDIBuilderInsertDeclareRecordBefore( | ||||||
|                         module.values.get(&instruction_value).unwrap().value_ref, |                             debug.builder, | ||||||
|                         *debug.metadata.get(&record.variable).unwrap(), |                             module.values.get(&instruction_value).unwrap().value_ref, | ||||||
|                         expr, |                             *debug.metadata.get(&record.variable).unwrap(), | ||||||
|                         location, |                             expr, | ||||||
|                         val, |                             location, | ||||||
|                     ), |                             val, | ||||||
|                     DebugRecordKind::Value(instruction_value) => LLVMDIBuilderInsertDbgValueRecordBefore( |                         ) | ||||||
|                         debug.builder, |                     } | ||||||
|                         module.values.get(&instruction_value).unwrap().value_ref, |                     DebugRecordKind::Value(instruction_value) => { | ||||||
|                         *debug.metadata.get(&record.variable).unwrap(), |                         LLVMDIBuilderInsertDbgValueRecordBefore( | ||||||
|                         expr, |                             debug.builder, | ||||||
|                         location, |                             module.values.get(&instruction_value).unwrap().value_ref, | ||||||
|                         val, |                             *debug.metadata.get(&record.variable).unwrap(), | ||||||
|                     ), |                             expr, | ||||||
|  |                             location, | ||||||
|  |                             val, | ||||||
|  |                         ) | ||||||
|  |                     } | ||||||
|                 }; |                 }; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @ -1101,7 +1194,13 @@ impl InstructionHolder { | |||||||
|                     | LLVMValueKind::LLVMMemoryPhiValueKind => { |                     | LLVMValueKind::LLVMMemoryPhiValueKind => { | ||||||
|                         LLVMInstructionSetDebugLoc( |                         LLVMInstructionSetDebugLoc( | ||||||
|                             val, |                             val, | ||||||
|                             *module.debug.as_ref().unwrap().locations.get(&location).unwrap(), |                             *module | ||||||
|  |                                 .debug | ||||||
|  |                                 .as_ref() | ||||||
|  |                                 .unwrap() | ||||||
|  |                                 .locations | ||||||
|  |                                 .get(&location) | ||||||
|  |                                 .unwrap(), | ||||||
|                         ); |                         ); | ||||||
|                     } |                     } | ||||||
|                     _ => {} |                     _ => {} | ||||||
| @ -1116,7 +1215,12 @@ impl InstructionHolder { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl TerminatorKind { | impl TerminatorKind { | ||||||
|     fn compile(&self, module: &LLVMModule, _function: &LLVMFunction, _block: LLVMBasicBlockRef) -> LLVMValue { |     fn compile( | ||||||
|  |         &self, | ||||||
|  |         module: &LLVMModule, | ||||||
|  |         _function: &LLVMFunction, | ||||||
|  |         _block: LLVMBasicBlockRef, | ||||||
|  |     ) -> LLVMValue { | ||||||
|         let _ty = self.get_type(module.builder).unwrap(); |         let _ty = self.get_type(module.builder).unwrap(); | ||||||
|         let val = unsafe { |         let val = unsafe { | ||||||
|             match self { |             match self { | ||||||
| @ -1226,7 +1330,11 @@ impl ConstValueKind { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Type { | impl Type { | ||||||
|     fn as_llvm(&self, context: LLVMContextRef, typemap: &HashMap<TypeValue, LLVMTypeRef>) -> LLVMTypeRef { |     fn as_llvm( | ||||||
|  |         &self, | ||||||
|  |         context: LLVMContextRef, | ||||||
|  |         typemap: &HashMap<TypeValue, LLVMTypeRef>, | ||||||
|  |     ) -> LLVMTypeRef { | ||||||
|         use Type::*; |         use Type::*; | ||||||
|         unsafe { |         unsafe { | ||||||
|             match self { |             match self { | ||||||
| @ -1247,6 +1355,18 @@ impl Type { | |||||||
|                 F80 => LLVMX86FP80TypeInContext(context), |                 F80 => LLVMX86FP80TypeInContext(context), | ||||||
|                 F128 => LLVMFP128TypeInContext(context), |                 F128 => LLVMFP128TypeInContext(context), | ||||||
|                 F128PPC => LLVMPPCFP128TypeInContext(context), |                 F128PPC => LLVMPPCFP128TypeInContext(context), | ||||||
|  |                 Function(params, ret) => { | ||||||
|  |                     let mut params_llvm = params | ||||||
|  |                         .iter() | ||||||
|  |                         .map(|v| v.as_llvm(context, typemap)) | ||||||
|  |                         .collect::<Vec<_>>(); | ||||||
|  |                     LLVMFunctionType( | ||||||
|  |                         ret.as_llvm(context, typemap), | ||||||
|  |                         params_llvm.as_mut_ptr(), | ||||||
|  |                         params_llvm.len() as u32, | ||||||
|  |                         0, | ||||||
|  |                     ) | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | |||||||
							
								
								
									
										61
									
								
								src/fmt.rs
									
									
									
									
									
								
							
							
						
						
									
										61
									
								
								src/fmt.rs
									
									
									
									
									
								
							| @ -9,10 +9,10 @@ use crate::{ | |||||||
|     CmpPredicate, Context, Instr, InstructionData, TerminatorKind, |     CmpPredicate, Context, Instr, InstructionData, TerminatorKind, | ||||||
|     builder::*, |     builder::*, | ||||||
|     debug_information::{ |     debug_information::{ | ||||||
|         DebugArrayType, DebugBasicType, DebugFieldType, DebugInformation, DebugLocalVariable, DebugLocation, |         DebugArrayType, DebugBasicType, DebugFieldType, DebugInformation, DebugLocalVariable, | ||||||
|         DebugLocationValue, DebugMetadata, DebugMetadataValue, DebugParamVariable, DebugPointerType, DebugPosition, |         DebugLocation, DebugLocationValue, DebugMetadata, DebugMetadataValue, DebugParamVariable, | ||||||
|         DebugRecordKind, DebugScopeValue, DebugStructType, DebugSubprogramType, DebugTypeData, DebugTypeHolder, |         DebugPointerType, DebugPosition, DebugRecordKind, DebugScopeValue, DebugStructType, | ||||||
|         DebugTypeValue, |         DebugSubprogramType, DebugTypeData, DebugTypeHolder, DebugTypeValue, | ||||||
|     }, |     }, | ||||||
|     pad_adapter::PadAdapter, |     pad_adapter::PadAdapter, | ||||||
| }; | }; | ||||||
| @ -68,7 +68,11 @@ impl FunctionHolder { | |||||||
|             .map(|p| format!("{:?}", p)) |             .map(|p| format!("{:?}", p)) | ||||||
|             .collect::<Vec<_>>() |             .collect::<Vec<_>>() | ||||||
|             .join(", "); |             .join(", "); | ||||||
|         write!(f, "fn {}({}) -> {:?} ", self.data.name, params, self.data.ret)?; |         write!( | ||||||
|  |             f, | ||||||
|  |             "fn {}({}) -> {:?} ", | ||||||
|  |             self.data.name, params, self.data.ret | ||||||
|  |         )?; | ||||||
| 
 | 
 | ||||||
|         writeln!(f, "{{")?; |         writeln!(f, "{{")?; | ||||||
|         let mut state = Default::default(); |         let mut state = Default::default(); | ||||||
| @ -112,7 +116,11 @@ impl BlockHolder { | |||||||
|             terminator.builder_fmt(&mut inner, builder, debug)?; |             terminator.builder_fmt(&mut inner, builder, debug)?; | ||||||
|         } |         } | ||||||
|         if let Some(location) = &self.data.terminator_location { |         if let Some(location) = &self.data.terminator_location { | ||||||
|             writeln!(inner, "  ^  (At {}) ", debug.as_ref().unwrap().get_location(location))?; |             writeln!( | ||||||
|  |                 inner, | ||||||
|  |                 "  ^  (At {}) ", | ||||||
|  |                 debug.as_ref().unwrap().get_location(location) | ||||||
|  |             )?; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         Ok(()) |         Ok(()) | ||||||
| @ -140,7 +148,11 @@ impl InstructionHolder { | |||||||
|                 writeln!(f, "  (Debug {} {})", record.variable.hr(debug), kind)?; |                 writeln!(f, "  (Debug {} {})", record.variable.hr(debug), kind)?; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         writeln!(f, "{:?} ({}) = {:?} ", self.value, self.name, self.data.kind)?; |         writeln!( | ||||||
|  |             f, | ||||||
|  |             "{:?} ({}) = {:?} ", | ||||||
|  |             self.value, self.name, self.data.kind | ||||||
|  |         )?; | ||||||
|         if let Some(debug) = debug { |         if let Some(debug) = debug { | ||||||
|             if let Some(location) = &self.data.location { |             if let Some(location) = &self.data.location { | ||||||
|                 writeln!(f, "  ^  (At {}) ", debug.get_location(location))?; |                 writeln!(f, "  ^  (At {}) ", debug.get_location(location))?; | ||||||
| @ -176,7 +188,9 @@ impl TerminatorKind { | |||||||
| impl DebugMetadataValue { | impl DebugMetadataValue { | ||||||
|     fn hr(&self, debug: &DebugInformation) -> String { |     fn hr(&self, debug: &DebugInformation) -> String { | ||||||
|         let kind = match debug.get_metadata(*self) { |         let kind = match debug.get_metadata(*self) { | ||||||
|             DebugMetadata::ParamVar(DebugParamVariable { name, arg_idx, ty, .. }) => { |             DebugMetadata::ParamVar(DebugParamVariable { | ||||||
|  |                 name, arg_idx, ty, .. | ||||||
|  |             }) => { | ||||||
|                 format!("param {} (idx {}) (type {:?}) ", name, arg_idx, ty) |                 format!("param {} (idx {}) (type {:?}) ", name, arg_idx, ty) | ||||||
|             } |             } | ||||||
|             DebugMetadata::LocalVar(DebugLocalVariable { name, ty, .. }) => { |             DebugMetadata::LocalVar(DebugLocalVariable { name, ty, .. }) => { | ||||||
| @ -241,11 +255,14 @@ impl Debug for FunctionHolder { | |||||||
| impl Debug for BlockHolder { | impl Debug for BlockHolder { | ||||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||||
|         let deleted = if self.data.deleted { " (deleted)" } else { "" }; |         let deleted = if self.data.deleted { " (deleted)" } else { "" }; | ||||||
|         f.debug_tuple(&format!("{}[{:?}]{} ", &self.data.name, &self.value, deleted)) |         f.debug_tuple(&format!( | ||||||
|             .field(&self.instructions) |             "{}[{:?}]{} ", | ||||||
|             .field(&self.data.terminator) |             &self.data.name, &self.value, deleted | ||||||
|             .field(&self.data.terminator_location) |         )) | ||||||
|             .finish() |         .field(&self.instructions) | ||||||
|  |         .field(&self.data.terminator) | ||||||
|  |         .field(&self.data.terminator_location) | ||||||
|  |         .finish() | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -288,7 +305,11 @@ impl Debug for BlockValue { | |||||||
| 
 | 
 | ||||||
| impl Debug for InstructionValue { | impl Debug for InstructionValue { | ||||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||||
|         write!(f, "%{}.{}.{}.{}", self.0.0.0.0, self.0.0.1, self.0.1, self.1) |         write!( | ||||||
|  |             f, | ||||||
|  |             "%{}.{}.{}.{}", | ||||||
|  |             self.0.0.0.0, self.0.0.1, self.0.1, self.1 | ||||||
|  |         ) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -350,7 +371,9 @@ impl Debug for Instr { | |||||||
|                 fmt_index(f, instruction_value, &index.to_string())?; |                 fmt_index(f, instruction_value, &index.to_string())?; | ||||||
|                 write!(f, ")") |                 write!(f, ")") | ||||||
|             } |             } | ||||||
|             Instr::ExtractValue(instruction_value, index) => fmt_index(f, instruction_value, &index.to_string()), |             Instr::ExtractValue(instruction_value, index) => { | ||||||
|  |                 fmt_index(f, instruction_value, &index.to_string()) | ||||||
|  |             } | ||||||
|             Instr::Trunc(instr_val, ty) => { |             Instr::Trunc(instr_val, ty) => { | ||||||
|                 write!(f, "{:?} to {:?} ({})", instr_val, ty, self.default_name()) |                 write!(f, "{:?} to {:?} ({})", instr_val, ty, self.default_name()) | ||||||
|             } |             } | ||||||
| @ -394,6 +417,8 @@ impl Debug for Instr { | |||||||
|             Instr::ShiftLeft(lhs, rhs) => fmt_binop(f, lhs, &"<<", rhs), |             Instr::ShiftLeft(lhs, rhs) => fmt_binop(f, lhs, &"<<", rhs), | ||||||
|             Instr::GetGlobal(global_value) => write!(f, "global {:?}", global_value), |             Instr::GetGlobal(global_value) => write!(f, "global {:?}", global_value), | ||||||
|             Instr::IsNull(_) => write!(f, "is_null"), |             Instr::IsNull(_) => write!(f, "is_null"), | ||||||
|  |             Instr::Function(function_value) => write!(f, "func {:?}", function_value), | ||||||
|  |             Instr::DynFunctionCall(fun, params) => fmt_call(f, fun, params), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -565,7 +590,11 @@ impl Debug for DebugScopeValue { | |||||||
|         write!( |         write!( | ||||||
|             f, |             f, | ||||||
|             "Scope[{}]", |             "Scope[{}]", | ||||||
|             self.0.iter().map(|v| v.to_string()).collect::<Vec<_>>().join(", ") |             self.0 | ||||||
|  |                 .iter() | ||||||
|  |                 .map(|v| v.to_string()) | ||||||
|  |                 .collect::<Vec<_>>() | ||||||
|  |                 .join(", ") | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -36,7 +36,9 @@ impl LLVMIntrinsic { | |||||||
|             LLVMIntrinsic::Max(ty) => { |             LLVMIntrinsic::Max(ty) => { | ||||||
|                 let name = match ty.category() { |                 let name = match ty.category() { | ||||||
|                     TypeCategory::SignedInteger => format!("llvm.smax.{}", ty.llvm_ty_str(builder)), |                     TypeCategory::SignedInteger => format!("llvm.smax.{}", ty.llvm_ty_str(builder)), | ||||||
|                     TypeCategory::UnsignedInteger => format!("llvm.umax.{}", ty.llvm_ty_str(builder)), |                     TypeCategory::UnsignedInteger => { | ||||||
|  |                         format!("llvm.umax.{}", ty.llvm_ty_str(builder)) | ||||||
|  |                     } | ||||||
|                     TypeCategory::Real => format!("llvm.maximum.{}", ty.llvm_ty_str(builder)), |                     TypeCategory::Real => format!("llvm.maximum.{}", ty.llvm_ty_str(builder)), | ||||||
|                     _ => return Err(crate::ErrorKind::Null), |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|                 }; |                 }; | ||||||
| @ -45,7 +47,9 @@ impl LLVMIntrinsic { | |||||||
|             LLVMIntrinsic::Min(ty) => { |             LLVMIntrinsic::Min(ty) => { | ||||||
|                 let name = match ty.category() { |                 let name = match ty.category() { | ||||||
|                     TypeCategory::SignedInteger => format!("llvm.smin.{}", ty.llvm_ty_str(builder)), |                     TypeCategory::SignedInteger => format!("llvm.smin.{}", ty.llvm_ty_str(builder)), | ||||||
|                     TypeCategory::UnsignedInteger => format!("llvm.umin.{}", ty.llvm_ty_str(builder)), |                     TypeCategory::UnsignedInteger => { | ||||||
|  |                         format!("llvm.umin.{}", ty.llvm_ty_str(builder)) | ||||||
|  |                     } | ||||||
|                     TypeCategory::Real => format!("llvm.minimum.{}", ty.llvm_ty_str(builder)), |                     TypeCategory::Real => format!("llvm.minimum.{}", ty.llvm_ty_str(builder)), | ||||||
|                     _ => return Err(crate::ErrorKind::Null), |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|                 }; |                 }; | ||||||
| @ -54,7 +58,9 @@ impl LLVMIntrinsic { | |||||||
|             LLVMIntrinsic::Abs(ty) => { |             LLVMIntrinsic::Abs(ty) => { | ||||||
|                 let name = match ty.category() { |                 let name = match ty.category() { | ||||||
|                     TypeCategory::SignedInteger => format!("llvm.abs.{}", ty.llvm_ty_str(builder)), |                     TypeCategory::SignedInteger => format!("llvm.abs.{}", ty.llvm_ty_str(builder)), | ||||||
|                     TypeCategory::UnsignedInteger => format!("llvm.abs.{}", ty.llvm_ty_str(builder)), |                     TypeCategory::UnsignedInteger => { | ||||||
|  |                         format!("llvm.abs.{}", ty.llvm_ty_str(builder)) | ||||||
|  |                     } | ||||||
|                     TypeCategory::Real => format!("llvm.fabs.{}", ty.llvm_ty_str(builder)), |                     TypeCategory::Real => format!("llvm.fabs.{}", ty.llvm_ty_str(builder)), | ||||||
|                     _ => return Err(crate::ErrorKind::Null), |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|                 }; |                 }; | ||||||
| @ -65,7 +71,11 @@ impl LLVMIntrinsic { | |||||||
|                     TypeCategory::Ptr => String::from("llvm.memcpy"), |                     TypeCategory::Ptr => String::from("llvm.memcpy"), | ||||||
|                     _ => return Err(crate::ErrorKind::Null), |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|                 }; |                 }; | ||||||
|                 Ok((name, vec![ty.clone(), ty.clone(), Type::U64, Type::Bool], Type::Void)) |                 Ok(( | ||||||
|  |                     name, | ||||||
|  |                     vec![ty.clone(), ty.clone(), Type::U64, Type::Bool], | ||||||
|  |                     Type::Void, | ||||||
|  |                 )) | ||||||
|             } |             } | ||||||
|             LLVMIntrinsic::Sqrt(ty) => { |             LLVMIntrinsic::Sqrt(ty) => { | ||||||
|                 let name = match ty.category() { |                 let name = match ty.category() { | ||||||
| @ -77,10 +87,18 @@ impl LLVMIntrinsic { | |||||||
|             LLVMIntrinsic::PowI(ty1, ty2) => { |             LLVMIntrinsic::PowI(ty1, ty2) => { | ||||||
|                 let name = match (ty1.category(), ty2.category()) { |                 let name = match (ty1.category(), ty2.category()) { | ||||||
|                     (TypeCategory::Real, TypeCategory::SignedInteger) => { |                     (TypeCategory::Real, TypeCategory::SignedInteger) => { | ||||||
|                         format!("llvm.powi.{}.{}", ty1.llvm_ty_str(builder), ty2.llvm_ty_str(builder)) |                         format!( | ||||||
|  |                             "llvm.powi.{}.{}", | ||||||
|  |                             ty1.llvm_ty_str(builder), | ||||||
|  |                             ty2.llvm_ty_str(builder) | ||||||
|  |                         ) | ||||||
|                     } |                     } | ||||||
|                     (TypeCategory::Real, TypeCategory::UnsignedInteger) => { |                     (TypeCategory::Real, TypeCategory::UnsignedInteger) => { | ||||||
|                         format!("llvm.powi.{}.{}", ty1.llvm_ty_str(builder), ty2.llvm_ty_str(builder)) |                         format!( | ||||||
|  |                             "llvm.powi.{}.{}", | ||||||
|  |                             ty1.llvm_ty_str(builder), | ||||||
|  |                             ty2.llvm_ty_str(builder) | ||||||
|  |                         ) | ||||||
|                     } |                     } | ||||||
|                     _ => return Err(crate::ErrorKind::Null), |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|                 }; |                 }; | ||||||
| @ -258,6 +276,14 @@ impl Type { | |||||||
|             } |             } | ||||||
|             Type::Array(ty, len) => format!("[{} x {}]", len, ty.llvm_ty_str(builder)), |             Type::Array(ty, len) => format!("[{} x {}]", len, ty.llvm_ty_str(builder)), | ||||||
|             Type::Ptr(_) => String::from("ptr"), |             Type::Ptr(_) => String::from("ptr"), | ||||||
|  |             Type::Function(params, ret) => format!( | ||||||
|  |                 "fn {:?} -> {}", | ||||||
|  |                 params | ||||||
|  |                     .iter() | ||||||
|  |                     .map(|v| v.llvm_ty_str(builder)) | ||||||
|  |                     .collect::<Vec<_>>(), | ||||||
|  |                 ret.llvm_ty_str(builder) | ||||||
|  |             ), | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										63
									
								
								src/lib.rs
									
									
									
									
									
								
							
							
						
						
									
										63
									
								
								src/lib.rs
									
									
									
									
									
								
							| @ -164,7 +164,10 @@ impl<'ctx> Module<'ctx> { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn create_debug_info(&mut self, file: DebugFileData) -> (DebugInformation, DebugScopeValue) { |     pub fn create_debug_info( | ||||||
|  |         &mut self, | ||||||
|  |         file: DebugFileData, | ||||||
|  |     ) -> (DebugInformation, DebugScopeValue) { | ||||||
|         let (debug_info, scope_value) = DebugInformation::from_file(file); |         let (debug_info, scope_value) = DebugInformation::from_file(file); | ||||||
|         self.debug_info = Some(debug_info.clone()); |         self.debug_info = Some(debug_info.clone()); | ||||||
|         (debug_info, scope_value) |         (debug_info, scope_value) | ||||||
| @ -327,12 +330,18 @@ impl Instr { | |||||||
|             Instr::ShiftLeft(..) => "shl", |             Instr::ShiftLeft(..) => "shl", | ||||||
|             Instr::GetGlobal(..) => "global", |             Instr::GetGlobal(..) => "global", | ||||||
|             Instr::IsNull(..) => "is_null", |             Instr::IsNull(..) => "is_null", | ||||||
|  |             Instr::Function(..) => "func", | ||||||
|  |             Instr::DynFunctionCall(..) => "call", | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<'builder> Block<'builder> { | impl<'builder> Block<'builder> { | ||||||
|     pub fn build_named<T: Into<String>>(&mut self, name: T, instruction: Instr) -> CompileResult<InstructionValue> { |     pub fn build_named<T: Into<String>>( | ||||||
|  |         &mut self, | ||||||
|  |         name: T, | ||||||
|  |         instruction: Instr, | ||||||
|  |     ) -> CompileResult<InstructionValue> { | ||||||
|         unsafe { |         unsafe { | ||||||
|             self.builder.add_instruction( |             self.builder.add_instruction( | ||||||
|                 &self.value, |                 &self.value, | ||||||
| @ -367,13 +376,15 @@ impl<'builder> Block<'builder> { | |||||||
| 
 | 
 | ||||||
|     pub fn set_instr_location(&self, instruction: InstructionValue, location: DebugLocationValue) { |     pub fn set_instr_location(&self, instruction: InstructionValue, location: DebugLocationValue) { | ||||||
|         unsafe { |         unsafe { | ||||||
|             self.builder.add_instruction_location(&instruction, location); |             self.builder | ||||||
|  |                 .add_instruction_location(&instruction, location); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn set_instr_metadata(&self, instruction: InstructionValue, location: DebugMetadataValue) { |     pub fn set_instr_metadata(&self, instruction: InstructionValue, location: DebugMetadataValue) { | ||||||
|         unsafe { |         unsafe { | ||||||
|             self.builder.add_instruction_metadata(&instruction, location); |             self.builder | ||||||
|  |                 .add_instruction_metadata(&instruction, location); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -425,6 +436,7 @@ pub enum Instr { | |||||||
|     Param(usize), |     Param(usize), | ||||||
|     Constant(ConstValueKind), |     Constant(ConstValueKind), | ||||||
|     GetGlobal(GlobalValue), |     GetGlobal(GlobalValue), | ||||||
|  |     Function(FunctionValue), | ||||||
| 
 | 
 | ||||||
|     /// Add two integers
 |     /// Add two integers
 | ||||||
|     Add(InstructionValue, InstructionValue), |     Add(InstructionValue, InstructionValue), | ||||||
| @ -524,6 +536,7 @@ pub enum Instr { | |||||||
|     IsNull(InstructionValue), |     IsNull(InstructionValue), | ||||||
| 
 | 
 | ||||||
|     FunctionCall(FunctionValue, Vec<InstructionValue>), |     FunctionCall(FunctionValue, Vec<InstructionValue>), | ||||||
|  |     DynFunctionCall(InstructionValue, Vec<InstructionValue>), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, PartialEq, Eq, Clone, Hash, PartialOrd)] | #[derive(Debug, PartialEq, Eq, Clone, Hash, PartialOrd)] | ||||||
| @ -550,6 +563,7 @@ pub enum Type { | |||||||
|     CustomType(TypeValue), |     CustomType(TypeValue), | ||||||
|     Array(Box<Type>, u64), |     Array(Box<Type>, u64), | ||||||
|     Ptr(Box<Type>), |     Ptr(Box<Type>), | ||||||
|  |     Function(Vec<Type>, Box<Type>), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, Clone)] | #[derive(Debug, Clone)] | ||||||
| @ -666,16 +680,25 @@ impl TypeCategory { | |||||||
| impl Type { | impl Type { | ||||||
|     pub fn category(&self) -> TypeCategory { |     pub fn category(&self) -> TypeCategory { | ||||||
|         match self { |         match self { | ||||||
|             Type::I8 | Type::I16 | Type::I32 | Type::I64 | Type::I128 => TypeCategory::SignedInteger, |             Type::I8 | Type::I16 | Type::I32 | Type::I64 | Type::I128 => { | ||||||
|             Type::U8 | Type::U16 | Type::U32 | Type::U64 | Type::U128 => TypeCategory::UnsignedInteger, |                 TypeCategory::SignedInteger | ||||||
|             Type::F16 | Type::F32B | Type::F32 | Type::F64 | Type::F80 | Type::F128 | Type::F128PPC => { |  | ||||||
|                 TypeCategory::Real |  | ||||||
|             } |             } | ||||||
|  |             Type::U8 | Type::U16 | Type::U32 | Type::U64 | Type::U128 => { | ||||||
|  |                 TypeCategory::UnsignedInteger | ||||||
|  |             } | ||||||
|  |             Type::F16 | ||||||
|  |             | Type::F32B | ||||||
|  |             | Type::F32 | ||||||
|  |             | Type::F64 | ||||||
|  |             | Type::F80 | ||||||
|  |             | Type::F128 | ||||||
|  |             | Type::F128PPC => TypeCategory::Real, | ||||||
|             Type::Bool => TypeCategory::UnsignedInteger, |             Type::Bool => TypeCategory::UnsignedInteger, | ||||||
|             Type::Void => TypeCategory::Void, |             Type::Void => TypeCategory::Void, | ||||||
|             Type::CustomType(_) => TypeCategory::CustomType, |             Type::CustomType(_) => TypeCategory::CustomType, | ||||||
|             Type::Array(_, _) => TypeCategory::Array, |             Type::Array(_, _) => TypeCategory::Array, | ||||||
|             Type::Ptr(_) => TypeCategory::Ptr, |             Type::Ptr(_) => TypeCategory::Ptr, | ||||||
|  |             Type::Function(..) => TypeCategory::Ptr, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -686,15 +709,23 @@ impl Type { | |||||||
|             (I16, I32 | I64 | I128) => Some(Instr::SExt(value, other.clone())), |             (I16, I32 | I64 | I128) => Some(Instr::SExt(value, other.clone())), | ||||||
|             (I32, I64 | I128) => Some(Instr::SExt(value, other.clone())), |             (I32, I64 | I128) => Some(Instr::SExt(value, other.clone())), | ||||||
|             (I64, I128) => Some(Instr::SExt(value, other.clone())), |             (I64, I128) => Some(Instr::SExt(value, other.clone())), | ||||||
|             (I128 | U128, I64 | U64 | I32 | U32 | I16 | U16 | I8 | U8) => Some(Instr::Trunc(value, other.clone())), |             (I128 | U128, I64 | U64 | I32 | U32 | I16 | U16 | I8 | U8) => { | ||||||
|             (I64 | U64, I32 | U32 | I16 | U16 | I8 | U8) => Some(Instr::Trunc(value, other.clone())), |                 Some(Instr::Trunc(value, other.clone())) | ||||||
|  |             } | ||||||
|  |             (I64 | U64, I32 | U32 | I16 | U16 | I8 | U8) => { | ||||||
|  |                 Some(Instr::Trunc(value, other.clone())) | ||||||
|  |             } | ||||||
|             (I32 | U32, I16 | U16 | I8 | U8) => Some(Instr::Trunc(value, other.clone())), |             (I32 | U32, I16 | U16 | I8 | U8) => Some(Instr::Trunc(value, other.clone())), | ||||||
|             (I16 | U16, I8 | U8) => Some(Instr::Trunc(value, other.clone())), |             (I16 | U16, I8 | U8) => Some(Instr::Trunc(value, other.clone())), | ||||||
|             (U8 | I8, U8 | I8 | U16 | I16 | U32 | I32 | U64 | I64 | U128 | I128) => { |             (U8 | I8, U8 | I8 | U16 | I16 | U32 | I32 | U64 | I64 | U128 | I128) => { | ||||||
|                 Some(Instr::ZExt(value, other.clone())) |                 Some(Instr::ZExt(value, other.clone())) | ||||||
|             } |             } | ||||||
|             (U16 | I16, U16 | I16 | U32 | I32 | U64 | I64 | U128 | I128) => Some(Instr::ZExt(value, other.clone())), |             (U16 | I16, U16 | I16 | U32 | I32 | U64 | I64 | U128 | I128) => { | ||||||
|             (U32 | I32, U32 | I32 | U64 | I64 | U128 | I128) => Some(Instr::ZExt(value, other.clone())), |                 Some(Instr::ZExt(value, other.clone())) | ||||||
|  |             } | ||||||
|  |             (U32 | I32, U32 | I32 | U64 | I64 | U128 | I128) => { | ||||||
|  |                 Some(Instr::ZExt(value, other.clone())) | ||||||
|  |             } | ||||||
|             (U64 | I64, U64 | I64 | U128 | I128) => Some(Instr::ZExt(value, other.clone())), |             (U64 | I64, U64 | I64 | U128 | I128) => Some(Instr::ZExt(value, other.clone())), | ||||||
|             (U128 | I128, U128 | I128) => Some(Instr::ZExt(value, other.clone())), |             (U128 | I128, U128 | I128) => Some(Instr::ZExt(value, other.clone())), | ||||||
|             (U8 | U16 | U32 | U64 | U128, F16 | F32 | F32B | F64 | F80 | F128 | F128PPC) => { |             (U8 | U16 | U32 | U64 | U128, F16 | F32 | F32B | F64 | F80 | F128 | F128PPC) => { | ||||||
| @ -715,11 +746,15 @@ impl Type { | |||||||
|             (Ptr(_), I128 | U128 | I64 | U64 | I32 | U32 | I16 | U16 | I8 | U8) => { |             (Ptr(_), I128 | U128 | I64 | U64 | I32 | U32 | I16 | U16 | I8 | U8) => { | ||||||
|                 Some(Instr::PtrToInt(value, other.clone())) |                 Some(Instr::PtrToInt(value, other.clone())) | ||||||
|             } |             } | ||||||
|             (F16, F32 | F32B | F64 | F80 | F128 | F128PPC) => Some(Instr::FPExt(value, other.clone())), |             (F16, F32 | F32B | F64 | F80 | F128 | F128PPC) => { | ||||||
|  |                 Some(Instr::FPExt(value, other.clone())) | ||||||
|  |             } | ||||||
|             (F32 | F32B, F64 | F80 | F128 | F128PPC) => Some(Instr::FPExt(value, other.clone())), |             (F32 | F32B, F64 | F80 | F128 | F128PPC) => Some(Instr::FPExt(value, other.clone())), | ||||||
|             (F64, F80 | F128 | F128PPC) => Some(Instr::FPExt(value, other.clone())), |             (F64, F80 | F128 | F128PPC) => Some(Instr::FPExt(value, other.clone())), | ||||||
|             (F80, F128 | F128PPC) => Some(Instr::FPExt(value, other.clone())), |             (F80, F128 | F128PPC) => Some(Instr::FPExt(value, other.clone())), | ||||||
|             (F128PPC | F128, F80 | F64 | F32B | F32 | F16) => Some(Instr::FPTrunc(value, other.clone())), |             (F128PPC | F128, F80 | F64 | F32B | F32 | F16) => { | ||||||
|  |                 Some(Instr::FPTrunc(value, other.clone())) | ||||||
|  |             } | ||||||
|             (F80, F64 | F32B | F32 | F16) => Some(Instr::FPTrunc(value, other.clone())), |             (F80, F64 | F32B | F32 | F16) => Some(Instr::FPTrunc(value, other.clone())), | ||||||
|             (F64, F32B | F32 | F16) => Some(Instr::FPTrunc(value, other.clone())), |             (F64, F32B | F32 | F16) => Some(Instr::FPTrunc(value, other.clone())), | ||||||
|             (F32B | F32, F16) => Some(Instr::FPTrunc(value, other.clone())), |             (F32B | F32, F16) => Some(Instr::FPTrunc(value, other.clone())), | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user