summaryrefslogtreecommitdiff
path: root/chapter22/src
diff options
context:
space:
mode:
Diffstat (limited to 'chapter22/src')
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/Parser.java53
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java5
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/codegen/Encoding.java2
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/FunNode.java6
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/ShlNode.java11
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/Chapter09Test.java13
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/Chapter10Test.java1
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/Chapter11Test.java4
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/Chapter13Test.java3
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/Chapter15Test.java2
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/Chapter18Test.java3
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/Chapter19Test.java1
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/Chapter21Test.java6
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/Chapter22Test.java7
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/Eval2.java1
15 files changed, 68 insertions, 50 deletions
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/Parser.java b/chapter22/src/main/java/com/seaofnodes/simple/Parser.java
index bbf841c8..5b9a3820 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/Parser.java
@@ -132,34 +132,17 @@ public class Parser {
private <N extends Node> N ctrl(N n) { return _scope.ctrl(n); }
public void parse() {
- _scope.define(ScopeNode.CTRL, Type.CONTROL , false, null, null);
- _scope.define(ScopeNode.MEM0, TypeMem.BOT , false, null, null);
- _scope.define(ScopeNode.ARG0, TypeInteger.BOT, false, null, null);
+ _lexer = new Lexer(_code._src);
+ _xScopes.push(_scope);
+ _scope.define(ScopeNode.CTRL, Type.CONTROL , false, null, _lexer);
+ _scope.define(ScopeNode.MEM0, TypeMem.BOT , false, null, _lexer);
+ _scope.define(ScopeNode.ARG0, TypeInteger.BOT, false, null, _lexer);
ctrl(XCTRL);
_scope.mem(new MemMergeNode(false));
- // Parse the "sys" import
- //_parse(com.seaofnodes.simple.sys.sys.SYS);
-
- _code._stop.popUntil(0); // Delete return from parsing sys import
-
- // Parse program text
- _parse(_code._src);
-
- // Clean up and reset
- _scope.kill();
- for( StructNode init : INITS.values() )
- init.unkeep().kill();
- INITS.clear();
- _code._stop.peephole();
- }
-
- private void _parse(String src) {
- _lexer = new Lexer(src);
- _xScopes.push(_scope);
-
// Parse whole program, as-if function header "{ int arg -> body }"
+
parseFunctionBody(_code._main,loc(),"arg");
// Kill an empty default main. Keep only if it was explicitly defined
@@ -167,9 +150,10 @@ public class Parser {
// default main).
FunNode main = _code.link(_code._main);
StopNode stop = _code._stop;
- if( main.ret().expr() instanceof ConstantNode && main.ret().mem().in(0)==main && stop.nIns() > 1 ) {
+ if( main.ret().expr()._type==Type.TOP ) {
// Kill an empty default main; so it does not attempt to put a
// "main" in any final ELF file
+ main.setDef(1,XCTRL); // Delete default start input
stop.delDef(stop._inputs.find(main.ret()));
} else {
// We have a non-empty default main.
@@ -185,6 +169,11 @@ public class Parser {
// Clean up and reset
_xScopes.pop();
+ _scope.kill();
+ for( StructNode init : INITS.values() )
+ init.unkeep().kill();
+ INITS.clear();
+ stop.peephole();
}
/**
@@ -233,13 +222,22 @@ public class Parser {
_scope.define(ids[i], t, false, new ParmNode(ids[i],i+2,t,fun,con(t)).peephole(), loc);
}
+ //// If top-level parser, parse the sys import
+ //if( fun.sig()==_code._main ) {
+ // Lexer old = _lexer;
+ // _lexer = new Lexer(com.seaofnodes.simple.sys.sys.SYS);
+ // while(!_lexer.isEOF() )
+ // parseStatement();
+ // _lexer = old;
+ //}
+
// Parse the body
Node last=ZERO;
while (!peek('}') && !_lexer.isEOF())
last = parseStatement();
- // Last expression is the return
- if( ctrl()._type==Type.CONTROL )
+ // Last expression is the return except for the top-level main
+ if( ctrl()._type==Type.CONTROL && fun.sig() != _code._main )
fun.addReturn(ctrl(), _scope.mem().merge(), last);
// Pop off the inProgress node on the multi-exit Region merge
@@ -1286,9 +1284,8 @@ public class Parser {
throw error("Accessing unknown field '" + name + "' from 'null'");
// Sanity check expr for being a reference
- if( !(expr._type instanceof TypeMemPtr ptr) ) {
+ if( !(expr._type instanceof TypeMemPtr ptr) )
throw error( "Expected "+(name=="#" || name=="[]" ? "array" : "reference")+" but found " + expr._type.str() );
- }
// Find the field from the Type. Lookup in the base object field names.
TypeStruct base = ptr._obj;
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java b/chapter22/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java
index bf6d67b0..26f2e522 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java
@@ -111,7 +111,7 @@ public class CodeGen {
return TypeFunPtr.make((byte)2,sig,ret, 1L<<fidx );
}
// Signature for MAIN
- public TypeFunPtr _main = makeFun(TypeTuple.MAIN,Type.BOTTOM);
+ public final TypeFunPtr _main = makeFun(TypeTuple.MAIN,Type.BOTTOM);
// Reverse from a constant function pointer to the IR function being called
public FunNode link( TypeFunPtr tfp ) {
assert tfp.isConstant();
@@ -269,7 +269,8 @@ public class CodeGen {
var map = new IdentityHashMap<Node,Node>();
_instSelect( _stop, map );
_stop = ( StopNode)map.get(_stop );
- _start = (StartNode)map.get(_start);
+ StartNode start = (StartNode)map.get(_start);
+ _start = start==null ? new StartNode(_start) : start;
_instOuts(_stop,visit());
_visit.clear();
_tInsSel = (int)(System.currentTimeMillis() - t0);
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/codegen/Encoding.java b/chapter22/src/main/java/com/seaofnodes/simple/codegen/Encoding.java
index d7057839..bc7de99a 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/codegen/Encoding.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/codegen/Encoding.java
@@ -185,12 +185,10 @@ public class Encoding {
Ary<CFGNode> rpo = new Ary<>(CFGNode.class);
rpos.put(_code._start.loop(),rpo);
BitSet visit = _code.visit();
- //IdentityHashMap<CFGNode,LoopNode> looptail = new IdentityHashMap<>();
rpo.add(_code._stop);
for( Node n : _code._start._outputs )
if( n instanceof FunNode fun ) {
int x = rpo._len;
- //_rpo_cfg2(fun, visit, rpo, looptail);
_rpo_cfg(fun, visit, rpos );
assert rpo.at(x) instanceof ReturnNode;
}
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/FunNode.java b/chapter22/src/main/java/com/seaofnodes/simple/node/FunNode.java
index c477e125..5a356185 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/FunNode.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/FunNode.java
@@ -72,7 +72,9 @@ public class FunNode extends RegionNode {
@Override
public Type compute() {
// Only dead if no callers after SCCP
- return Type.CONTROL;
+ if( unknownCallers() )
+ return Type.CONTROL;
+ return super.compute();
}
@Override
@@ -118,7 +120,7 @@ public class FunNode extends RegionNode {
@Override public CFGNode idom(Node dep) { return cfg(1); }
// Always in-progress until we run out of unknown callers
- public boolean unknownCallers() { return in(1) instanceof StartNode; }
+ public boolean unknownCallers() { return nIns()<2 || in(1) instanceof StartNode; }
@Override public boolean inProgress() { return unknownCallers(); }
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/ShlNode.java b/chapter22/src/main/java/com/seaofnodes/simple/node/ShlNode.java
index 82e01841..39a2698a 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/ShlNode.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/ShlNode.java
@@ -22,8 +22,15 @@ public class ShlNode extends LogicalNode {
t2 instanceof TypeInteger i1 ) {
if( i0 == TypeInteger.ZERO )
return TypeInteger.ZERO;
- if( i0.isConstant() && i1.isConstant() )
- return TypeInteger.constant(i0.value()<<i1.value());
+ if( i1.isConstant() ) {
+ int shf = (int)i1.value();
+ if( i0.isConstant() )
+ return TypeInteger.constant(i0.value()<<shf);
+ // If no overflow, shift endpoints
+ if( !(((i0._min<<shf)>>shf) != i0._min ||
+ ((i0._max<<shf)>>shf) != i0._max ) )
+ return TypeInteger.make(i0._min<<shf,i0._max<<shf);
+ }
}
return TypeInteger.BOT;
}
diff --git a/chapter22/src/test/java/com/seaofnodes/simple/Chapter09Test.java b/chapter22/src/test/java/com/seaofnodes/simple/Chapter09Test.java
index 401f346f..a4aade16 100644
--- a/chapter22/src/test/java/com/seaofnodes/simple/Chapter09Test.java
+++ b/chapter22/src/test/java/com/seaofnodes/simple/Chapter09Test.java
@@ -128,14 +128,14 @@ while(v1+arg) {
}
""");
code.parse().opto();
- assertEquals("return 0;", code.print());
+ assertEquals("Stop[ ]", code.print());
}
@Test
public void testWhile0() {
- CodeGen code = new CodeGen("while(0) continue; if(0) arg=0;");
+ CodeGen code = new CodeGen("while(0) continue; if(0) arg=0; return arg;");
code.parse().opto();
- assertEquals("return 0;", code.print());
+ assertEquals("return arg;", code.print());
}
@Test
@@ -145,6 +145,7 @@ if(0) while(0) {
int arg=arg;
while(0) {}
}
+return 0;
""");
code.parse().opto();
assertEquals("return 0;", code.print());
@@ -221,7 +222,7 @@ while(1) {
}
""");
code.parse().opto();
- assertEquals("return Top;", code.print());
+ assertEquals("Stop[ ]", code.print());
}
@Test
@@ -255,7 +256,7 @@ while(0==1) while(v0)
v0=1+v0;
""");
code.parse().opto();
- assertEquals("return 0;", code.print());
+ assertEquals("Stop[ ]", code.print());
}
@Test
@@ -271,7 +272,7 @@ while(1)
return v1+v0;
""");
code.parse().opto();
- assertEquals("return Top;", code.print());
+ assertEquals("Stop[ ]", code.print());
}
@Test
diff --git a/chapter22/src/test/java/com/seaofnodes/simple/Chapter10Test.java b/chapter22/src/test/java/com/seaofnodes/simple/Chapter10Test.java
index 1253e4a6..b7d65b95 100644
--- a/chapter22/src/test/java/com/seaofnodes/simple/Chapter10Test.java
+++ b/chapter22/src/test/java/com/seaofnodes/simple/Chapter10Test.java
@@ -304,6 +304,7 @@ if(0) {
v0=v2;
}
}
+return 0;
""");
code.parse().opto();
assertEquals("return 0;", code.print());
diff --git a/chapter22/src/test/java/com/seaofnodes/simple/Chapter11Test.java b/chapter22/src/test/java/com/seaofnodes/simple/Chapter11Test.java
index f6539ac4..1fb9f75a 100644
--- a/chapter22/src/test/java/com/seaofnodes/simple/Chapter11Test.java
+++ b/chapter22/src/test/java/com/seaofnodes/simple/Chapter11Test.java
@@ -435,7 +435,7 @@ while(1)
arg = arg+ptr.v;
""");
code.parse().opto();
- assertEquals("return Top;", code.print());
+ assertEquals("Stop[ ]", code.print());
}
@Test
@@ -527,7 +527,7 @@ while(0>=0) {
return 0;
""");
code.parse().opto();
- assertEquals("return Top;", code.print());
+ assertEquals("Stop[ ]", code.print());
}
@Test
diff --git a/chapter22/src/test/java/com/seaofnodes/simple/Chapter13Test.java b/chapter22/src/test/java/com/seaofnodes/simple/Chapter13Test.java
index 6bf45a22..a4644917 100644
--- a/chapter22/src/test/java/com/seaofnodes/simple/Chapter13Test.java
+++ b/chapter22/src/test/java/com/seaofnodes/simple/Chapter13Test.java
@@ -130,7 +130,7 @@ return n.i;
@Test
public void testNullRef4() {
- CodeGen code = new CodeGen("-null-5/null-5;");
+ CodeGen code = new CodeGen("return -null-5/null-5;");
try { code.parse().opto().typeCheck(); fail(); }
catch( Exception e ) { assertEquals("Cannot 'Add' null",e.getMessage()); }
}
@@ -146,6 +146,7 @@ return n.i;
CodeGen code = new CodeGen(
"""
struct S{};
+return 0;
""");
code.parse().opto();
assertEquals("return 0;", code.print());
diff --git a/chapter22/src/test/java/com/seaofnodes/simple/Chapter15Test.java b/chapter22/src/test/java/com/seaofnodes/simple/Chapter15Test.java
index 8b138b46..cebbf4a0 100644
--- a/chapter22/src/test/java/com/seaofnodes/simple/Chapter15Test.java
+++ b/chapter22/src/test/java/com/seaofnodes/simple/Chapter15Test.java
@@ -323,6 +323,7 @@ while(0) {}
u32 v7=0;
int v8=0;
while(0<--1>>>---(v7*0==v8)) {}
+return 0;
""");
code.parse().opto();
assertEquals("return 0;", code.print());
@@ -347,6 +348,7 @@ else {
}
}
}
+return 0;
""");
code.parse().opto();
assertEquals("return 0;", code.print());
diff --git a/chapter22/src/test/java/com/seaofnodes/simple/Chapter18Test.java b/chapter22/src/test/java/com/seaofnodes/simple/Chapter18Test.java
index c0e28412..9c8ad66c 100644
--- a/chapter22/src/test/java/com/seaofnodes/simple/Chapter18Test.java
+++ b/chapter22/src/test/java/com/seaofnodes/simple/Chapter18Test.java
@@ -214,7 +214,7 @@ val fcn = { Person?[] ps, int x ->
var ps = new Person?[2];
ps[0] = new Person;
ps[1] = new Person;
-fcn(ps,1);
+return fcn(ps,1);
""");
code.driver(Phase.LocalSched);
assertEquals("return 0;", code._stop.toString());
@@ -249,6 +249,7 @@ for(;;) {
if (i2i(2) == arg) break;
i2i = null;
}
+return 0;
""");
try { code.parse().opto().typeCheck(); fail(); }
catch( Exception e ) { assertEquals("Might be null calling { int -> int #1}?",e.getMessage()); }
diff --git a/chapter22/src/test/java/com/seaofnodes/simple/Chapter19Test.java b/chapter22/src/test/java/com/seaofnodes/simple/Chapter19Test.java
index bce75c81..f06d8a6a 100644
--- a/chapter22/src/test/java/com/seaofnodes/simple/Chapter19Test.java
+++ b/chapter22/src/test/java/com/seaofnodes/simple/Chapter19Test.java
@@ -271,6 +271,7 @@ for( int i=0; i<A#; i++ )
A[i] = i;
for( int i=0; i<A#; i++ )
B[i] += A[i];
+return 0;
""");
code.driver(Phase.LocalSched,"x86_64_v2", "SystemV");
assertEquals("return 0;", code.print());
diff --git a/chapter22/src/test/java/com/seaofnodes/simple/Chapter21Test.java b/chapter22/src/test/java/com/seaofnodes/simple/Chapter21Test.java
index ea23728c..0e8c05fe 100644
--- a/chapter22/src/test/java/com/seaofnodes/simple/Chapter21Test.java
+++ b/chapter22/src/test/java/com/seaofnodes/simple/Chapter21Test.java
@@ -40,9 +40,9 @@ public class Chapter21Test {
@Test public void testInfinite() {
String src = "struct S { int i; }; S !s = new S; while(1) s.i++;";
- testCPU(src,"x86_64_v2", "SystemV",0,"return Top;");
- testCPU(src,"riscv" , "SystemV",2,"return Top;");
- testCPU(src,"arm" , "SystemV",2,"return Top;");
+ testCPU(src,"x86_64_v2", "SystemV",0,"Stop[ ]");
+ testCPU(src,"riscv" , "SystemV",0,"Stop[ ]");
+ testCPU(src,"arm" , "SystemV",0,"Stop[ ]");
}
@Test
diff --git a/chapter22/src/test/java/com/seaofnodes/simple/Chapter22Test.java b/chapter22/src/test/java/com/seaofnodes/simple/Chapter22Test.java
index 6bec499e..1dc6db5b 100644
--- a/chapter22/src/test/java/com/seaofnodes/simple/Chapter22Test.java
+++ b/chapter22/src/test/java/com/seaofnodes/simple/Chapter22Test.java
@@ -28,7 +28,7 @@ public class Chapter22Test {
assertEquals(stop, code._stop.toString());
}
- @Test @Ignore
+ @Test
public void testCoRecur() {
String src = """
struct A { B? b; C? c; i64 ax; val az = x*2; };
@@ -48,6 +48,11 @@ return cc.cz;
assertEquals("25", Eval2.eval(code, 0));
}
+ @Test @Ignore
+ public void testNo() {
+ String src = "val foo = { int arg -> 3; };";
+ CodeGen code = new CodeGen(src).parse().opto().typeCheck();
+ }
@Test @Ignore
public void testHelloWorld() throws IOException {
diff --git a/chapter22/src/test/java/com/seaofnodes/simple/Eval2.java b/chapter22/src/test/java/com/seaofnodes/simple/Eval2.java
index ecea97dd..03221325 100644
--- a/chapter22/src/test/java/com/seaofnodes/simple/Eval2.java
+++ b/chapter22/src/test/java/com/seaofnodes/simple/Eval2.java
@@ -114,6 +114,7 @@ public abstract class Eval2 {
public static String eval( CodeGen code, long arg ) { return eval(code,arg,1000); }
public static String eval( CodeGen code, long arg, int timeout ) {
+ if( code._start.uctrl()==null ) return ""; // The empty program
SB trace = null; // new SB(); // TRACE, set to null for off, new SB() for on
// Force local scheduling phase
if( code._phase.ordinal() < CodeGen.Phase.TypeCheck .ordinal() ) code.typeCheck();