diff options
| author | Cliff Click <cliffc@acm.org> | 2025-04-29 21:52:24 -0700 |
|---|---|---|
| committer | Cliff Click <cliffc@acm.org> | 2025-04-29 21:52:24 -0700 |
| commit | d85354f39d267e1840edeebf1e6e81b90985d3a8 (patch) | |
| tree | 0f308aa6b333762d7aad5fa8a3ca0a5f809d5eeb /chapter22/src/main | |
| parent | 6eb2979c1ac89e04b583dc687efe2012aa65d9ba (diff) | |
| download | Simple-d85354f39d267e1840edeebf1e6e81b90985d3a8.tar.gz Simple-d85354f39d267e1840edeebf1e6e81b90985d3a8.zip | |
Drop a false start for adding clazz fields.
GLB does not widen primitives in memory.
Missing float-cmp-copy
Diffstat (limited to 'chapter22/src/main')
18 files changed, 107 insertions, 167 deletions
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/Parser.java b/chapter22/src/main/java/com/seaofnodes/simple/Parser.java index ebc7cdc5..bbf841c8 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/Parser.java @@ -81,11 +81,31 @@ public class Parser { ScopeNode _breakScope; // Merge all the while-breaks here FunNode _fun; // Current function being parsed - // Mapping from a primitive name to a Type. The string name matches + // Mapping from a type name to a Type. The string name matches // `type.str()` call. No TypeMemPtrs are in here, because Simple does not // have C-style '*ptr' references. - public static final HashMap<String, Type> PRIMS = - new HashMap<>() {{ + public static HashMap<String, Type> TYPES = defaultTypes(); + + // Mapping from a type name to the constructor for a Type. + public final HashMap<String, StructNode> INITS; + + + public Parser(CodeGen code, TypeInteger arg) { + _code = code; + _scope = new ScopeNode(); + _continueScope = _breakScope = null; + ZERO = con(TypeInteger.ZERO).keep(); + NIL = con(Type.NIL).keep(); + XCTRL= new XCtrlNode().peephole().keep(); + TYPES = defaultTypes(); + INITS = new HashMap<>(); + } + + @Override + public String toString() { return _lexer.toString(); } + + public static HashMap<String, Type> defaultTypes() { + return new HashMap<>() {{ put("bool",TypeInteger.U1 ); put("byte",TypeInteger.U8 ); put("f32" ,TypeFloat .F32); @@ -103,25 +123,8 @@ public class Parser { put("val" ,Type.TOP); // Marker type, indicates type inference put("var" ,Type.BOTTOM); // Marker type, indicates type inference }}; - - - // Mapping from a type name to the constructor for a Type. - public final HashMap<String, StructNode> INITS; - - - public Parser(CodeGen code, TypeInteger arg) { - _code = code; - _scope = new ScopeNode(); - _continueScope = _breakScope = null; - ZERO = con(TypeInteger.ZERO).keep(); - NIL = con(Type.NIL).keep(); - XCTRL= new XCtrlNode().peephole().keep(); - INITS = new HashMap<>(); } - @Override - public String toString() { return _lexer.toString(); } - // Debugging utility to find a Node by index public Node f(int nid) { return _code.f(nid); } @@ -217,7 +220,7 @@ public class Parser { // Pre-call the function from Start, with worse-case arguments. This // represents all the future, yet-to-be-parsed functions calls and // external calls. - _scope.push(ScopeNode.Kind.Function,null); + _scope.push(ScopeNode.Kind.Function); ctrl(fun); // Scope control from function // Private mem alias tracking per function MemMergeNode mem = new MemMergeNode(true); @@ -276,7 +279,7 @@ public class Parser { */ private Node parseBlock(ScopeNode.Kind kind) { // Enter a new scope - _scope.push(kind,null); + _scope.push(kind); Node last = ZERO; while (!peek('}') && !_lexer.isEOF()) last = parseStatement(); @@ -343,7 +346,7 @@ public class Parser { // } // } require("("); - _scope.push(ScopeNode.Kind.Block,null); // Scope for the index variables + _scope.push(ScopeNode.Kind.Block); // Scope for the index variables if( !match(";") ) // Can be empty init "for(;test;next) body" parseDeclarationStatement(); // Non-empty init Node rez = parseLooping(true); @@ -677,17 +680,9 @@ public class Parser { * exprAsgn = var '=' exprAsgn | expr */ private Node parseDeclarationStatement() { - int old = pos(); Type t = type(); if( t == null ) return require(parseAsgn(),";"); - // Ambiguous leading type then doing a type/class static field lookup. - // "T var" - declare a variable of type T - // "T.fld" - lookup field "fld" in type T - if( peek('.') ) { - pos(old); - return require(parseAsgn(),";"); - } // now parse var['=' asgnexpr] in a loop Node n = parseDeclaration(t); @@ -727,7 +722,7 @@ public class Parser { if( expr._type==Type.NIL ) throw error("a not-null/non-zero expression"); t = expr._type; - if( !xfinal ) t = t.glb(); // Widen if not final + if( !xfinal ) t = t.glb(false); // Widen if not final } // expr is a constant function if( t instanceof TypeFunPtr && expr._type instanceof TypeFunPtr tfp && tfp.isConstant() ) { @@ -739,7 +734,7 @@ public class Parser { // Need an expression to infer the type. // Also, if not-null then need an initializing expression. // Allowed in a class def, because type/init will happen in the constructor. - if( (inferType || (t instanceof TypeNil tn && !tn.nullable() )) && !_scope.inDeclarationQ() ) + if( (inferType || (t instanceof TypeNil tn && !tn.nullable() )) && !_scope.inConstructor() ) throw errorSyntax("=expression"); // Initial value for uninitialized struct fields. expr = switch( t ) { @@ -784,7 +779,7 @@ public class Parser { String typeName = requireId(); // A Block scope parse, and inspect the scope afterward for fields. - _scope.push(ScopeNode.Kind.DeclarationQ,typeName); + _scope.push(ScopeNode.Kind.Constructor); require("{"); while (!peek('}') && !_lexer.isEOF()) parseStatement().isKill(); @@ -792,43 +787,24 @@ public class Parser { // Grab the declarations and build fields and a Struct int lexlen = _scope._lexSize.last(); int varlen = _scope._vars._len; - StructNode inst = new StructNode(); - StructNode clz = new StructNode(); - Ary<Field> fs = new Ary<>(Field.class); // Struct fields - Ary<Field> cs = new Ary<>(Field.class); // Class fields + StructNode s = new StructNode(); + Ary<Field> fs = new Ary<>(Field.class); for( int i=lexlen; i<varlen; i++ ) { Var v = _scope.var(i); if( v.isFRef() ) continue; // Promote to outer scope, not defined here - var flds = v._final && v.type().isConstant() ? cs : fs; - var stru = v._final && v.type().isConstant() ? clz : inst; - // Declare field, gather field init - flds.push(Field.make(v._name,v.type(),_code.getALIAS(),v._final)); - stru.addDef(_scope.in(i)); + s.addDef(_scope.in(i)); // Keep the program code to generate instance + fs.push(Field.make(v._name,v.type(),_code.getALIAS(),v._final)); } - TypeStruct ts = inst._ts = TypeStruct.make(typeName, fs.asAry()); - //PRIMS.put(typeName, TypeMemPtr.make(ts)); - INITS.put(typeName,inst.peephole().keep()); + // Save instance default constructor + TypeStruct ts = s._ts = TypeStruct.make(typeName, fs.asAry()); + TYPES.put(typeName, TypeMemPtr.make(ts)); + INITS.put(typeName,s.peephole().keep()); - //String clzName = typeName + ".clz"; // Class name - //PRIMS.put(clzName, TypeMemPtr.make(TypeStruct.make(clzName, cs.asAry()))); // Done with struct/block scope require("}"); require(";"); _scope.pop(); - // Make a pointer to the class fields - - // ISSUE: LOOKUP EXPECTS TO FIND INSTANCE FIELDS FOR 'NEW' OR TYPE DECLS: - // Vector2D v = ...; - // Type for 'v' includes fields 'x,y'. - // Whereas: Vector2D.PI lookups up via the class struct. - // So e.g. add a hidden " decl" field that gets the instance fields. - cs.push(Field.make(" decl",TypeMemPtr.make(ts),-1,true)); - - TypeMemPtr tclz = TypeMemPtr.make(TypeStruct.make(typeName, cs.asAry())); - ConstantNode nclz = con(tclz); - // Define the constant clazz fields - _scope.define(typeName,tclz, true, nclz, true, loc()); - return nclz; + return ZERO; } @@ -847,15 +823,14 @@ public class Parser { String tname = _lexer.matchId(); if( tname==null ) return null; - // Convert the type name to a type, either user instance type or a primitive. - Type t0 = _scope.lookupInstance(tname); - if( t0 == null ) t0 = PRIMS.get(tname); + // Convert the type name to a type. + Type t0 = TYPES.get(tname); // No new types as keywords if( t0 == null && KEYWORDS.contains(tname) ) return posT(old1); if( t0 == Type.BOTTOM || t0 == Type.TOP ) return t0; // var/val type inference // Still no type found? Assume forward reference - Type t1 = t0 == null ? TypeMemPtr.make(TypeStruct.makeFRef(tname)) : t0; // Null: assume a forward ref type + Type t1 = t0 == null ? TypeMemPtr.make(TypeStruct.makeFRef(tname)) :t0; // Null: assume a forward ref type // Nest arrays and '?' as needed Type t2 = t1; while( true ) { @@ -881,7 +856,7 @@ public class Parser { return posT(old1); // Reset lexer to reparse pos(old2); // Reset lexer to reparse // Yes a forward ref, so declare it - _scope.define(tname, t1, true, XCTRL, true, null); + TYPES.put(tname,t1); // Return the (array, final) type return t2; } @@ -891,15 +866,14 @@ public class Parser { if( t instanceof TypeMemPtr tmp && tmp.notNull() ) throw error("Arrays of reference types must always be nullable"); String tname = "["+t.str()+"]"; - Type ta = PRIMS.get(tname); + Type ta = TYPES.get(tname); if( ta != null ) return (TypeMemPtr)ta; // Need make an array type. TypeStruct ts = TypeStruct.makeAry(TypeInteger.U32,_code.getALIAS(),t,_code.getALIAS()); assert ts.str().equals(tname); TypeMemPtr tary = TypeMemPtr.make(ts); - //PRIMS.put(tname,tary); - //return tary; - throw Utils.TODO(); + TYPES.put(tname,tary); + return tary; } // A function type is `{ type... -> type }` or `{ type }`. @@ -1217,7 +1191,7 @@ public class Parser { if( hasConstructor ) { idx = _scope.nIns(); // Push a scope, and pre-assign all struct fields. - _scope.push(ScopeNode.Kind.Block,null); + _scope.push(ScopeNode.Kind.Block); Lexer loc = loc(); for( int i=0; i<fs.length; i++ ) _scope.define(fs[i]._fname, fs[i]._type, fs[i]._final, s.in(i)._type==Type.TOP ? con(Type.BOTTOM) : s.in(i), loc); @@ -1318,22 +1292,15 @@ public class Parser { // Find the field from the Type. Lookup in the base object field names. TypeStruct base = ptr._obj; - if( base.isFRef() ) { - //ptr = _scope.lookupInstance(base._name); - //base = ptr._obj; - throw Utils.TODO(); - } + assert !base.isFRef(); int fidx = base.find(name); - if( fidx == -1 ) { // No such field! - throw error("Accessing unknown field '" + name + "' from '" + ptr.str() + "'"); - // TODO: ch22 allow class field lookups - } + if( fidx == -1 ) throw error("Accessing unknown field '" + name + "' from '" + ptr.str() + "'"); // Get field type and layout offset from base type and field index fidx Field f = base._fields[fidx]; // Field from field index Type tf = f._type; if( tf instanceof TypeMemPtr ftmp && ftmp.isFRef() ) - tf = ftmp.makeFrom(((TypeMemPtr)(PRIMS.get(ftmp._obj._name)))._obj); + tf = ftmp.makeFrom(((TypeMemPtr)(TYPES.get(ftmp._obj._name)))._obj); // Field offset; fixed for structs, computed for arrays Node off = (name.equals("[]") // If field is an array body @@ -1439,7 +1406,7 @@ public class Parser { if( expr._type == Type.NIL ) throw error("Calling a null function pointer"); if( !(expr instanceof FRefNode) && !expr._type.isa(TypeFunPtr.BOT) ) - throw error("Expected a function but got "+expr._type.glb().str()); + throw error("Expected a function but got "+expr._type.glb(false).str()); expr.keep(); // Keep while parsing args Ary<Node> args = new Ary<Node>(Node.class); diff --git a/chapter22/src/main/java/com/seaofnodes/simple/Var.java b/chapter22/src/main/java/com/seaofnodes/simple/Var.java index 154b99f4..cf549cd6 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/Var.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/Var.java @@ -15,31 +15,24 @@ public class Var { private Type _type; // Declared type public boolean _final; // Final field public boolean _fref; // Forward ref - public final boolean _clz; // Is a Simple clazz public Parser.Lexer _loc; // Source location public Var(int idx, String name, Type type, boolean xfinal, Parser.Lexer loc ) { - this(idx,name,type,xfinal,loc,false,false); + this(idx,name,type,xfinal,loc,false); } - public Var(int idx, String name, Type type, boolean xfinal, Parser.Lexer loc, boolean clz, boolean fref) { + public Var(int idx, String name, Type type, boolean xfinal, Parser.Lexer loc, boolean fref) { _idx = idx; _name = name; _type = type; _final = xfinal; _fref = fref; - _clz = clz; _loc = loc; } public Type type() { if( !_type.isFRef() ) return _type; // Update self to no longer use the forward ref type - //Type def = Parser.TYPES.get(((TypeMemPtr)_type)._obj._name); - //return (_type=_type.meet(def)); - throw Utils.TODO(); - } - public Type lazyGLB() { - Type t = type(); - return t instanceof TypeMemPtr ? t : t.glb(); + Type def = Parser.TYPES.get(((TypeMemPtr)_type)._obj._name); + return (_type=_type.meet(def)); } // Forward reference variables (not types) must be BOTTOM and @@ -55,6 +48,6 @@ public class Var { } @Override public String toString() { - return _type.toString()+(_final ? " ": " !")+(_clz?"@":"")+_name; + return _type.toString()+(_final ? " ": " !")+_name; } } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/BoolNode.java b/chapter22/src/main/java/com/seaofnodes/simple/node/BoolNode.java index fd6448a2..301e1517 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/BoolNode.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/BoolNode.java @@ -130,9 +130,24 @@ abstract public class BoolNode extends Node { Node copyF() { return new LEF(null,null); } } - public static class EQF extends EQ { public EQF(Node lhs, Node rhs) { super(lhs,rhs); } boolean doOp(double lhs, double rhs) { return lhs == rhs; } public boolean isFloat() { return true; } } - public static class LTF extends LT { public LTF(Node lhs, Node rhs) { super(lhs,rhs); } boolean doOp(double lhs, double rhs) { return lhs < rhs; } public boolean isFloat() { return true; } } - public static class LEF extends LE { public LEF(Node lhs, Node rhs) { super(lhs,rhs); } boolean doOp(double lhs, double rhs) { return lhs <= rhs; } public boolean isFloat() { return true; } } + public static class EQF extends EQ { + public EQF(Node lhs, Node rhs) { super(lhs,rhs); } + @Override boolean doOp(double lhs, double rhs) { return lhs == rhs; } + @Override public boolean isFloat() { return true; } + @Override Node copy(Node lhs, Node rhs) { return new EQF(lhs,rhs); } + } + public static class LTF extends LT { + public LTF(Node lhs, Node rhs) { super(lhs,rhs); } + @Override boolean doOp(double lhs, double rhs) { return lhs < rhs; } + @Override public boolean isFloat() { return true; } + @Override Node copy(Node lhs, Node rhs) { return new LTF(lhs,rhs); } + } + public static class LEF extends LE { + public LEF(Node lhs, Node rhs) { super(lhs,rhs); } + @Override boolean doOp(double lhs, double rhs) { return lhs <= rhs; } + @Override public boolean isFloat() { return true; } + @Override Node copy(Node lhs, Node rhs) { return new LEF(lhs,rhs); } + } // Unsigned less that, for range checks. Not directly user writable. public static class ULT extends BoolNode { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java b/chapter22/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java index 32c25a8b..5b923bf0 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java @@ -122,7 +122,7 @@ public class MemMergeNode extends Node { // by alias as it will trigger a phi creation Node lhs = this._mem(i,null); Node rhs = that._mem(i,null); - alias(i, new PhiNode(Parser.memName(i), lhs._type.glb().meet(rhs._type.glb()), r, lhs, rhs).peephole()); + alias(i, new PhiNode(Parser.memName(i), lhs._type.glb(true).meet(rhs._type.glb(true)), r, lhs, rhs).peephole()); } } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/MulNode.java b/chapter22/src/main/java/com/seaofnodes/simple/node/MulNode.java index 384dbace..c1a5a524 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/MulNode.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/MulNode.java @@ -80,8 +80,8 @@ public class MulNode extends Node { @Override Node copyF() { return new MulFNode(null,null); } @Override public Parser.ParseException err() { if( in(1)._type.isHigh() || in(2)._type.isHigh() ) return null; - if( !(in(1)._type instanceof TypeInteger) ) return Parser.error("Cannot '"+label()+"' " + in(1)._type.glb(),null); - if( !(in(2)._type instanceof TypeInteger) ) return Parser.error("Cannot '"+label()+"' " + in(2)._type.glb(),null); + if( !(in(1)._type instanceof TypeInteger) ) return Parser.error("Cannot '"+label()+"' " + in(1)._type.glb(false),null); + if( !(in(2)._type instanceof TypeInteger) ) return Parser.error("Cannot '"+label()+"' " + in(2)._type.glb(false),null); return null; } } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/PhiNode.java b/chapter22/src/main/java/com/seaofnodes/simple/node/PhiNode.java index e6f9cae7..79251839 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/PhiNode.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/PhiNode.java @@ -54,7 +54,7 @@ public class PhiNode extends Node { // During parsing Phis have to be computed type pessimistically. if( r.inProgress() ) return _declaredType; // Set type to local top of the starting type - Type t = _declaredType.glb().dual();//Type.TOP; + Type t = _declaredType.glb(false).dual();//Type.TOP; for (int i = 1; i < nIns(); i++) // If the region's control input is live, add this as a dependency // to the control because we can be peeped should it become dead. @@ -148,7 +148,7 @@ public class PhiNode extends Node { if( in(i).in(j) != x ) { needsPhi=true; break; } if( needsPhi ) { - x = new PhiNode(_label,op.in(j)._type.glb()); + x = new PhiNode(_label,op.in(j)._type.glb(false)); x.addDef(region()); for( int i=1; i<nIns(); i++ ) x.addDef(in(i).in(j)); diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/ScopeNode.java b/chapter22/src/main/java/com/seaofnodes/simple/node/ScopeNode.java index eda29915..3127e491 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/ScopeNode.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/ScopeNode.java @@ -28,12 +28,9 @@ public class ScopeNode extends MemMergeNode { // Lexical scope is typed: // - Block scope - basic block scoping // - Constructor - struct type is defined, and here we give values to all fields - // - Declaration - struct is declared, final constant fields defined // - Function - out-of-scope lookups restricted to final constants - public enum Kind { Block, Constructor, DeclarationQ, Function }; + public enum Kind { Block, Constructor, Function }; public final Ary<Kind> _kinds; - // Each Constructor scope is named, allowing for nested Type names - public final Ary<String> _tnamesQ; // Extra guards; tested predicates and casted results private final Ary<Node> _guards; @@ -44,7 +41,6 @@ public class ScopeNode extends MemMergeNode { _vars = new Ary<>(Var .class); _lexSize= new Ary<>(Integer.class); _kinds = new Ary<>(Kind .class); - _tnamesQ = new Ary<>(String .class); _guards = new Ary<>(Node .class); } @@ -93,21 +89,18 @@ public class ScopeNode extends MemMergeNode { public <N extends Node> N ctrl(N n) { return setDef(0,n); } public Node mem(Node n) { return setDef(1,n); } - public void push(Kind kind, String tnameQ) { - assert _lexSize._len==_kinds._len && _lexSize._len==_tnamesQ._len; - assert !(kind==Kind.DeclarationQ && tnameQ==null); + public void push( Kind kind ) { + assert _lexSize._len==_kinds._len; _lexSize.push(_vars.size()); _kinds .push(kind); - _tnamesQ .push(tnameQ); } // Pop a lexical scope public void pop() { - assert _lexSize._len==_kinds._len && _lexSize._len==_tnamesQ._len; + assert _lexSize._len==_kinds._len; promote(); // Promote forward references to the next outer scope int n = _lexSize.pop(); _kinds.pop(); - _tnamesQ.pop(); popUntil(n); // Pop off inputs going out of scope _vars.setLen(n); // Pop off variables going out of scope } @@ -132,14 +125,6 @@ public class ScopeNode extends MemMergeNode { public boolean inConstructor() { return _kinds.last() == Kind.Constructor; } - public boolean inDeclarationQ() { return _kinds.last() == Kind.DeclarationQ; } - // Nearest enclosing declaration scope name - public String declNameQ() { - for( int i=_lexSize._len-1; i>=0; i-- ) - if( _kinds.at(i)==Kind.DeclarationQ ) - return _tnamesQ.at(i); - return null; - } // Is v outside any current function scope? public boolean outOfFunction( Var v ) { @@ -153,9 +138,9 @@ public class ScopeNode extends MemMergeNode { // Find name in reverse, return an index into _vars or -1. Linear scan // instead of hashtable, but probably doesn't matter until the scan // typically hits many dozens of variables. - public int find( String name, boolean clz ) { + public int find( String name ) { for( int i=_vars.size()-1; i>=0; i-- ) - if( var(i)._name.equals(name) && var(i)._clz==clz ) + if( var(i)._name.equals(name) ) return i; return -1; } @@ -164,9 +149,6 @@ public class ScopeNode extends MemMergeNode { * Create a new variable name in the current scope */ public boolean define( String name, Type declaredType, boolean xfinal, Node init, Parser.Lexer loc ) { - return define(name,declaredType,xfinal,init,false,loc); - } - public boolean define( String name, Type declaredType, boolean xfinal, Node init, boolean clz, Parser.Lexer loc ) { assert _lexSize.isEmpty() || name.charAt(0)!='$' ; // Later scopes do not define memory if( _lexSize._len > 0 ) for( int i=_vars.size()-1; i>=_lexSize.last(); i-- ) { @@ -179,7 +161,7 @@ public class ScopeNode extends MemMergeNode { setDef(n._idx,fref.addDef(init)); // Set FRef to defined; tell parser also } } - Var v = new Var(nIns(),name,declaredType,xfinal,loc,clz,init==Parser.XCTRL); + Var v = new Var(nIns(),name,declaredType,xfinal,loc,init==Parser.XCTRL); _vars.add(v); // Creating a forward reference if( init==Parser.XCTRL ) @@ -201,35 +183,19 @@ public class ScopeNode extends MemMergeNode { * @return null if not found, or the implementing Node */ public Var lookup( String name ) { - int idx = find(name,false); + int idx = find(name); // -1 is missed in all scopes, not found return idx == -1 ? null : update(var(idx),null); } /** - * Lookup a type name and return the instance TypeMemPtr - * - * @param name of Type - * @return null if not found, or *instance* TypeMemPtr - */ - public TypeMemPtr lookupInstance( String name ) { - int idx = find(name,true); - // -1 is missed in all scopes, not found - if( idx == -1 ) return null; - // Class types are always TMPs - TypeMemPtr clz = (TypeMemPtr)var(idx).type(); - // Instance types are always TMPs - return (TypeMemPtr)(clz._obj.field(" decl")._type); - } - - /** * Redefine an existing name * * @param name Name being redefined * @param n The node to bind to the name */ public void update( String name, Node n ) { - int idx = find(name,false); + int idx = find(name); assert idx>=0; update(var(idx),n); } @@ -245,7 +211,7 @@ public class ScopeNode extends MemMergeNode { // Set real Phi in the loop head // The phi takes its one input (no backedge yet) from a recursive // lookup, which might have insert a Phi in every loop nest. - : loop.setDef(v._idx,new PhiNode(v._name, v.lazyGLB(), loop.ctrl(), loop.in(loop.update(v,null)._idx),null).peephole()); + : loop.setDef(v._idx,new PhiNode(v._name, v.type(), loop.ctrl(), loop.in(loop.update(v,null)._idx),null).peephole()); setDef(v._idx,old); } assert !v._final || st==null; @@ -276,7 +242,6 @@ public class ScopeNode extends MemMergeNode { dup._vars .addAll(_vars ); dup._lexSize.addAll(_lexSize); dup._kinds .addAll(_kinds ); - dup._tnamesQ .addAll(_tnamesQ ); dup._guards .addAll(_guards ); // The dup'd guards all need dup'd keepers, to keep proper accounting // when later removing all guards diff --git a/chapter22/src/main/java/com/seaofnodes/simple/type/Field.java b/chapter22/src/main/java/com/seaofnodes/simple/type/Field.java index ffa9d2a6..bd67735a 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/type/Field.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/type/Field.java @@ -51,8 +51,8 @@ public class Field extends Type { @Override public Field dual() { return make(_fname,_type.dual(),_alias,!_final); } - @Override public Field glb() { - Type glb = _type.glb(); + @Override public Field glb(boolean mem) { + Type glb = _type.glb(mem); return (glb==_type && _final) ? this : make(_fname,glb,_alias,true); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/type/Type.java b/chapter22/src/main/java/com/seaofnodes/simple/type/Type.java index 6df4e7ab..38414dcf 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/type/Type.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/type/Type.java @@ -200,8 +200,9 @@ public class Type { // Make a zero version of this type, 0 for integers and null for pointers. public Type makeZero() { return Type.NIL; } - /** Compute greatest lower bound in the lattice */ - public Type glb() { return Type.BOTTOM; } + /** Compute greatest lower bound in the lattice. If values are in memory, + * ints and floats cannot widen. */ + public Type glb(boolean mem) { return Type.BOTTOM; } // Is forward-reference public boolean isFRef() { return false; } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeFloat.java b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeFloat.java index aa205149..a0940f8b 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeFloat.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeFloat.java @@ -81,7 +81,7 @@ public class TypeFloat extends Type { } @Override public Type makeZero() { return FZERO; } - @Override public Type glb() { return F64; } + @Override public Type glb(boolean mem) { return mem ? (isHigh() ? dual() : this) : F64; } @Override int hash() { return (int)(Double.hashCode(_con) ^ _sz ^ (1<<17)); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java index bd64bd81..abfcf1e3 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java @@ -59,7 +59,7 @@ public class TypeFunPtr extends TypeNil { // RHS is NIL; do not deep-dual when crossing the centerline @Override public Type meet0() { return _nil==3 ? this : make((byte)3,_sig,_ret,_fidxs); } - @Override public TypeFunPtr glb() { return make((byte)3,_sig,_ret,-1L); } + @Override public TypeFunPtr glb(boolean mem) { return make((byte)3,_sig,_ret,-1L); } @Override public boolean isHigh () { return _nil <= 1 || (_nil==2 && _fidxs==0); } @Override public boolean isConstant() { return (_nil==2 && Long.bitCount(_fidxs)==1) || (_nil==3 && _fidxs==0); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeInteger.java b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeInteger.java index cccb85a5..9f017fd1 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeInteger.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeInteger.java @@ -119,7 +119,7 @@ public class TypeInteger extends Type { return this; } @Override public Type makeZero() { return ZERO; } - @Override public TypeInteger glb() { return BOT; } + @Override public Type glb(boolean mem) { return mem ? (isHigh() ? dual() : this) : BOT; } @Override int hash() { return Utils.fold(_min) * Utils.fold(_max); } @Override public boolean eq( Type t ) { TypeInteger i = (TypeInteger)t; // Contract diff --git a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeMem.java b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeMem.java index 9ed4c7a8..9be4908b 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeMem.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeMem.java @@ -50,7 +50,7 @@ public class TypeMem extends Type { } @Override public boolean isHigh() { return _t.isHigh(); } - @Override public Type glb() { return make(_alias,_t.glb()); } + @Override public Type glb(boolean mem) { return make(_alias,_t.glb(true)); } @Override int hash() { return 9876543 + _alias + _t.hashCode(); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java index 284bf581..67ed65a9 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java @@ -73,7 +73,7 @@ public class TypeMemPtr extends TypeNil { throw Utils.TODO(); // return _obj.shallowISA(that._obj); } - @Override public TypeMemPtr glb() { return make((byte)3,_obj.glb()); } + @Override public TypeMemPtr glb(boolean mem) { return make((byte)3,_obj.glb(true)); } // Is forward-reference @Override public boolean isFRef() { return _obj.isFRef(); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeNil.java b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeNil.java index aee623ba..3902c40b 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeNil.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeNil.java @@ -48,7 +48,7 @@ public abstract class TypeNil extends Type { @Override public boolean isConstant () { return false; } @Override public boolean isHighOrConst() { return isHigh() || isConstant(); } - @Override public Type glb() { return Type.NIL; } + @Override public Type glb(boolean mem) { return Type.NIL; } public boolean notNull() { return _nil==1 || _nil==2; } public boolean nullable() { return _nil==3; } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/type/TypePtr.java b/chapter22/src/main/java/com/seaofnodes/simple/type/TypePtr.java index e9091c25..d9de5cd7 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/type/TypePtr.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/type/TypePtr.java @@ -45,7 +45,7 @@ public class TypePtr extends TypeNil { // 0->xscalar, 1->nscalar, 2->nscalar, 3->scalar @Override Type meetX() { return _nil==0 ? XNIL : (_nil==3 ? PTR : NPTR); } - @Override public TypePtr glb() { return PTR; } + @Override public TypePtr glb(boolean mem) { return PTR; } private static final String[] STRS = new String[]{"~ptr","~nptr","nptr","ptr"}; @Override public String str() { return STRS[_nil]; } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeStruct.java b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeStruct.java index e981b5dc..13105d20 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeStruct.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeStruct.java @@ -129,18 +129,18 @@ public class TypeStruct extends Type { } // Keeps the same struct, but lower-bounds all fields. - @Override public TypeStruct glb() { - if( _glb() ) return this; + @Override public TypeStruct glb(boolean mem) { + if( _glb(mem) ) return this; // Need to glb each field Field[] flds = new Field[_fields.length]; for( int i=0; i<_fields.length; i++ ) - flds[i] = _fields[i].glb(); + flds[i] = _fields[i].glb(mem); return make(_name,flds); } - private boolean _glb() { + private boolean _glb(boolean mem) { if( _fields!=null ) for( Field f : _fields ) - if( f.glb() != f ) + if( f.glb(mem) != f ) return false; return true; } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeTuple.java b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeTuple.java index d3b19b52..c9f88efa 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeTuple.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeTuple.java @@ -48,11 +48,10 @@ public class TypeTuple extends Type { return make(ts); } - @Override - public Type glb() { + @Override public Type glb(boolean mem) { Type[] ts = new Type[_types.length]; for( int i=0; i<_types.length; i++ ) - ts[i] = _types[i].glb(); + ts[i] = _types[i].glb(mem); return make(ts); } |
