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