From 066f441a77a944e2ea7a5cfd494f4628e8026887 Mon Sep 17 00:00:00 2001 From: sofia Date: Mon, 21 Jul 2025 20:34:27 +0300 Subject: [PATCH] Add FCmp --- reid-llvm-lib/src/builder.rs | 12 ++++++++++-- reid-llvm-lib/src/compile.rs | 27 +++++++++++++++++++++++++-- reid-llvm-lib/src/fmt.rs | 1 + reid-llvm-lib/src/lib.rs | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 71 insertions(+), 4 deletions(-) diff --git a/reid-llvm-lib/src/builder.rs b/reid-llvm-lib/src/builder.rs index 232ca7a..645a568 100644 --- a/reid-llvm-lib/src/builder.rs +++ b/reid-llvm-lib/src/builder.rs @@ -5,7 +5,7 @@ use std::{cell::RefCell, rc::Rc}; use crate::{ BlockData, CustomTypeKind, FunctionData, Instr, InstructionData, ModuleData, NamedStruct, - TerminatorKind, Type, TypeData, + TerminatorKind, Type, TypeCategory, TypeData, debug_information::{ DebugInformation, DebugLocationValue, DebugMetadataValue, DebugProgramValue, InstructionDebugRecordData, @@ -369,7 +369,15 @@ impl Builder { Instr::And(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), Instr::ICmp(_, lhs, rhs) => { let t = match_types(&lhs, &rhs, self)?; - if t.comparable() { + if t.comparable() || t.category() != TypeCategory::Integer { + Ok(()) + } else { + Err(()) // TODO error: Types not comparable + } + } + Instr::FCmp(_, lhs, rhs) => { + let t = match_types(&lhs, &rhs, self)?; + if t.comparable() || t.category() != TypeCategory::Real { Ok(()) } else { Err(()) // TODO error: Types not comparable diff --git a/reid-llvm-lib/src/compile.rs b/reid-llvm-lib/src/compile.rs index 7bfdbe8..96131ff 100644 --- a/reid-llvm-lib/src/compile.rs +++ b/reid-llvm-lib/src/compile.rs @@ -8,7 +8,7 @@ use std::{ }; use llvm_sys::{ - LLVMIntPredicate, LLVMLinkage, LLVMValueKind, + LLVMIntPredicate, LLVMLinkage, LLVMRealPredicate, LLVMValueKind, analysis::LLVMVerifyModule, core::*, debuginfo::*, @@ -774,7 +774,6 @@ impl InstructionHolder { let rhs_val = module.values.get(&rhs).unwrap().value_ref; LLVMBuildMul(module.builder_ref, lhs_val, rhs_val, name.as_ptr()) } - FMul(lhs, rhs) => { let lhs_val = module.values.get(&lhs).unwrap().value_ref; let rhs_val = module.values.get(&rhs).unwrap().value_ref; @@ -827,6 +826,17 @@ impl InstructionHolder { name.as_ptr(), ) } + FCmp(pred, lhs, rhs) => { + let lhs = module.values.get(&lhs).unwrap(); + let rhs_val = module.values.get(&rhs).unwrap().value_ref; + LLVMBuildFCmp( + module.builder_ref, + pred.as_llvm_unsorted_float(), + lhs.value_ref, + rhs_val, + name.as_ptr(), + ) + } FunctionCall(function_value, instruction_values) => { let fun = module.functions.get(&function_value).unwrap(); let mut param_list: Vec = instruction_values @@ -1057,6 +1067,19 @@ impl CmpPredicate { (NE, _) => LLVMIntNE, } } + + fn as_llvm_unsorted_float(&self) -> LLVMRealPredicate { + use CmpPredicate::*; + use LLVMRealPredicate::*; + match self { + LT => LLVMRealULT, + LE => LLVMRealULE, + GT => LLVMRealUGT, + GE => LLVMRealUGE, + EQ => LLVMRealUEQ, + NE => LLVMRealUNE, + } + } } impl ConstValue { diff --git a/reid-llvm-lib/src/fmt.rs b/reid-llvm-lib/src/fmt.rs index 6c05c2d..1ebfb05 100644 --- a/reid-llvm-lib/src/fmt.rs +++ b/reid-llvm-lib/src/fmt.rs @@ -317,6 +317,7 @@ impl Debug for Instr { Instr::And(lhs, rhs) => fmt_binop(f, lhs, &"&&", rhs), Instr::Phi(val) => fmt_call(f, &"Phi", &val), Instr::ICmp(cmp, lhs, rhs) => fmt_binop(f, lhs, cmp, rhs), + Instr::FCmp(cmp, lhs, rhs) => fmt_binop(f, lhs, cmp, rhs), Instr::FunctionCall(fun, params) => fmt_call(f, fun, params), Instr::Alloca(ty) => write!(f, "alloca<{:?}>", ty), Instr::Load(val, ty) => write!(f, "load<{:?}>({:?})", ty, val), diff --git a/reid-llvm-lib/src/lib.rs b/reid-llvm-lib/src/lib.rs index 215843a..232d415 100644 --- a/reid-llvm-lib/src/lib.rs +++ b/reid-llvm-lib/src/lib.rs @@ -232,6 +232,7 @@ impl Instr { Instr::ExtractValue(..) => "extractvalue", Instr::ICmp(..) => "icmp", Instr::FunctionCall(..) => "call", + Instr::FCmp(_, _, _) => "fcmp", } } } @@ -396,6 +397,7 @@ pub enum Instr { /// Integer Comparison ICmp(CmpPredicate, InstructionValue, InstructionValue), + FCmp(CmpPredicate, InstructionValue, InstructionValue), FunctionCall(FunctionValue, Vec), } @@ -497,6 +499,7 @@ impl InstructionValue { FRem(lhs, rhs) => match_types(lhs, rhs, &builder), And(lhs, rhs) => match_types(lhs, rhs, &builder), ICmp(_, _, _) => Ok(Type::Bool), + FCmp(_, _, _) => Ok(Type::Bool), FunctionCall(function_value, _) => Ok(builder.function_data(function_value).ret), Phi(values) => values.first().ok_or(()).and_then(|v| v.get_type(&builder)), Alloca(ty) => Ok(Type::Ptr(Box::new(ty.clone()))), @@ -629,6 +632,38 @@ impl Type { Type::F128PPC => true, } } + + pub fn category(&self) -> TypeCategory { + match self { + Type::I8 + | Type::I16 + | Type::I32 + | Type::I64 + | Type::I128 + | Type::U8 + | Type::U16 + | Type::U32 + | Type::U64 + | Type::U128 => TypeCategory::Integer, + Type::F16 + | Type::F32B + | Type::F32 + | Type::F64 + | Type::F80 + | Type::F128 + | Type::F128PPC => TypeCategory::Real, + Type::Bool | Type::Void | Type::CustomType(_) | Type::Array(_, _) | Type::Ptr(_) => { + TypeCategory::Other + } + } + } +} + +#[derive(PartialEq, Eq, PartialOrd, Ord)] +pub enum TypeCategory { + Integer, + Real, + Other, } impl TerminatorKind {