From 0203213b28242e804d5cb9139a5bbd57a6b0f7cd Mon Sep 17 00:00:00 2001 From: sofia Date: Tue, 12 Aug 2025 21:21:10 +0300 Subject: [PATCH] Fix a bunch of errors in reid-llvm-lib --- reid-llvm-lib/src/builder.rs | 118 ++++++++++++++++++++++++----------- reid-llvm-lib/src/lib.rs | 28 ++++++++- reid-llvm-lib/src/util.rs | 37 +++-------- 3 files changed, 118 insertions(+), 65 deletions(-) diff --git a/reid-llvm-lib/src/builder.rs b/reid-llvm-lib/src/builder.rs index 42ab14c..e37bc8b 100644 --- a/reid-llvm-lib/src/builder.rs +++ b/reid-llvm-lib/src/builder.rs @@ -20,13 +20,13 @@ pub struct ModuleValue(pub(crate) usize); #[derive(Clone, Hash, Copy, PartialEq, Eq, PartialOrd)] pub struct TypeValue(pub(crate) ModuleValue, pub(crate) usize); -#[derive(Clone, Hash, Copy, PartialEq, Eq)] +#[derive(Clone, Hash, Copy, PartialEq, Eq, PartialOrd)] pub struct FunctionValue(pub(crate) ModuleValue, pub(crate) usize); -#[derive(Clone, Hash, Copy, PartialEq, Eq)] +#[derive(Clone, Hash, Copy, PartialEq, Eq, PartialOrd)] pub struct BlockValue(pub(crate) FunctionValue, pub(crate) usize); -#[derive(Clone, Hash, Copy, PartialEq, Eq)] +#[derive(Clone, Hash, Copy, PartialEq, Eq, PartialOrd)] pub struct InstructionValue(pub(crate) BlockValue, pub(crate) usize); #[derive(Debug, Clone, Hash, Copy, PartialEq, Eq)] @@ -278,7 +278,7 @@ impl Builder { let function = module.functions.get_unchecked_mut(block.0.1); let block = function.blocks.get_unchecked_mut(block.1); if let Some(_) = &block.data.terminator { - Err(ErrorKind::Null) + Err(ErrorKind::BlockAlreadyTerminated) } else { block.data.terminator = Some(value); Ok(()) @@ -297,7 +297,7 @@ impl Builder { let function = module.functions.get_unchecked_mut(block.0.1); let block = function.blocks.get_unchecked_mut(block.1); if let Some(_) = &block.data.terminator_location { - Err(ErrorKind::Null) + Err(ErrorKind::BlockTerminatorLocated) } else { block.data.terminator_location = Some(location); Ok(()) @@ -411,84 +411,120 @@ impl Builder { if match_types(&lhs, &rhs, &self)?.category().integer() { Ok(()) } else { - Err(ErrorKind::Null) + Err(ErrorKind::TypeNotInteger(lhs, lhs.get_type(&self)?)) } } Instr::FAdd(lhs, rhs) => { if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::Real { Ok(()) } else { - Err(ErrorKind::Null) + Err(ErrorKind::TypeWrongCategory( + lhs, + lhs.get_type(&self)?, + TypeCategory::Real, + )) } } Instr::Sub(lhs, rhs) => { if match_types(&lhs, &rhs, &self)?.category().integer() { Ok(()) } else { - Err(ErrorKind::Null) + Err(ErrorKind::TypeNotInteger(lhs, lhs.get_type(&self)?)) } } Instr::FSub(lhs, rhs) => { if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::Real { Ok(()) } else { - Err(ErrorKind::Null) + Err(ErrorKind::TypeWrongCategory( + lhs, + lhs.get_type(&self)?, + TypeCategory::Real, + )) } } Instr::Mul(lhs, rhs) => { if match_types(&lhs, &rhs, &self)?.category().integer() { Ok(()) } else { - Err(ErrorKind::Null) + Err(ErrorKind::TypeNotInteger(lhs, lhs.get_type(&self)?)) } } Instr::FMul(lhs, rhs) => { if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::Real { Ok(()) } else { - Err(ErrorKind::Null) + Err(ErrorKind::TypeWrongCategory( + lhs, + lhs.get_type(&self)?, + TypeCategory::Real, + )) } } Instr::UDiv(lhs, rhs) => { if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::UnsignedInteger { Ok(()) } else { - Err(ErrorKind::Null) + Err(ErrorKind::TypeWrongCategory( + lhs, + lhs.get_type(&self)?, + TypeCategory::UnsignedInteger, + )) } } Instr::SDiv(lhs, rhs) => { if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::SignedInteger { Ok(()) } else { - Err(ErrorKind::Null) + Err(ErrorKind::TypeWrongCategory( + lhs, + lhs.get_type(&self)?, + TypeCategory::SignedInteger, + )) } } Instr::FDiv(lhs, rhs) => { if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::Real { Ok(()) } else { - Err(ErrorKind::Null) + Err(ErrorKind::TypeWrongCategory( + lhs, + lhs.get_type(&self)?, + TypeCategory::Real, + )) } } Instr::URem(lhs, rhs) => { if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::UnsignedInteger { Ok(()) } else { - Err(ErrorKind::Null) + Err(ErrorKind::TypeWrongCategory( + lhs, + lhs.get_type(&self)?, + TypeCategory::UnsignedInteger, + )) } } Instr::SRem(lhs, rhs) => { if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::SignedInteger { Ok(()) } else { - Err(ErrorKind::Null) + Err(ErrorKind::TypeWrongCategory( + lhs, + lhs.get_type(&self)?, + TypeCategory::SignedInteger, + )) } } Instr::FRem(lhs, rhs) => { if match_types(&lhs, &rhs, &self)?.category() == TypeCategory::Real { Ok(()) } else { - Err(ErrorKind::Null) + Err(ErrorKind::TypeWrongCategory( + lhs, + lhs.get_type(&self)?, + TypeCategory::Real, + )) } } Instr::And(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), @@ -499,7 +535,7 @@ impl Builder { if t.category().comparable() || !t.category().integer() { Ok(()) } else { - Err(ErrorKind::Null) // TODO error: Types not comparable + Err(ErrorKind::TypeNotComparable(lhs, t)) } } Instr::FCmp(_, lhs, rhs) => { @@ -507,17 +543,17 @@ impl Builder { if t.category().comparable() || t.category() != TypeCategory::Real { Ok(()) } else { - Err(ErrorKind::Null) // TODO error: Types not comparable + Err(ErrorKind::TypeNotComparable(lhs, t)) } } Instr::FunctionCall(fun, params) => { let param_types = self.function_data(&fun).params; if param_types.len() != params.len() { - return Err(ErrorKind::Null); // TODO error: invalid amount of params + return Err(ErrorKind::InvalidLenParams(params.len(), param_types.len())); } 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)?)); // TODO error: params do not match + return Err(ErrorKind::TypesIncompatible(a.clone(), b.get_type(&self)?)); } } Ok(()) @@ -530,7 +566,7 @@ impl Builder { // incoming values come from blocks that are added later // than the one where this one exists. - let first = iter.next().ok_or(ErrorKind::Null)?; + let first = iter.next().ok_or(ErrorKind::EmptyPhiList)?; for item in iter { match_types(first, item, &self)?; } @@ -543,10 +579,10 @@ impl Builder { if *ptr_ty_inner == load_ty { Ok(()) } else { - Err(ErrorKind::Null) // TODO error: inner type mismatch + Err(ErrorKind::TypesIncompatible(*ptr_ty_inner, load_ty)) } } else { - Err(ErrorKind::Null) // TODO error: not a pointer + Err(ErrorKind::NotPointer(ptr, ptr_ty)) } } Instr::Store(ptr, _) => { @@ -554,21 +590,25 @@ impl Builder { if let Type::Ptr(_) = ty { Ok(()) } else { - Err(ErrorKind::Null) // TODO error: not a pointer + Err(ErrorKind::NotPointer(ptr, ty)) } } Instr::ArrayAlloca(_, val) => { if val.get_type(self)?.category() == TypeCategory::UnsignedInteger { Ok(()) } else { - Err(ErrorKind::Null) // TODO error: not a pointer + Err(ErrorKind::TypeWrongCategory( + val, + val.get_type(self)?, + TypeCategory::UnsignedInteger, + )) } } Instr::GetElemPtr(ptr_val, _) => { let ptr_ty = ptr_val.get_type(&self)?; match ptr_ty { Type::Ptr(_) => Ok(()), - _ => Err(ErrorKind::Null), + _ => Err(ErrorKind::NotPointer(ptr_val, ptr_ty)), } } Instr::GetStructElemPtr(ptr_val, idx) => { @@ -578,16 +618,16 @@ impl Builder { match self.type_data(&val).kind { CustomTypeKind::NamedStruct(NamedStruct(_, fields)) => { if fields.len() <= idx as usize { - return Err(ErrorKind::Null); // TODO error: no such field + return Err(ErrorKind::NoSuchField(*ty, idx)); } } } Ok(()) } else { - Err(ErrorKind::Null) // TODO error: not a struct + Err(ErrorKind::NotStruct(ptr_val, *ty)) } } else { - Err(ErrorKind::Null) // TODO error: not a pointer + Err(ErrorKind::NotPointer(ptr_val, ptr_ty)) } } Instr::ExtractValue(val, _) => { @@ -597,7 +637,7 @@ impl Builder { CustomTypeKind::NamedStruct(_) => Ok(()), }, Type::Array(_, _) => Ok(()), - _ => Err(ErrorKind::Null), + _ => Err(ErrorKind::NotExtractable(val, val_ty)), } } Instr::Trunc(instr, ty) => instr.cast_to(self, &ty).map(|_| ()), @@ -621,7 +661,7 @@ impl Builder { if let Type::Ptr(_) = val_ty { Ok(()) } else { - Err(ErrorKind::Null) + Err(ErrorKind::NotPointer(val, val_ty)) } } } @@ -695,7 +735,7 @@ impl InstructionValue { .params .get(*nth) .cloned() - .ok_or(ErrorKind::Null), + .ok_or(ErrorKind::NoSuchParam(self.0.0, *nth)), Constant(c) => Ok(c.get_type()), Add(lhs, rhs) => match_types(lhs, rhs, &builder), FAdd(lhs, rhs) => match_types(lhs, rhs, &builder), @@ -715,7 +755,10 @@ 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::EmptyPhiList) + .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), @@ -757,7 +800,7 @@ impl InstructionValue { } } Type::Array(elem_ty, _) => *elem_ty.clone(), - _ => return Err(ErrorKind::Null), + _ => return Err(ErrorKind::NotExtractable(*instr, instr_ty)), }) } Trunc(instr, ty) => instr.cast_to(builder, ty).map(|_| ty.clone()), @@ -786,8 +829,9 @@ impl InstructionValue { } fn cast_to(&self, builder: &Builder, ty: &Type) -> CompileResult { - self.get_type(builder)? + let own_type = self.get_type(builder)?; + own_type .cast_instruction(*self, &ty) - .ok_or(ErrorKind::Null) + .ok_or(ErrorKind::ImpossibleCast(own_type, ty.clone())) } } diff --git a/reid-llvm-lib/src/lib.rs b/reid-llvm-lib/src/lib.rs index a89b516..6a4e735 100644 --- a/reid-llvm-lib/src/lib.rs +++ b/reid-llvm-lib/src/lib.rs @@ -28,6 +28,32 @@ pub enum ErrorKind { Null, #[error("Types {0:?} and {1:?} incompatible")] TypesIncompatible(Type, Type), + #[error("Phi list of values is empty")] + EmptyPhiList, + #[error("Type {1:?} of value {0:?} is not extractable")] + NotExtractable(InstructionValue, Type), + #[error("Type {0:?} is not castable to {1:?}")] + ImpossibleCast(Type, Type), + #[error("Block is already terminated")] + BlockAlreadyTerminated, + #[error("Block terminator already has a location")] + BlockTerminatorLocated, + #[error("Value {0:?} must be an integer type. Is {1:?}")] + TypeNotInteger(InstructionValue, Type), + #[error("Value {0:?} must be a {2:?} type. Is {1:?}")] + TypeWrongCategory(InstructionValue, Type, TypeCategory), + #[error("Value {0:?} must be comparable, was {1:?}")] + TypeNotComparable(InstructionValue, Type), + #[error("Got {0:?} parameters, expected {1:?}")] + InvalidLenParams(usize, usize), + #[error("Value {0:?} is not a pointer, is {1:?}")] + NotPointer(InstructionValue, Type), + #[error("Value {0:?} is not a struct, is {1:?}")] + NotStruct(InstructionValue, Type), + #[error("Struct {0:?} has no such field as {1:?}")] + NoSuchField(Type, u32), + #[error("Function {0:?} has no such parameter as {1:?}")] + NoSuchParam(FunctionValue, usize), } pub type CompileResult = Result; @@ -600,7 +626,7 @@ impl ConstValueKind { } } -#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)] +#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone)] pub enum TypeCategory { SignedInteger, UnsignedInteger, diff --git a/reid-llvm-lib/src/util.rs b/reid-llvm-lib/src/util.rs index be7735a..4df2b83 100644 --- a/reid-llvm-lib/src/util.rs +++ b/reid-llvm-lib/src/util.rs @@ -5,10 +5,7 @@ use std::{ }; use llvm_sys::{ - core::{ - LLVMCreateMemoryBufferWithMemoryRange, LLVMDisposeMemoryBuffer, LLVMGetBufferSize, - LLVMGetBufferStart, - }, + core::{LLVMCreateMemoryBufferWithMemoryRange, LLVMDisposeMemoryBuffer, LLVMGetBufferSize, LLVMGetBufferStart}, error::LLVMDisposeErrorMessage, prelude::LLVMMemoryBufferRef, }; @@ -32,9 +29,7 @@ pub fn from_cstring(pointer: *mut c_char) -> Option { } fn cstring_to_err(value: *mut c_char) -> Result<(), String> { - from_cstring(value) - .filter(|s| !s.is_empty()) - .map_or(Ok(()), |s| Err(s)) + from_cstring(value).filter(|s| !s.is_empty()).map_or(Ok(()), |s| Err(s)) } /// Utility struct for LLVM's Error Messages, which need to be disposed @@ -75,12 +70,8 @@ impl MemoryBufferHolder { pub fn empty(name: &str) -> MemoryBufferHolder { let array = [0i8; 0]; unsafe { - let buffer = LLVMCreateMemoryBufferWithMemoryRange( - array.as_ptr(), - array.len(), - into_cstring(name).as_ptr(), - 0, - ); + let buffer = + LLVMCreateMemoryBufferWithMemoryRange(array.as_ptr(), array.len(), into_cstring(name).as_ptr(), 0); MemoryBufferHolder { buffer } } } @@ -113,20 +104,12 @@ impl Drop for MemoryBufferHolder { /// Make sure types for given instructions match. Return Ok(type) if they do, /// and error otherwise. -pub fn match_types( - lhs: &InstructionValue, - rhs: &InstructionValue, - builder: &Builder, -) -> CompileResult { - let lhs_type = lhs.get_type(&builder); - let rhs_type = rhs.get_type(&builder); - if let (Ok(lhs_t), Ok(rhs_t)) = (lhs_type, rhs_type) { - if lhs_t == rhs_t { - Ok(lhs_t) - } else { - Err(ErrorKind::Null) - } +pub fn match_types(lhs: &InstructionValue, rhs: &InstructionValue, builder: &Builder) -> CompileResult { + let lhs_t = lhs.get_type(&builder)?; + let rhs_t = rhs.get_type(&builder)?; + if lhs_t == rhs_t { + Ok(lhs_t) } else { - Err(ErrorKind::Null) + Err(ErrorKind::TypesIncompatible(lhs_t, rhs_t)) } }