Skip to content

Commit 86da2a0

Browse files
added ir verifier
1 parent 90ba66a commit 86da2a0

6 files changed

Lines changed: 96 additions & 13 deletions

File tree

src/ir/lowerer.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ impl BlockId {
2727
pub fn index(&self) -> u32 { self.0 }
2828
}
2929

30-
pub struct FunctionIRBuilder<'a> {
30+
struct FunctionIRBuilder<'a> {
3131
locals: Vec<Local>,
3232
temps: Vec<Temp>,
3333
blocks: Vec<Block>,
@@ -38,7 +38,7 @@ pub struct FunctionIRBuilder<'a> {
3838
env: HashMap<SymbolId, LocalId>,
3939
}
4040
impl<'a> FunctionIRBuilder<'a> {
41-
pub fn new(symbols: &'a SymbolTable) -> Self {
41+
fn new(symbols: &'a SymbolTable) -> Self {
4242
Self {
4343
locals: Vec::new(),
4444
temps: Vec::new(),
@@ -54,13 +54,13 @@ impl<'a> FunctionIRBuilder<'a> {
5454
}
5555
}
5656

57-
pub fn lower_function(&mut self, ast: t::TypedAst) {
57+
fn lower_function(&mut self, ast: t::TypedAst) {
5858
for stmt in ast.stmts {
5959
self.lower_stmt(stmt);
6060
}
6161
}
6262

63-
pub fn finish(mut self) -> FunctionIR {
63+
fn finish(mut self) -> FunctionIR {
6464
self.blocks[self.current_block.0 as usize].terminator = Terminator::Return(Value::Const(Const::Unit));
6565
FunctionIR {
6666
blocks: self.blocks,

src/ir/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
mod ir;
22
mod lowerer;
3+
mod verifier;
34
pub mod pretty;
45

56
pub use ir::*;

src/ir/verifier.rs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
use std::collections::HashSet;
2+
use crate::ir::{ir::*, lowerer::TempId};
3+
4+
pub fn verify_ir(ir: &ProgramIR) {
5+
for func in &ir.functions {
6+
let mut verifier = FunctionIRVerifier { ir: func, defined: HashSet::new() };
7+
verifier.verify_entry_exists();
8+
for block in &func.blocks {
9+
verifier.verify_block(block);
10+
}
11+
}
12+
}
13+
14+
struct FunctionIRVerifier<'a> {
15+
ir: &'a FunctionIR,
16+
defined: HashSet<TempId>,
17+
}
18+
19+
impl FunctionIRVerifier<'_> {
20+
fn verify_entry_exists(&self) {
21+
self.ir.blocks.len() > 0;
22+
}
23+
24+
fn verify_temp(&self, id: TempId) {
25+
self.defined.contains(&id);
26+
}
27+
28+
fn verify_temp_def(&mut self, id: TempId) {
29+
self.ir.temps.len() > id.index();
30+
self.defined.insert(id);
31+
}
32+
33+
fn verify_instr(&mut self, instr: &Instr) {
34+
match instr {
35+
Instr::LoadConst { dst, .. } => {
36+
self.verify_temp_def(*dst)
37+
}
38+
Instr::Binary { dst, lhs, rhs, .. } {
39+
self.verify_temp(*lhs);
40+
self.verify_temp(*rhs);
41+
self.verify_temp_def(*dst);
42+
}
43+
Instr::Store { place, value } => {
44+
match value {
45+
Value::Temp(*id) => self.verify_temp(*id),
46+
_ => {}
47+
}
48+
49+
match place {
50+
Place::Local(id) => self.ir.locals.len() > id.index(),
51+
};
52+
}
53+
Instr::Load { dst, place } => {
54+
match place {
55+
Place::Local(id) => self.ir.locals.len() > id.index(),
56+
};
57+
self.verify_temp_def(dst)
58+
}
59+
Instr::Poision { dst } => {
60+
if let Some(id) = dst {
61+
self.verify_temp_def(*id)
62+
}
63+
}
64+
}
65+
}
66+
67+
fn verify_terminator(&self, term: &Terminator) {
68+
match term {
69+
Goto(id) => { self.ir.blocks.len() > id.len(); },
70+
Return(Value::Temp(id)) => self.verify_temp(*id),
71+
_ => {}
72+
}
73+
}
74+
75+
fn verify_block(&mut self, block: &Block) {
76+
for instr in &block.instrs {
77+
self.verify_instr(instr);
78+
}
79+
self.verify_terminator(&block.terminator)
80+
}
81+
}
82+

src/semantics/resolver.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ impl ScopeGraph {
9999

100100
// Resolution
101101

102-
pub struct Resolver<'d, D: DiagnosticSink> {
102+
struct Resolver<'d, D: DiagnosticSink> {
103103
scopes: ScopeGraph,
104104
symbols: SymbolTable,
105105
diags: &'d mut D,
@@ -108,7 +108,7 @@ pub struct Resolver<'d, D: DiagnosticSink> {
108108
}
109109

110110
impl<'d, D: DiagnosticSink> Resolver<'d, D> {
111-
pub fn new(diags: &'d mut D) -> Self {
111+
fn new(diags: &'d mut D) -> Self {
112112
let mut scopes = ScopeGraph { scopes: Vec::new() };
113113
let global = scopes.new_scope(None);
114114

@@ -120,7 +120,7 @@ impl<'d, D: DiagnosticSink> Resolver<'d, D> {
120120
}
121121
}
122122

123-
pub fn resolve_program(&mut self, ast: p::ParsedAst) -> r::ResolvedAst {
123+
fn resolve_program(&mut self, ast: p::ParsedAst) -> r::ResolvedAst {
124124
for stmt in &ast.stmts {
125125
self.declare_stmt(stmt);
126126
}

src/semantics/typechecker.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,20 @@ pub enum TypeError {
2424
UntypedSymbol(Span),
2525
}
2626

27-
pub struct TypeChecker<'a> {
27+
struct TypeChecker<'a> {
2828
symbols: &'a mut SymbolTable,
2929
errors: Vec<TypeError>
3030
}
3131

3232
impl<'a> TypeChecker<'a> {
33-
pub fn new(symbols: &'a mut SymbolTable) -> Self {
33+
fn new(symbols: &'a mut SymbolTable) -> Self {
3434
Self {
3535
symbols,
3636
errors: Vec::new(),
3737
}
3838
}
3939

40-
pub fn type_check(&mut self, ast: r::ResolvedAst) -> t::TypedAst {
40+
fn type_check(&mut self, ast: r::ResolvedAst) -> t::TypedAst {
4141
let typed_stmts = ast.stmts
4242
.into_iter()
4343
.map(|stmt| self.check_stmt(stmt));

src/syntax/parser.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,20 +33,20 @@ impl<'a, 'd, D: DiagnosticSink> Operator<'a, 'd, D> {
3333
}
3434
}
3535

36-
pub struct Parser<'a, 'd, D: DiagnosticSink> {
36+
struct Parser<'a, 'd, D: DiagnosticSink> {
3737
stream: TokenStream<'a>,
3838
diags: &'d mut D,
3939
}
4040

4141
impl<'a, 'd, D: DiagnosticSink> Parser<'a, 'd, D> {
42-
pub fn new(stream: TokenStream<'a>, diags: &'d mut D) -> Self {
42+
fn new(stream: TokenStream<'a>, diags: &'d mut D) -> Self {
4343
Self {
4444
stream,
4545
diags,
4646
}
4747
}
4848

49-
pub fn parse_program(&mut self) -> ParsedAst<'a> {
49+
fn parse_program(&mut self) -> ParsedAst<'a> {
5050
let mut stmts = Vec::new();
5151

5252
while !matches!(self.stream.peek_with(LexHint::Any).map(|t| t.kind), Some(TokenKind::EOF) | None) {

0 commit comments

Comments
 (0)