diff --git a/lang/README.md b/lang/README.md index 241dd03b..0f0d1b3d 100644 --- a/lang/README.md +++ b/lang/README.md @@ -612,6 +612,30 @@ main := fn(): uint { ### Purely Testing Examples +#### null_check_in_the_loop +```hb +A := struct { + x_change: u8, + y_change: u8, + left: u8, + middle: u8, + right: u8, +} + +return_fn := fn(): ?A { + return A.(0, 0, 0, 0, 0) +} + +main := fn(): int { + loop { + ret := return_fn() + if ret != null { + return 1 + } + } +} +``` + #### stack_provenance ```hb main := fn(): uint { diff --git a/lang/src/son.rs b/lang/src/son.rs index 7e126e45..5a2082b4 100644 --- a/lang/src/son.rs +++ b/lang/src/son.rs @@ -225,13 +225,13 @@ impl Nodes { return; } - let mut deepest = VOID; - for i in 0..self[node].inputs.len() { - let inp = self[node].inputs[i]; + let mut deepest = self[node].inputs[0]; + for &inp in self[node].inputs[1..].iter() { if self.idepth(inp) > self.idepth(deepest) { if matches!(self[inp].kind, Kind::Call { .. }) { deepest = inp; } else { + debug_assert!(!self.is_cfg(inp)); deepest = self.idom(inp); } } @@ -256,14 +256,15 @@ impl Nodes { self[deepest].outputs.push(node); } - fn collect_rpo(&mut self, node: Nid, rpo: &mut Vec, visited: &mut BitSet) { + fn collect_rpo(&self, node: Nid, rpo: &mut Vec, visited: &mut BitSet) { if !self.is_cfg(node) || !visited.set(node) { return; } - for i in 0..self[node].outputs.len() { - self.collect_rpo(self[node].outputs[i], rpo, visited); + for &n in self[node].outputs.iter() { + self.collect_rpo(n, rpo, visited); } + rpo.push(node); } @@ -1251,6 +1252,8 @@ impl Nodes { return Some(NEVER); } + std::dbg!(&self[self[target].inputs[1]]); + if self[target].inputs[1] == NEVER { self.lock(target); for o in self[target].outputs.clone() { @@ -2390,6 +2393,11 @@ impl<'a> Codegen<'a> { } let (index, _) = self.ci.nodes.aclass_index(region); + if self.ci.nodes[value].kind == Kind::Load { + let (lindex, _) = self.ci.nodes.aclass_index(self.ci.nodes[value].inputs[1]); + let clobber = self.ci.scope.aclasses[lindex].clobber.get(); + self.ci.scope.aclasses[index].clobber.set(clobber, &mut self.ci.nodes); + } let aclass = &mut self.ci.scope.aclasses[index]; self.ci.nodes.load_loop_aclass(index, aclass, &mut self.ci.loops); let vc = Vc::from([aclass.clobber.get(), value, region, aclass.last_store.get()]); @@ -2416,7 +2424,7 @@ impl<'a> Codegen<'a> { let (index, _) = self.ci.nodes.aclass_index(region); let aclass = &mut self.ci.scope.aclasses[index]; self.ci.nodes.load_loop_aclass(index, aclass, &mut self.ci.loops); - let vc = [aclass.clobber.get(), region, aclass.last_store.get()]; + let vc = [std::dbg!(aclass.clobber.get()), region, aclass.last_store.get()]; self.ci.nodes.new_node(ty, Kind::Load, vc) } @@ -2567,15 +2575,10 @@ impl<'a> Codegen<'a> { } } - self.ci.ctrl.set( - self.ci.nodes.new_node_nop(ty::Id::VOID, Kind::Return, inps), - &mut self.ci.nodes, - ); - - self.ci.nodes[self.ci.ctrl.get()].pos = pos; - - self.ci.nodes[NEVER].inputs.push(self.ci.ctrl.get()); - self.ci.nodes[self.ci.ctrl.get()].outputs.push(NEVER); + let ret = self.ci.nodes.new_node_nop(ty::Id::VOID, Kind::Return, inps); + self.ci.ctrl.set(NEVER, &mut self.ci.nodes); + self.ci.nodes[ret].pos = pos; + self.ci.nodes.bind(ret, NEVER); } else if let Some((pv, ctrl, scope)) = &mut self.ci.inline_ret { ctrl.set( self.ci @@ -3164,6 +3167,7 @@ impl<'a> Codegen<'a> { Loc::Reg => None, Loc::Stack => { let stck = self.new_stack(func.pos(), sig.ret); + clobbered_aliases.set(self.ci.nodes.aclass_index(stck).0 as _); inps.push(stck); Some(Value::ptr(stck).ty(sig.ret)) } @@ -4638,6 +4642,7 @@ mod tests { fb_driver; // Purely Testing Examples; + null_check_in_the_loop; stack_provenance; advanced_floating_point_arithmetic; nullable_structure; diff --git a/lang/tests/son_tests_null_check_in_the_loop.txt b/lang/tests/son_tests_null_check_in_the_loop.txt new file mode 100644 index 00000000..c7735b3f --- /dev/null +++ b/lang/tests/son_tests_null_check_in_the_loop.txt @@ -0,0 +1,34 @@ +main: + ADDI64 r254, r254, -38d + ST r31, r254, 6a, 32h + LI8 r32, 0b + ADDI64 r33, r254, 0d + 2: JAL r31, r0, :return_fn + ST r1, r254, 0a, 6h + LD r34, r254, 0a, 1h + ANDI r34, r34, 255d + ANDI r32, r32, 255d + JEQ r34, r32, :0 + LI64 r1, 1d + JMP :1 + 0: JMP :2 + 1: LD r31, r254, 6a, 32h + ADDI64 r254, r254, 38d + JALA r0, r31, 0a +return_fn: + ADDI64 r254, r254, -6d + LI8 r4, 1b + ADDI64 r3, r254, 0d + ST r4, r254, 0a, 1h + LI8 r4, 0b + ST r4, r254, 1a, 1h + ST r4, r254, 2a, 1h + ST r4, r254, 3a, 1h + ST r4, r254, 4a, 1h + ST r4, r254, 5a, 1h + LD r1, r3, 0a, 6h + ADDI64 r254, r254, 6d + JALA r0, r31, 0a +code size: 302 +ret: 1 +status: Ok(())