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},
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<SourceModuleId, ModuleCodegen<'ctx>>,
tokens: &'ctx Vec<FullToken>,
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<TypeValue, TypeDefinition>,
pub(super) type_values: &'scope HashMap<CustomTypeKey, TypeValue>,
types: &'scope HashMap<TypeValue, TypeDefinition>,
type_values: &'scope HashMap<CustomTypeKey, TypeValue>,
functions: &'scope HashMap<String, Function<'ctx>>,
binops: &'scope HashMap<ScopeBinopKey, StackBinopDefinition<'ctx>>,
stack_values: HashMap<String, StackValue>,
debug: Option<Debug<'ctx>>,
allocator: Rc<RefCell<Allocator>>,
@ -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,14 +862,26 @@ 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();
.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()
@ -856,8 +898,12 @@ impl mir::Expression {
(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::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),
@ -912,6 +958,7 @@ impl mir::Expression {
lhs_type,
))
}
}
mir::ExprKind::FunctionCall(call) => {
let ret_type_kind = call
.return_type