Fix a bunch of errors in reid-llvm-lib
This commit is contained in:
parent
c23160bc32
commit
0203213b28
@ -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<Instr> {
|
||||
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()))
|
||||
}
|
||||
}
|
||||
|
@ -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<T> = Result<T, ErrorKind>;
|
||||
@ -600,7 +626,7 @@ impl ConstValueKind {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone)]
|
||||
pub enum TypeCategory {
|
||||
SignedInteger,
|
||||
UnsignedInteger,
|
||||
|
@ -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<String> {
|
||||
}
|
||||
|
||||
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<Type> {
|
||||
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) {
|
||||
pub fn match_types(lhs: &InstructionValue, rhs: &InstructionValue, builder: &Builder) -> CompileResult<Type> {
|
||||
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)
|
||||
}
|
||||
} else {
|
||||
Err(ErrorKind::Null)
|
||||
Err(ErrorKind::TypesIncompatible(lhs_t, rhs_t))
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user