Implement codegen for binops

This commit is contained in:
Sofia 2025-07-24 15:52:46 +03:00
parent b12e0a18a9
commit d448c8b9f1

View File

@ -18,9 +18,12 @@ use crate::{
allocator::{Allocator, AllocatorScope}, allocator::{Allocator, AllocatorScope},
lexer::{FullToken, Position}, lexer::{FullToken, Position},
mir::{ mir::{
self, implement::TypeCategory, pass::ScopeBinopKey, CustomTypeKey, FunctionDefinitionKind, self,
Metadata, NamedVariableRef, SourceModuleId, StructField, StructType, TypeDefinition, implement::TypeCategory,
TypeDefinitionKind, TypeKind, VagueLiteral, WhileStatement, pass::{ScopeBinopDef, ScopeBinopKey},
CustomTypeKey, FunctionDefinitionKind, Metadata, NamedVariableRef, SourceModuleId,
StructField, StructType, TypeDefinition, TypeDefinitionKind, TypeKind, VagueLiteral,
WhileStatement,
}, },
util::try_all, util::try_all,
}; };
@ -77,12 +80,13 @@ pub struct Scope<'ctx, 'scope> {
modules: &'scope HashMap<SourceModuleId, ModuleCodegen<'ctx>>, modules: &'scope HashMap<SourceModuleId, ModuleCodegen<'ctx>>,
tokens: &'ctx Vec<FullToken>, tokens: &'ctx Vec<FullToken>,
module: &'ctx Module<'ctx>, module: &'ctx Module<'ctx>,
pub(super) module_id: SourceModuleId, module_id: SourceModuleId,
function: &'ctx Function<'ctx>, function: &'ctx Function<'ctx>,
pub(super) block: Block<'ctx>, pub(super) block: Block<'ctx>,
pub(super) types: &'scope HashMap<TypeValue, TypeDefinition>, types: &'scope HashMap<TypeValue, TypeDefinition>,
pub(super) type_values: &'scope HashMap<CustomTypeKey, TypeValue>, type_values: &'scope HashMap<CustomTypeKey, TypeValue>,
functions: &'scope HashMap<String, Function<'ctx>>, functions: &'scope HashMap<String, Function<'ctx>>,
binops: &'scope HashMap<ScopeBinopKey, StackBinopDefinition<'ctx>>,
stack_values: HashMap<String, StackValue>, stack_values: HashMap<String, StackValue>,
debug: Option<Debug<'ctx>>, debug: Option<Debug<'ctx>>,
allocator: Rc<RefCell<Allocator>>, allocator: Rc<RefCell<Allocator>>,
@ -104,6 +108,7 @@ impl<'ctx, 'a> Scope<'ctx, 'a> {
stack_values: self.stack_values.clone(), stack_values: self.stack_values.clone(),
debug: self.debug.clone(), debug: self.debug.clone(),
allocator: self.allocator.clone(), allocator: self.allocator.clone(),
binops: self.binops,
} }
} }
@ -186,6 +191,29 @@ pub struct StackBinopDefinition<'ctx> {
ir: Function<'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)] #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
struct State { struct State {
should_load: bool, should_load: bool,
@ -376,6 +404,7 @@ impl mir::Module {
scope: compile_unit, scope: compile_unit,
types: &debug_types, types: &debug_types,
}), }),
binops: &binops,
allocator: Rc::new(RefCell::new(allocator)), allocator: Rc::new(RefCell::new(allocator)),
}; };
@ -442,6 +471,7 @@ impl mir::Module {
scope: compile_unit, scope: compile_unit,
types: &debug_types, types: &debug_types,
}), }),
binops: &binops,
allocator: Rc::new(RefCell::new(allocator)), allocator: Rc::new(RefCell::new(allocator)),
}; };
@ -832,14 +862,26 @@ impl mir::Expression {
lit.as_type(), lit.as_type(),
)), )),
mir::ExprKind::BinOp(binop, lhs_exp, rhs_exp) => { mir::ExprKind::BinOp(binop, lhs_exp, rhs_exp) => {
let lhs = lhs_exp let lhs_val = lhs_exp
.codegen(scope, state)? .codegen(scope, state)?
.expect("lhs has no return value") .expect("lhs has no return value");
.instr(); let rhs_val = rhs_exp
let rhs = rhs_exp
.codegen(scope, state)? .codegen(scope, state)?
.expect("rhs has no return value") .expect("rhs has no return value");
.instr(); 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 let lhs_type = lhs_exp
.return_type(&Default::default(), scope.module_id) .return_type(&Default::default(), scope.module_id)
.unwrap() .unwrap()
@ -856,8 +898,12 @@ impl mir::Expression {
(mir::BinaryOperator::Mult, _, false) => Instr::Mul(lhs, rhs), (mir::BinaryOperator::Mult, _, false) => Instr::Mul(lhs, rhs),
(mir::BinaryOperator::Mult, _, true) => Instr::FMul(lhs, rhs), (mir::BinaryOperator::Mult, _, true) => Instr::FMul(lhs, rhs),
(mir::BinaryOperator::And, _, _) => Instr::And(lhs, rhs), (mir::BinaryOperator::And, _, _) => Instr::And(lhs, rhs),
(mir::BinaryOperator::Cmp(i), _, false) => Instr::ICmp(i.predicate(), lhs, rhs), (mir::BinaryOperator::Cmp(i), _, false) => {
(mir::BinaryOperator::Cmp(i), _, true) => Instr::FCmp(i.predicate(), lhs, rhs), 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, false, false) => Instr::UDiv(lhs, rhs),
(mir::BinaryOperator::Div, true, false) => Instr::SDiv(lhs, rhs), (mir::BinaryOperator::Div, true, false) => Instr::SDiv(lhs, rhs),
(mir::BinaryOperator::Div, _, true) => Instr::FDiv(lhs, rhs), (mir::BinaryOperator::Div, _, true) => Instr::FDiv(lhs, rhs),
@ -912,6 +958,7 @@ impl mir::Expression {
lhs_type, lhs_type,
)) ))
} }
}
mir::ExprKind::FunctionCall(call) => { mir::ExprKind::FunctionCall(call) => {
let ret_type_kind = call let ret_type_kind = call
.return_type .return_type