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 crate::{ | ||||
|     Block, BlockData, CompileResult, ConstValueKind, CustomTypeKind, ErrorKind, FunctionData, Instr, InstructionData, | ||||
|     ModuleData, NamedStruct, TerminatorKind, Type, TypeCategory, TypeData, | ||||
|     Block, BlockData, CompileResult, ConstValueKind, CustomTypeKind, ErrorKind, FunctionData, | ||||
|     Instr, InstructionData, ModuleData, NamedStruct, TerminatorKind, Type, TypeCategory, TypeData, | ||||
|     debug_information::{ | ||||
|         DebugInformation, DebugLocationValue, DebugMetadataValue, DebugScopeValue, InstructionDebugRecordData, | ||||
|         DebugInformation, DebugLocationValue, DebugMetadataValue, DebugScopeValue, | ||||
|         InstructionDebugRecordData, | ||||
|     }, | ||||
|     util::match_types, | ||||
| }; | ||||
| @ -114,7 +115,11 @@ impl Builder { | ||||
|         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 { | ||||
|             let mut modules = self.modules.borrow_mut(); | ||||
|             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 { | ||||
|             let mut modules = self.modules.borrow_mut(); | ||||
|             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 { | ||||
|             let mut modules = self.modules.borrow_mut(); | ||||
|             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 { | ||||
|             let mut modules = self.modules.borrow_mut(); | ||||
|             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 { | ||||
|             let mut modules = self.modules.borrow_mut(); | ||||
|             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 { | ||||
|             let mut modules = self.modules.borrow_mut(); | ||||
|             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 { | ||||
|             let mut modules = self.modules.borrow_mut(); | ||||
|             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 { | ||||
|             let mut modules = self.modules.borrow_mut(); | ||||
|             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 { | ||||
|             let mut modules = self.modules.borrow_mut(); | ||||
|             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) { | ||||
|                         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(()) | ||||
| @ -662,6 +706,14 @@ impl Builder { | ||||
|                         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 | ||||
|     } | ||||
| 
 | ||||
|     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 { | ||||
|             if let Some(location) = location { | ||||
|                 block.builder.add_instruction_location(&self, location); | ||||
| @ -822,6 +878,17 @@ impl InstructionValue { | ||||
|                     Ok(kind.get_type()) | ||||
|                 } | ||||
|                 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, | ||||
|     }, | ||||
|     target_machine::{ | ||||
|         LLVMCodeGenFileType, LLVMCreateTargetDataLayout, LLVMCreateTargetMachine, LLVMGetDefaultTargetTriple, | ||||
|         LLVMGetTargetFromTriple, LLVMTargetMachineEmitToMemoryBuffer, | ||||
|         LLVMCodeGenFileType, LLVMCreateTargetDataLayout, LLVMCreateTargetMachine, | ||||
|         LLVMGetDefaultTargetTriple, LLVMGetTargetFromTriple, LLVMTargetMachineEmitToMemoryBuffer, | ||||
|     }, | ||||
| }; | ||||
| 
 | ||||
| @ -35,8 +35,8 @@ use crate::{ | ||||
| use super::{ | ||||
|     CmpPredicate, ConstValueKind, Context, TerminatorKind, Type, | ||||
|     builder::{ | ||||
|         BlockHolder, BlockValue, Builder, FunctionHolder, FunctionValue, InstructionHolder, InstructionValue, | ||||
|         ModuleHolder, | ||||
|         BlockHolder, BlockValue, Builder, FunctionHolder, FunctionValue, InstructionHolder, | ||||
|         InstructionValue, ModuleHolder, | ||||
|     }, | ||||
| }; | ||||
| 
 | ||||
| @ -120,8 +120,8 @@ impl CompiledModule { | ||||
|             ); | ||||
|             err.into_result().unwrap(); | ||||
| 
 | ||||
|             let llvm_ir = | ||||
|                 from_cstring(LLVMPrintModuleToString(self.module_ref)).expect("Unable to print LLVM IR to string"); | ||||
|             let llvm_ir = from_cstring(LLVMPrintModuleToString(self.module_ref)) | ||||
|                 .expect("Unable to print LLVM IR to string"); | ||||
| 
 | ||||
|             let mut err = ErrorMessageHolder::null(); | ||||
|             LLVMVerifyModule( | ||||
| @ -231,8 +231,10 @@ pub struct LLVMValue { | ||||
| impl ModuleHolder { | ||||
|     fn compile(&self, context: &LLVMContext, builder: &Builder) -> LLVMModuleRef { | ||||
|         unsafe { | ||||
|             let module_ref = | ||||
|                 LLVMModuleCreateWithNameInContext(into_cstring(&self.data.name).as_ptr(), context.context_ref); | ||||
|             let module_ref = LLVMModuleCreateWithNameInContext( | ||||
|                 into_cstring(&self.data.name).as_ptr(), | ||||
|                 context.context_ref, | ||||
|             ); | ||||
| 
 | ||||
|             // Compile the contents
 | ||||
| 
 | ||||
| @ -327,9 +329,12 @@ impl ModuleHolder { | ||||
|                     constant.value, | ||||
|                     LLVMValue { | ||||
|                         ty: constant.kind.get_type(), | ||||
|                         value_ref: constant | ||||
|                             .kind | ||||
|                             .as_llvm(context.context_ref, context.builder_ref, &constants, &types), | ||||
|                         value_ref: constant.kind.as_llvm( | ||||
|                             context.context_ref, | ||||
|                             context.builder_ref, | ||||
|                             &constants, | ||||
|                             &types, | ||||
|                         ), | ||||
|                     }, | ||||
|                 ); | ||||
|             } | ||||
| @ -357,7 +362,12 @@ impl ModuleHolder { | ||||
|                         scope = Ref::map(scope, |v| v.inner_scopes.get_unchecked(*i)); | ||||
|                     } | ||||
|                     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 { | ||||
|     unsafe fn compile(&self, context: &LLVMContext, debug: &LLVMDebugInformation) -> LLVMMetadataRef { | ||||
|     unsafe fn compile( | ||||
|         &self, | ||||
|         context: &LLVMContext, | ||||
|         debug: &LLVMDebugInformation, | ||||
|     ) -> LLVMMetadataRef { | ||||
|         unsafe { | ||||
|             LLVMDIBuilderCreateDebugLocation( | ||||
|                 context.context_ref, | ||||
| @ -515,7 +529,8 @@ impl DebugTypeHolder { | ||||
|                     ptr.name.len(), | ||||
|                 ), | ||||
|                 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]; | ||||
|                     LLVMDIBuilderCreateArrayType( | ||||
|                         debug.builder, | ||||
| @ -577,7 +592,11 @@ impl DwarfFlags { | ||||
| } | ||||
| 
 | ||||
| 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 { | ||||
|             match &self.data.kind { | ||||
|                 CustomTypeKind::NamedStruct(named_struct) => { | ||||
| @ -585,9 +604,16 @@ impl TypeHolder { | ||||
|                     for ty in &named_struct.1 { | ||||
|                         elem_types.push(ty.as_llvm(context.context_ref, types)); | ||||
|                     } | ||||
|                     let struct_ty = | ||||
|                         LLVMStructCreateNamed(context.context_ref, into_cstring(named_struct.0.clone()).as_ptr()); | ||||
|                     LLVMStructSetBody(struct_ty, elem_types.as_mut_ptr(), elem_types.len() as u32, 0); | ||||
|                     let struct_ty = LLVMStructCreateNamed( | ||||
|                         context.context_ref, | ||||
|                         into_cstring(named_struct.0.clone()).as_ptr(), | ||||
|                     ); | ||||
|                     LLVMStructSetBody( | ||||
|                         struct_ty, | ||||
|                         elem_types.as_mut_ptr(), | ||||
|                         elem_types.len() as u32, | ||||
|                         0, | ||||
|                     ); | ||||
|                     struct_ty | ||||
|                 } | ||||
|             } | ||||
| @ -617,7 +643,13 @@ impl FunctionHolder { | ||||
|             let name = if self.data.flags.is_main { | ||||
|                 c"main" | ||||
|             } 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); | ||||
| @ -625,7 +657,11 @@ impl FunctionHolder { | ||||
|             let function_ref = LLVMAddFunction(module_ref, name.as_ptr(), fn_type); | ||||
| 
 | ||||
|             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); | ||||
|             } | ||||
| 
 | ||||
| @ -688,7 +724,10 @@ impl FunctionHolder { | ||||
| 
 | ||||
|             if self.data.flags.is_imported { | ||||
|                 if self.data.flags.is_extern { | ||||
|                     LLVMSetLinkage(own_function.value_ref, LLVMLinkage::LLVMAvailableExternallyLinkage); | ||||
|                     LLVMSetLinkage( | ||||
|                         own_function.value_ref, | ||||
|                         LLVMLinkage::LLVMAvailableExternallyLinkage, | ||||
|                     ); | ||||
|                 } else { | ||||
|                     LLVMSetLinkage(own_function.value_ref, LLVMLinkage::LLVMExternalLinkage); | ||||
|                 } | ||||
| @ -705,8 +744,10 @@ impl FunctionHolder { | ||||
|                     continue; | ||||
|                 } | ||||
| 
 | ||||
|                 let block_ref = | ||||
|                     LLVMCreateBasicBlockInContext(module.context_ref, into_cstring(&block.data.name).as_ptr()); | ||||
|                 let block_ref = LLVMCreateBasicBlockInContext( | ||||
|                     module.context_ref, | ||||
|                     into_cstring(&block.data.name).as_ptr(), | ||||
|                 ); | ||||
|                 LLVMAppendExistingBasicBlock(own_function.value_ref, block_ref); | ||||
|                 module.blocks.insert(block.value, block_ref); | ||||
|             } | ||||
| @ -738,13 +779,22 @@ impl BlockHolder { | ||||
|                 .data | ||||
|                 .terminator | ||||
|                 .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); | ||||
| 
 | ||||
|             if let Some(location) = &self.data.terminator_location { | ||||
|                 LLVMInstructionSetDebugLoc( | ||||
|                     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 { | ||||
|     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 name = into_cstring(self.name.clone()); | ||||
|         let val = unsafe { | ||||
|             use super::Instr::*; | ||||
|             match &self.data.kind { | ||||
|                 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) => { | ||||
|                     let lhs_val = module.values.get(&lhs).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; | ||||
|                     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 { | ||||
| @ -1062,7 +1150,8 @@ impl InstructionHolder { | ||||
| 
 | ||||
|             unsafe { | ||||
|                 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( | ||||
|                     module.context_ref, | ||||
| @ -1073,22 +1162,26 @@ impl InstructionHolder { | ||||
|                 ); | ||||
| 
 | ||||
|                 match record.kind { | ||||
|                     DebugRecordKind::Declare(instruction_value) => LLVMDIBuilderInsertDeclareRecordBefore( | ||||
|                         debug.builder, | ||||
|                         module.values.get(&instruction_value).unwrap().value_ref, | ||||
|                         *debug.metadata.get(&record.variable).unwrap(), | ||||
|                         expr, | ||||
|                         location, | ||||
|                         val, | ||||
|                     ), | ||||
|                     DebugRecordKind::Value(instruction_value) => LLVMDIBuilderInsertDbgValueRecordBefore( | ||||
|                         debug.builder, | ||||
|                         module.values.get(&instruction_value).unwrap().value_ref, | ||||
|                         *debug.metadata.get(&record.variable).unwrap(), | ||||
|                         expr, | ||||
|                         location, | ||||
|                         val, | ||||
|                     ), | ||||
|                     DebugRecordKind::Declare(instruction_value) => { | ||||
|                         LLVMDIBuilderInsertDeclareRecordBefore( | ||||
|                             debug.builder, | ||||
|                             module.values.get(&instruction_value).unwrap().value_ref, | ||||
|                             *debug.metadata.get(&record.variable).unwrap(), | ||||
|                             expr, | ||||
|                             location, | ||||
|                             val, | ||||
|                         ) | ||||
|                     } | ||||
|                     DebugRecordKind::Value(instruction_value) => { | ||||
|                         LLVMDIBuilderInsertDbgValueRecordBefore( | ||||
|                             debug.builder, | ||||
|                             module.values.get(&instruction_value).unwrap().value_ref, | ||||
|                             *debug.metadata.get(&record.variable).unwrap(), | ||||
|                             expr, | ||||
|                             location, | ||||
|                             val, | ||||
|                         ) | ||||
|                     } | ||||
|                 }; | ||||
|             } | ||||
|         } | ||||
| @ -1101,7 +1194,13 @@ impl InstructionHolder { | ||||
|                     | LLVMValueKind::LLVMMemoryPhiValueKind => { | ||||
|                         LLVMInstructionSetDebugLoc( | ||||
|                             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 { | ||||
|     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 val = unsafe { | ||||
|             match self { | ||||
| @ -1226,7 +1330,11 @@ impl ConstValueKind { | ||||
| } | ||||
| 
 | ||||
| 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::*; | ||||
|         unsafe { | ||||
|             match self { | ||||
| @ -1247,6 +1355,18 @@ impl Type { | ||||
|                 F80 => LLVMX86FP80TypeInContext(context), | ||||
|                 F128 => LLVMFP128TypeInContext(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, | ||||
|     builder::*, | ||||
|     debug_information::{ | ||||
|         DebugArrayType, DebugBasicType, DebugFieldType, DebugInformation, DebugLocalVariable, DebugLocation, | ||||
|         DebugLocationValue, DebugMetadata, DebugMetadataValue, DebugParamVariable, DebugPointerType, DebugPosition, | ||||
|         DebugRecordKind, DebugScopeValue, DebugStructType, DebugSubprogramType, DebugTypeData, DebugTypeHolder, | ||||
|         DebugTypeValue, | ||||
|         DebugArrayType, DebugBasicType, DebugFieldType, DebugInformation, DebugLocalVariable, | ||||
|         DebugLocation, DebugLocationValue, DebugMetadata, DebugMetadataValue, DebugParamVariable, | ||||
|         DebugPointerType, DebugPosition, DebugRecordKind, DebugScopeValue, DebugStructType, | ||||
|         DebugSubprogramType, DebugTypeData, DebugTypeHolder, DebugTypeValue, | ||||
|     }, | ||||
|     pad_adapter::PadAdapter, | ||||
| }; | ||||
| @ -68,7 +68,11 @@ impl FunctionHolder { | ||||
|             .map(|p| format!("{:?}", p)) | ||||
|             .collect::<Vec<_>>() | ||||
|             .join(", "); | ||||
|         write!(f, "fn {}({}) -> {:?} ", self.data.name, params, self.data.ret)?; | ||||
|         write!( | ||||
|             f, | ||||
|             "fn {}({}) -> {:?} ", | ||||
|             self.data.name, params, self.data.ret | ||||
|         )?; | ||||
| 
 | ||||
|         writeln!(f, "{{")?; | ||||
|         let mut state = Default::default(); | ||||
| @ -112,7 +116,11 @@ impl BlockHolder { | ||||
|             terminator.builder_fmt(&mut inner, builder, debug)?; | ||||
|         } | ||||
|         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(()) | ||||
| @ -140,7 +148,11 @@ impl InstructionHolder { | ||||
|                 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(location) = &self.data.location { | ||||
|                 writeln!(f, "  ^  (At {}) ", debug.get_location(location))?; | ||||
| @ -176,7 +188,9 @@ impl TerminatorKind { | ||||
| impl DebugMetadataValue { | ||||
|     fn hr(&self, debug: &DebugInformation) -> String { | ||||
|         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) | ||||
|             } | ||||
|             DebugMetadata::LocalVar(DebugLocalVariable { name, ty, .. }) => { | ||||
| @ -241,11 +255,14 @@ impl Debug for FunctionHolder { | ||||
| impl Debug for BlockHolder { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         let deleted = if self.data.deleted { " (deleted)" } else { "" }; | ||||
|         f.debug_tuple(&format!("{}[{:?}]{} ", &self.data.name, &self.value, deleted)) | ||||
|             .field(&self.instructions) | ||||
|             .field(&self.data.terminator) | ||||
|             .field(&self.data.terminator_location) | ||||
|             .finish() | ||||
|         f.debug_tuple(&format!( | ||||
|             "{}[{:?}]{} ", | ||||
|             &self.data.name, &self.value, deleted | ||||
|         )) | ||||
|         .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 { | ||||
|     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())?; | ||||
|                 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) => { | ||||
|                 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::GetGlobal(global_value) => write!(f, "global {:?}", global_value), | ||||
|             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!( | ||||
|             f, | ||||
|             "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) => { | ||||
|                 let name = match ty.category() { | ||||
|                     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)), | ||||
|                     _ => return Err(crate::ErrorKind::Null), | ||||
|                 }; | ||||
| @ -45,7 +47,9 @@ impl LLVMIntrinsic { | ||||
|             LLVMIntrinsic::Min(ty) => { | ||||
|                 let name = match ty.category() { | ||||
|                     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)), | ||||
|                     _ => return Err(crate::ErrorKind::Null), | ||||
|                 }; | ||||
| @ -54,7 +58,9 @@ impl LLVMIntrinsic { | ||||
|             LLVMIntrinsic::Abs(ty) => { | ||||
|                 let name = match ty.category() { | ||||
|                     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)), | ||||
|                     _ => return Err(crate::ErrorKind::Null), | ||||
|                 }; | ||||
| @ -65,7 +71,11 @@ impl LLVMIntrinsic { | ||||
|                     TypeCategory::Ptr => String::from("llvm.memcpy"), | ||||
|                     _ => 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) => { | ||||
|                 let name = match ty.category() { | ||||
| @ -77,10 +87,18 @@ impl LLVMIntrinsic { | ||||
|             LLVMIntrinsic::PowI(ty1, ty2) => { | ||||
|                 let name = match (ty1.category(), ty2.category()) { | ||||
|                     (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) => { | ||||
|                         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), | ||||
|                 }; | ||||
| @ -258,6 +276,14 @@ impl Type { | ||||
|             } | ||||
|             Type::Array(ty, len) => format!("[{} x {}]", len, ty.llvm_ty_str(builder)), | ||||
|             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); | ||||
|         self.debug_info = Some(debug_info.clone()); | ||||
|         (debug_info, scope_value) | ||||
| @ -327,12 +330,18 @@ impl Instr { | ||||
|             Instr::ShiftLeft(..) => "shl", | ||||
|             Instr::GetGlobal(..) => "global", | ||||
|             Instr::IsNull(..) => "is_null", | ||||
|             Instr::Function(..) => "func", | ||||
|             Instr::DynFunctionCall(..) => "call", | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 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 { | ||||
|             self.builder.add_instruction( | ||||
|                 &self.value, | ||||
| @ -367,13 +376,15 @@ impl<'builder> Block<'builder> { | ||||
| 
 | ||||
|     pub fn set_instr_location(&self, instruction: InstructionValue, location: DebugLocationValue) { | ||||
|         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) { | ||||
|         unsafe { | ||||
|             self.builder.add_instruction_metadata(&instruction, location); | ||||
|             self.builder | ||||
|                 .add_instruction_metadata(&instruction, location); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -425,6 +436,7 @@ pub enum Instr { | ||||
|     Param(usize), | ||||
|     Constant(ConstValueKind), | ||||
|     GetGlobal(GlobalValue), | ||||
|     Function(FunctionValue), | ||||
| 
 | ||||
|     /// Add two integers
 | ||||
|     Add(InstructionValue, InstructionValue), | ||||
| @ -524,6 +536,7 @@ pub enum Instr { | ||||
|     IsNull(InstructionValue), | ||||
| 
 | ||||
|     FunctionCall(FunctionValue, Vec<InstructionValue>), | ||||
|     DynFunctionCall(InstructionValue, Vec<InstructionValue>), | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, PartialEq, Eq, Clone, Hash, PartialOrd)] | ||||
| @ -550,6 +563,7 @@ pub enum Type { | ||||
|     CustomType(TypeValue), | ||||
|     Array(Box<Type>, u64), | ||||
|     Ptr(Box<Type>), | ||||
|     Function(Vec<Type>, Box<Type>), | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
| @ -666,16 +680,25 @@ impl TypeCategory { | ||||
| impl Type { | ||||
|     pub fn category(&self) -> TypeCategory { | ||||
|         match self { | ||||
|             Type::I8 | Type::I16 | Type::I32 | Type::I64 | Type::I128 => TypeCategory::SignedInteger, | ||||
|             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::I8 | Type::I16 | Type::I32 | Type::I64 | Type::I128 => { | ||||
|                 TypeCategory::SignedInteger | ||||
|             } | ||||
|             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::Void => TypeCategory::Void, | ||||
|             Type::CustomType(_) => TypeCategory::CustomType, | ||||
|             Type::Array(_, _) => TypeCategory::Array, | ||||
|             Type::Ptr(_) => TypeCategory::Ptr, | ||||
|             Type::Function(..) => TypeCategory::Ptr, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -686,15 +709,23 @@ impl Type { | ||||
|             (I16, 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())), | ||||
|             (I128 | U128, I64 | U64 | I32 | U32 | I16 | U16 | I8 | U8) => Some(Instr::Trunc(value, other.clone())), | ||||
|             (I64 | U64, I32 | U32 | I16 | U16 | I8 | U8) => Some(Instr::Trunc(value, other.clone())), | ||||
|             (I128 | U128, I64 | U64 | I32 | U32 | I16 | U16 | I8 | U8) => { | ||||
|                 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())), | ||||
|             (I16 | U16, I8 | U8) => Some(Instr::Trunc(value, other.clone())), | ||||
|             (U8 | I8, U8 | I8 | U16 | I16 | U32 | I32 | U64 | I64 | U128 | I128) => { | ||||
|                 Some(Instr::ZExt(value, other.clone())) | ||||
|             } | ||||
|             (U16 | I16, U16 | I16 | U32 | I32 | U64 | I64 | U128 | I128) => Some(Instr::ZExt(value, other.clone())), | ||||
|             (U32 | I32, U32 | I32 | U64 | I64 | U128 | I128) => Some(Instr::ZExt(value, other.clone())), | ||||
|             (U16 | I16, U16 | I16 | U32 | I32 | U64 | I64 | U128 | I128) => { | ||||
|                 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())), | ||||
|             (U128 | I128, U128 | I128) => Some(Instr::ZExt(value, other.clone())), | ||||
|             (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) => { | ||||
|                 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())), | ||||
|             (F64, 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())), | ||||
|             (F64, 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