summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chapter17/README.md2
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/node/CallEndNode.java31
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/node/ReturnNode.java2
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java12
4 files changed, 34 insertions, 13 deletions
diff --git a/chapter17/README.md b/chapter17/README.md
index e0c8d6d9..8a7cc8b1 100644
--- a/chapter17/README.md
+++ b/chapter17/README.md
@@ -92,7 +92,7 @@ bar.x = 3; // Ok, bar is mutable
struct Foo { Bar !bar; int y; }
Foo !foo = new Foo;
-foo.bar = barl // Ok bar is mutable
+foo.bar = bar; // Ok bar is mutable
foo.bar.x++; // Ok foo and foo.bar and foo.bar.x are all mutable
val xfoo = foo; // Throw away mutability
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/CallEndNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/CallEndNode.java
index a2866d65..07a2b5a3 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/node/CallEndNode.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/node/CallEndNode.java
@@ -50,24 +50,31 @@ public class CallEndNode extends CFGNode implements MultiNode {
CallNode call = call();
Node fptr = call.fptr();
if( fptr.nOuts() == 1 && // Only user is this call
- fptr instanceof ConstantNode &&
+ fptr instanceof ConstantNode && // We have an immediate call
// Function is being called, and its not-null
- fptr._type instanceof TypeFunPtr tfp && tfp.notNull()) {
+ fptr._type instanceof TypeFunPtr tfp && tfp.notNull() &&
+ // Arguments are correct
+ call.err()==null ) {
ReturnNode ret = (ReturnNode)in(1);
FunNode fun = ret.fun();
// Expecting Start, and the Call
if( fun.nIns()==3 ) {
assert fun.in(1) instanceof StartNode && fun.in(2)==call;
-
- // Trivial inline: rewrite
- _folding = true;
- // Rewrite Fun so the normal RegionNode ideal collapses
- fun._folding = true;
- fun.setDef(1,Parser.XCTRL); // No default/unknown StartNode caller
- fun.setDef(2,call.ctrl()); // Bypass the Call;
- fun.ret().setDef(3,null); // Return is folding also
- IterPeeps.addAll(fun._outputs);
- return this;
+ // Disallow self-recursive inlining (loop unrolling by another name)
+ CFGNode idom = call;
+ while( !(idom instanceof FunNode fun2) )
+ idom = idom.idom();
+ if( idom != fun ) {
+ // Trivial inline: rewrite
+ _folding = true;
+ // Rewrite Fun so the normal RegionNode ideal collapses
+ fun._folding = true;
+ fun.setDef(1,Parser.XCTRL); // No default/unknown StartNode caller
+ fun.setDef(2,call.ctrl()); // Bypass the Call;
+ fun.ret().setDef(3,null); // Return is folding also
+ IterPeeps.addAll(fun._outputs);
+ return this;
+ }
} else {
fun.addDep(this);
}
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/ReturnNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/ReturnNode.java
index 2fe722c6..e543f9ea 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/node/ReturnNode.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/node/ReturnNode.java
@@ -117,6 +117,8 @@ public class ReturnNode extends CFGNode {
}
static Parser.ParseException mixerr( boolean ti, boolean tf, boolean tp, boolean tn, Parser.Lexer loc ) {
+ if( !ti && !tf && !tp && !tn )
+ return Parser.error("No defined return type", loc);
SB sb = new SB().p("No common type amongst ");
if( ti ) sb.p("int and ");
if( tf ) sb.p("f64 and ");
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java
index 0e92c8c0..1d7abde5 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java
@@ -259,6 +259,18 @@ for(;;) {
catch( Exception e ) { assertEquals("Accessing unknown field 'x' from '*S'",e.getMessage()); }
}
+ @Test
+ public void testErr5() {
+ CodeGen code = new CodeGen(
+"""
+val g = { ->
+ g();
+};
+return 0;
+""");
+ try { code.parse().opto().typeCheck(); fail(); }
+ catch( Exception e ) { assertEquals("No defined return type",e.getMessage()); }
+ }
// Mutual recursion. Fails without SCCP to lift the recursive return types.