From d32f97238c903765dec4e9a9f3cbfa5fd12cded6 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Mon, 10 Aug 2026 11:11:18 -0700 Subject: Chapter 25: Modules, Separate Compilation, and SSA Construction Co-authored-by: Hsiang-Ying Fu <66062782+fuhsnn@users.noreply.github.com> Co-authored-by: fuhsnn <66062782+fuhsnn@users.noreply.github.com> Co-authored-by: Symious <14933944+symious@users.noreply.github.com> Co-authored-by: Jun Kawasaki Co-authored-by: Claude Opus 5 --- .../java/com/seaofnodes/simple/node/StartNode.java | 58 ++++++++++++++++++---- 1 file changed, 48 insertions(+), 10 deletions(-) (limited to 'src/main/java/com/seaofnodes/simple/node/StartNode.java') diff --git a/src/main/java/com/seaofnodes/simple/node/StartNode.java b/src/main/java/com/seaofnodes/simple/node/StartNode.java index e13d35c0..84c8a3a7 100644 --- a/src/main/java/com/seaofnodes/simple/node/StartNode.java +++ b/src/main/java/com/seaofnodes/simple/node/StartNode.java @@ -5,39 +5,76 @@ import com.seaofnodes.print.ExprPrinter; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.Parser; import com.seaofnodes.simple.type.*; +import com.seaofnodes.simple.util.Utils; +import java.util.Arrays; import java.util.HashSet; -import static com.seaofnodes.simple.util.Utils.TODO; -/** Start supplies control, whole memory, and the argument, in that order. */ +/** + * The Start node represents the external world calling, be it calling the + * entry or just some linked caller calling. + *

+ * Start initially has 1 input (arg) from outside and the initial control. + * In ch10 we also add mem aliases as structs get defined; each field in struct + * adds a distinct alias to Start's tuple. + *

+ * By ch25, Start is the external world (or linker) calling with everything + * that has escaped. Start is NOT the entry itself, which can assume + * no memory nor fidxs exist nor escaped. Start gets escaped things from Stop; + * together these close the Grand Cycle between the code we know and the code + * we don't. + */ public class StartNode extends LoopNode implements MultiNode { final Type _arg; - public StartNode(Type arg) { super(null,null); _arg = arg; _type = compute(); } + public StartNode(StartNode start, StopNode stop, Type arg) { super(null,start,stop); _arg = arg; } public StartNode(StartNode start) { super(start); _arg = start==null ? null : start._arg; } - - @Override public String label() { return "Start"; } + @Override public Tag serialTag() { return Tag.Start; } + public Type arg() { return _arg; } @Override protected ExprPrinter _print1(ExprPrinter p) { return p.p(label()); } - @Override public CFGNode cfg0() { return null; } + @Override public CFGNode cfg0() { return null; } // Get the one control following; error to call with more than one e.g. an - // IfNode or other multi-way branch. For Start, its "main" + // IfNode or other multi-way branch. For Start, it's the class init for + // this compilation unit. @Override public CFGNode uctrl() { - // Find "main", it's the start. + // Find module., it's the start. CFGNode C = null; for( Node use : _outputs ) - if( use instanceof FunNode fun && fun.sig().isa(CodeGen.CODE._main) ) + if( use instanceof FunNode fun && fun.isModInit() ) { assert C==null; C = fun; } + if( C==null ) + for( FunNode fun : CodeGen.CODE._linker ) + if( fun!=null && !fun.isDead() && fun.isModInit() ) + { assert C==null; C = fun; } return C; } + boolean escapedFIDX(int fidx) { + // Public class fields are callable by the unknown external world + // regardless of the current SCCP approximation of Start memory. + if( CodeGen.CODE.publicFIDX(fidx) ) return true; + if( !(_type instanceof TypeTuple tt) ) + return !_type.isHigh(); // TOP never escapes, BOTTOM always escapes + TypeMem tmem = (TypeMem)tt._types[1]; + if( tmem == TypeMem.BOT ) return false; + if( tmem == TypeMem.TOP ) return false; + if( XInt.isHigh(tmem._escFs) ) + return false; + return XInt.bit(tmem._escFs,fidx); + } @Override public TypeTuple compute() { - return TypeTuple.make(Type.CONTROL,TypeMem.BOT,_arg); + StopNode stop = (StopNode)in(1); + TypeMem tmem = stop._type instanceof TypeTuple tt + ? tt.mem() + : stop._type.isHigh() ? TypeMem.START : TypeMem.BOT; + assert tmem._alias==1 && !tmem._one; + return TypeTuple.make(Type.CONTROL,tmem,_arg); } @Override public Node idealize() { return null; } @@ -46,4 +83,5 @@ public class StartNode extends LoopNode implements MultiNode { @Override public int idepth() { return 0; } @Override public CFGNode idom(Node dep) { return null; } + @Override public boolean eq( Node n ) { return true; } } -- cgit v1.2.3