From 7b27f30b9ee8e567c965ac77971e7b261000038d Mon Sep 17 00:00:00 2001 From: sofia Date: Sun, 27 Jul 2025 20:46:17 +0300 Subject: [PATCH] Implement builtin associated alloca and nullptr --- examples/associated_functions.reid | 6 + reid-llvm-lib/src/builder.rs | 168 ++++++++++++++++---------- reid-llvm-lib/src/compile.rs | 185 +++++++++-------------------- reid-llvm-lib/src/lib.rs | 100 ++++++---------- reid/src/codegen/intrinsics.rs | 52 ++++++-- 5 files changed, 247 insertions(+), 264 deletions(-) diff --git a/examples/associated_functions.reid b/examples/associated_functions.reid index 3959909..4e94035 100644 --- a/examples/associated_functions.reid +++ b/examples/associated_functions.reid @@ -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; } diff --git a/reid-llvm-lib/src/builder.rs b/reid-llvm-lib/src/builder.rs index 67de72b..47806f3 100644 --- a/reid-llvm-lib/src/builder.rs +++ b/reid-llvm-lib/src/builder.rs @@ -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, - ) -> InstructionValue { + pub fn maybe_location(self, block: &mut Block, location: Option) -> 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), diff --git a/reid-llvm-lib/src/compile.rs b/reid-llvm-lib/src/compile.rs index fc29261..271a6cf 100644 --- a/reid-llvm-lib/src/compile.rs +++ b/reid-llvm-lib/src/compile.rs @@ -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, - ) -> LLVMTypeRef { + unsafe fn compile_type(&self, context: &LLVMContext, types: &HashMap) -> 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::::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, - ) -> LLVMTypeRef { + fn as_llvm(&self, context: LLVMContextRef, typemap: &HashMap) -> LLVMTypeRef { use Type::*; unsafe { match self { diff --git a/reid-llvm-lib/src/lib.rs b/reid-llvm-lib/src/lib.rs index 6b34787..628c31b 100644 --- a/reid-llvm-lib/src/lib.rs +++ b/reid-llvm-lib/src/lib.rs @@ -375,7 +375,7 @@ pub enum Instr { Alloca(Type), Load(InstructionValue, Type), Store(InstructionValue, InstructionValue), - ArrayAlloca(Type, u32), + ArrayAlloca(Type, InstructionValue), GetElemPtr(InstructionValue, Vec), 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 { use TerminatorKind::*; diff --git a/reid/src/codegen/intrinsics.rs b/reid/src/codegen/intrinsics.rs index 3bca6ff..a5a23b4 100644 --- a/reid/src/codegen/intrinsics.rs +++ b/reid/src/codegen/intrinsics.rs @@ -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 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 { 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 { + 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 { + 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,