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("i32: ") + i32::test(54) as u64); | ||||||
|     print(from_str("sizeof i32: ") + i32::sizeof()); |     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; |     return i32::sizeof() as u32; | ||||||
| } | } | ||||||
|  | |||||||
| @ -4,11 +4,10 @@ | |||||||
| use std::{cell::RefCell, rc::Rc}; | use std::{cell::RefCell, rc::Rc}; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     Block, BlockData, CompileResult, CustomTypeKind, ErrorKind, FunctionData, Instr, |     Block, BlockData, CompileResult, CustomTypeKind, ErrorKind, FunctionData, Instr, InstructionData, ModuleData, | ||||||
|     InstructionData, ModuleData, NamedStruct, TerminatorKind, Type, TypeCategory, TypeData, |     NamedStruct, TerminatorKind, Type, TypeCategory, TypeData, | ||||||
|     debug_information::{ |     debug_information::{ | ||||||
|         DebugInformation, DebugLocationValue, DebugMetadataValue, DebugProgramValue, |         DebugInformation, DebugLocationValue, DebugMetadataValue, DebugProgramValue, InstructionDebugRecordData, | ||||||
|         InstructionDebugRecordData, |  | ||||||
|     }, |     }, | ||||||
|     util::match_types, |     util::match_types, | ||||||
| }; | }; | ||||||
| @ -91,11 +90,7 @@ impl Builder { | |||||||
|         value |         value | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub(crate) fn set_debug_information( |     pub(crate) fn set_debug_information(&self, mod_val: &ModuleValue, debug_info: DebugInformation) { | ||||||
|         &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); | ||||||
| @ -113,11 +108,7 @@ impl Builder { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub(crate) unsafe fn add_function( |     pub(crate) unsafe fn add_function(&self, mod_val: &ModuleValue, data: FunctionData) -> FunctionValue { | ||||||
|         &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); | ||||||
| @ -174,11 +165,7 @@ impl Builder { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub(crate) unsafe fn add_instruction_location( |     pub(crate) unsafe fn add_instruction_location(&self, value: &InstructionValue, location: DebugLocationValue) { | ||||||
|         &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); | ||||||
| @ -189,11 +176,7 @@ impl Builder { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub(crate) unsafe fn add_instruction_metadata( |     pub(crate) unsafe fn add_instruction_metadata(&self, value: &InstructionValue, metadata: DebugMetadataValue) { | ||||||
|         &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); | ||||||
| @ -204,11 +187,7 @@ impl Builder { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub(crate) unsafe fn add_instruction_record( |     pub(crate) unsafe fn add_instruction_record(&self, value: &InstructionValue, record: InstructionDebugRecordData) { | ||||||
|         &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); | ||||||
| @ -219,11 +198,7 @@ impl Builder { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub(crate) unsafe fn set_debug_subprogram( |     pub(crate) unsafe fn set_debug_subprogram(&self, value: &FunctionValue, subprogram: DebugProgramValue) { | ||||||
|         &self, |  | ||||||
|         value: &FunctionValue, |  | ||||||
|         subprogram: DebugProgramValue, |  | ||||||
|     ) { |  | ||||||
|         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); | ||||||
| @ -232,11 +207,7 @@ impl Builder { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub(crate) unsafe fn terminate( |     pub(crate) unsafe fn terminate(&self, block: &BlockValue, value: TerminatorKind) -> CompileResult<()> { | ||||||
|         &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); | ||||||
| @ -354,22 +325,94 @@ impl Builder { | |||||||
|             match self.instr_data(&instruction).kind { |             match self.instr_data(&instruction).kind { | ||||||
|                 Instr::Param(_) => Ok(()), |                 Instr::Param(_) => Ok(()), | ||||||
|                 Instr::Constant(_) => Ok(()), |                 Instr::Constant(_) => Ok(()), | ||||||
|                 Instr::Add(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), |                 Instr::Add(lhs, rhs) => { | ||||||
|                 Instr::FAdd(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), |                     if match_types(&lhs, &rhs, &self)?.category().integer() { | ||||||
|                 Instr::Sub(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), |                         Ok(()) | ||||||
|                 Instr::FSub(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), |                     } else { | ||||||
|                 Instr::Mul(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), |                         Err(ErrorKind::Null) | ||||||
|                 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::FAdd(lhs, rhs) => { | ||||||
|                 Instr::FDiv(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), |                     if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::Real { | ||||||
|                 Instr::URem(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), |                         Ok(()) | ||||||
|                 Instr::SRem(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), |                     } else { | ||||||
|                 Instr::FRem(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), |                         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::And(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), | ||||||
|                 Instr::ICmp(_, lhs, rhs) => { |                 Instr::ICmp(_, lhs, rhs) => { | ||||||
|                     let t = match_types(&lhs, &rhs, self)?; |                     let t = match_types(&lhs, &rhs, self)?; | ||||||
|                     if t.comparable() || t.category() != TypeCategory::Integer { |                     if t.category().comparable() || !t.category().integer() { | ||||||
|                         Ok(()) |                         Ok(()) | ||||||
|                     } else { |                     } else { | ||||||
|                         Err(ErrorKind::Null) // TODO error: Types not comparable
 |                         Err(ErrorKind::Null) // TODO error: Types not comparable
 | ||||||
| @ -377,7 +420,7 @@ impl Builder { | |||||||
|                 } |                 } | ||||||
|                 Instr::FCmp(_, lhs, rhs) => { |                 Instr::FCmp(_, lhs, rhs) => { | ||||||
|                     let t = match_types(&lhs, &rhs, self)?; |                     let t = match_types(&lhs, &rhs, self)?; | ||||||
|                     if t.comparable() || t.category() != TypeCategory::Real { |                     if t.category().comparable() || t.category() != TypeCategory::Real { | ||||||
|                         Ok(()) |                         Ok(()) | ||||||
|                     } else { |                     } else { | ||||||
|                         Err(ErrorKind::Null) // TODO error: Types not comparable
 |                         Err(ErrorKind::Null) // TODO error: Types not comparable
 | ||||||
| @ -430,7 +473,13 @@ impl Builder { | |||||||
|                         Err(ErrorKind::Null) // TODO error: not a pointer
 |                         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, _) => { |                 Instr::GetElemPtr(ptr_val, _) => { | ||||||
|                     let ptr_ty = ptr_val.get_type(&self)?; |                     let ptr_ty = ptr_val.get_type(&self)?; | ||||||
|                     match ptr_ty { |                     match ptr_ty { | ||||||
| @ -526,11 +575,7 @@ impl InstructionValue { | |||||||
|         self |         self | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn maybe_location( |     pub fn maybe_location(self, block: &mut Block, location: Option<DebugLocationValue>) -> InstructionValue { | ||||||
|         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); | ||||||
| @ -572,10 +617,7 @@ impl InstructionValue { | |||||||
|                 ICmp(_, _, _) => Ok(Type::Bool), |                 ICmp(_, _, _) => Ok(Type::Bool), | ||||||
|                 FCmp(_, _, _) => Ok(Type::Bool), |                 FCmp(_, _, _) => Ok(Type::Bool), | ||||||
|                 FunctionCall(function_value, _) => Ok(builder.function_data(function_value).ret), |                 FunctionCall(function_value, _) => Ok(builder.function_data(function_value).ret), | ||||||
|                 Phi(values) => values |                 Phi(values) => values.first().ok_or(ErrorKind::Null).and_then(|v| v.get_type(&builder)), | ||||||
|                     .first() |  | ||||||
|                     .ok_or(ErrorKind::Null) |  | ||||||
|                     .and_then(|v| v.get_type(&builder)), |  | ||||||
|                 Alloca(ty) => Ok(Type::Ptr(Box::new(ty.clone()))), |                 Alloca(ty) => Ok(Type::Ptr(Box::new(ty.clone()))), | ||||||
|                 Load(_, ty) => Ok(ty.clone()), |                 Load(_, ty) => Ok(ty.clone()), | ||||||
|                 Store(_, value) => value.get_type(builder), |                 Store(_, value) => value.get_type(builder), | ||||||
|  | |||||||
| @ -19,8 +19,8 @@ use llvm_sys::{ | |||||||
|         LLVM_InitializeAllTargetMCs, LLVM_InitializeAllTargets, LLVMSetModuleDataLayout, |         LLVM_InitializeAllTargetMCs, LLVM_InitializeAllTargets, LLVMSetModuleDataLayout, | ||||||
|     }, |     }, | ||||||
|     target_machine::{ |     target_machine::{ | ||||||
|         LLVMCodeGenFileType, LLVMCreateTargetDataLayout, LLVMCreateTargetMachine, |         LLVMCodeGenFileType, LLVMCreateTargetDataLayout, LLVMCreateTargetMachine, LLVMGetDefaultTargetTriple, | ||||||
|         LLVMGetDefaultTargetTriple, LLVMGetTargetFromTriple, LLVMTargetMachineEmitToMemoryBuffer, |         LLVMGetTargetFromTriple, LLVMTargetMachineEmitToMemoryBuffer, | ||||||
|     }, |     }, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -34,8 +34,8 @@ use crate::{ | |||||||
| use super::{ | use super::{ | ||||||
|     CmpPredicate, ConstValue, Context, TerminatorKind, Type, |     CmpPredicate, ConstValue, Context, TerminatorKind, Type, | ||||||
|     builder::{ |     builder::{ | ||||||
|         BlockHolder, BlockValue, Builder, FunctionHolder, FunctionValue, InstructionHolder, |         BlockHolder, BlockValue, Builder, FunctionHolder, FunctionValue, InstructionHolder, InstructionValue, | ||||||
|         InstructionValue, ModuleHolder, |         ModuleHolder, | ||||||
|     }, |     }, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -119,8 +119,8 @@ impl CompiledModule { | |||||||
|             ); |             ); | ||||||
|             err.into_result().unwrap(); |             err.into_result().unwrap(); | ||||||
| 
 | 
 | ||||||
|             let llvm_ir = from_cstring(LLVMPrintModuleToString(self.module_ref)) |             let llvm_ir = | ||||||
|                 .expect("Unable to print LLVM IR to string"); |                 from_cstring(LLVMPrintModuleToString(self.module_ref)).expect("Unable to print LLVM IR to string"); | ||||||
| 
 | 
 | ||||||
|             println!("{}", llvm_ir); |             println!("{}", llvm_ir); | ||||||
| 
 | 
 | ||||||
| @ -224,17 +224,15 @@ pub struct LLVMFunction { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub struct LLVMValue { | pub struct LLVMValue { | ||||||
|     _ty: Type, |     ty: Type, | ||||||
|     value_ref: LLVMValueRef, |     value_ref: LLVMValueRef, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 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 = LLVMModuleCreateWithNameInContext( |             let module_ref = | ||||||
|                 into_cstring(&self.data.name).as_ptr(), |                 LLVMModuleCreateWithNameInContext(into_cstring(&self.data.name).as_ptr(), context.context_ref); | ||||||
|                 context.context_ref, |  | ||||||
|             ); |  | ||||||
| 
 | 
 | ||||||
|             // Compile the contents
 |             // Compile the contents
 | ||||||
| 
 | 
 | ||||||
| @ -372,11 +370,7 @@ impl ModuleHolder { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl DebugLocationHolder { | impl DebugLocationHolder { | ||||||
|     unsafe fn compile( |     unsafe fn compile(&self, context: &LLVMContext, debug: &LLVMDebugInformation) -> LLVMMetadataRef { | ||||||
|         &self, |  | ||||||
|         context: &LLVMContext, |  | ||||||
|         debug: &LLVMDebugInformation, |  | ||||||
|     ) -> LLVMMetadataRef { |  | ||||||
|         unsafe { |         unsafe { | ||||||
|             LLVMDIBuilderCreateDebugLocation( |             LLVMDIBuilderCreateDebugLocation( | ||||||
|                 context.context_ref, |                 context.context_ref, | ||||||
| @ -399,13 +393,7 @@ impl DebugScopeHolder { | |||||||
|     ) { |     ) { | ||||||
|         unsafe { |         unsafe { | ||||||
|             let scope = if let Some(location) = &self.location { |             let scope = if let Some(location) = &self.location { | ||||||
|                 LLVMDIBuilderCreateLexicalBlock( |                 LLVMDIBuilderCreateLexicalBlock(di_builder, parent, file, location.pos.line, location.pos.column) | ||||||
|                     di_builder, |  | ||||||
|                     parent, |  | ||||||
|                     file, |  | ||||||
|                     location.pos.line, |  | ||||||
|                     location.pos.column, |  | ||||||
|                 ) |  | ||||||
|             } else { |             } else { | ||||||
|                 LLVMDIBuilderCreateLexicalBlockFile(di_builder, parent, file, 0) |                 LLVMDIBuilderCreateLexicalBlockFile(di_builder, parent, file, 0) | ||||||
|             }; |             }; | ||||||
| @ -489,8 +477,7 @@ impl DebugTypeHolder { | |||||||
|                     ptr.name.len(), |                     ptr.name.len(), | ||||||
|                 ), |                 ), | ||||||
|                 DebugTypeData::Array(array) => { |                 DebugTypeData::Array(array) => { | ||||||
|                     let subrange = |                     let subrange = LLVMDIBuilderGetOrCreateSubrange(debug.builder, 0, array.length as i64); | ||||||
|                         LLVMDIBuilderGetOrCreateSubrange(debug.builder, 0, array.length as i64); |  | ||||||
|                     let mut elements = vec![subrange]; |                     let mut elements = vec![subrange]; | ||||||
|                     LLVMDIBuilderCreateArrayType( |                     LLVMDIBuilderCreateArrayType( | ||||||
|                         debug.builder, |                         debug.builder, | ||||||
| @ -552,11 +539,7 @@ impl DwarfFlags { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl TypeHolder { | impl TypeHolder { | ||||||
|     unsafe fn compile_type( |     unsafe fn compile_type(&self, context: &LLVMContext, types: &HashMap<TypeValue, LLVMTypeRef>) -> LLVMTypeRef { | ||||||
|         &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) => { | ||||||
| @ -564,16 +547,9 @@ 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 = LLVMStructCreateNamed( |                     let struct_ty = | ||||||
|                         context.context_ref, |                         LLVMStructCreateNamed(context.context_ref, into_cstring(named_struct.0.clone()).as_ptr()); | ||||||
|                         into_cstring(named_struct.0.clone()).as_ptr(), |                     LLVMStructSetBody(struct_ty, elem_types.as_mut_ptr(), elem_types.len() as u32, 0); | ||||||
|                     ); |  | ||||||
|                     LLVMStructSetBody( |  | ||||||
|                         struct_ty, |  | ||||||
|                         elem_types.as_mut_ptr(), |  | ||||||
|                         elem_types.len() as u32, |  | ||||||
|                         0, |  | ||||||
|                     ); |  | ||||||
|                     struct_ty |                     struct_ty | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @ -602,15 +578,10 @@ impl FunctionHolder { | |||||||
| 
 | 
 | ||||||
|             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); | ||||||
| 
 | 
 | ||||||
|             let function_ref = |             let function_ref = LLVMAddFunction(module_ref, into_cstring(&self.data.name).as_ptr(), fn_type); | ||||||
|                 LLVMAddFunction(module_ref, into_cstring(&self.data.name).as_ptr(), fn_type); |  | ||||||
| 
 | 
 | ||||||
|             if self.data.flags.inline { |             if self.data.flags.inline { | ||||||
|                 let attribute = LLVMCreateEnumAttribute( |                 let attribute = LLVMCreateEnumAttribute(context.context_ref, LLVMEnumAttribute::AlwaysInline as u32, 0); | ||||||
|                     context.context_ref, |  | ||||||
|                     LLVMEnumAttribute::AlwaysInline as u32, |  | ||||||
|                     0, |  | ||||||
|                 ); |  | ||||||
|                 LLVMAddAttributeAtIndex(function_ref, 0, attribute); |                 LLVMAddAttributeAtIndex(function_ref, 0, attribute); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| @ -667,10 +638,7 @@ 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( |                     LLVMSetLinkage(own_function.value_ref, LLVMLinkage::LLVMAvailableExternallyLinkage); | ||||||
|                         own_function.value_ref, |  | ||||||
|                         LLVMLinkage::LLVMAvailableExternallyLinkage, |  | ||||||
|                     ); |  | ||||||
|                 } else { |                 } else { | ||||||
|                     LLVMSetLinkage(own_function.value_ref, LLVMLinkage::LLVMExternalLinkage); |                     LLVMSetLinkage(own_function.value_ref, LLVMLinkage::LLVMExternalLinkage); | ||||||
|                 } |                 } | ||||||
| @ -687,10 +655,8 @@ impl FunctionHolder { | |||||||
|                     continue; |                     continue; | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 let block_ref = LLVMCreateBasicBlockInContext( |                 let block_ref = | ||||||
|                     module.context_ref, |                     LLVMCreateBasicBlockInContext(module.context_ref, into_cstring(&block.data.name).as_ptr()); | ||||||
|                     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); | ||||||
|             } |             } | ||||||
| @ -722,22 +688,13 @@ impl BlockHolder { | |||||||
|                 .data |                 .data | ||||||
|                 .terminator |                 .terminator | ||||||
|                 .clone() |                 .clone() | ||||||
|                 .expect(&format!( |                 .expect(&format!("Block {} does not have a terminator!", self.data.name)) | ||||||
|                     "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 |                     *module.debug.as_ref().unwrap().locations.get(&location).unwrap(), | ||||||
|                         .debug |  | ||||||
|                         .as_ref() |  | ||||||
|                         .unwrap() |  | ||||||
|                         .locations |  | ||||||
|                         .get(&location) |  | ||||||
|                         .unwrap(), |  | ||||||
|                 ); |                 ); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @ -745,12 +702,7 @@ impl BlockHolder { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl InstructionHolder { | impl InstructionHolder { | ||||||
|     unsafe fn compile( |     unsafe fn compile(&self, module: &LLVMModule, function: &LLVMFunction, _block: LLVMBasicBlockRef) -> LLVMValue { | ||||||
|         &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 { | ||||||
| @ -829,7 +781,7 @@ impl InstructionHolder { | |||||||
|                     LLVMBuildICmp( |                     LLVMBuildICmp( | ||||||
|                         module.builder_ref, |                         module.builder_ref, | ||||||
|                         // Signedness from LHS
 |                         // Signedness from LHS
 | ||||||
|                         pred.as_llvm_int(lhs._ty.signed()), |                         pred.as_llvm_int(lhs.ty.category().signed()), | ||||||
|                         lhs.value_ref, |                         lhs.value_ref, | ||||||
|                         rhs_val, |                         rhs_val, | ||||||
|                         name.as_ptr(), |                         name.as_ptr(), | ||||||
| @ -909,15 +861,12 @@ impl InstructionHolder { | |||||||
|                     ); |                     ); | ||||||
|                     store |                     store | ||||||
|                 } |                 } | ||||||
|                 ArrayAlloca(ty, len) => { |                 ArrayAlloca(ty, len) => LLVMBuildArrayAlloca( | ||||||
|                     let array_len = ConstValue::U16(*len as u16).as_llvm(module); |  | ||||||
|                     LLVMBuildArrayAlloca( |  | ||||||
|                     module.builder_ref, |                     module.builder_ref, | ||||||
|                     ty.as_llvm(module.context_ref, &module.types), |                     ty.as_llvm(module.context_ref, &module.types), | ||||||
|                         array_len, |                     module.values.get(&len).unwrap().value_ref, | ||||||
|                     name.as_ptr(), |                     name.as_ptr(), | ||||||
|                     ) |                 ), | ||||||
|                 } |  | ||||||
|                 GetElemPtr(arr, indices) => { |                 GetElemPtr(arr, indices) => { | ||||||
|                     let t = arr.get_type(module.builder).unwrap(); |                     let t = arr.get_type(module.builder).unwrap(); | ||||||
|                     let Type::Ptr(elem_t) = t else { panic!() }; |                     let Type::Ptr(elem_t) = t else { panic!() }; | ||||||
| @ -1033,8 +982,7 @@ impl InstructionHolder { | |||||||
| 
 | 
 | ||||||
|             unsafe { |             unsafe { | ||||||
|                 let mut addr = Vec::<u64>::new(); |                 let mut addr = Vec::<u64>::new(); | ||||||
|                 let expr = |                 let expr = LLVMDIBuilderCreateExpression(debug.builder, addr.as_mut_ptr(), addr.len()); | ||||||
|                     LLVMDIBuilderCreateExpression(debug.builder, addr.as_mut_ptr(), addr.len()); |  | ||||||
| 
 | 
 | ||||||
|                 let location = LLVMDIBuilderCreateDebugLocation( |                 let location = LLVMDIBuilderCreateDebugLocation( | ||||||
|                     module.context_ref, |                     module.context_ref, | ||||||
| @ -1045,26 +993,22 @@ impl InstructionHolder { | |||||||
|                 ); |                 ); | ||||||
| 
 | 
 | ||||||
|                 match record.kind { |                 match record.kind { | ||||||
|                     DebugRecordKind::Declare(instruction_value) => { |                     DebugRecordKind::Declare(instruction_value) => LLVMDIBuilderInsertDeclareRecordBefore( | ||||||
|                         LLVMDIBuilderInsertDeclareRecordBefore( |  | ||||||
|                         debug.builder, |                         debug.builder, | ||||||
|                         module.values.get(&instruction_value).unwrap().value_ref, |                         module.values.get(&instruction_value).unwrap().value_ref, | ||||||
|                         *debug.metadata.get(&record.variable).unwrap(), |                         *debug.metadata.get(&record.variable).unwrap(), | ||||||
|                         expr, |                         expr, | ||||||
|                         location, |                         location, | ||||||
|                         val, |                         val, | ||||||
|                         ) |                     ), | ||||||
|                     } |                     DebugRecordKind::Value(instruction_value) => LLVMDIBuilderInsertDbgValueRecordBefore( | ||||||
|                     DebugRecordKind::Value(instruction_value) => { |  | ||||||
|                         LLVMDIBuilderInsertDbgValueRecordBefore( |  | ||||||
|                         debug.builder, |                         debug.builder, | ||||||
|                         module.values.get(&instruction_value).unwrap().value_ref, |                         module.values.get(&instruction_value).unwrap().value_ref, | ||||||
|                         *debug.metadata.get(&record.variable).unwrap(), |                         *debug.metadata.get(&record.variable).unwrap(), | ||||||
|                         expr, |                         expr, | ||||||
|                         location, |                         location, | ||||||
|                         val, |                         val, | ||||||
|                         ) |                     ), | ||||||
|                     } |  | ||||||
|                 }; |                 }; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @ -1077,13 +1021,7 @@ impl InstructionHolder { | |||||||
|                     | LLVMValueKind::LLVMMemoryPhiValueKind => { |                     | LLVMValueKind::LLVMMemoryPhiValueKind => { | ||||||
|                         LLVMInstructionSetDebugLoc( |                         LLVMInstructionSetDebugLoc( | ||||||
|                             val, |                             val, | ||||||
|                             *module |                             *module.debug.as_ref().unwrap().locations.get(&location).unwrap(), | ||||||
|                                 .debug |  | ||||||
|                                 .as_ref() |  | ||||||
|                                 .unwrap() |  | ||||||
|                                 .locations |  | ||||||
|                                 .get(&location) |  | ||||||
|                                 .unwrap(), |  | ||||||
|                         ); |                         ); | ||||||
|                     } |                     } | ||||||
|                     _ => {} |                     _ => {} | ||||||
| @ -1091,19 +1029,14 @@ impl InstructionHolder { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         LLVMValue { |         LLVMValue { | ||||||
|             _ty, |             ty: _ty, | ||||||
|             value_ref: val, |             value_ref: val, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl TerminatorKind { | impl TerminatorKind { | ||||||
|     fn compile( |     fn compile(&self, module: &LLVMModule, _function: &LLVMFunction, _block: LLVMBasicBlockRef) -> LLVMValue { | ||||||
|         &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 { | ||||||
| @ -1125,7 +1058,7 @@ impl TerminatorKind { | |||||||
|             } |             } | ||||||
|         }; |         }; | ||||||
|         LLVMValue { |         LLVMValue { | ||||||
|             _ty, |             ty: _ty, | ||||||
|             value_ref: val, |             value_ref: val, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -1179,11 +1112,9 @@ impl ConstValue { | |||||||
|                 ConstValue::U32(val) => LLVMConstInt(t, *val as u64, 1), |                 ConstValue::U32(val) => LLVMConstInt(t, *val as u64, 1), | ||||||
|                 ConstValue::U64(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::U128(val) => LLVMConstInt(t, *val as u64, 1), | ||||||
|                 ConstValue::Str(val) => LLVMBuildGlobalString( |                 ConstValue::Str(val) => { | ||||||
|                     module.builder_ref, |                     LLVMBuildGlobalString(module.builder_ref, into_cstring(val).as_ptr(), c"string".as_ptr()) | ||||||
|                     into_cstring(val).as_ptr(), |                 } | ||||||
|                     c"string".as_ptr(), |  | ||||||
|                 ), |  | ||||||
|                 ConstValue::F16(val) => LLVMConstReal(t, *val as f64), |                 ConstValue::F16(val) => LLVMConstReal(t, *val as f64), | ||||||
|                 ConstValue::F32B(val) => LLVMConstReal(t, *val as f64), |                 ConstValue::F32B(val) => LLVMConstReal(t, *val as f64), | ||||||
|                 ConstValue::F32(val) => LLVMConstReal(t, *val as f64), |                 ConstValue::F32(val) => LLVMConstReal(t, *val as f64), | ||||||
| @ -1197,11 +1128,7 @@ impl ConstValue { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Type { | impl Type { | ||||||
|     fn as_llvm( |     fn as_llvm(&self, context: LLVMContextRef, typemap: &HashMap<TypeValue, LLVMTypeRef>) -> LLVMTypeRef { | ||||||
|         &self, |  | ||||||
|         context: LLVMContextRef, |  | ||||||
|         typemap: &HashMap<TypeValue, LLVMTypeRef>, |  | ||||||
|     ) -> LLVMTypeRef { |  | ||||||
|         use Type::*; |         use Type::*; | ||||||
|         unsafe { |         unsafe { | ||||||
|             match self { |             match self { | ||||||
|  | |||||||
| @ -375,7 +375,7 @@ pub enum Instr { | |||||||
|     Alloca(Type), |     Alloca(Type), | ||||||
|     Load(InstructionValue, Type), |     Load(InstructionValue, Type), | ||||||
|     Store(InstructionValue, InstructionValue), |     Store(InstructionValue, InstructionValue), | ||||||
|     ArrayAlloca(Type, u32), |     ArrayAlloca(Type, InstructionValue), | ||||||
|     GetElemPtr(InstructionValue, Vec<InstructionValue>), |     GetElemPtr(InstructionValue, Vec<InstructionValue>), | ||||||
|     GetStructElemPtr(InstructionValue, u32), |     GetStructElemPtr(InstructionValue, u32), | ||||||
|     ExtractValue(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 { |     pub fn comparable(&self) -> bool { | ||||||
|         match self { |         match self { | ||||||
|             Type::I8 => true, |             TypeCategory::SignedInteger => true, | ||||||
|             Type::I16 => true, |             TypeCategory::UnsignedInteger => true, | ||||||
|             Type::I32 => true, |             TypeCategory::Real => true, | ||||||
|             Type::I64 => true, |             _ => false, | ||||||
|             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, |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn signed(&self) -> bool { |     pub fn signed(&self) -> bool { | ||||||
|         match self { |         match self { | ||||||
|             Type::I8 => true, |             TypeCategory::SignedInteger => true, | ||||||
|             Type::I16 => true, |             _ => false, | ||||||
|             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, |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     pub fn integer(&self) -> bool { | ||||||
|  |         match self { | ||||||
|  |             TypeCategory::SignedInteger => true, | ||||||
|  |             TypeCategory::UnsignedInteger => true, | ||||||
|  |             _ => false, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Type { | ||||||
|     pub fn category(&self) -> TypeCategory { |     pub fn category(&self) -> TypeCategory { | ||||||
|         match self { |         match self { | ||||||
|             Type::I8 |             Type::I8 | Type::I16 | Type::I32 | Type::I64 | Type::I128 => TypeCategory::SignedInteger, | ||||||
|             | Type::I16 |             Type::U8 | Type::U16 | Type::U32 | Type::U64 | Type::U128 => TypeCategory::UnsignedInteger, | ||||||
|             | Type::I32 |  | ||||||
|             | Type::I64 |  | ||||||
|             | Type::I128 |  | ||||||
|             | Type::U8 |  | ||||||
|             | Type::U16 |  | ||||||
|             | Type::U32 |  | ||||||
|             | Type::U64 |  | ||||||
|             | Type::U128 => TypeCategory::Integer, |  | ||||||
|             Type::F16 | Type::F32B | Type::F32 | Type::F64 | Type::F80 | Type::F128 | Type::F128PPC => { |             Type::F16 | Type::F32B | Type::F32 | Type::F64 | Type::F80 | Type::F128 | Type::F128PPC => { | ||||||
|                 TypeCategory::Real |                 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 { | impl TerminatorKind { | ||||||
|     pub(crate) fn get_type(&self, builder: &Builder) -> CompileResult<Type> { |     pub(crate) fn get_type(&self, builder: &Builder) -> CompileResult<Type> { | ||||||
|         use TerminatorKind::*; |         use TerminatorKind::*; | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| use reid_lib::{builder::InstructionValue, CmpPredicate, Instr}; | use reid_lib::{builder::InstructionValue, CmpPredicate, ConstValue, Instr}; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     codegen::{ErrorKind, StackValueKind}, |     codegen::{ErrorKind, StackValueKind}, | ||||||
| @ -46,6 +46,22 @@ pub fn get_intrinsic_assoc_func(ty: &TypeKind, name: &str) -> Option<FunctionDef | |||||||
|             parameters: Vec::new(), |             parameters: Vec::new(), | ||||||
|             kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSizeOf(ty.clone()))), |             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, |         _ => None, | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -233,14 +249,8 @@ where | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Clone)] | #[derive(Clone, Debug)] | ||||||
| pub struct IntrinsicSizeOf(TypeKind); | 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 { | impl IntrinsicFunction for IntrinsicSizeOf { | ||||||
|     fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, _: &[StackValue]) -> Result<StackValue, ErrorKind> { |     fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, _: &[StackValue]) -> Result<StackValue, ErrorKind> { | ||||||
|         let instr = scope |         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 {
 | // impl IntrinsicFunction for IntrinsicIAdd {
 | ||||||
| //     fn codegen<'ctx, 'a>(
 | //     fn codegen<'ctx, 'a>(
 | ||||||
| //         &self,
 | //         &self,
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user