Skip to content

Commit

Permalink
[FIX] fixes #45 #43
Browse files Browse the repository at this point in the history
  • Loading branch information
Cr0a3 committed Oct 31, 2024
1 parent c53e9e2 commit 8076716
Show file tree
Hide file tree
Showing 7 changed files with 199 additions and 32 deletions.
19 changes: 19 additions & 0 deletions src/IR/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,14 @@ pub enum IrError {
/// expected amount
expected: usize,
},

/// a block branches to a phi node, but the input of the block is not handled
PhiBranchNotHandled {
/// location
loc: Loc,
/// the branch name
branch: String,
}
}

impl Display for IrError {
Expand Down Expand Up @@ -315,6 +323,17 @@ impl Display for IrError {
fab.setCodeLine(loc.line_string.to_owned());
fab.addWhere(format!("to many arguments were supplyed - expected {expected}"), loc.coloumn, loc.length);

fab.to_string()
},

IrError::PhiBranchNotHandled { loc, branch } => {
let mut fab = Support::Error::new("unhandled phi branch", "", "", "");

fab.deactivateLocationDisplay();

fab.setCodeLine(loc.line_string.to_owned());
fab.addWhere(format!("block {branch} can branch to the phi node but there is no specified input"), loc.coloumn, loc.length);

fab.to_string()
}
})
Expand Down
60 changes: 59 additions & 1 deletion src/IR/parser/semnatic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,31 @@ impl<'a> IrSemnatic<'a> {

let func = name;

// analyise block dependence

let mut branches_to = HashMap::new(); // HashMap<BlockName, Vec<Branches to these blocks>>

for (name, block) in body {
for node in &block.body {

let mut branches = Vec::new();

if let Some(br) = node.inst.as_any().downcast_ref::<Br<BlockId>>() {
branches.push(br.inner1.to_owned());
} else if let Some(br) = node.inst.as_any().downcast_ref::<BrCond<Var, BlockId, BlockId>>() {
branches.push(br.inner2.to_owned());
branches.push(br.inner3.to_owned());
} else if let Some(switch) = node.inst.as_any().downcast_ref::<Switch>() {
branches.push(switch.default.to_owned());
for (_, case) in &switch.cases {
branches.push(case.to_owned());
}
}

branches_to.insert(name.to_owned(), branches);
}
}

for (name, block) in body {
if blocks.contains(name) {
Err(IrError::DefinedTwice {
Expand Down Expand Up @@ -219,10 +244,43 @@ impl<'a> IrSemnatic<'a> {
self.analaysiz_load(&mut vars, node, loc)?;
} else if let Some(node) = any.downcast_ref::<Phi>() {
if vars.contains_key(&node.out.name) {
Err(IrError::DefinedTwice { loc: loc, name: node.out.name.to_owned() })?
Err(IrError::DefinedTwice { loc: loc.to_owned(), name: node.out.name.to_owned() })?
} else {
vars.insert(node.out.name.to_owned(), node.typ);
}

let mut handled = Vec::new();

for (branch, branches) in &branches_to {
if branches.contains(&BlockId(name.to_owned())) {
let mut recived = false;

for recive in &node.recive_from_blocks {
if recive.0.name == branch.to_owned() {
handled.push(recive.0.name.clone());
recived = true;
break;
}
}

if !recived {
Err(IrError::PhiBranchNotHandled {
loc: loc.to_owned(),
branch: branch.to_owned(),
})?
}
}
}

for (recive, _) in &node.recive_from_blocks {
if !handled.contains(&recive.name) {
Err(IrError::Unkown {
what: "block".into(),
name: recive.name.to_owned(),
loc: loc.to_owned()
})?
}
}
} else if let Some(node) = any.downcast_ref::<Switch>() {
self.analyze_switch(func, &mut vars, node, loc)?;
} else if let Some(node) = any.downcast_ref::<Neg<Var, Var>>() {
Expand Down
76 changes: 46 additions & 30 deletions src/Optimizations/Passes/DeadNodeElimination.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{prelude::Call, Optimizations::Pass, IR::{FuncId, Var}};
use crate::{prelude::{Call, Phi}, Optimizations::Pass, IR::{FuncId, Var}};

/// ## Pass DeadNodeElimination <br>
/// deletes unused nodes
Expand All @@ -11,49 +11,65 @@ pub fn DeadNodeElimination() -> Box<dyn Pass> {

impl Pass for DeadNodeElimination_ {
fn run_func(&self, func: &mut crate::prelude::Function) {
let mut used: Vec<String> = Vec::new();
for _ in 0..2 { // iterate two times, cuz then we can remove dependants with a dept of 1
let mut used: Vec<String> = Vec::new();

let mut to_remove = Vec::new();
let mut to_remove = Vec::new();

for block in func.blocks.iter().rev() {
let iter = block.nodes.iter();
let iter = iter.rev();
// first iterate over all phis

let mut index = iter.len() as i32;

for node in iter {
let inputs = node.inputs();
let out = node.output();

for input in inputs {
if !used.contains(&input.name) {
used.push(input.name);
for block in func.blocks.iter() {
for node in &block.nodes {
if let Some(phi) = node.as_any().downcast_ref::<Phi>() {
for (_, reciver) in &phi.recive_from_blocks {
used.push(reciver.name.to_owned());
}
}
}
}

// now we can iterate over all normal nodes

for block in func.blocks.iter().rev() {
let iter = block.nodes.iter();
let iter = iter.rev();

if let Some(out) = out {
if !used.contains(&out.name) {
if let Some(_) = node.as_any().downcast_ref::<Call<FuncId, Vec<Var>, Var>>() {} else {
// node isn't a call
to_remove.push((block.name.clone(), index - 1));
let mut index = iter.len() as i32;

for node in iter {
let inputs = node.inputs();
let out = node.output();

for input in inputs {
if !used.contains(&input.name) {
used.push(input.name);
}
}

if let Some(out) = out {
if !used.contains(&out.name) {
if let Some(_) = node.as_any().downcast_ref::<Call<FuncId, Vec<Var>, Var>>() {} else {
// node isn't a call
to_remove.push((block.name.clone(), index - 1));
}
}
}

index -= 1;
}

index -= 1;
}
}

for block in &mut func.blocks {
let mut off = 0;
for block in &mut func.blocks {
let mut off = 0;

for (target_block, node) in &to_remove {
if target_block == &block.name {
block.nodes.remove((*node - off) as usize);
for (target_block, node) in &to_remove {
if target_block == &block.name {
block.nodes.remove((*node - off) as usize);

off += 1;
off += 1;
}
}
}
}
}
}
}
26 changes: 26 additions & 0 deletions tests/Optimizations/dne/dne1.yl
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# RUN:
cargo run -p ylc -- -in=%s -passes=dne -fmt
# IN:

define void @main() {
entry:
br loop
loop:
%0 = phi i64 [%1, loop]
%1 = sub i64 %0, 1
br cond %0 end, loop
end:
ret void 0
}

# STDOUT:
define void @main() {
entry:
br loop
loop:
%0 = phi i64 [%1, loop]
%1 = sub i64 %0, 1
br cond %0 end, loop
end:
ret void 0
}
16 changes: 16 additions & 0 deletions tests/Optimizations/dne/dne2.yl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# RUN:
cargo run -p ylc -- -in=%s -passes=dne -fmt
# IN:

define i32 @main() {
entry:
%0 = i32 5
%2 = add i32 %0, 3
ret i32 4
}

# STDOUT:
define i32 @main() {
entry:
ret i32 4
}
22 changes: 22 additions & 0 deletions tests/bugs/phi_non_recive.yl
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# RUN:
cargo run -p ylc -- -in=%s -fmt
# IN:

define void @main() {
entry:
%tmp = i32 0
br loop

loop:
%0 = phi i64 [ %tmp, entry %1, loop ]
%1 = sub i64 %0, 1
br cond %0 end, loop

abc:
br loop

end:
ret void 0

}
# EXPECT_FAIL
12 changes: 11 additions & 1 deletion tools/ytest/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,17 @@ fn main() {

match cmd.status() {
Ok(status) => {
if parsed.ignore_fail {
code = status.code().expect("expected exit code") as u32;
continue;
}

if !status.success() {
if let Some(exit_code) = status.code() {
code = exit_code as u32;

if let Some(expected_code) = parsed.expected_code {
if expected_code == 0 || (cli.opt("exit") && code == (-1i32 as u32)) && !parsed.ignore_fail {
if (expected_code == 0 || (cli.opt("exit")) && code == (-1i32 as u32)) && !parsed.ignore_fail {
println!("{}: the programm didn't exit sucessfull with code {}", "Error".red().bold(), exit_code);
if !cli.opt("no-exit") {
exit(-1);
Expand Down Expand Up @@ -209,4 +214,9 @@ fn main() {
println!("expected exit code {} matched with found one {}", expected_code, code);
}
}

if parsed.ignore_fail && code == 0 { // expected fail but it did not fail
println!("{}: expect fail", "Error".red().bold());
exit(-1);
}
}

0 comments on commit 8076716

Please sign in to comment.