Add possibility to call instructions and store functions in values

This commit is contained in:
Sofia 2025-10-23 17:16:03 +03:00
parent 100cd96a6d
commit 17545baa50
5 changed files with 375 additions and 98 deletions

View File

@ -4,10 +4,11 @@
use std::{cell::RefCell, rc::Rc}; use std::{cell::RefCell, rc::Rc};
use crate::{ use crate::{
Block, BlockData, CompileResult, ConstValueKind, CustomTypeKind, ErrorKind, FunctionData, Instr, InstructionData, Block, BlockData, CompileResult, ConstValueKind, CustomTypeKind, ErrorKind, FunctionData,
ModuleData, NamedStruct, TerminatorKind, Type, TypeCategory, TypeData, Instr, InstructionData, ModuleData, NamedStruct, TerminatorKind, Type, TypeCategory, TypeData,
debug_information::{ debug_information::{
DebugInformation, DebugLocationValue, DebugMetadataValue, DebugScopeValue, InstructionDebugRecordData, DebugInformation, DebugLocationValue, DebugMetadataValue, DebugScopeValue,
InstructionDebugRecordData,
}, },
util::match_types, util::match_types,
}; };
@ -114,7 +115,11 @@ impl Builder {
value 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 { 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);
@ -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 { 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);
@ -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 { unsafe {
let mut modules = self.modules.borrow_mut(); let mut modules = self.modules.borrow_mut();
let module = modules.get_unchecked_mut(module.0); let module = modules.get_unchecked_mut(module.0);
@ -219,15 +232,27 @@ impl Builder {
} }
} }
pub(crate) unsafe fn find_function(&self, module: ModuleValue, name: &String) -> Option<FunctionValue> { pub(crate) unsafe fn find_function(
&self,
module: ModuleValue,
name: &String,
) -> Option<FunctionValue> {
unsafe { unsafe {
let mut modules = self.modules.borrow_mut(); let mut modules = self.modules.borrow_mut();
let module = modules.get_unchecked_mut(module.0); 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 { 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);
@ -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 { 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);
@ -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 { 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);
@ -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 { 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);
@ -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 { 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);
@ -551,7 +592,10 @@ impl Builder {
} }
for (a, b) in param_types.iter().zip(params) { for (a, b) in param_types.iter().zip(params) {
if *a != b.get_type(&self)? { 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(()) Ok(())
@ -662,6 +706,14 @@ impl Builder {
Err(ErrorKind::NotPointer(val, val_ty)) 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 self
} }
pub fn maybe_location(self, block: &mut Block, location: Option<DebugLocationValue>) -> InstructionValue { pub fn maybe_location(
self,
block: &mut Block,
location: Option<DebugLocationValue>,
) -> InstructionValue {
unsafe { 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);
@ -822,6 +878,17 @@ impl InstructionValue {
Ok(kind.get_type()) Ok(kind.get_type())
} }
IsNull(_) => Ok(Type::Bool), 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)
}
} }
} }
} }

View File

@ -20,8 +20,8 @@ use llvm_sys::{
LLVM_InitializeAllTargetMCs, LLVM_InitializeAllTargets, LLVMSetModuleDataLayout, LLVM_InitializeAllTargetMCs, LLVM_InitializeAllTargets, LLVMSetModuleDataLayout,
}, },
target_machine::{ target_machine::{
LLVMCodeGenFileType, LLVMCreateTargetDataLayout, LLVMCreateTargetMachine, LLVMGetDefaultTargetTriple, LLVMCodeGenFileType, LLVMCreateTargetDataLayout, LLVMCreateTargetMachine,
LLVMGetTargetFromTriple, LLVMTargetMachineEmitToMemoryBuffer, LLVMGetDefaultTargetTriple, LLVMGetTargetFromTriple, LLVMTargetMachineEmitToMemoryBuffer,
}, },
}; };
@ -35,8 +35,8 @@ use crate::{
use super::{ use super::{
CmpPredicate, ConstValueKind, Context, TerminatorKind, Type, CmpPredicate, ConstValueKind, Context, TerminatorKind, Type,
builder::{ builder::{
BlockHolder, BlockValue, Builder, FunctionHolder, FunctionValue, InstructionHolder, InstructionValue, BlockHolder, BlockValue, Builder, FunctionHolder, FunctionValue, InstructionHolder,
ModuleHolder, InstructionValue, ModuleHolder,
}, },
}; };
@ -120,8 +120,8 @@ impl CompiledModule {
); );
err.into_result().unwrap(); err.into_result().unwrap();
let llvm_ir = let llvm_ir = from_cstring(LLVMPrintModuleToString(self.module_ref))
from_cstring(LLVMPrintModuleToString(self.module_ref)).expect("Unable to print LLVM IR to string"); .expect("Unable to print LLVM IR to string");
let mut err = ErrorMessageHolder::null(); let mut err = ErrorMessageHolder::null();
LLVMVerifyModule( LLVMVerifyModule(
@ -231,8 +231,10 @@ pub struct LLVMValue {
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 = let module_ref = LLVMModuleCreateWithNameInContext(
LLVMModuleCreateWithNameInContext(into_cstring(&self.data.name).as_ptr(), context.context_ref); into_cstring(&self.data.name).as_ptr(),
context.context_ref,
);
// Compile the contents // Compile the contents
@ -327,9 +329,12 @@ impl ModuleHolder {
constant.value, constant.value,
LLVMValue { LLVMValue {
ty: constant.kind.get_type(), ty: constant.kind.get_type(),
value_ref: constant value_ref: constant.kind.as_llvm(
.kind context.context_ref,
.as_llvm(context.context_ref, context.builder_ref, &constants, &types), context.builder_ref,
&constants,
&types,
),
}, },
); );
} }
@ -357,7 +362,12 @@ impl ModuleHolder {
scope = Ref::map(scope, |v| v.inner_scopes.get_unchecked(*i)); scope = Ref::map(scope, |v| v.inner_scopes.get_unchecked(*i));
} }
for scope in &scope.inner_scopes { 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 { impl DebugLocationHolder {
unsafe fn compile(&self, context: &LLVMContext, debug: &LLVMDebugInformation) -> LLVMMetadataRef { unsafe fn compile(
&self,
context: &LLVMContext,
debug: &LLVMDebugInformation,
) -> LLVMMetadataRef {
unsafe { unsafe {
LLVMDIBuilderCreateDebugLocation( LLVMDIBuilderCreateDebugLocation(
context.context_ref, context.context_ref,
@ -515,7 +529,8 @@ impl DebugTypeHolder {
ptr.name.len(), ptr.name.len(),
), ),
DebugTypeData::Array(array) => { 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]; let mut elements = vec![subrange];
LLVMDIBuilderCreateArrayType( LLVMDIBuilderCreateArrayType(
debug.builder, debug.builder,
@ -577,7 +592,11 @@ impl DwarfFlags {
} }
impl TypeHolder { impl TypeHolder {
unsafe fn compile_type(&self, context: &LLVMContext, types: &HashMap<TypeValue, LLVMTypeRef>) -> LLVMTypeRef { unsafe fn compile_type(
&self,
context: &LLVMContext,
types: &HashMap<TypeValue, LLVMTypeRef>,
) -> LLVMTypeRef {
unsafe { unsafe {
match &self.data.kind { match &self.data.kind {
CustomTypeKind::NamedStruct(named_struct) => { CustomTypeKind::NamedStruct(named_struct) => {
@ -585,9 +604,16 @@ 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 = let struct_ty = LLVMStructCreateNamed(
LLVMStructCreateNamed(context.context_ref, into_cstring(named_struct.0.clone()).as_ptr()); context.context_ref,
LLVMStructSetBody(struct_ty, elem_types.as_mut_ptr(), elem_types.len() as u32, 0); into_cstring(named_struct.0.clone()).as_ptr(),
);
LLVMStructSetBody(
struct_ty,
elem_types.as_mut_ptr(),
elem_types.len() as u32,
0,
);
struct_ty struct_ty
} }
} }
@ -617,7 +643,13 @@ impl FunctionHolder {
let name = if self.data.flags.is_main { let name = if self.data.flags.is_main {
c"main" c"main"
} else { } 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); 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); let function_ref = LLVMAddFunction(module_ref, name.as_ptr(), fn_type);
if self.data.flags.inline { 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); LLVMAddAttributeAtIndex(function_ref, 0, attribute);
} }
@ -688,7 +724,10 @@ 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(own_function.value_ref, LLVMLinkage::LLVMAvailableExternallyLinkage); LLVMSetLinkage(
own_function.value_ref,
LLVMLinkage::LLVMAvailableExternallyLinkage,
);
} else { } else {
LLVMSetLinkage(own_function.value_ref, LLVMLinkage::LLVMExternalLinkage); LLVMSetLinkage(own_function.value_ref, LLVMLinkage::LLVMExternalLinkage);
} }
@ -705,8 +744,10 @@ impl FunctionHolder {
continue; continue;
} }
let block_ref = let block_ref = LLVMCreateBasicBlockInContext(
LLVMCreateBasicBlockInContext(module.context_ref, into_cstring(&block.data.name).as_ptr()); module.context_ref,
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);
} }
@ -738,13 +779,22 @@ impl BlockHolder {
.data .data
.terminator .terminator
.clone() .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); .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.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 { 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 _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 {
use super::Instr::*; use super::Instr::*;
match &self.data.kind { match &self.data.kind {
Param(nth) => LLVMGetParam(function.value_ref, *nth as u32), 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) => { Add(lhs, rhs) => {
let lhs_val = module.values.get(&lhs).unwrap().value_ref; let lhs_val = module.values.get(&lhs).unwrap().value_ref;
let rhs_val = module.values.get(&rhs).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; let val = module.values.get(&*instruction_value).unwrap().value_ref;
LLVMBuildIsNull(module.builder_ref, val, name.as_ptr()) LLVMBuildIsNull(module.builder_ref, val, name.as_ptr())
} }
Function(function_value) => module.functions.get(function_value).unwrap().value_ref,
DynFunctionCall(function_value, instruction_values) => {
let fun = module.values.get(&*function_value).unwrap();
let ret_ty =
LLVMGetReturnType(fun.ty.as_llvm(module.context_ref, &module.types));
let mut param_list: Vec<LLVMValueRef> = instruction_values
.iter()
.map(|i| module.values.get(i).unwrap().value_ref)
.collect();
let is_void = Type::Void.as_llvm(module.context_ref, &module.types) == ret_ty;
if is_void {
LLVMContextSetDiscardValueNames(module.context_ref, 1);
}
let value = LLVMBuildCall2(
module.builder_ref,
fun.ty.as_llvm(module.context_ref, &module.types),
fun.value_ref,
param_list.as_mut_ptr(),
param_list.len() as u32,
name.as_ptr(),
);
if is_void {
LLVMContextSetDiscardValueNames(module.context_ref, 0);
}
value
}
} }
}; };
if let Some(record) = &self.record { if let Some(record) = &self.record {
@ -1062,7 +1150,8 @@ impl InstructionHolder {
unsafe { unsafe {
let mut addr = Vec::<u64>::new(); let mut addr = Vec::<u64>::new();
let expr = LLVMDIBuilderCreateExpression(debug.builder, addr.as_mut_ptr(), addr.len()); let expr =
LLVMDIBuilderCreateExpression(debug.builder, addr.as_mut_ptr(), addr.len());
let location = LLVMDIBuilderCreateDebugLocation( let location = LLVMDIBuilderCreateDebugLocation(
module.context_ref, module.context_ref,
@ -1073,22 +1162,26 @@ impl InstructionHolder {
); );
match record.kind { match record.kind {
DebugRecordKind::Declare(instruction_value) => LLVMDIBuilderInsertDeclareRecordBefore( DebugRecordKind::Declare(instruction_value) => {
debug.builder, LLVMDIBuilderInsertDeclareRecordBefore(
module.values.get(&instruction_value).unwrap().value_ref, debug.builder,
*debug.metadata.get(&record.variable).unwrap(), module.values.get(&instruction_value).unwrap().value_ref,
expr, *debug.metadata.get(&record.variable).unwrap(),
location, expr,
val, location,
), val,
DebugRecordKind::Value(instruction_value) => LLVMDIBuilderInsertDbgValueRecordBefore( )
debug.builder, }
module.values.get(&instruction_value).unwrap().value_ref, DebugRecordKind::Value(instruction_value) => {
*debug.metadata.get(&record.variable).unwrap(), LLVMDIBuilderInsertDbgValueRecordBefore(
expr, debug.builder,
location, module.values.get(&instruction_value).unwrap().value_ref,
val, *debug.metadata.get(&record.variable).unwrap(),
), expr,
location,
val,
)
}
}; };
} }
} }
@ -1101,7 +1194,13 @@ impl InstructionHolder {
| LLVMValueKind::LLVMMemoryPhiValueKind => { | LLVMValueKind::LLVMMemoryPhiValueKind => {
LLVMInstructionSetDebugLoc( LLVMInstructionSetDebugLoc(
val, 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 { 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 _ty = self.get_type(module.builder).unwrap();
let val = unsafe { let val = unsafe {
match self { match self {
@ -1226,7 +1330,11 @@ impl ConstValueKind {
} }
impl Type { impl Type {
fn as_llvm(&self, context: LLVMContextRef, typemap: &HashMap<TypeValue, LLVMTypeRef>) -> LLVMTypeRef { fn as_llvm(
&self,
context: LLVMContextRef,
typemap: &HashMap<TypeValue, LLVMTypeRef>,
) -> LLVMTypeRef {
use Type::*; use Type::*;
unsafe { unsafe {
match self { match self {
@ -1247,6 +1355,18 @@ impl Type {
F80 => LLVMX86FP80TypeInContext(context), F80 => LLVMX86FP80TypeInContext(context),
F128 => LLVMFP128TypeInContext(context), F128 => LLVMFP128TypeInContext(context),
F128PPC => LLVMPPCFP128TypeInContext(context), F128PPC => LLVMPPCFP128TypeInContext(context),
Function(params, ret) => {
let mut params_llvm = params
.iter()
.map(|v| v.as_llvm(context, typemap))
.collect::<Vec<_>>();
LLVMFunctionType(
ret.as_llvm(context, typemap),
params_llvm.as_mut_ptr(),
params_llvm.len() as u32,
0,
)
}
} }
} }
} }

View File

@ -9,10 +9,10 @@ use crate::{
CmpPredicate, Context, Instr, InstructionData, TerminatorKind, CmpPredicate, Context, Instr, InstructionData, TerminatorKind,
builder::*, builder::*,
debug_information::{ debug_information::{
DebugArrayType, DebugBasicType, DebugFieldType, DebugInformation, DebugLocalVariable, DebugLocation, DebugArrayType, DebugBasicType, DebugFieldType, DebugInformation, DebugLocalVariable,
DebugLocationValue, DebugMetadata, DebugMetadataValue, DebugParamVariable, DebugPointerType, DebugPosition, DebugLocation, DebugLocationValue, DebugMetadata, DebugMetadataValue, DebugParamVariable,
DebugRecordKind, DebugScopeValue, DebugStructType, DebugSubprogramType, DebugTypeData, DebugTypeHolder, DebugPointerType, DebugPosition, DebugRecordKind, DebugScopeValue, DebugStructType,
DebugTypeValue, DebugSubprogramType, DebugTypeData, DebugTypeHolder, DebugTypeValue,
}, },
pad_adapter::PadAdapter, pad_adapter::PadAdapter,
}; };
@ -68,7 +68,11 @@ impl FunctionHolder {
.map(|p| format!("{:?}", p)) .map(|p| format!("{:?}", p))
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join(", "); .join(", ");
write!(f, "fn {}({}) -> {:?} ", self.data.name, params, self.data.ret)?; write!(
f,
"fn {}({}) -> {:?} ",
self.data.name, params, self.data.ret
)?;
writeln!(f, "{{")?; writeln!(f, "{{")?;
let mut state = Default::default(); let mut state = Default::default();
@ -112,7 +116,11 @@ impl BlockHolder {
terminator.builder_fmt(&mut inner, builder, debug)?; terminator.builder_fmt(&mut inner, builder, debug)?;
} }
if let Some(location) = &self.data.terminator_location { 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(()) Ok(())
@ -140,7 +148,11 @@ impl InstructionHolder {
writeln!(f, " (Debug {} {})", record.variable.hr(debug), kind)?; 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(debug) = debug {
if let Some(location) = &self.data.location { if let Some(location) = &self.data.location {
writeln!(f, " ^ (At {}) ", debug.get_location(location))?; writeln!(f, " ^ (At {}) ", debug.get_location(location))?;
@ -176,7 +188,9 @@ impl TerminatorKind {
impl DebugMetadataValue { impl DebugMetadataValue {
fn hr(&self, debug: &DebugInformation) -> String { fn hr(&self, debug: &DebugInformation) -> String {
let kind = match debug.get_metadata(*self) { 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) format!("param {} (idx {}) (type {:?}) ", name, arg_idx, ty)
} }
DebugMetadata::LocalVar(DebugLocalVariable { name, ty, .. }) => { DebugMetadata::LocalVar(DebugLocalVariable { name, ty, .. }) => {
@ -241,11 +255,14 @@ impl Debug for FunctionHolder {
impl Debug for BlockHolder { impl Debug for BlockHolder {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let deleted = if self.data.deleted { " (deleted)" } else { "" }; let deleted = if self.data.deleted { " (deleted)" } else { "" };
f.debug_tuple(&format!("{}[{:?}]{} ", &self.data.name, &self.value, deleted)) f.debug_tuple(&format!(
.field(&self.instructions) "{}[{:?}]{} ",
.field(&self.data.terminator) &self.data.name, &self.value, deleted
.field(&self.data.terminator_location) ))
.finish() .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 { impl Debug for InstructionValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 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())?; fmt_index(f, instruction_value, &index.to_string())?;
write!(f, ")") 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) => { Instr::Trunc(instr_val, ty) => {
write!(f, "{:?} to {:?} ({})", instr_val, ty, self.default_name()) 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::ShiftLeft(lhs, rhs) => fmt_binop(f, lhs, &"<<", rhs),
Instr::GetGlobal(global_value) => write!(f, "global {:?}", global_value), Instr::GetGlobal(global_value) => write!(f, "global {:?}", global_value),
Instr::IsNull(_) => write!(f, "is_null"), 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!( write!(
f, f,
"Scope[{}]", "Scope[{}]",
self.0.iter().map(|v| v.to_string()).collect::<Vec<_>>().join(", ") self.0
.iter()
.map(|v| v.to_string())
.collect::<Vec<_>>()
.join(", ")
) )
} }
} }

View File

@ -36,7 +36,9 @@ impl LLVMIntrinsic {
LLVMIntrinsic::Max(ty) => { LLVMIntrinsic::Max(ty) => {
let name = match ty.category() { let name = match ty.category() {
TypeCategory::SignedInteger => format!("llvm.smax.{}", ty.llvm_ty_str(builder)), 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)), TypeCategory::Real => format!("llvm.maximum.{}", ty.llvm_ty_str(builder)),
_ => return Err(crate::ErrorKind::Null), _ => return Err(crate::ErrorKind::Null),
}; };
@ -45,7 +47,9 @@ impl LLVMIntrinsic {
LLVMIntrinsic::Min(ty) => { LLVMIntrinsic::Min(ty) => {
let name = match ty.category() { let name = match ty.category() {
TypeCategory::SignedInteger => format!("llvm.smin.{}", ty.llvm_ty_str(builder)), 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)), TypeCategory::Real => format!("llvm.minimum.{}", ty.llvm_ty_str(builder)),
_ => return Err(crate::ErrorKind::Null), _ => return Err(crate::ErrorKind::Null),
}; };
@ -54,7 +58,9 @@ impl LLVMIntrinsic {
LLVMIntrinsic::Abs(ty) => { LLVMIntrinsic::Abs(ty) => {
let name = match ty.category() { let name = match ty.category() {
TypeCategory::SignedInteger => format!("llvm.abs.{}", ty.llvm_ty_str(builder)), 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)), TypeCategory::Real => format!("llvm.fabs.{}", ty.llvm_ty_str(builder)),
_ => return Err(crate::ErrorKind::Null), _ => return Err(crate::ErrorKind::Null),
}; };
@ -65,7 +71,11 @@ impl LLVMIntrinsic {
TypeCategory::Ptr => String::from("llvm.memcpy"), TypeCategory::Ptr => String::from("llvm.memcpy"),
_ => return Err(crate::ErrorKind::Null), _ => 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) => { LLVMIntrinsic::Sqrt(ty) => {
let name = match ty.category() { let name = match ty.category() {
@ -77,10 +87,18 @@ impl LLVMIntrinsic {
LLVMIntrinsic::PowI(ty1, ty2) => { LLVMIntrinsic::PowI(ty1, ty2) => {
let name = match (ty1.category(), ty2.category()) { let name = match (ty1.category(), ty2.category()) {
(TypeCategory::Real, TypeCategory::SignedInteger) => { (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) => { (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), _ => return Err(crate::ErrorKind::Null),
}; };
@ -258,6 +276,14 @@ impl Type {
} }
Type::Array(ty, len) => format!("[{} x {}]", len, ty.llvm_ty_str(builder)), Type::Array(ty, len) => format!("[{} x {}]", len, ty.llvm_ty_str(builder)),
Type::Ptr(_) => String::from("ptr"), Type::Ptr(_) => String::from("ptr"),
Type::Function(params, ret) => format!(
"fn {:?} -> {}",
params
.iter()
.map(|v| v.llvm_ty_str(builder))
.collect::<Vec<_>>(),
ret.llvm_ty_str(builder)
),
} }
} }
} }

View File

@ -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); let (debug_info, scope_value) = DebugInformation::from_file(file);
self.debug_info = Some(debug_info.clone()); self.debug_info = Some(debug_info.clone());
(debug_info, scope_value) (debug_info, scope_value)
@ -327,12 +330,18 @@ impl Instr {
Instr::ShiftLeft(..) => "shl", Instr::ShiftLeft(..) => "shl",
Instr::GetGlobal(..) => "global", Instr::GetGlobal(..) => "global",
Instr::IsNull(..) => "is_null", Instr::IsNull(..) => "is_null",
Instr::Function(..) => "func",
Instr::DynFunctionCall(..) => "call",
} }
} }
} }
impl<'builder> Block<'builder> { impl<'builder> Block<'builder> {
pub fn build_named<T: Into<String>>(&mut self, name: T, instruction: Instr) -> CompileResult<InstructionValue> { pub fn build_named<T: Into<String>>(
&mut self,
name: T,
instruction: Instr,
) -> CompileResult<InstructionValue> {
unsafe { unsafe {
self.builder.add_instruction( self.builder.add_instruction(
&self.value, &self.value,
@ -367,13 +376,15 @@ impl<'builder> Block<'builder> {
pub fn set_instr_location(&self, instruction: InstructionValue, location: DebugLocationValue) { pub fn set_instr_location(&self, instruction: InstructionValue, location: DebugLocationValue) {
unsafe { 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) { pub fn set_instr_metadata(&self, instruction: InstructionValue, location: DebugMetadataValue) {
unsafe { unsafe {
self.builder.add_instruction_metadata(&instruction, location); self.builder
.add_instruction_metadata(&instruction, location);
} }
} }
@ -425,6 +436,7 @@ pub enum Instr {
Param(usize), Param(usize),
Constant(ConstValueKind), Constant(ConstValueKind),
GetGlobal(GlobalValue), GetGlobal(GlobalValue),
Function(FunctionValue),
/// Add two integers /// Add two integers
Add(InstructionValue, InstructionValue), Add(InstructionValue, InstructionValue),
@ -524,6 +536,7 @@ pub enum Instr {
IsNull(InstructionValue), IsNull(InstructionValue),
FunctionCall(FunctionValue, Vec<InstructionValue>), FunctionCall(FunctionValue, Vec<InstructionValue>),
DynFunctionCall(InstructionValue, Vec<InstructionValue>),
} }
#[derive(Debug, PartialEq, Eq, Clone, Hash, PartialOrd)] #[derive(Debug, PartialEq, Eq, Clone, Hash, PartialOrd)]
@ -550,6 +563,7 @@ pub enum Type {
CustomType(TypeValue), CustomType(TypeValue),
Array(Box<Type>, u64), Array(Box<Type>, u64),
Ptr(Box<Type>), Ptr(Box<Type>),
Function(Vec<Type>, Box<Type>),
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -666,16 +680,25 @@ impl TypeCategory {
impl Type { impl Type {
pub fn category(&self) -> TypeCategory { pub fn category(&self) -> TypeCategory {
match self { match self {
Type::I8 | Type::I16 | Type::I32 | Type::I64 | Type::I128 => TypeCategory::SignedInteger, Type::I8 | Type::I16 | Type::I32 | Type::I64 | Type::I128 => {
Type::U8 | Type::U16 | Type::U32 | Type::U64 | Type::U128 => TypeCategory::UnsignedInteger, TypeCategory::SignedInteger
Type::F16 | Type::F32B | Type::F32 | Type::F64 | Type::F80 | Type::F128 | Type::F128PPC => {
TypeCategory::Real
} }
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::Bool => TypeCategory::UnsignedInteger,
Type::Void => TypeCategory::Void, Type::Void => TypeCategory::Void,
Type::CustomType(_) => TypeCategory::CustomType, Type::CustomType(_) => TypeCategory::CustomType,
Type::Array(_, _) => TypeCategory::Array, Type::Array(_, _) => TypeCategory::Array,
Type::Ptr(_) => TypeCategory::Ptr, Type::Ptr(_) => TypeCategory::Ptr,
Type::Function(..) => TypeCategory::Ptr,
} }
} }
@ -686,15 +709,23 @@ impl Type {
(I16, I32 | I64 | I128) => Some(Instr::SExt(value, other.clone())), (I16, I32 | I64 | I128) => Some(Instr::SExt(value, other.clone())),
(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())), (I64, I128) => Some(Instr::SExt(value, other.clone())),
(I128 | U128, I64 | U64 | I32 | U32 | I16 | U16 | I8 | U8) => Some(Instr::Trunc(value, other.clone())), (I128 | U128, I64 | U64 | I32 | U32 | I16 | U16 | I8 | U8) => {
(I64 | U64, I32 | U32 | I16 | U16 | I8 | U8) => Some(Instr::Trunc(value, other.clone())), 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())), (I32 | U32, I16 | U16 | I8 | U8) => Some(Instr::Trunc(value, other.clone())),
(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) => { (U8 | I8, U8 | I8 | U16 | I16 | U32 | I32 | U64 | I64 | U128 | I128) => {
Some(Instr::ZExt(value, other.clone())) Some(Instr::ZExt(value, other.clone()))
} }
(U16 | I16, U16 | I16 | U32 | I32 | U64 | I64 | U128 | I128) => Some(Instr::ZExt(value, other.clone())), (U16 | I16, U16 | I16 | U32 | I32 | U64 | I64 | U128 | I128) => {
(U32 | I32, U32 | I32 | U64 | I64 | U128 | I128) => Some(Instr::ZExt(value, other.clone())), 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())), (U64 | I64, U64 | I64 | U128 | I128) => Some(Instr::ZExt(value, other.clone())),
(U128 | I128, 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) => { (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) => { (Ptr(_), I128 | U128 | I64 | U64 | I32 | U32 | I16 | U16 | I8 | U8) => {
Some(Instr::PtrToInt(value, other.clone())) 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())), (F32 | F32B, F64 | F80 | F128 | F128PPC) => Some(Instr::FPExt(value, other.clone())),
(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())), (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())), (F80, F64 | F32B | F32 | F16) => Some(Instr::FPTrunc(value, other.clone())),
(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())), (F32B | F32, F16) => Some(Instr::FPTrunc(value, other.clone())),