From d448c8b9f14c64f1218bb547d377d06f21ab45f2 Mon Sep 17 00:00:00 2001 From: sofia Date: Thu, 24 Jul 2025 15:52:46 +0300 Subject: [PATCH] Implement codegen for binops --- reid/src/codegen.rs | 213 +++++++++++++++++++++++++++----------------- 1 file changed, 130 insertions(+), 83 deletions(-) diff --git a/reid/src/codegen.rs b/reid/src/codegen.rs index 2a0f1d7..9cf5b2a 100644 --- a/reid/src/codegen.rs +++ b/reid/src/codegen.rs @@ -18,9 +18,12 @@ use crate::{ allocator::{Allocator, AllocatorScope}, lexer::{FullToken, Position}, mir::{ - self, implement::TypeCategory, pass::ScopeBinopKey, CustomTypeKey, FunctionDefinitionKind, - Metadata, NamedVariableRef, SourceModuleId, StructField, StructType, TypeDefinition, - TypeDefinitionKind, TypeKind, VagueLiteral, WhileStatement, + self, + implement::TypeCategory, + pass::{ScopeBinopDef, ScopeBinopKey}, + CustomTypeKey, FunctionDefinitionKind, Metadata, NamedVariableRef, SourceModuleId, + StructField, StructType, TypeDefinition, TypeDefinitionKind, TypeKind, VagueLiteral, + WhileStatement, }, util::try_all, }; @@ -77,12 +80,13 @@ pub struct Scope<'ctx, 'scope> { modules: &'scope HashMap>, tokens: &'ctx Vec, module: &'ctx Module<'ctx>, - pub(super) module_id: SourceModuleId, + module_id: SourceModuleId, function: &'ctx Function<'ctx>, pub(super) block: Block<'ctx>, - pub(super) types: &'scope HashMap, - pub(super) type_values: &'scope HashMap, + types: &'scope HashMap, + type_values: &'scope HashMap, functions: &'scope HashMap>, + binops: &'scope HashMap>, stack_values: HashMap, debug: Option>, allocator: Rc>, @@ -104,6 +108,7 @@ impl<'ctx, 'a> Scope<'ctx, 'a> { stack_values: self.stack_values.clone(), debug: self.debug.clone(), allocator: self.allocator.clone(), + binops: self.binops, } } @@ -186,6 +191,29 @@ pub struct StackBinopDefinition<'ctx> { ir: Function<'ctx>, } +impl<'ctx> StackBinopDefinition<'ctx> { + fn codegen<'a>( + &self, + lhs: &StackValue, + rhs: &StackValue, + scope: &mut Scope<'ctx, 'a>, + ) -> StackValue { + let (lhs, rhs) = if lhs.1 == self.parameters.0 .1 && rhs.1 == self.parameters.1 .1 { + (lhs, rhs) + } else { + (rhs, lhs) + }; + let instr = scope + .block + .build(Instr::FunctionCall( + self.ir.value(), + vec![lhs.instr(), rhs.instr()], + )) + .unwrap(); + StackValue(StackValueKind::Immutable(instr), self.return_ty.clone()) + } +} + #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] struct State { should_load: bool, @@ -376,6 +404,7 @@ impl mir::Module { scope: compile_unit, types: &debug_types, }), + binops: &binops, allocator: Rc::new(RefCell::new(allocator)), }; @@ -442,6 +471,7 @@ impl mir::Module { scope: compile_unit, types: &debug_types, }), + binops: &binops, allocator: Rc::new(RefCell::new(allocator)), }; @@ -832,85 +862,102 @@ impl mir::Expression { lit.as_type(), )), mir::ExprKind::BinOp(binop, lhs_exp, rhs_exp) => { - let lhs = lhs_exp + let lhs_val = lhs_exp .codegen(scope, state)? - .expect("lhs has no return value") - .instr(); - let rhs = rhs_exp + .expect("lhs has no return value"); + let rhs_val = rhs_exp .codegen(scope, state)? - .expect("rhs has no return value") - .instr(); - let lhs_type = lhs_exp - .return_type(&Default::default(), scope.module_id) - .unwrap() - .1; - let instr = match ( - binop, - lhs_type.signed(), - lhs_type.category() == TypeCategory::Real, - ) { - (mir::BinaryOperator::Add, _, false) => Instr::Add(lhs, rhs), - (mir::BinaryOperator::Add, _, true) => Instr::FAdd(lhs, rhs), - (mir::BinaryOperator::Minus, _, false) => Instr::Sub(lhs, rhs), - (mir::BinaryOperator::Minus, _, true) => Instr::FSub(lhs, rhs), - (mir::BinaryOperator::Mult, _, false) => Instr::Mul(lhs, rhs), - (mir::BinaryOperator::Mult, _, true) => Instr::FMul(lhs, rhs), - (mir::BinaryOperator::And, _, _) => Instr::And(lhs, rhs), - (mir::BinaryOperator::Cmp(i), _, false) => Instr::ICmp(i.predicate(), lhs, rhs), - (mir::BinaryOperator::Cmp(i), _, true) => Instr::FCmp(i.predicate(), lhs, rhs), - (mir::BinaryOperator::Div, false, false) => Instr::UDiv(lhs, rhs), - (mir::BinaryOperator::Div, true, false) => Instr::SDiv(lhs, rhs), - (mir::BinaryOperator::Div, _, true) => Instr::FDiv(lhs, rhs), - (mir::BinaryOperator::Mod, false, false) => { - let div = scope - .block - .build(Instr::UDiv(lhs, rhs)) - .unwrap() - .maybe_location(&mut scope.block, location); - let mul = scope - .block - .build(Instr::Mul(rhs, div)) - .unwrap() - .maybe_location(&mut scope.block, location); - Instr::Sub(lhs, mul) - } - (mir::BinaryOperator::Mod, true, false) => { - let div = scope - .block - .build(Instr::SDiv(lhs, rhs)) - .unwrap() - .maybe_location(&mut scope.block, location); - let mul = scope - .block - .build(Instr::Mul(rhs, div)) - .unwrap() - .maybe_location(&mut scope.block, location); - Instr::Sub(lhs, mul) - } - (mir::BinaryOperator::Mod, _, true) => { - let div = scope - .block - .build(Instr::FDiv(lhs, rhs)) - .unwrap() - .maybe_location(&mut scope.block, location); - let mul = scope - .block - .build(Instr::Mul(rhs, div)) - .unwrap() - .maybe_location(&mut scope.block, location); - Instr::Sub(lhs, mul) - } - }; - Some(StackValue( - StackValueKind::Immutable( - scope - .block - .build(instr) - .unwrap() - .maybe_location(&mut scope.block, location), - ), - lhs_type, - )) + .expect("rhs has no return value"); + let lhs = lhs_val.instr(); + let rhs = rhs_val.instr(); + + let operation = scope.binops.get(&ScopeBinopKey { + params: (lhs_val.1.clone(), rhs_val.1.clone()), + operator: *binop, + }); + + if let Some(operation) = operation { + Some(operation.codegen(&lhs_val, &rhs_val, scope)) + } else { + dbg!((lhs_val.1.clone(), rhs_val.1.clone())); + dbg!(&operation.map(|b| &b.return_ty)); + + let lhs_type = lhs_exp + .return_type(&Default::default(), scope.module_id) + .unwrap() + .1; + let instr = match ( + binop, + lhs_type.signed(), + lhs_type.category() == TypeCategory::Real, + ) { + (mir::BinaryOperator::Add, _, false) => Instr::Add(lhs, rhs), + (mir::BinaryOperator::Add, _, true) => Instr::FAdd(lhs, rhs), + (mir::BinaryOperator::Minus, _, false) => Instr::Sub(lhs, rhs), + (mir::BinaryOperator::Minus, _, true) => Instr::FSub(lhs, rhs), + (mir::BinaryOperator::Mult, _, false) => Instr::Mul(lhs, rhs), + (mir::BinaryOperator::Mult, _, true) => Instr::FMul(lhs, rhs), + (mir::BinaryOperator::And, _, _) => Instr::And(lhs, rhs), + (mir::BinaryOperator::Cmp(i), _, false) => { + Instr::ICmp(i.predicate(), lhs, rhs) + } + (mir::BinaryOperator::Cmp(i), _, true) => { + Instr::FCmp(i.predicate(), lhs, rhs) + } + (mir::BinaryOperator::Div, false, false) => Instr::UDiv(lhs, rhs), + (mir::BinaryOperator::Div, true, false) => Instr::SDiv(lhs, rhs), + (mir::BinaryOperator::Div, _, true) => Instr::FDiv(lhs, rhs), + (mir::BinaryOperator::Mod, false, false) => { + let div = scope + .block + .build(Instr::UDiv(lhs, rhs)) + .unwrap() + .maybe_location(&mut scope.block, location); + let mul = scope + .block + .build(Instr::Mul(rhs, div)) + .unwrap() + .maybe_location(&mut scope.block, location); + Instr::Sub(lhs, mul) + } + (mir::BinaryOperator::Mod, true, false) => { + let div = scope + .block + .build(Instr::SDiv(lhs, rhs)) + .unwrap() + .maybe_location(&mut scope.block, location); + let mul = scope + .block + .build(Instr::Mul(rhs, div)) + .unwrap() + .maybe_location(&mut scope.block, location); + Instr::Sub(lhs, mul) + } + (mir::BinaryOperator::Mod, _, true) => { + let div = scope + .block + .build(Instr::FDiv(lhs, rhs)) + .unwrap() + .maybe_location(&mut scope.block, location); + let mul = scope + .block + .build(Instr::Mul(rhs, div)) + .unwrap() + .maybe_location(&mut scope.block, location); + Instr::Sub(lhs, mul) + } + }; + Some(StackValue( + StackValueKind::Immutable( + scope + .block + .build(instr) + .unwrap() + .maybe_location(&mut scope.block, location), + ), + lhs_type, + )) + } } mir::ExprKind::FunctionCall(call) => { let ret_type_kind = call