Implement codegen for binops
This commit is contained in:
parent
b12e0a18a9
commit
d448c8b9f1
@ -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,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
|
||||
|
Loading…
Reference in New Issue
Block a user