From b23577aa1897dcbe221464faf171b8ad59716887 Mon Sep 17 00:00:00 2001 From: sofia Date: Mon, 21 Jul 2025 15:44:47 +0300 Subject: [PATCH] Check for trivial expressions that they are >0 when unsigned --- reid-llvm-lib/src/builder.rs | 2 - reid/src/mir/implement.rs | 71 ++++++++++++++++++++++++++++++++++++ reid/src/mir/linker.rs | 8 ++-- reid/src/mir/mod.rs | 4 +- reid/src/mir/typecheck.rs | 12 ++++++ reid_src/arithmetic.reid | 2 +- 6 files changed, 90 insertions(+), 9 deletions(-) diff --git a/reid-llvm-lib/src/builder.rs b/reid-llvm-lib/src/builder.rs index e9504fc..5b39f43 100644 --- a/reid-llvm-lib/src/builder.rs +++ b/reid-llvm-lib/src/builder.rs @@ -395,8 +395,6 @@ impl Builder { Instr::Alloca(_) => Ok(()), Instr::Load(ptr, load_ty) => { let ptr_ty = ptr.get_type(&self)?; - dbg!(&self); - dbg!(&ptr_ty, &load_ty); if let Type::Ptr(ptr_ty_inner) = ptr_ty { if *ptr_ty_inner == load_ty { Ok(()) diff --git a/reid/src/mir/implement.rs b/reid/src/mir/implement.rs index 5b3483b..43fa900 100644 --- a/reid/src/mir/implement.rs +++ b/reid/src/mir/implement.rs @@ -29,6 +29,30 @@ impl TypeKind { } } + pub fn signed(&self) -> bool { + match self { + TypeKind::Bool => false, + TypeKind::I8 => true, + TypeKind::I16 => true, + TypeKind::I32 => true, + TypeKind::I64 => true, + TypeKind::I128 => true, + TypeKind::U8 => false, + TypeKind::U16 => false, + TypeKind::U32 => false, + TypeKind::U64 => false, + TypeKind::U128 => false, + TypeKind::Void => false, + TypeKind::StringPtr => false, + TypeKind::Array(type_kind, len) => false, + TypeKind::CustomType(_) => false, + TypeKind::CodegenPtr(_) => false, + TypeKind::Vague(_) => false, + TypeKind::Borrow(_, _) => false, + TypeKind::UserPtr(_) => false, + } + } + pub fn size_of(&self) -> u64 { match self { TypeKind::Bool => 1, @@ -262,6 +286,33 @@ impl Expression { ExprKind::If(_) => None, } } + + pub fn is_zero(&self) -> Option { + Some(self.num_value()? == 0) + } + + pub fn num_value(&self) -> Option { + match &self.0 { + ExprKind::Variable(_) => None, + ExprKind::Indexed(..) => None, + ExprKind::Accessed(..) => None, + ExprKind::Array(_) => None, + ExprKind::Struct(..) => None, + ExprKind::Literal(literal) => literal.num_value(), + ExprKind::BinOp(op, lhs, rhs) => match op { + BinaryOperator::Add => Some(lhs.num_value()? + rhs.num_value()?), + BinaryOperator::Minus => Some(lhs.num_value()? - rhs.num_value()?), + BinaryOperator::Mult => Some(lhs.num_value()? * rhs.num_value()?), + BinaryOperator::And => None, + BinaryOperator::Cmp(_) => None, + }, + ExprKind::FunctionCall(..) => None, + ExprKind::If(_) => None, + ExprKind::Block(_) => None, + ExprKind::Borrow(_, _) => None, + ExprKind::Deref(_) => None, + } + } } impl IfExpression { @@ -407,6 +458,26 @@ impl Collapsable for TypeKind { } } +impl Literal { + pub fn num_value(&self) -> Option { + match self { + Literal::I8(val) => Some(*val as i128), + Literal::I16(val) => Some(*val as i128), + Literal::I32(val) => Some(*val as i128), + Literal::I64(val) => Some(*val as i128), + Literal::I128(val) => Some(*val as i128), + Literal::U8(val) => Some(*val as i128), + Literal::U16(val) => Some(*val as i128), + Literal::U32(val) => Some(*val as i128), + Literal::U64(val) => Some(*val as i128), + Literal::U128(val) => Some(*val as i128), + Literal::Bool(_) => None, + Literal::String(_) => None, + Literal::Vague(VagueLiteral::Number(val)) => Some(*val as i128), + } + } +} + impl Collapsable for ScopeFunction { fn collapse_into(&self, other: &ScopeFunction) -> Result { Ok(ScopeFunction { diff --git a/reid/src/mir/linker.rs b/reid/src/mir/linker.rs index 0dcd38d..287fca2 100644 --- a/reid/src/mir/linker.rs +++ b/reid/src/mir/linker.rs @@ -103,10 +103,10 @@ impl<'map> Pass for LinkerPass<'map> { modules.insert(module.name.clone(), Rc::new(RefCell::new((module, tokens)))); } - modules.insert( - "std".to_owned(), - Rc::new(RefCell::new(compile_std(&mut self.module_map)?)), - ); + // modules.insert( + // "std".to_owned(), + // Rc::new(RefCell::new(compile_std(&mut self.module_map)?)), + // ); let mut modules_to_process: Vec)>>> = modules.values().cloned().collect(); diff --git a/reid/src/mir/mod.rs b/reid/src/mir/mod.rs index 0fe2b2b..cb08ac3 100644 --- a/reid/src/mir/mod.rs +++ b/reid/src/mir/mod.rs @@ -183,7 +183,7 @@ impl VagueLiteral { } } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub enum BinaryOperator { Add, Minus, @@ -193,7 +193,7 @@ pub enum BinaryOperator { } /// Specifically the operators that LLVM likes to take in as "icmp" parameters -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub enum CmpOperator { LT, LE, diff --git a/reid/src/mir/typecheck.rs b/reid/src/mir/typecheck.rs index 248e1dd..04a4a93 100644 --- a/reid/src/mir/typecheck.rs +++ b/reid/src/mir/typecheck.rs @@ -65,6 +65,8 @@ pub enum ErrorKind { ImpossibleMutableBorrow(String), #[error("Cannot declare variable {0} as mutable, when it's type is immutable")] ImpossibleMutLet(String), + #[error("Cannot produce a negative unsigned value of type {0}!")] + NegativeUnsignedValue(TypeKind), } /// Struct used to implement a type-checking pass that can be performed on the @@ -409,6 +411,16 @@ impl Expression { } let both_t = lhs_type.collapse_into(&rhs_type)?; + + dbg!(&op, &both_t, both_t.signed(), lhs.is_zero(), rhs.is_zero()); + if *op == BinaryOperator::Minus && !lhs_type.signed() { + if let (Some(lhs_val), Some(rhs_val)) = (lhs.num_value(), rhs.num_value()) { + if lhs_val < rhs_val { + return Err(ErrorKind::NegativeUnsignedValue(lhs_type)); + } + } + } + Ok(both_t.binop_type(op)) } ExprKind::FunctionCall(function_call) => { diff --git a/reid_src/arithmetic.reid b/reid_src/arithmetic.reid index 6b012be..95223af 100644 --- a/reid_src/arithmetic.reid +++ b/reid_src/arithmetic.reid @@ -5,5 +5,5 @@ fn main() -> u32 { let value = 6; let other = 15; - return value * other + 7 * (-value); + return value * other + 7 * -value; }