Implement builtin associated alloca and nullptr
This commit is contained in:
		
							parent
							
								
									acc2964305
								
							
						
					
					
						commit
						7b27f30b9e
					
				| @ -24,5 +24,11 @@ fn main() -> u32 { | ||||
|     print(from_str("i32: ") + i32::test(54) as u64); | ||||
|     print(from_str("sizeof i32: ") + i32::sizeof()); | ||||
| 
 | ||||
|     let nullptr = i32::null(); | ||||
|     let mut list = u64::alloca(15); | ||||
|     list[4] = 17; | ||||
| 
 | ||||
|     print(from_str("value: ") + list[4]); | ||||
| 
 | ||||
|     return i32::sizeof() as u32; | ||||
| } | ||||
|  | ||||
| @ -4,11 +4,10 @@ | ||||
| use std::{cell::RefCell, rc::Rc}; | ||||
| 
 | ||||
| use crate::{ | ||||
|     Block, BlockData, CompileResult, CustomTypeKind, ErrorKind, FunctionData, Instr, | ||||
|     InstructionData, ModuleData, NamedStruct, TerminatorKind, Type, TypeCategory, TypeData, | ||||
|     Block, BlockData, CompileResult, CustomTypeKind, ErrorKind, FunctionData, Instr, InstructionData, ModuleData, | ||||
|     NamedStruct, TerminatorKind, Type, TypeCategory, TypeData, | ||||
|     debug_information::{ | ||||
|         DebugInformation, DebugLocationValue, DebugMetadataValue, DebugProgramValue, | ||||
|         InstructionDebugRecordData, | ||||
|         DebugInformation, DebugLocationValue, DebugMetadataValue, DebugProgramValue, InstructionDebugRecordData, | ||||
|     }, | ||||
|     util::match_types, | ||||
| }; | ||||
| @ -91,11 +90,7 @@ 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); | ||||
| @ -113,11 +108,7 @@ 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); | ||||
| @ -174,11 +165,7 @@ impl Builder { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     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); | ||||
| @ -189,11 +176,7 @@ 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); | ||||
| @ -204,11 +187,7 @@ 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); | ||||
| @ -219,11 +198,7 @@ impl Builder { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub(crate) unsafe fn set_debug_subprogram( | ||||
|         &self, | ||||
|         value: &FunctionValue, | ||||
|         subprogram: DebugProgramValue, | ||||
|     ) { | ||||
|     pub(crate) unsafe fn set_debug_subprogram(&self, value: &FunctionValue, subprogram: DebugProgramValue) { | ||||
|         unsafe { | ||||
|             let mut modules = self.modules.borrow_mut(); | ||||
|             let module = modules.get_unchecked_mut(value.0.0); | ||||
| @ -232,11 +207,7 @@ 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); | ||||
| @ -354,22 +325,94 @@ impl Builder { | ||||
|             match self.instr_data(&instruction).kind { | ||||
|                 Instr::Param(_) => Ok(()), | ||||
|                 Instr::Constant(_) => Ok(()), | ||||
|                 Instr::Add(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), | ||||
|                 Instr::FAdd(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), | ||||
|                 Instr::Sub(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), | ||||
|                 Instr::FSub(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), | ||||
|                 Instr::Mul(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), | ||||
|                 Instr::FMul(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), | ||||
|                 Instr::UDiv(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), | ||||
|                 Instr::SDiv(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), | ||||
|                 Instr::FDiv(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), | ||||
|                 Instr::URem(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), | ||||
|                 Instr::SRem(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), | ||||
|                 Instr::FRem(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), | ||||
|                 Instr::Add(lhs, rhs) => { | ||||
|                     if match_types(&lhs, &rhs, &self)?.category().integer() { | ||||
|                         Ok(()) | ||||
|                     } else { | ||||
|                         Err(ErrorKind::Null) | ||||
|                     } | ||||
|                 } | ||||
|                 Instr::FAdd(lhs, rhs) => { | ||||
|                     if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::Real { | ||||
|                         Ok(()) | ||||
|                     } else { | ||||
|                         Err(ErrorKind::Null) | ||||
|                     } | ||||
|                 } | ||||
|                 Instr::Sub(lhs, rhs) => { | ||||
|                     if match_types(&lhs, &rhs, &self)?.category().integer() { | ||||
|                         Ok(()) | ||||
|                     } else { | ||||
|                         Err(ErrorKind::Null) | ||||
|                     } | ||||
|                 } | ||||
|                 Instr::FSub(lhs, rhs) => { | ||||
|                     if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::Real { | ||||
|                         Ok(()) | ||||
|                     } else { | ||||
|                         Err(ErrorKind::Null) | ||||
|                     } | ||||
|                 } | ||||
|                 Instr::Mul(lhs, rhs) => { | ||||
|                     if match_types(&lhs, &rhs, &self)?.category().integer() { | ||||
|                         Ok(()) | ||||
|                     } else { | ||||
|                         Err(ErrorKind::Null) | ||||
|                     } | ||||
|                 } | ||||
|                 Instr::FMul(lhs, rhs) => { | ||||
|                     if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::Real { | ||||
|                         Ok(()) | ||||
|                     } else { | ||||
|                         Err(ErrorKind::Null) | ||||
|                     } | ||||
|                 } | ||||
|                 Instr::UDiv(lhs, rhs) => { | ||||
|                     if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::UnsignedInteger { | ||||
|                         Ok(()) | ||||
|                     } else { | ||||
|                         Err(ErrorKind::Null) | ||||
|                     } | ||||
|                 } | ||||
|                 Instr::SDiv(lhs, rhs) => { | ||||
|                     if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::SignedInteger { | ||||
|                         Ok(()) | ||||
|                     } else { | ||||
|                         Err(ErrorKind::Null) | ||||
|                     } | ||||
|                 } | ||||
|                 Instr::FDiv(lhs, rhs) => { | ||||
|                     if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::Real { | ||||
|                         Ok(()) | ||||
|                     } else { | ||||
|                         Err(ErrorKind::Null) | ||||
|                     } | ||||
|                 } | ||||
|                 Instr::URem(lhs, rhs) => { | ||||
|                     if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::UnsignedInteger { | ||||
|                         Ok(()) | ||||
|                     } else { | ||||
|                         Err(ErrorKind::Null) | ||||
|                     } | ||||
|                 } | ||||
|                 Instr::SRem(lhs, rhs) => { | ||||
|                     if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::SignedInteger { | ||||
|                         Ok(()) | ||||
|                     } else { | ||||
|                         Err(ErrorKind::Null) | ||||
|                     } | ||||
|                 } | ||||
|                 Instr::FRem(lhs, rhs) => { | ||||
|                     if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::Real { | ||||
|                         Ok(()) | ||||
|                     } else { | ||||
|                         Err(ErrorKind::Null) | ||||
|                     } | ||||
|                 } | ||||
|                 Instr::And(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), | ||||
|                 Instr::ICmp(_, lhs, rhs) => { | ||||
|                     let t = match_types(&lhs, &rhs, self)?; | ||||
|                     if t.comparable() || t.category() != TypeCategory::Integer { | ||||
|                     if t.category().comparable() || !t.category().integer() { | ||||
|                         Ok(()) | ||||
|                     } else { | ||||
|                         Err(ErrorKind::Null) // TODO error: Types not comparable
 | ||||
| @ -377,7 +420,7 @@ impl Builder { | ||||
|                 } | ||||
|                 Instr::FCmp(_, lhs, rhs) => { | ||||
|                     let t = match_types(&lhs, &rhs, self)?; | ||||
|                     if t.comparable() || t.category() != TypeCategory::Real { | ||||
|                     if t.category().comparable() || t.category() != TypeCategory::Real { | ||||
|                         Ok(()) | ||||
|                     } else { | ||||
|                         Err(ErrorKind::Null) // TODO error: Types not comparable
 | ||||
| @ -430,7 +473,13 @@ impl Builder { | ||||
|                         Err(ErrorKind::Null) // TODO error: not a pointer
 | ||||
|                     } | ||||
|                 } | ||||
|                 Instr::ArrayAlloca(_, _) => Ok(()), | ||||
|                 Instr::ArrayAlloca(_, val) => { | ||||
|                     if val.get_type(self)?.category() == TypeCategory::UnsignedInteger { | ||||
|                         Ok(()) | ||||
|                     } else { | ||||
|                         Err(ErrorKind::Null) // TODO error: not a pointer
 | ||||
|                     } | ||||
|                 } | ||||
|                 Instr::GetElemPtr(ptr_val, _) => { | ||||
|                     let ptr_ty = ptr_val.get_type(&self)?; | ||||
|                     match ptr_ty { | ||||
| @ -526,11 +575,7 @@ 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); | ||||
| @ -572,10 +617,7 @@ impl InstructionValue { | ||||
|                 ICmp(_, _, _) => Ok(Type::Bool), | ||||
|                 FCmp(_, _, _) => Ok(Type::Bool), | ||||
|                 FunctionCall(function_value, _) => Ok(builder.function_data(function_value).ret), | ||||
|                 Phi(values) => values | ||||
|                     .first() | ||||
|                     .ok_or(ErrorKind::Null) | ||||
|                     .and_then(|v| v.get_type(&builder)), | ||||
|                 Phi(values) => values.first().ok_or(ErrorKind::Null).and_then(|v| v.get_type(&builder)), | ||||
|                 Alloca(ty) => Ok(Type::Ptr(Box::new(ty.clone()))), | ||||
|                 Load(_, ty) => Ok(ty.clone()), | ||||
|                 Store(_, value) => value.get_type(builder), | ||||
|  | ||||
| @ -19,8 +19,8 @@ use llvm_sys::{ | ||||
|         LLVM_InitializeAllTargetMCs, LLVM_InitializeAllTargets, LLVMSetModuleDataLayout, | ||||
|     }, | ||||
|     target_machine::{ | ||||
|         LLVMCodeGenFileType, LLVMCreateTargetDataLayout, LLVMCreateTargetMachine, | ||||
|         LLVMGetDefaultTargetTriple, LLVMGetTargetFromTriple, LLVMTargetMachineEmitToMemoryBuffer, | ||||
|         LLVMCodeGenFileType, LLVMCreateTargetDataLayout, LLVMCreateTargetMachine, LLVMGetDefaultTargetTriple, | ||||
|         LLVMGetTargetFromTriple, LLVMTargetMachineEmitToMemoryBuffer, | ||||
|     }, | ||||
| }; | ||||
| 
 | ||||
| @ -34,8 +34,8 @@ use crate::{ | ||||
| use super::{ | ||||
|     CmpPredicate, ConstValue, Context, TerminatorKind, Type, | ||||
|     builder::{ | ||||
|         BlockHolder, BlockValue, Builder, FunctionHolder, FunctionValue, InstructionHolder, | ||||
|         InstructionValue, ModuleHolder, | ||||
|         BlockHolder, BlockValue, Builder, FunctionHolder, FunctionValue, InstructionHolder, InstructionValue, | ||||
|         ModuleHolder, | ||||
|     }, | ||||
| }; | ||||
| 
 | ||||
| @ -119,8 +119,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"); | ||||
| 
 | ||||
|             println!("{}", llvm_ir); | ||||
| 
 | ||||
| @ -224,17 +224,15 @@ pub struct LLVMFunction { | ||||
| } | ||||
| 
 | ||||
| pub struct LLVMValue { | ||||
|     _ty: Type, | ||||
|     ty: Type, | ||||
|     value_ref: LLVMValueRef, | ||||
| } | ||||
| 
 | ||||
| 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
 | ||||
| 
 | ||||
| @ -372,11 +370,7 @@ 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, | ||||
| @ -399,13 +393,7 @@ impl DebugScopeHolder { | ||||
|     ) { | ||||
|         unsafe { | ||||
|             let scope = if let Some(location) = &self.location { | ||||
|                 LLVMDIBuilderCreateLexicalBlock( | ||||
|                     di_builder, | ||||
|                     parent, | ||||
|                     file, | ||||
|                     location.pos.line, | ||||
|                     location.pos.column, | ||||
|                 ) | ||||
|                 LLVMDIBuilderCreateLexicalBlock(di_builder, parent, file, location.pos.line, location.pos.column) | ||||
|             } else { | ||||
|                 LLVMDIBuilderCreateLexicalBlockFile(di_builder, parent, file, 0) | ||||
|             }; | ||||
| @ -489,8 +477,7 @@ 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, | ||||
| @ -552,11 +539,7 @@ 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) => { | ||||
| @ -564,16 +547,9 @@ 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 | ||||
|                 } | ||||
|             } | ||||
| @ -602,15 +578,10 @@ impl FunctionHolder { | ||||
| 
 | ||||
|             let fn_type = LLVMFunctionType(ret_type, param_ptr, param_len as u32, 0); | ||||
| 
 | ||||
|             let function_ref = | ||||
|                 LLVMAddFunction(module_ref, into_cstring(&self.data.name).as_ptr(), fn_type); | ||||
|             let function_ref = LLVMAddFunction(module_ref, into_cstring(&self.data.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); | ||||
|             } | ||||
| 
 | ||||
| @ -667,10 +638,7 @@ 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); | ||||
|                 } | ||||
| @ -687,10 +655,8 @@ 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); | ||||
|             } | ||||
| @ -722,22 +688,13 @@ 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(), | ||||
|                 ); | ||||
|             } | ||||
|         } | ||||
| @ -745,12 +702,7 @@ 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 { | ||||
| @ -829,7 +781,7 @@ impl InstructionHolder { | ||||
|                     LLVMBuildICmp( | ||||
|                         module.builder_ref, | ||||
|                         // Signedness from LHS
 | ||||
|                         pred.as_llvm_int(lhs._ty.signed()), | ||||
|                         pred.as_llvm_int(lhs.ty.category().signed()), | ||||
|                         lhs.value_ref, | ||||
|                         rhs_val, | ||||
|                         name.as_ptr(), | ||||
| @ -909,15 +861,12 @@ impl InstructionHolder { | ||||
|                     ); | ||||
|                     store | ||||
|                 } | ||||
|                 ArrayAlloca(ty, len) => { | ||||
|                     let array_len = ConstValue::U16(*len as u16).as_llvm(module); | ||||
|                     LLVMBuildArrayAlloca( | ||||
|                         module.builder_ref, | ||||
|                         ty.as_llvm(module.context_ref, &module.types), | ||||
|                         array_len, | ||||
|                         name.as_ptr(), | ||||
|                     ) | ||||
|                 } | ||||
|                 ArrayAlloca(ty, len) => LLVMBuildArrayAlloca( | ||||
|                     module.builder_ref, | ||||
|                     ty.as_llvm(module.context_ref, &module.types), | ||||
|                     module.values.get(&len).unwrap().value_ref, | ||||
|                     name.as_ptr(), | ||||
|                 ), | ||||
|                 GetElemPtr(arr, indices) => { | ||||
|                     let t = arr.get_type(module.builder).unwrap(); | ||||
|                     let Type::Ptr(elem_t) = t else { panic!() }; | ||||
| @ -1033,8 +982,7 @@ 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, | ||||
| @ -1045,26 +993,22 @@ 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, | ||||
|                     ), | ||||
|                 }; | ||||
|             } | ||||
|         } | ||||
| @ -1077,13 +1021,7 @@ impl InstructionHolder { | ||||
|                     | LLVMValueKind::LLVMMemoryPhiValueKind => { | ||||
|                         LLVMInstructionSetDebugLoc( | ||||
|                             val, | ||||
|                             *module | ||||
|                                 .debug | ||||
|                                 .as_ref() | ||||
|                                 .unwrap() | ||||
|                                 .locations | ||||
|                                 .get(&location) | ||||
|                                 .unwrap(), | ||||
|                             *module.debug.as_ref().unwrap().locations.get(&location).unwrap(), | ||||
|                         ); | ||||
|                     } | ||||
|                     _ => {} | ||||
| @ -1091,19 +1029,14 @@ impl InstructionHolder { | ||||
|             } | ||||
|         } | ||||
|         LLVMValue { | ||||
|             _ty, | ||||
|             ty: _ty, | ||||
|             value_ref: val, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 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 { | ||||
| @ -1125,7 +1058,7 @@ impl TerminatorKind { | ||||
|             } | ||||
|         }; | ||||
|         LLVMValue { | ||||
|             _ty, | ||||
|             ty: _ty, | ||||
|             value_ref: val, | ||||
|         } | ||||
|     } | ||||
| @ -1179,11 +1112,9 @@ impl ConstValue { | ||||
|                 ConstValue::U32(val) => LLVMConstInt(t, *val as u64, 1), | ||||
|                 ConstValue::U64(val) => LLVMConstInt(t, *val as u64, 1), | ||||
|                 ConstValue::U128(val) => LLVMConstInt(t, *val as u64, 1), | ||||
|                 ConstValue::Str(val) => LLVMBuildGlobalString( | ||||
|                     module.builder_ref, | ||||
|                     into_cstring(val).as_ptr(), | ||||
|                     c"string".as_ptr(), | ||||
|                 ), | ||||
|                 ConstValue::Str(val) => { | ||||
|                     LLVMBuildGlobalString(module.builder_ref, into_cstring(val).as_ptr(), c"string".as_ptr()) | ||||
|                 } | ||||
|                 ConstValue::F16(val) => LLVMConstReal(t, *val as f64), | ||||
|                 ConstValue::F32B(val) => LLVMConstReal(t, *val as f64), | ||||
|                 ConstValue::F32(val) => LLVMConstReal(t, *val as f64), | ||||
| @ -1197,11 +1128,7 @@ impl ConstValue { | ||||
| } | ||||
| 
 | ||||
| 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 { | ||||
|  | ||||
| @ -375,7 +375,7 @@ pub enum Instr { | ||||
|     Alloca(Type), | ||||
|     Load(InstructionValue, Type), | ||||
|     Store(InstructionValue, InstructionValue), | ||||
|     ArrayAlloca(Type, u32), | ||||
|     ArrayAlloca(Type, InstructionValue), | ||||
|     GetElemPtr(InstructionValue, Vec<InstructionValue>), | ||||
|     GetStructElemPtr(InstructionValue, u32), | ||||
|     ExtractValue(InstructionValue, u32), | ||||
| @ -533,77 +533,56 @@ impl ConstValue { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Type { | ||||
| #[derive(PartialEq, Eq, PartialOrd, Ord, Debug)] | ||||
| enum TypeCategory { | ||||
|     SignedInteger, | ||||
|     UnsignedInteger, | ||||
|     Void, | ||||
|     Real, | ||||
|     Ptr, | ||||
|     CustomType, | ||||
|     Array, | ||||
| } | ||||
| 
 | ||||
| impl TypeCategory { | ||||
|     pub fn comparable(&self) -> bool { | ||||
|         match self { | ||||
|             Type::I8 => true, | ||||
|             Type::I16 => true, | ||||
|             Type::I32 => true, | ||||
|             Type::I64 => true, | ||||
|             Type::I128 => true, | ||||
|             Type::U8 => true, | ||||
|             Type::U16 => true, | ||||
|             Type::U32 => true, | ||||
|             Type::U64 => true, | ||||
|             Type::U128 => true, | ||||
|             Type::Bool => true, | ||||
|             Type::Void => false, | ||||
|             Type::Ptr(_) => false, | ||||
|             Type::CustomType(_) => false, | ||||
|             Type::Array(_, _) => false, | ||||
|             Type::F16 => true, | ||||
|             Type::F32B => true, | ||||
|             Type::F32 => true, | ||||
|             Type::F64 => true, | ||||
|             Type::F80 => true, | ||||
|             Type::F128 => true, | ||||
|             Type::F128PPC => true, | ||||
|             TypeCategory::SignedInteger => true, | ||||
|             TypeCategory::UnsignedInteger => true, | ||||
|             TypeCategory::Real => true, | ||||
|             _ => false, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn signed(&self) -> bool { | ||||
|         match self { | ||||
|             Type::I8 => true, | ||||
|             Type::I16 => true, | ||||
|             Type::I32 => true, | ||||
|             Type::I64 => true, | ||||
|             Type::I128 => true, | ||||
|             Type::U8 => false, | ||||
|             Type::U16 => false, | ||||
|             Type::U32 => false, | ||||
|             Type::U64 => false, | ||||
|             Type::U128 => false, | ||||
|             Type::Bool => false, | ||||
|             Type::Void => false, | ||||
|             Type::Ptr(_) => false, | ||||
|             Type::CustomType(_) => false, | ||||
|             Type::Array(_, _) => false, | ||||
|             Type::F16 => true, | ||||
|             Type::F32B => true, | ||||
|             Type::F32 => true, | ||||
|             Type::F64 => true, | ||||
|             Type::F80 => true, | ||||
|             Type::F128 => true, | ||||
|             Type::F128PPC => true, | ||||
|             TypeCategory::SignedInteger => true, | ||||
|             _ => false, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn integer(&self) -> bool { | ||||
|         match self { | ||||
|             TypeCategory::SignedInteger => true, | ||||
|             TypeCategory::UnsignedInteger => true, | ||||
|             _ => false, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Type { | ||||
|     pub fn category(&self) -> TypeCategory { | ||||
|         match self { | ||||
|             Type::I8 | ||||
|             | Type::I16 | ||||
|             | Type::I32 | ||||
|             | Type::I64 | ||||
|             | Type::I128 | ||||
|             | Type::U8 | ||||
|             | Type::U16 | ||||
|             | Type::U32 | ||||
|             | Type::U64 | ||||
|             | Type::U128 => TypeCategory::Integer, | ||||
|             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 | Type::Void | Type::CustomType(_) | Type::Array(_, _) | Type::Ptr(_) => TypeCategory::Other, | ||||
|             Type::Bool => TypeCategory::UnsignedInteger, | ||||
|             Type::Void => TypeCategory::Void, | ||||
|             Type::CustomType(_) => TypeCategory::CustomType, | ||||
|             Type::Array(_, _) => TypeCategory::Array, | ||||
|             Type::Ptr(_) => TypeCategory::Ptr, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -656,13 +635,6 @@ impl Type { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(PartialEq, Eq, PartialOrd, Ord)] | ||||
| pub enum TypeCategory { | ||||
|     Integer, | ||||
|     Real, | ||||
|     Other, | ||||
| } | ||||
| 
 | ||||
| impl TerminatorKind { | ||||
|     pub(crate) fn get_type(&self, builder: &Builder) -> CompileResult<Type> { | ||||
|         use TerminatorKind::*; | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| use reid_lib::{builder::InstructionValue, CmpPredicate, Instr}; | ||||
| use reid_lib::{builder::InstructionValue, CmpPredicate, ConstValue, Instr}; | ||||
| 
 | ||||
| use crate::{ | ||||
|     codegen::{ErrorKind, StackValueKind}, | ||||
| @ -46,6 +46,22 @@ pub fn get_intrinsic_assoc_func(ty: &TypeKind, name: &str) -> Option<FunctionDef | ||||
|             parameters: Vec::new(), | ||||
|             kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSizeOf(ty.clone()))), | ||||
|         }), | ||||
|         "alloca" => Some(FunctionDefinition { | ||||
|             name: "alloca".to_owned(), | ||||
|             is_pub: true, | ||||
|             is_imported: false, | ||||
|             return_type: TypeKind::UserPtr(Box::new(ty.clone())), | ||||
|             parameters: vec![(String::from("size"), TypeKind::U64)], | ||||
|             kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicAlloca(ty.clone()))), | ||||
|         }), | ||||
|         "null" => Some(FunctionDefinition { | ||||
|             name: "null".to_owned(), | ||||
|             is_pub: true, | ||||
|             is_imported: false, | ||||
|             return_type: TypeKind::UserPtr(Box::new(ty.clone())), | ||||
|             parameters: Vec::new(), | ||||
|             kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicNullPtr(ty.clone()))), | ||||
|         }), | ||||
|         _ => None, | ||||
|     } | ||||
| } | ||||
| @ -233,14 +249,8 @@ where | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct IntrinsicSizeOf(TypeKind); | ||||
| impl std::fmt::Debug for IntrinsicSizeOf { | ||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|         f.debug_tuple("IntrinsicSizeOf").finish() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl IntrinsicFunction for IntrinsicSizeOf { | ||||
|     fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, _: &[StackValue]) -> Result<StackValue, ErrorKind> { | ||||
|         let instr = scope | ||||
| @ -251,6 +261,32 @@ impl IntrinsicFunction for IntrinsicSizeOf { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct IntrinsicAlloca(TypeKind); | ||||
| impl IntrinsicFunction for IntrinsicAlloca { | ||||
|     fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, params: &[StackValue]) -> Result<StackValue, ErrorKind> { | ||||
|         let amount = params.get(0).unwrap(); | ||||
|         let instr = scope | ||||
|             .block | ||||
|             .build(Instr::ArrayAlloca(self.0.get_type(scope.type_values), amount.instr())) | ||||
|             .unwrap(); | ||||
|         Ok(StackValue(StackValueKind::Literal(instr), self.0.clone())) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct IntrinsicNullPtr(TypeKind); | ||||
| impl IntrinsicFunction for IntrinsicNullPtr { | ||||
|     fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, _: &[StackValue]) -> Result<StackValue, ErrorKind> { | ||||
|         let zero = scope.block.build(Instr::Constant(ConstValue::I8(0))).unwrap(); | ||||
|         let instr = scope | ||||
|             .block | ||||
|             .build(Instr::IntToPtr(zero, self.0.get_type(scope.type_values))) | ||||
|             .unwrap(); | ||||
|         Ok(StackValue(StackValueKind::Literal(instr), self.0.clone())) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // impl IntrinsicFunction for IntrinsicIAdd {
 | ||||
| //     fn codegen<'ctx, 'a>(
 | ||||
| //         &self,
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user