Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 30 additions & 11 deletions compiler/astoir_mir/src/blocks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::{collections::HashMap, fmt::Display};

use compiler_errors::errs::{BaseResult, base::BaseError};

use crate::{blocks::{refer::MIRBlockReference}, builder::build_phi, ctx::MIRContext, insts::{MIRInstruction}, vals::{base::BaseMIRValue, refer::MIRVariableReference}};
use crate::{blocks::refer::MIRBlockReference, builder::build_phi, ctx::MIRContext, inst_writer::BlockPosition, insts::MIRInstruction, vals::{base::BaseMIRValue, refer::MIRVariableReference}};

pub mod refer;
pub mod hints;
Expand Down Expand Up @@ -32,9 +32,15 @@ impl PartialEq for MIRBlockVariableSSAHint {
}
}

#[derive(Clone)]
pub enum MIRBlockHeldInstruction {
Valueless(MIRInstruction),
Valued(MIRInstruction, usize)
}

/// Represents a function block or a branch.
pub struct MIRBlock {
instructions: Vec<MIRInstruction>,
instructions: Vec<MIRBlockHeldInstruction>,

/// The block references that will merge into this one
pub merge_blocks: Vec<MIRBlockReference>,
Expand Down Expand Up @@ -84,15 +90,19 @@ impl MIRBlock {
return Ok(MIRVariableReference::from(unpacked.as_ptr()?));
}

pub fn append(&mut self, instruction: MIRInstruction) {
self.instructions.push(instruction.clone());
}

pub fn append_start(&mut self, instruction: MIRInstruction) {
if self.instructions.is_empty() {
self.instructions.push(instruction.clone());
} else {
self.instructions.insert(0, instruction.clone());
pub fn append(&mut self, instruction: MIRBlockHeldInstruction, pos: &BlockPosition) {
match pos {
BlockPosition::END => {
self.instructions.push(instruction.clone());
},

BlockPosition::START => {
if self.instructions.is_empty() {
self.instructions.push(instruction.clone());
} else {
self.instructions.insert(0, instruction.clone());
}
}
}
}

Expand Down Expand Up @@ -157,4 +167,13 @@ impl Display for MIRBlock {

Ok(())
}
}

impl Display for MIRBlockHeldInstruction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Valued(a, b) => write!(f, "#{} = {}", *b, a),
Self::Valueless(a) => write!(f, "{}", a)
}
}
}
4 changes: 2 additions & 2 deletions compiler/astoir_mir/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ pub fn build_static_string_const(ctx: &mut MIRContext, raw: String) -> BaseResul
return res.as_ptr();
}

pub fn build_call(ctx: &mut MIRContext, func: usize, ind: usize, args: Vec<BaseMIRValue>) -> BaseResult<BaseMIRValue> {
pub fn build_call(ctx: &mut MIRContext, func: usize, ind: usize, args: Vec<BaseMIRValue>) -> BaseResult<Option<BaseMIRValue>> {
let func = &ctx.functions[func];

for(arg, t) in args.iter().zip(func.arguments.iter()) {
Expand All @@ -397,7 +397,7 @@ pub fn build_call(ctx: &mut MIRContext, func: usize, ind: usize, args: Vec<BaseM
}
}

let res = ctx.append_inst(MIRInstruction::Call { function: ind, arguments: args }).get()?;
let res = ctx.append_inst(MIRInstruction::Call { function: ind, arguments: args }).val;

return Ok(res);
}
Expand Down
15 changes: 8 additions & 7 deletions compiler/astoir_mir/src/ctx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::fmt::Display;

use compiler_errors::errs::BaseResult;

use crate::{blocks::{MIRBlock, hints::{HintStorage, MIRValueHint}, refer::MIRBlockReference}, builder::build_phi, funcs::MIRFunction, inst_writer::{BlockPosition, InstructionWriterPosition}, insts::{MIRInstruction, val::InstructionValue}, vals::{base::BaseMIRValue}};
use crate::{blocks::{MIRBlock, MIRBlockHeldInstruction, hints::{HintStorage, MIRValueHint}, refer::MIRBlockReference}, builder::build_phi, funcs::MIRFunction, inst_writer::{BlockPosition, InstructionWriterPosition}, insts::{MIRInstruction, val::InstructionValue}, vals::base::BaseMIRValue};


pub struct MIRContext {
Expand All @@ -15,7 +15,7 @@ pub struct MIRContext {

impl MIRContext {
pub fn new() -> Self {
MIRContext { functions: vec![], ssa_hints: HintStorage::new(), blocks: vec![], writer: InstructionWriterPosition { curr_block: 0, curr_inst: BlockPosition::START } }
MIRContext { functions: vec![], ssa_hints: HintStorage::new(), blocks: vec![], writer: InstructionWriterPosition { curr_block: 0, curr_inst: BlockPosition::END } }
}

pub fn create_block(&mut self) -> MIRBlockReference {
Expand All @@ -35,25 +35,26 @@ impl MIRContext {
}

pub fn append_inst(&mut self, inst: MIRInstruction) -> InstructionValue {
match self.writer.curr_inst {
BlockPosition::START => self.blocks[self.writer.curr_block].append_start(inst.clone()),
BlockPosition::END => self.blocks[self.writer.curr_block].append(inst.clone())
};

if inst.has_return(self) {
let ret = inst.get_return_type(self);

if !inst.should_hint() {
let hint_ind = self.ssa_hints.vec.len();

self.blocks[self.writer.curr_block].append(MIRBlockHeldInstruction::Valued(inst.clone(), hint_ind), &self.writer.curr_inst);

return InstructionValue::new(Some(BaseMIRValue::new(hint_ind, ret)))
}

let hint_ind = self.ssa_hints.append_hint(MIRValueHint::Value(ret.clone()));

self.blocks[self.writer.curr_block].append(MIRBlockHeldInstruction::Valued(inst.clone(), hint_ind), &self.writer.curr_inst);

return InstructionValue::new(Some(BaseMIRValue::new(hint_ind, ret)));
}

self.blocks[self.writer.curr_block].append(MIRBlockHeldInstruction::Valueless(inst.clone()), &self.writer.curr_inst);

return InstructionValue::new(None);
}

Expand Down
1 change: 1 addition & 0 deletions compiler/astoir_mir/src/inst_writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use crate::{blocks::refer::MIRBlockReference};

#[derive(Clone)]
pub enum BlockPosition {
START,
END
Expand Down
2 changes: 1 addition & 1 deletion compiler/astoir_mir/src/insts/val.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use compiler_errors::errs::{BaseResult, base::BaseError};
use crate::vals::base::BaseMIRValue;

pub struct InstructionValue {
val: Option<BaseMIRValue>
pub val: Option<BaseMIRValue>
}

impl InstructionValue {
Expand Down
3 changes: 2 additions & 1 deletion compiler/astoir_mir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ pub mod blocks;
pub mod builder;
pub mod funcs;
pub mod ctx;
pub mod inst_writer;
pub mod inst_writer;
pub mod transmutation;
43 changes: 43 additions & 0 deletions compiler/astoir_mir/src/transmutation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//! Declarations for type transmutation in Quickfall.

use astoir_typing::base::BaseType;
use compiler_errors::{IR_TRANSMUTATION, errs::{BaseResult, base::BaseError}};

use crate::{builder::{build_downcast_int, build_upcast_int}, ctx::MIRContext, vals::base::BaseMIRValue};

/// Performs transmutation on the given value to try to get the targeted type.
pub fn transmute_value(val: BaseMIRValue, target: BaseType, ctx: &mut MIRContext) -> BaseResult<BaseMIRValue> {
if val.vtype.base.is_integer() != target.is_integer() || val.vtype.base.is_floating() != target.is_floating() || val.vtype.base.is_signed() != target.is_signed() {
return Err(BaseError::err(IR_TRANSMUTATION!().to_string()));
}

if target.is_integer() {
let sz = val.vtype.base.get_size()?;
let newsz = target.get_size()?;

if sz == newsz {
return Ok(val);
}

if sz > newsz {
let res = build_downcast_int(ctx, val.as_int()?, newsz)?;

return Ok(res.into());
} else {
let res = build_upcast_int(ctx, val.as_int()?, newsz)?;

return Ok(res.into());
}
}

if target.is_floating() {
let sz = val.vtype.base.get_floating_size()?;
let newsz = target.get_floating_size()?;

// TODO: change this since floats cannot have two sizes for now

return Ok(val);
}

return Err(BaseError::err(IR_TRANSMUTATION!().to_string()));
}
9 changes: 7 additions & 2 deletions compiler/astoir_mir_lowering/src/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use astoir_hir::nodes::HIRNode;
use astoir_mir::blocks::{refer::MIRBlockReference};
use compiler_errors::{IR_INVALID_NODE_TYPE, MATH_OP_NO_ASSIGN, errs::{BaseResult, base::BaseError}};

use crate::{MIRLoweringContext, control::{forloop::lower_hir_for_loop, ifstatement::lower_hir_if_statement}, math::lower_hir_math_operation, vars::{lower_hir_variable_assignment, lower_hir_variable_declaration}};
use crate::{MIRLoweringContext, control::{forloop::lower_hir_for_loop, ifstatement::lower_hir_if_statement}, funcs::lower_hir_function_call, math::lower_hir_math_operation, vars::{lower_hir_variable_assignment, lower_hir_variable_declaration}};

pub fn lower_hir_body_member(block: MIRBlockReference, node: Box<HIRNode>, ctx: &mut MIRLoweringContext) -> BaseResult<bool> {
return match *node {
Expand All @@ -13,13 +13,18 @@ pub fn lower_hir_body_member(block: MIRBlockReference, node: Box<HIRNode>, ctx:
return Err(BaseError::err(MATH_OP_NO_ASSIGN!().to_string()))
}

lower_hir_math_operation(block, node, ctx)?;
lower_hir_math_operation(block, node, ctx, None)?;

return Ok(true);
},

HIRNode::ForBlock { .. } => lower_hir_for_loop(block, node, ctx),
HIRNode::IfStatement { .. } => lower_hir_if_statement(block, node, ctx),
HIRNode::FunctionCall { .. } => {
lower_hir_function_call(block, node, ctx, None)?;

return Ok(true)
},

_ => return Err(BaseError::err(IR_INVALID_NODE_TYPE!().to_string()))
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/astoir_mir_lowering/src/control/forloop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub fn lower_hir_for_loop(block: MIRBlockReference, node: Box<HIRNode>, ctx: &mu
ctx.mir_ctx.writer.move_end(body_ref);

lower_hir_body(body_ref, body, ctx)?;
lower_hir_math_operation(body_ref, incrementation, ctx)?;
lower_hir_math_operation(body_ref, incrementation, ctx, None)?;

build_unconditional_branch(&mut ctx.mir_ctx, header_ref)?;

Expand Down
28 changes: 23 additions & 5 deletions compiler/astoir_mir_lowering/src/funcs.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use astoir_hir::{nodes::HIRNode};
use astoir_mir::{blocks::refer::MIRBlockReference, builder::build_call, funcs::MIRFunction, vals::base::BaseMIRValue};
use astoir_mir::{blocks::refer::MIRBlockReference, builder::build_call, funcs::MIRFunction, transmutation::transmute_value, vals::base::BaseMIRValue};
use astoir_typing::compacted::CompactedType;
use compiler_errors::{IR_FUNCTION_INVALID_ARGUMENTS, IR_INVALID_NODE_TYPE, errs::{BaseResult, base::BaseError}};
use compiler_errors::{IR_FUNCTION_INVALID_ARGUMENTS, IR_INVALID_NODE_TYPE, IR_TRANSMUTATION, errs::{BaseResult, base::BaseError}};

use crate::{MIRLoweringContext, body::lower_hir_body, values::lower_hir_value};

Expand All @@ -22,7 +22,9 @@ pub fn lower_hir_function_decl(node: Box<HIRNode>, cctx: &mut MIRLoweringContext
}

let mut func = MIRFunction::new(format!("func_{}", func_name), args, ret_type, requires_this);
let block =func.append_entry_block(&mut cctx.mir_ctx)?;
let block = func.append_entry_block(&mut cctx.mir_ctx)?;

cctx.mir_ctx.writer.move_end(block);

lower_hir_body(block, body, cctx)?;

Expand Down Expand Up @@ -59,7 +61,7 @@ pub fn lower_hir_shadow_decl(node: Box<HIRNode>, ctx: &mut MIRLoweringContext) -
return Err(BaseError::err(IR_INVALID_NODE_TYPE!().to_string()))
}

pub fn lower_hir_function_call(block: MIRBlockReference, node: Box<HIRNode>, ctx: &mut MIRLoweringContext) -> BaseResult<BaseMIRValue> {
pub fn lower_hir_function_call(block: MIRBlockReference, node: Box<HIRNode>, ctx: &mut MIRLoweringContext, expected: Option<CompactedType>) -> BaseResult<Option<BaseMIRValue>> {
if let HIRNode::FunctionCall { func_name, arguments } = *node {
let mut args = vec![];

Expand All @@ -77,7 +79,23 @@ pub fn lower_hir_function_call(block: MIRBlockReference, node: Box<HIRNode>, ctx
i += 1;
}

return build_call(&mut ctx.mir_ctx, func_name, func_name, args);
let res = build_call(&mut ctx.mir_ctx, func_name, func_name, args)?;

if res.is_some() {
let res = res.unwrap();

if expected.is_some() {
let expected = expected.unwrap();

if !res.vtype.can_transmute(&expected) {
return Err(BaseError::err(IR_TRANSMUTATION!().to_string()))
}

return Ok(Some(transmute_value(res, expected.base, &mut ctx.mir_ctx)?));
}
}

return Ok(None);
}

return Err(BaseError::err(IR_INVALID_NODE_TYPE!().to_string()))
Expand Down
12 changes: 7 additions & 5 deletions compiler/astoir_mir_lowering/src/math.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use astoir_hir::{nodes::HIRNode};
use astoir_mir::{blocks::{refer::MIRBlockReference}, builder::{build_float_add, build_float_div, build_float_mul, build_float_sub, build_int_add, build_int_div, build_int_mul, build_int_sub}, vals::base::BaseMIRValue};
use astoir_typing::base::BaseType;
use astoir_typing::{base::BaseType, compacted::CompactedType};
use compiler_errors::{IR_INVALID_NODE_TYPE, IR_REQ_VARIABLE_ASSIGN, errs::{BaseResult, base::BaseError}};
use lexer::toks::math::MathOperator;

use crate::{MIRLoweringContext, values::lower_hir_value, vars::lower_hir_variable_reference};

pub fn lower_hir_math_operation(block: MIRBlockReference, node: Box<HIRNode>, ctx: &mut MIRLoweringContext) -> BaseResult<BaseMIRValue> {
pub fn lower_hir_math_operation(block: MIRBlockReference, node: Box<HIRNode>, ctx: &mut MIRLoweringContext, expected: Option<CompactedType>) -> BaseResult<BaseMIRValue> {
if let HIRNode::MathOperation { left, right, operation, assignment } = *node {
if assignment && !left.is_variable_reference() {
return Err(BaseError::err(IR_REQ_VARIABLE_ASSIGN!().to_string()))
Expand All @@ -20,8 +20,8 @@ pub fn lower_hir_math_operation(block: MIRBlockReference, node: Box<HIRNode>, ct
ptr = None
}

let left_val = lower_hir_value(block, left, ctx, None)?;
let right_val = lower_hir_value(block, right, ctx, None)?;
let left_val = lower_hir_value(block, left, ctx, expected.clone())?;
let right_val = lower_hir_value(block, right, ctx, expected)?;


let val = match left_val.vtype.base {
Expand All @@ -36,8 +36,10 @@ pub fn lower_hir_math_operation(block: MIRBlockReference, node: Box<HIRNode>, ct
if assignment {
let v = ptr.unwrap();

v.write(block, &mut ctx.mir_ctx, val)?;
v.write(block, &mut ctx.mir_ctx, val.clone())?;
}

return Ok(val)
}

return Err(BaseError::err(IR_INVALID_NODE_TYPE!().to_string()))
Expand Down
17 changes: 13 additions & 4 deletions compiler/astoir_mir_lowering/src/values/mod.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
use astoir_hir::{nodes::HIRNode};
use astoir_mir::{blocks::{refer::MIRBlockReference}, vals::base::BaseMIRValue};
use astoir_typing::compacted::CompactedType;
use compiler_errors::{IR_INVALID_NODE_TYPE, errs::{BaseResult, base::BaseError}};
use compiler_errors::{EXPECTED_VAL_FUNC, IR_INVALID_NODE_TYPE, errs::{BaseResult, base::BaseError}};

use crate::{MIRLoweringContext, math::lower_hir_math_operation, values::{booleans::{lower_hir_boolean_operator, lowering_hir_boolean_condition}, consts::lower_hir_literal}, vars::lower_hir_variable_reference_value};
use crate::{MIRLoweringContext, funcs::lower_hir_function_call, math::lower_hir_math_operation, values::{booleans::{lower_hir_boolean_operator, lowering_hir_boolean_condition}, consts::lower_hir_literal}, vars::lower_hir_variable_reference_value};

pub mod consts;
pub mod booleans;

pub fn lower_hir_value(block: MIRBlockReference, node: Box<HIRNode>, ctx: &mut MIRLoweringContext, expected: Option<CompactedType>) -> BaseResult<BaseMIRValue> {
match *node {
HIRNode::IntegerLiteral { .. } | HIRNode::StringLiteral { .. } => return lower_hir_literal(node, ctx, expected),
HIRNode::VariableReference { .. } => return lower_hir_variable_reference_value(block, node, ctx),
HIRNode::VariableReference { .. } => return lower_hir_variable_reference_value(block, node, ctx, expected),
HIRNode::BooleanCondition { .. } => return Ok(lowering_hir_boolean_condition(block, node, ctx)?.into()),
HIRNode::BooleanOperator { .. } => return Ok(lower_hir_boolean_operator(block, node, ctx)?.into()),
HIRNode::MathOperation { .. } => return Ok(lower_hir_math_operation(block, node, ctx)?),
HIRNode::MathOperation { .. } => return Ok(lower_hir_math_operation(block, node, ctx, expected)?),
HIRNode::FunctionCall { .. } => {
let res = lower_hir_function_call(block, node, ctx, expected)?;

if res.is_none() {
return Err(BaseError::err(EXPECTED_VAL_FUNC!().to_string()));
}

return Ok(res.unwrap());
}

_ => return Err(BaseError::err(IR_INVALID_NODE_TYPE!().to_string()))
}
Expand Down
Loading