diff options
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(); |
