fixed the unreachable functions deleting branches
Signed-off-by: Jakub Doka <jakub.doka2@gmail.com>
This commit is contained in:
parent
47014c6164
commit
6085177982
|
@ -254,8 +254,7 @@ pub fn disasm<'a>(
|
|||
|| global_offset > off + len
|
||||
|| prev
|
||||
.get(global_offset as usize)
|
||||
.map_or(true, |&b| instr_from_byte(b).is_err())
|
||||
|| prev[global_offset as usize] == 0;
|
||||
.map_or(true, |&b| instr_from_byte(b).is_err());
|
||||
has_oob |= local_has_oob;
|
||||
let label = labels.get(&global_offset).unwrap();
|
||||
if local_has_oob {
|
||||
|
|
|
@ -662,10 +662,13 @@ main := fn(): uint {
|
|||
|
||||
#### die
|
||||
```hb
|
||||
|
||||
fun := fn(): never die
|
||||
|
||||
main := fn(): never {
|
||||
// simply emmits 'un' instruction that immediately terminates the execution
|
||||
// the expresion has similar properties to 'return' but does not accept a value
|
||||
die
|
||||
fun()
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ impl HbvmBackend {
|
|||
tys: &Types,
|
||||
files: &EntSlice<Module, parser::Ast>,
|
||||
) -> (usize, bool) {
|
||||
let tail = Function::build(nodes, tys, &mut self.ralloc, sig);
|
||||
let tail = FunctionBuilder::build(nodes, tys, &mut self.ralloc, sig);
|
||||
|
||||
let strip_load = |value| match nodes[value].kind {
|
||||
Kind::Load { .. } if nodes[value].ty.loc(tys) == Loc::Stack => nodes[value].inputs[1],
|
||||
|
@ -392,8 +392,9 @@ impl HbvmBackend {
|
|||
todo!("unhandled operator: {op}");
|
||||
}
|
||||
}
|
||||
Kind::Call { args, func } => {
|
||||
Kind::Call { args, func, .. } => {
|
||||
let (ret, mut parama) = tys.parama(node.ty);
|
||||
debug_assert!(node.ty != ty::Id::NEVER || ret.is_none());
|
||||
if let Some(PLoc::Ref(r, ..)) = ret {
|
||||
self.emit(instrs::cp(r, atr(*node.inputs.last().unwrap())))
|
||||
}
|
||||
|
@ -530,7 +531,7 @@ impl HbvmBackend {
|
|||
}
|
||||
}
|
||||
|
||||
struct Function<'a> {
|
||||
struct FunctionBuilder<'a> {
|
||||
sig: Sig,
|
||||
tail: bool,
|
||||
nodes: &'a Nodes,
|
||||
|
@ -538,7 +539,7 @@ struct Function<'a> {
|
|||
func: &'a mut Res,
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for Function<'_> {
|
||||
impl core::fmt::Debug for FunctionBuilder<'_> {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
for block in &self.func.blocks {
|
||||
writeln!(f, "{:?}", self.nodes[block.entry].kind)?;
|
||||
|
@ -551,7 +552,7 @@ impl core::fmt::Debug for Function<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> Function<'a> {
|
||||
impl<'a> FunctionBuilder<'a> {
|
||||
fn build(nodes: &'a Nodes, tys: &'a Types, func: &'a mut Res, sig: Sig) -> bool {
|
||||
func.blocks.clear();
|
||||
func.instrs.clear();
|
||||
|
@ -670,17 +671,21 @@ impl<'a> Function<'a> {
|
|||
self.emit_node(o);
|
||||
}
|
||||
}
|
||||
Kind::Call { func, .. } => {
|
||||
Kind::Call { func, unreachable, .. } => {
|
||||
self.tail &= func == ty::Func::ECA;
|
||||
|
||||
self.add_instr(nid);
|
||||
|
||||
for &o in node.outputs.iter().rev() {
|
||||
if self.nodes[o].inputs[0] == nid
|
||||
|| (matches!(self.nodes[o].kind, Kind::Loop | Kind::Region)
|
||||
&& self.nodes[o].inputs[1] == nid)
|
||||
{
|
||||
self.emit_node(o);
|
||||
if unreachable {
|
||||
self.close_block(nid);
|
||||
self.emit_node(node.outputs[0]);
|
||||
} else {
|
||||
self.add_instr(nid);
|
||||
for &o in node.outputs.iter().rev() {
|
||||
if self.nodes[o].inputs[0] == nid
|
||||
|| (matches!(self.nodes[o].kind, Kind::Loop | Kind::Region)
|
||||
&& self.nodes[o].inputs[1] == nid)
|
||||
{
|
||||
self.emit_node(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -177,8 +177,9 @@ pub fn run_compiler(
|
|||
|
||||
if options.dump_asm {
|
||||
let mut disasm = String::new();
|
||||
codegen.disasm(&mut disasm, out).map_err(|e| io::Error::other(e.to_string()))?;
|
||||
let err = codegen.disasm(&mut disasm, out).map_err(|e| io::Error::other(e.to_string()));
|
||||
*out = disasm.into_bytes();
|
||||
err?
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -97,6 +97,7 @@ impl Nodes {
|
|||
debug_assert_ne!(next, 0);
|
||||
if matches!(self[cursor].kind, Kind::Then | Kind::Else) {
|
||||
debug_assert_eq!(self[next].kind, Kind::If);
|
||||
debug_assert_eq!(self[next].ty, ty::Id::VOID);
|
||||
let other = self[next].outputs[(self[next].outputs[0] == cursor) as usize];
|
||||
self[other].loop_depth.set(depth - 1);
|
||||
}
|
||||
|
@ -1714,7 +1715,7 @@ impl Nodes {
|
|||
Kind::BinOp { op } | Kind::UnOp { op } => {
|
||||
write!(out, "{:>4}: ", op.name())
|
||||
}
|
||||
Kind::Call { func, args: _ } => {
|
||||
Kind::Call { func, args: _, unreachable: _ } => {
|
||||
write!(out, "call: {func} {} ", self[node].depth.get())
|
||||
}
|
||||
Kind::Global { global } => write!(out, "glob: {global:<5}"),
|
||||
|
@ -2109,6 +2110,7 @@ pub enum Kind {
|
|||
},
|
||||
// [ctrl, ...args]
|
||||
Call {
|
||||
unreachable: bool,
|
||||
func: ty::Func,
|
||||
args: ty::Tuple,
|
||||
},
|
||||
|
@ -2163,6 +2165,7 @@ impl Kind {
|
|||
|
||||
fn ends_basic_block(&self) -> bool {
|
||||
matches!(self, Self::Return { .. } | Self::If | Self::End | Self::Die)
|
||||
|| matches!(self, Kind::Call { unreachable: true, .. })
|
||||
}
|
||||
|
||||
pub fn starts_basic_block(&self) -> bool {
|
||||
|
|
|
@ -1516,7 +1516,11 @@ impl<'a> Codegen<'a> {
|
|||
|
||||
inps[0] = self.ci.ctrl.get();
|
||||
self.ci.ctrl.set(
|
||||
self.ci.nodes.new_node_nop(ty, Kind::Call { func: ty::Func::ECA, args }, inps),
|
||||
self.ci.nodes.new_node_nop(
|
||||
ty,
|
||||
Kind::Call { func: ty::Func::ECA, args, unreachable: false },
|
||||
inps,
|
||||
),
|
||||
&mut self.ci.nodes,
|
||||
);
|
||||
|
||||
|
@ -2656,13 +2660,19 @@ impl<'a> Codegen<'a> {
|
|||
|
||||
inps[0] = self.ci.ctrl.get();
|
||||
self.ci.ctrl.set(
|
||||
self.ci.nodes.new_node_nop(sig.ret, Kind::Call { func: fu, args: sig.args }, inps),
|
||||
self.ci.nodes.new_node_nop(
|
||||
sig.ret,
|
||||
Kind::Call { func: fu, args: sig.args, unreachable: sig.ret == ty::Id::NEVER },
|
||||
inps,
|
||||
),
|
||||
&mut self.ci.nodes,
|
||||
);
|
||||
|
||||
self.add_clobber_stores(clobbered_aliases);
|
||||
|
||||
if sig.ret == ty::Id::NEVER {
|
||||
self.ci.nodes.bind(self.ci.ctrl.get(), NEVER);
|
||||
self.ci.ctrl.set(NEVER, &mut self.ci.nodes);
|
||||
return None;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue