Skip to content

Commit 74227ae

Browse files
authored
Merge pull request #462 from Pat-Lafon/noret_brilirs
Noret brilirs
2 parents 593c343 + 993a5ad commit 74227ae

File tree

4 files changed

+40
-5
lines changed

4 files changed

+40
-5
lines changed

brilirs/src/basic_block.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ impl BBFunction {
162162
},
163163
) => {
164164
if curr_block.label.is_some() || blocks.is_empty() {
165+
curr_block.positions.push(i.get_pos());
165166
curr_block
166167
.flat_instrs
167168
.push(FlatIR::new(i, func_map, &mut num_var_map, &label_map)?);
@@ -170,6 +171,7 @@ impl BBFunction {
170171
curr_block = BasicBlock::new();
171172
}
172173
bril_rs::Code::Instruction(code) => {
174+
curr_block.positions.push(code.get_pos());
173175
curr_block
174176
.flat_instrs
175177
.push(FlatIR::new(code, func_map, &mut num_var_map, &label_map)?);

brilirs/src/check.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,8 @@ fn type_check_func(func: &Function, prog: &Program) -> Result<(), PositionalInte
560560
.map_err(|e| e.add_pos(func.pos.clone()));
561561
}
562562

563+
let mut has_return_type_should_have_return = func.return_type.is_none();
564+
563565
let mut env: FxHashMap<&str, Type> =
564566
FxHashMap::with_capacity_and_hasher(20, fxhash::FxBuildHasher::default());
565567
func.args.iter().for_each(|a| {
@@ -598,21 +600,34 @@ fn type_check_func(func: &Function, prog: &Program) -> Result<(), PositionalInte
598600
func.instrs.iter().try_for_each(|i| match i {
599601
bril_rs::Code::Label { .. } => Ok(()),
600602
bril_rs::Code::Instruction(instr) => {
603+
if matches!(
604+
instr,
605+
Instruction::Effect {
606+
op: EffectOps::Return,
607+
..
608+
}
609+
) {
610+
has_return_type_should_have_return = true;
611+
}
601612
type_check_instruction(instr, func, prog, &mut env).map_err(|e| e.add_pos(instr.get_pos()))
602613
}
603614
})?;
604615

605-
Ok(())
616+
if has_return_type_should_have_return {
617+
Ok(())
618+
} else {
619+
Err(InterpError::NonVoidFuncNoRet(func.return_type.clone().unwrap()).add_pos(func.pos.clone()))
620+
}
606621
}
607622

608623
/// Provides validation of Bril programs. This involves
609624
/// statically checking the types and number of arguments to Bril
610625
/// instructions.
611626
/// # Errors
612627
/// Will return an error if typechecking fails or if the input program is not well-formed.
613-
pub fn type_check(bbprog: &Program) -> Result<(), PositionalInterpError> {
614-
bbprog
628+
pub fn type_check(prog: &Program) -> Result<(), PositionalInterpError> {
629+
prog
615630
.functions
616631
.iter()
617-
.try_for_each(|bbfunc| type_check_func(bbfunc, bbprog))
632+
.try_for_each(|bbfunc| type_check_func(bbfunc, prog))
618633
}

brilirs/src/error.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::fmt::Display;
22

3-
use bril_rs::{Position, conversion::PositionalConversionError};
3+
use bril_rs::{Position, Type, conversion::PositionalConversionError};
44
use std::error::Error;
55
use thiserror::Error;
66

@@ -27,6 +27,8 @@ pub enum InterpError {
2727
DuplicateLabel(String),
2828
#[error("Expected empty return for `{0}`, found value")]
2929
NonEmptyRetForFunc(String),
30+
#[error("non-void function (type {0}) didn't return anything")]
31+
NonVoidFuncNoRet(Type),
3032
#[error("cannot allocate `{0}` entries")]
3133
CannotAllocSize(i64),
3234
#[error("Tried to free illegal memory location base: `{0}`, offset: `{1}`. Offset must be 0.")]

brilirs/src/interp.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,22 @@ fn execute<'a, T: std::io::Write>(
671671
}
672672

673673
if !jumped {
674+
if let Some(ty) = &func.return_type {
675+
return Err(
676+
InterpError::NonVoidFuncNoRet(ty.clone()).add_pos(if curr_instrs.is_empty() {
677+
// Ideally we use the last instruction in the block before the fatal
678+
// (implicit) return... but if that block is empty, we should just
679+
// point to the function itself
680+
func.pos.clone()
681+
} else {
682+
curr_block
683+
.positions
684+
.get(curr_instrs.len() - 1)
685+
.cloned()
686+
.unwrap_or_default()
687+
}),
688+
);
689+
}
674690
return Ok(None);
675691
}
676692
}

0 commit comments

Comments
 (0)