Implement codegen for binops
This commit is contained in:
parent
b12e0a18a9
commit
d448c8b9f1
@ -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,85 +862,102 @@ 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 lhs_type = lhs_exp
|
let rhs = rhs_val.instr();
|
||||||
.return_type(&Default::default(), scope.module_id)
|
|
||||||
.unwrap()
|
let operation = scope.binops.get(&ScopeBinopKey {
|
||||||
.1;
|
params: (lhs_val.1.clone(), rhs_val.1.clone()),
|
||||||
let instr = match (
|
operator: *binop,
|
||||||
binop,
|
});
|
||||||
lhs_type.signed(),
|
|
||||||
lhs_type.category() == TypeCategory::Real,
|
if let Some(operation) = operation {
|
||||||
) {
|
Some(operation.codegen(&lhs_val, &rhs_val, scope))
|
||||||
(mir::BinaryOperator::Add, _, false) => Instr::Add(lhs, rhs),
|
} else {
|
||||||
(mir::BinaryOperator::Add, _, true) => Instr::FAdd(lhs, rhs),
|
dbg!((lhs_val.1.clone(), rhs_val.1.clone()));
|
||||||
(mir::BinaryOperator::Minus, _, false) => Instr::Sub(lhs, rhs),
|
dbg!(&operation.map(|b| &b.return_ty));
|
||||||
(mir::BinaryOperator::Minus, _, true) => Instr::FSub(lhs, rhs),
|
|
||||||
(mir::BinaryOperator::Mult, _, false) => Instr::Mul(lhs, rhs),
|
let lhs_type = lhs_exp
|
||||||
(mir::BinaryOperator::Mult, _, true) => Instr::FMul(lhs, rhs),
|
.return_type(&Default::default(), scope.module_id)
|
||||||
(mir::BinaryOperator::And, _, _) => Instr::And(lhs, rhs),
|
.unwrap()
|
||||||
(mir::BinaryOperator::Cmp(i), _, false) => Instr::ICmp(i.predicate(), lhs, rhs),
|
.1;
|
||||||
(mir::BinaryOperator::Cmp(i), _, true) => Instr::FCmp(i.predicate(), lhs, rhs),
|
let instr = match (
|
||||||
(mir::BinaryOperator::Div, false, false) => Instr::UDiv(lhs, rhs),
|
binop,
|
||||||
(mir::BinaryOperator::Div, true, false) => Instr::SDiv(lhs, rhs),
|
lhs_type.signed(),
|
||||||
(mir::BinaryOperator::Div, _, true) => Instr::FDiv(lhs, rhs),
|
lhs_type.category() == TypeCategory::Real,
|
||||||
(mir::BinaryOperator::Mod, false, false) => {
|
) {
|
||||||
let div = scope
|
(mir::BinaryOperator::Add, _, false) => Instr::Add(lhs, rhs),
|
||||||
.block
|
(mir::BinaryOperator::Add, _, true) => Instr::FAdd(lhs, rhs),
|
||||||
.build(Instr::UDiv(lhs, rhs))
|
(mir::BinaryOperator::Minus, _, false) => Instr::Sub(lhs, rhs),
|
||||||
.unwrap()
|
(mir::BinaryOperator::Minus, _, true) => Instr::FSub(lhs, rhs),
|
||||||
.maybe_location(&mut scope.block, location);
|
(mir::BinaryOperator::Mult, _, false) => Instr::Mul(lhs, rhs),
|
||||||
let mul = scope
|
(mir::BinaryOperator::Mult, _, true) => Instr::FMul(lhs, rhs),
|
||||||
.block
|
(mir::BinaryOperator::And, _, _) => Instr::And(lhs, rhs),
|
||||||
.build(Instr::Mul(rhs, div))
|
(mir::BinaryOperator::Cmp(i), _, false) => {
|
||||||
.unwrap()
|
Instr::ICmp(i.predicate(), lhs, rhs)
|
||||||
.maybe_location(&mut scope.block, location);
|
}
|
||||||
Instr::Sub(lhs, mul)
|
(mir::BinaryOperator::Cmp(i), _, true) => {
|
||||||
}
|
Instr::FCmp(i.predicate(), lhs, rhs)
|
||||||
(mir::BinaryOperator::Mod, true, false) => {
|
}
|
||||||
let div = scope
|
(mir::BinaryOperator::Div, false, false) => Instr::UDiv(lhs, rhs),
|
||||||
.block
|
(mir::BinaryOperator::Div, true, false) => Instr::SDiv(lhs, rhs),
|
||||||
.build(Instr::SDiv(lhs, rhs))
|
(mir::BinaryOperator::Div, _, true) => Instr::FDiv(lhs, rhs),
|
||||||
.unwrap()
|
(mir::BinaryOperator::Mod, false, false) => {
|
||||||
.maybe_location(&mut scope.block, location);
|
let div = scope
|
||||||
let mul = scope
|
.block
|
||||||
.block
|
.build(Instr::UDiv(lhs, rhs))
|
||||||
.build(Instr::Mul(rhs, div))
|
.unwrap()
|
||||||
.unwrap()
|
.maybe_location(&mut scope.block, location);
|
||||||
.maybe_location(&mut scope.block, location);
|
let mul = scope
|
||||||
Instr::Sub(lhs, mul)
|
.block
|
||||||
}
|
.build(Instr::Mul(rhs, div))
|
||||||
(mir::BinaryOperator::Mod, _, true) => {
|
.unwrap()
|
||||||
let div = scope
|
.maybe_location(&mut scope.block, location);
|
||||||
.block
|
Instr::Sub(lhs, mul)
|
||||||
.build(Instr::FDiv(lhs, rhs))
|
}
|
||||||
.unwrap()
|
(mir::BinaryOperator::Mod, true, false) => {
|
||||||
.maybe_location(&mut scope.block, location);
|
let div = scope
|
||||||
let mul = scope
|
.block
|
||||||
.block
|
.build(Instr::SDiv(lhs, rhs))
|
||||||
.build(Instr::Mul(rhs, div))
|
.unwrap()
|
||||||
.unwrap()
|
.maybe_location(&mut scope.block, location);
|
||||||
.maybe_location(&mut scope.block, location);
|
let mul = scope
|
||||||
Instr::Sub(lhs, mul)
|
.block
|
||||||
}
|
.build(Instr::Mul(rhs, div))
|
||||||
};
|
.unwrap()
|
||||||
Some(StackValue(
|
.maybe_location(&mut scope.block, location);
|
||||||
StackValueKind::Immutable(
|
Instr::Sub(lhs, mul)
|
||||||
scope
|
}
|
||||||
.block
|
(mir::BinaryOperator::Mod, _, true) => {
|
||||||
.build(instr)
|
let div = scope
|
||||||
.unwrap()
|
.block
|
||||||
.maybe_location(&mut scope.block, location),
|
.build(Instr::FDiv(lhs, rhs))
|
||||||
),
|
.unwrap()
|
||||||
lhs_type,
|
.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) => {
|
mir::ExprKind::FunctionCall(call) => {
|
||||||
let ret_type_kind = call
|
let ret_type_kind = call
|
||||||
|
Loading…
Reference in New Issue
Block a user