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