From 664761624f4b0e3d6d1593b99e576854beec5949 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Tue, 6 May 2025 13:44:10 -0700 Subject: Chapter 23: Methods and Revisiting Types --- .../java/com/seaofnodes/simple/node/AddNode.java | 9 +- .../java/com/seaofnodes/simple/node/ArithNode.java | 9 +- .../java/com/seaofnodes/simple/node/BoolNode.java | 4 +- .../java/com/seaofnodes/simple/node/CFGNode.java | 7 +- .../java/com/seaofnodes/simple/node/CProjNode.java | 2 +- .../com/seaofnodes/simple/node/CallEndMach.java | 2 +- .../com/seaofnodes/simple/node/CallEndNode.java | 5 +- .../java/com/seaofnodes/simple/node/CallNode.java | 10 +- .../java/com/seaofnodes/simple/node/CastMach.java | 2 +- .../java/com/seaofnodes/simple/node/CastNode.java | 15 ++- .../com/seaofnodes/simple/node/ConFldOffNode.java | 43 ++++++++ .../com/seaofnodes/simple/node/ConstantNode.java | 38 ++----- .../com/seaofnodes/simple/node/ExternNode.java | 6 +- .../java/com/seaofnodes/simple/node/FunNode.java | 9 +- .../java/com/seaofnodes/simple/node/IfNode.java | 6 +- .../java/com/seaofnodes/simple/node/LoadNode.java | 41 +++++--- .../java/com/seaofnodes/simple/node/LoopNode.java | 24 +++-- .../seaofnodes/simple/node/MachConcreteNode.java | 2 +- .../java/com/seaofnodes/simple/node/MachNode.java | 2 + .../com/seaofnodes/simple/node/MemMergeNode.java | 9 +- .../java/com/seaofnodes/simple/node/MemOpNode.java | 2 +- .../java/com/seaofnodes/simple/node/MinusNode.java | 3 +- .../java/com/seaofnodes/simple/node/MultiNode.java | 2 +- .../java/com/seaofnodes/simple/node/NewNode.java | 34 +++++-- src/main/java/com/seaofnodes/simple/node/Node.java | 7 +- .../java/com/seaofnodes/simple/node/NotNode.java | 4 +- .../java/com/seaofnodes/simple/node/ParmNode.java | 11 +- .../java/com/seaofnodes/simple/node/PhiNode.java | 77 +++++++++++--- .../com/seaofnodes/simple/node/ReadOnlyMach.java | 2 +- .../com/seaofnodes/simple/node/RegionNode.java | 2 +- .../com/seaofnodes/simple/node/ReturnNode.java | 15 ++- .../java/com/seaofnodes/simple/node/ScopeNode.java | 111 ++++++++++++++------- .../java/com/seaofnodes/simple/node/SplitNode.java | 2 +- .../java/com/seaofnodes/simple/node/StartNode.java | 11 +- .../java/com/seaofnodes/simple/node/StopNode.java | 2 +- .../java/com/seaofnodes/simple/node/StoreNode.java | 15 ++- .../com/seaofnodes/simple/node/StructNode.java | 9 +- .../seaofnodes/simple/node/cpus/arm/AddARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/AddFARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/AddIARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/AndARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/AndIARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/AsrARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/AsrIARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/BranchARM.java | 3 +- .../seaofnodes/simple/node/cpus/arm/CallARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/CallRRARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/CmpARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/CmpFARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/CmpIARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/DivARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/DivFARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/FloatARM.java | 4 +- .../seaofnodes/simple/node/cpus/arm/FunARM.java | 4 +- .../seaofnodes/simple/node/cpus/arm/I2F8ARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/IntARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/LoadARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/LslARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/LslIARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/LsrARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/LsrIARM.java | 3 +- .../seaofnodes/simple/node/cpus/arm/MemOpARM.java | 5 +- .../seaofnodes/simple/node/cpus/arm/MulARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/MulFARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/NegARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/NewARM.java | 3 +- .../seaofnodes/simple/node/cpus/arm/NotARM.java | 3 +- .../com/seaofnodes/simple/node/cpus/arm/OrARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/OrIARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/SetARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/SplitARM.java | 5 +- .../seaofnodes/simple/node/cpus/arm/StoreARM.java | 4 +- .../seaofnodes/simple/node/cpus/arm/SubARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/SubFARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/SubIARM.java | 5 +- .../seaofnodes/simple/node/cpus/arm/TFPARM.java | 3 +- .../seaofnodes/simple/node/cpus/arm/TMPARM.java | 3 +- .../seaofnodes/simple/node/cpus/arm/UJmpARM.java | 3 +- .../seaofnodes/simple/node/cpus/arm/XorARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/XorIARM.java | 7 +- .../com/seaofnodes/simple/node/cpus/arm/arm.java | 2 +- .../seaofnodes/simple/node/cpus/riscv/AUIPC.java | 3 +- .../simple/node/cpus/riscv/AddFRISC.java | 2 +- .../simple/node/cpus/riscv/AddIRISC.java | 2 +- .../seaofnodes/simple/node/cpus/riscv/AddRISC.java | 2 +- .../simple/node/cpus/riscv/AndIRISC.java | 2 +- .../seaofnodes/simple/node/cpus/riscv/AndRISC.java | 2 +- .../simple/node/cpus/riscv/BranchRISC.java | 3 +- .../simple/node/cpus/riscv/CallRISC.java | 3 +- .../simple/node/cpus/riscv/CallRRISC.java | 2 +- .../simple/node/cpus/riscv/DivFRISC.java | 2 +- .../seaofnodes/simple/node/cpus/riscv/DivRISC.java | 2 +- .../seaofnodes/simple/node/cpus/riscv/FltRISC.java | 4 +- .../seaofnodes/simple/node/cpus/riscv/FunRISC.java | 4 +- .../simple/node/cpus/riscv/I2F8RISC.java | 2 +- .../seaofnodes/simple/node/cpus/riscv/ImmRISC.java | 2 +- .../simple/node/cpus/riscv/Int8RISC.java | 5 +- .../seaofnodes/simple/node/cpus/riscv/IntRISC.java | 2 +- .../com/seaofnodes/simple/node/cpus/riscv/LUI.java | 2 +- .../simple/node/cpus/riscv/LoadRISC.java | 2 +- .../simple/node/cpus/riscv/MemOpRISC.java | 4 +- .../simple/node/cpus/riscv/MulFRISC.java | 2 +- .../seaofnodes/simple/node/cpus/riscv/MulRISC.java | 2 +- .../seaofnodes/simple/node/cpus/riscv/NegRISC.java | 2 +- .../seaofnodes/simple/node/cpus/riscv/NewRISC.java | 3 +- .../seaofnodes/simple/node/cpus/riscv/NotRISC.java | 2 +- .../seaofnodes/simple/node/cpus/riscv/OrIRISC.java | 2 +- .../seaofnodes/simple/node/cpus/riscv/OrRISC.java | 2 +- .../seaofnodes/simple/node/cpus/riscv/RetRISC.java | 4 +- .../simple/node/cpus/riscv/SetFRISC.java | 2 +- .../simple/node/cpus/riscv/SetIRISC.java | 2 +- .../seaofnodes/simple/node/cpus/riscv/SetRISC.java | 2 +- .../simple/node/cpus/riscv/SllIRISC.java | 2 +- .../seaofnodes/simple/node/cpus/riscv/SllRISC.java | 2 +- .../simple/node/cpus/riscv/SplitRISC.java | 4 +- .../simple/node/cpus/riscv/SraIRISC.java | 2 +- .../seaofnodes/simple/node/cpus/riscv/SraRISC.java | 2 +- .../simple/node/cpus/riscv/SrlIRISC.java | 2 +- .../seaofnodes/simple/node/cpus/riscv/SrlRISC.java | 2 +- .../simple/node/cpus/riscv/StoreRISC.java | 4 +- .../simple/node/cpus/riscv/SubFRISC.java | 2 +- .../seaofnodes/simple/node/cpus/riscv/SubRISC.java | 2 +- .../seaofnodes/simple/node/cpus/riscv/TFPRISC.java | 3 +- .../seaofnodes/simple/node/cpus/riscv/TMPRISC.java | 2 +- .../simple/node/cpus/riscv/UJmpRISC.java | 3 +- .../simple/node/cpus/riscv/XorIRISC.java | 2 +- .../seaofnodes/simple/node/cpus/riscv/XorRISC.java | 2 +- .../seaofnodes/simple/node/cpus/riscv/riscv.java | 2 +- .../simple/node/cpus/x86_64_v2/AddFMemX86.java | 4 +- .../simple/node/cpus/x86_64_v2/AddFX86.java | 2 +- .../simple/node/cpus/x86_64_v2/AddIX86.java | 4 +- .../simple/node/cpus/x86_64_v2/AddMemX86.java | 2 +- .../simple/node/cpus/x86_64_v2/CallRX86.java | 2 +- .../simple/node/cpus/x86_64_v2/CallX86.java | 2 +- .../simple/node/cpus/x86_64_v2/CmpFX86.java | 2 +- .../simple/node/cpus/x86_64_v2/CmpIX86.java | 2 +- .../simple/node/cpus/x86_64_v2/CmpMemX86.java | 2 +- .../simple/node/cpus/x86_64_v2/CmpX86.java | 2 +- .../simple/node/cpus/x86_64_v2/DivFX86.java | 2 +- .../simple/node/cpus/x86_64_v2/DivX86.java | 2 +- .../simple/node/cpus/x86_64_v2/FltX86.java | 2 +- .../simple/node/cpus/x86_64_v2/FunX86.java | 2 +- .../simple/node/cpus/x86_64_v2/I2f8X86.java | 2 +- .../simple/node/cpus/x86_64_v2/ImmX86.java | 2 +- .../simple/node/cpus/x86_64_v2/IntX86.java | 2 +- .../simple/node/cpus/x86_64_v2/JmpX86.java | 3 +- .../simple/node/cpus/x86_64_v2/LeaX86.java | 2 +- .../simple/node/cpus/x86_64_v2/LoadX86.java | 9 +- .../simple/node/cpus/x86_64_v2/MemAddX86.java | 2 +- .../simple/node/cpus/x86_64_v2/MemOpX86.java | 4 +- .../simple/node/cpus/x86_64_v2/MulFX86.java | 2 +- .../simple/node/cpus/x86_64_v2/MulIX86.java | 4 +- .../simple/node/cpus/x86_64_v2/MulX86.java | 2 +- .../simple/node/cpus/x86_64_v2/NegX86.java | 3 +- .../simple/node/cpus/x86_64_v2/NewX86.java | 2 +- .../simple/node/cpus/x86_64_v2/NotX86.java | 2 +- .../simple/node/cpus/x86_64_v2/RegX86.java | 2 +- .../simple/node/cpus/x86_64_v2/SarIX86.java | 5 +- .../simple/node/cpus/x86_64_v2/SarX86.java | 2 +- .../simple/node/cpus/x86_64_v2/SetX86.java | 3 +- .../simple/node/cpus/x86_64_v2/ShlIX86.java | 5 +- .../simple/node/cpus/x86_64_v2/ShlX86.java | 2 +- .../simple/node/cpus/x86_64_v2/ShrIX86.java | 5 +- .../simple/node/cpus/x86_64_v2/ShrX86.java | 2 +- .../simple/node/cpus/x86_64_v2/SplitX86.java | 4 +- .../simple/node/cpus/x86_64_v2/StoreX86.java | 2 +- .../simple/node/cpus/x86_64_v2/SubFX86.java | 2 +- .../simple/node/cpus/x86_64_v2/TFPX86.java | 2 +- .../simple/node/cpus/x86_64_v2/TMPX86.java | 8 +- .../simple/node/cpus/x86_64_v2/UJmpX86.java | 3 +- .../simple/node/cpus/x86_64_v2/x86_64_v2.java | 5 +- 171 files changed, 533 insertions(+), 376 deletions(-) create mode 100644 src/main/java/com/seaofnodes/simple/node/ConFldOffNode.java (limited to 'src/main/java/com/seaofnodes/simple/node') diff --git a/src/main/java/com/seaofnodes/simple/node/AddNode.java b/src/main/java/com/seaofnodes/simple/node/AddNode.java index 0f472829..f1615f70 100644 --- a/src/main/java/com/seaofnodes/simple/node/AddNode.java +++ b/src/main/java/com/seaofnodes/simple/node/AddNode.java @@ -1,10 +1,7 @@ package com.seaofnodes.simple.node; -import com.seaofnodes.simple.Parser; import com.seaofnodes.simple.type.*; -import java.util.BitSet; - import static com.seaofnodes.simple.Parser.con; public class AddNode extends ArithNode { @@ -129,7 +126,7 @@ public class AddNode extends ArithNode { for( int i=1; i= 2 && !lhs.inProgress() && - lhs.region()==rhs.region() ) { + lhs.region()==rhs.region() && + lhs.nIns()>2 && // A 1-input Phi will collapse already + // Disallow with self-looping phi; these will collapse + (lhs.in(2)!=lhs && rhs.in(2)!=rhs) ) { // Profit check: only 1 instance of `this` will remain, all the // others will fold to constants. int cnt=0; @@ -73,7 +76,7 @@ public abstract class ArithNode extends Node { : copy(lhs.in(i), rhs.in(i)).peephole(); } String label = lhs._label==rhs._label ? lhs._label : lhs._label + rhs._label; - return new PhiNode(label,lhs._declaredType,ns).peephole(); + return new PhiNode(label,lhs._minType,ns).peephole(); } } return null; diff --git a/src/main/java/com/seaofnodes/simple/node/BoolNode.java b/src/main/java/com/seaofnodes/simple/node/BoolNode.java index 301e1517..2765c308 100644 --- a/src/main/java/com/seaofnodes/simple/node/BoolNode.java +++ b/src/main/java/com/seaofnodes/simple/node/BoolNode.java @@ -1,8 +1,8 @@ package com.seaofnodes.simple.node; import com.seaofnodes.simple.Parser; -import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.type.*; +import com.seaofnodes.simple.util.Utils; import java.util.BitSet; import static com.seaofnodes.simple.type.TypeInteger.*; @@ -33,7 +33,7 @@ abstract public class BoolNode extends Node { Type t2 = in(2)._type; // Exactly equals? if( t1.isHigh() || t2.isHigh() ) - return BOOL.dual(); + return (TypeInteger)BOOL.dual(); if( in(1)==in(2) ) // LT fails, both EQ and LE succeed return this instanceof LT ? FALSE : TRUE; diff --git a/src/main/java/com/seaofnodes/simple/node/CFGNode.java b/src/main/java/com/seaofnodes/simple/node/CFGNode.java index 1dddc171..b9c70e5f 100644 --- a/src/main/java/com/seaofnodes/simple/node/CFGNode.java +++ b/src/main/java/com/seaofnodes/simple/node/CFGNode.java @@ -1,10 +1,10 @@ package com.seaofnodes.simple.node; -import com.seaofnodes.simple.Ary; import com.seaofnodes.simple.Parser; -import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.type.*; +import com.seaofnodes.simple.util.Ary; +import com.seaofnodes.simple.util.Utils; import java.util.BitSet; import java.util.HashMap; import java.util.HashSet; @@ -59,7 +59,7 @@ public abstract class CFGNode extends Node { // Used by the encoding / final BB layout public CFGNode uctrlSkipEmpty() { CFGNode x = this, y; - while( x.nOuts() == 1 && (y=x.uctrl())!=null ) // Skip empty blocks + while( x.nOuts() == 1 && (y=x.uctrl())!=null && !(y instanceof CallNode) ) // Skip empty blocks x = y; return x; } @@ -89,6 +89,7 @@ public abstract class CFGNode extends Node { var comp = lhs.idepth() - rhs.idepth(); if( comp >= 0 ) lhs = (dep==null ? lhs : dep.addDep(lhs)).idom(); if( comp <= 0 ) rhs = (dep==null ? rhs : dep.addDep(rhs)).idom(); + if( lhs==null || rhs==null ) return null; } return lhs; } diff --git a/src/main/java/com/seaofnodes/simple/node/CProjNode.java b/src/main/java/com/seaofnodes/simple/node/CProjNode.java index 94770f16..a6e21ea0 100644 --- a/src/main/java/com/seaofnodes/simple/node/CProjNode.java +++ b/src/main/java/com/seaofnodes/simple/node/CProjNode.java @@ -1,10 +1,10 @@ package com.seaofnodes.simple.node; import com.seaofnodes.simple.Parser; -import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.type.Type; import com.seaofnodes.simple.type.TypeMem; import com.seaofnodes.simple.type.TypeTuple; +import com.seaofnodes.simple.util.Utils; import java.util.BitSet; public class CProjNode extends CFGNode { diff --git a/src/main/java/com/seaofnodes/simple/node/CallEndMach.java b/src/main/java/com/seaofnodes/simple/node/CallEndMach.java index 47cab07a..d26ea33b 100644 --- a/src/main/java/com/seaofnodes/simple/node/CallEndMach.java +++ b/src/main/java/com/seaofnodes/simple/node/CallEndMach.java @@ -1,7 +1,7 @@ package com.seaofnodes.simple.node; -import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.*; +import com.seaofnodes.simple.util.SB; public class CallEndMach extends CallEndNode implements MachNode { public CallEndMach( CallEndNode n ) { super(n); } diff --git a/src/main/java/com/seaofnodes/simple/node/CallEndNode.java b/src/main/java/com/seaofnodes/simple/node/CallEndNode.java index cf3f337c..b75852a4 100644 --- a/src/main/java/com/seaofnodes/simple/node/CallEndNode.java +++ b/src/main/java/com/seaofnodes/simple/node/CallEndNode.java @@ -74,10 +74,10 @@ public class CallEndNode extends CFGNode implements MultiNode { assert fun.in(1) instanceof StartNode && fun.in(2)==call; // Disallow self-recursive inlining (loop unrolling by another name) CFGNode idom = call; - while( !(idom instanceof FunNode) ) + while( !(idom instanceof FunNode) && idom!=null ) idom = idom.idom(); // Inline? - if( idom != fun ) { + if( idom != fun && idom != null ) { // Trivial inline: rewrite _folding = true; // Rewrite Fun so the normal RegionNode ideal collapses @@ -105,5 +105,4 @@ public class CallEndNode extends CFGNode implements MultiNode { @Override public Node pcopy(int idx) { return _folding ? in(1).in(idx) : null; } - } diff --git a/src/main/java/com/seaofnodes/simple/node/CallNode.java b/src/main/java/com/seaofnodes/simple/node/CallNode.java index 8b243e87..ba08c87a 100644 --- a/src/main/java/com/seaofnodes/simple/node/CallNode.java +++ b/src/main/java/com/seaofnodes/simple/node/CallNode.java @@ -1,11 +1,11 @@ package com.seaofnodes.simple.node; -import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.IterPeeps; import com.seaofnodes.simple.Parser; -import com.seaofnodes.simple.Utils; +import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.type.Type; import com.seaofnodes.simple.type.TypeFunPtr; +import com.seaofnodes.simple.util.Utils; import java.util.BitSet; /** @@ -162,8 +162,10 @@ public class CallNode extends CFGNode { // Check for args for( int i=0; i * Constants have no semantic inputs. However, we set Start as an input to * Constants to enable a forward graph walk. This edge carries no semantic @@ -26,8 +22,7 @@ public class ConstantNode extends Node { super(new Node[]{CodeGen.CODE._start}); _con = _type = type; } - public ConstantNode( Node con, Type t ) { super(con); _con = t; } - public ConstantNode( ConstantNode con ) { this(con,con._type); } + public ConstantNode( ConstantNode con ) { super(con); _con = con._type; } public static Node make( Type type ) { if( type==Type. CONTROL ) return new CtrlNode(); @@ -36,10 +31,8 @@ public class ConstantNode extends Node { } @Override public String label() { return "#"+_con; } - @Override public String glabel() { return _con.gprint(new SB().p("#")).toString(); } - - @Override - public String uniqueName() { return "Con_" + _nid; } + @Override public String glabel() { return "#"+_con.gprint(); } + @Override public String uniqueName() { return "Con_" + _nid; } @Override public StringBuilder _print1(StringBuilder sb, BitSet visited) { @@ -48,23 +41,12 @@ public class ConstantNode extends Node { if( fun!=null && fun._name != null ) return sb.append("{ ").append(fun._name).append("}"); } - return sb.append(_con==null ? "---" : _con.print(new SB())); + return sb.append(_con==null ? "---" : _con.toString()); } @Override public boolean isConst() { return true; } - - @Override - public Type compute() { return _con; } - - @Override - public Node idealize() { return null; } - - @Override - public boolean eq(Node n) { - ConstantNode con = (ConstantNode)n; // Contract - return _con==con._con; - } - - @Override - int hash() { return _con.hashCode(); } + @Override public Type compute() { return _con; } + @Override public Node idealize() { return null; } + @Override public boolean eq(Node n) { return _con==((ConstantNode)n)._con; } + @Override int hash() { return _con.hashCode(); } } diff --git a/src/main/java/com/seaofnodes/simple/node/ExternNode.java b/src/main/java/com/seaofnodes/simple/node/ExternNode.java index 33fc0c1e..a10bb84a 100644 --- a/src/main/java/com/seaofnodes/simple/node/ExternNode.java +++ b/src/main/java/com/seaofnodes/simple/node/ExternNode.java @@ -1,10 +1,10 @@ package com.seaofnodes.simple.node; -import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.Parser; -import com.seaofnodes.simple.SB; +import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.type.Type; import com.seaofnodes.simple.type.TypeFunPtr; +import com.seaofnodes.simple.util.SB; import java.util.BitSet; /** @@ -16,7 +16,7 @@ public class ExternNode extends ConstantNode { public ExternNode(Type t, String ex) { super(t); _extern = ex; } @Override public String label() { return "#"+_con+":"+_extern; } - @Override public String glabel() { return _con.gprint(new SB().p("#")).p(":").p(_extern).toString(); } + @Override public String glabel() { return _con.print(new SB().p("#"), new BitSet(), true).p(":").p(_extern).toString(); } @Override public String uniqueName() { return "Extern_" + _nid; } @Override public boolean eq(Node n) { return this==n; } diff --git a/src/main/java/com/seaofnodes/simple/node/FunNode.java b/src/main/java/com/seaofnodes/simple/node/FunNode.java index 81fa627a..4bd0fd97 100644 --- a/src/main/java/com/seaofnodes/simple/node/FunNode.java +++ b/src/main/java/com/seaofnodes/simple/node/FunNode.java @@ -1,13 +1,14 @@ package com.seaofnodes.simple.node; - -import com.seaofnodes.simple.*; +import com.seaofnodes.simple.Parser; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.codegen.Encoding; import com.seaofnodes.simple.codegen.RegMask; import com.seaofnodes.simple.type.Type; import com.seaofnodes.simple.type.TypeFunPtr; import com.seaofnodes.simple.type.TypeTuple; +import com.seaofnodes.simple.util.SB; +import com.seaofnodes.simple.util.Utils; import java.util.BitSet; import static com.seaofnodes.simple.codegen.CodeGen.CODE; @@ -125,10 +126,10 @@ public class FunNode extends RegionNode { return _folding ? super.idepth() : CodeGen.CODE.iDepthAt(1); } // Bypass Region idom, always assume idom is Start - @Override public CFGNode idom(Node dep) { return _folding && nIns()==3 ? cfg(2) : cfg(1); } + @Override public CFGNode idom(Node dep) { return _folding && nIns()==3 ? cfg(2) : (nIns()>1 ? cfg(1) : null); } // Always in-progress until we run out of unknown callers - public boolean unknownCallers() { return nIns()<2 || in(1) instanceof StartNode; } + public boolean unknownCallers() { return nIns()>=2 && in(1) instanceof StartNode; } @Override public boolean inProgress() { return unknownCallers(); } diff --git a/src/main/java/com/seaofnodes/simple/node/IfNode.java b/src/main/java/com/seaofnodes/simple/node/IfNode.java index 5d90449e..c5d687e5 100644 --- a/src/main/java/com/seaofnodes/simple/node/IfNode.java +++ b/src/main/java/com/seaofnodes/simple/node/IfNode.java @@ -1,8 +1,8 @@ package com.seaofnodes.simple.node; -import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.type.*; +import com.seaofnodes.simple.util.Utils; import java.util.BitSet; public class IfNode extends CFGNode implements MultiNode { @@ -87,8 +87,8 @@ public class IfNode extends CFGNode implements MultiNode { return switch( bop ) { case "<" -> ">" ; case "<=" -> ">="; - case "==" -> "!="; - case "!=" -> "=="; + case "==" -> "=="; + case "!=" -> "!="; case ">" -> "<" ; case ">=" -> "<="; default -> throw Utils.TODO(); diff --git a/src/main/java/com/seaofnodes/simple/node/LoadNode.java b/src/main/java/com/seaofnodes/simple/node/LoadNode.java index eebe94a3..b58ea498 100644 --- a/src/main/java/com/seaofnodes/simple/node/LoadNode.java +++ b/src/main/java/com/seaofnodes/simple/node/LoadNode.java @@ -1,8 +1,9 @@ package com.seaofnodes.simple.node; import com.seaofnodes.simple.Parser; -import com.seaofnodes.simple.Utils; +import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.type.*; +import com.seaofnodes.simple.util.Utils; import java.util.BitSet; /** @@ -33,15 +34,21 @@ public class LoadNode extends MemOpNode { @Override public Type compute() { - if( mem()._type instanceof TypeMem mem ) { - // Update declared forward ref to the actual - if( _declaredType.isFRef() && mem._t instanceof TypeMemPtr tmp && !tmp.isFRef() ) - _declaredType = tmp; - // No lifting if ptr might null-check - if( err()==null ) - return _declaredType.join(mem._t); + if( !(mem()._type instanceof TypeMem mem) ) + return _declaredType; // No memory yet? Declared type + assert !_declaredType.isFRef(); + // No lifting if ptr might null-check + if( err()!=null || !(ptr()._type instanceof TypeMemPtr tmp) ) + return _declaredType; // No pointer yet? Declared type + Type t = tmp._obj.field(_name)._t; + if( t instanceof TypeConAry ary ) { + t = ary.elem(); // TODO: if offset is known, can peek the constant } - return _declaredType; + // Lift from declared type and memory input + t = t.join(_declaredType).join(mem._t); + if( _declaredType.isFinal() ) + t = t.makeRO(); // Deep final applied + return t; } @Override @@ -49,6 +56,11 @@ public class LoadNode extends MemOpNode { Node ptr = ptr(); Node mem = mem(); + if( mem instanceof CastNode cast ) { + setDef(1,cast.in(1)); + return this; + } + // Simple Load-after-Store on same address. if( mem instanceof StoreNode st && ptr == st.ptr() && off() == st.off() ) { // Must check same object @@ -58,7 +70,11 @@ public class LoadNode extends MemOpNode { // Simple load-after-MemMerge to a known alias can bypass. Happens when inlining. if( mem instanceof MemMergeNode mem2 ) { - setDef(1,mem2.alias(_alias)); + Node memA = mem2.alias(_alias); + for( Node ld : memA._outputs ) + if( ld instanceof LoadNode ) + CodeGen.CODE.add(ld); + setDef(1,memA); return this; } @@ -111,6 +127,7 @@ public class LoadNode extends MemOpNode { default: throw Utils.TODO(); } break; + case CastNode cast: mem = cast.in(1); break; case MemMergeNode merge: mem = merge.alias(_alias); break; default: @@ -147,7 +164,7 @@ public class LoadNode extends MemOpNode { // Load a flavored zero from a New private Node zero(NewNode nnn) { TypeStruct ts = nnn._ptr._obj; - Type zero = ts._fields[ts.findAlias(_alias)]._type.makeZero(); + Type zero = ts._fields[ts.findAlias(_alias)]._t.makeZero(); return castRO(new ConstantNode(zero).peephole()); } @@ -187,7 +204,7 @@ public class LoadNode extends MemOpNode { Node px = phi.in(idx); if( px==null ) return false; if( px._type instanceof TypeMem mem && mem._t.isHighOrConst() ) return true; - if( px instanceof StoreNode st1 && ptr()==st1.ptr() && off()==st1.off() ) return true; + if( px instanceof StoreNode st1 && ptr()==addDep(st1.ptr() )&& off()==st1.off() ) return true; addDep(px); return false; } diff --git a/src/main/java/com/seaofnodes/simple/node/LoopNode.java b/src/main/java/com/seaofnodes/simple/node/LoopNode.java index ec9055dc..fc50e17f 100644 --- a/src/main/java/com/seaofnodes/simple/node/LoopNode.java +++ b/src/main/java/com/seaofnodes/simple/node/LoopNode.java @@ -1,11 +1,11 @@ package com.seaofnodes.simple.node; import com.seaofnodes.simple.Parser; -import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.type.Type; import com.seaofnodes.simple.type.TypeInteger; import com.seaofnodes.simple.type.TypeMem; +import com.seaofnodes.simple.util.Utils; import java.util.BitSet; import java.util.HashSet; @@ -48,7 +48,7 @@ public class LoopNode extends RegionNode { x = x.idom(); } // Found a no-exit loop. Insert an exit - NeverNode iff = new NeverNode(back()); // Ideal never-branch + NeverNode iff = (NeverNode)new NeverNode(back()).peephole(); // Ideal never-branch CProjNode t = new CProjNode(iff,0,"True" ).init(); CProjNode f = new CProjNode(iff,1,"False").init(); setDef(2,t); // True continues loop, False (never) exits loop @@ -78,17 +78,19 @@ public class LoopNode extends RegionNode { expr = new PhiNode(r,expr).init(); } // Append new Never exit - ctrl.addDef(f ); - mem .addDef(memout); - expr.addDef(top); + ctrl.keep().addDef(f ); + mem .keep().addDef(memout); + expr.keep().addDef(top); } else { - ctrl = f; - mem = memout; - expr = top; + ctrl = f .keep(); + mem = memout.keep(); + expr = top .keep(); } - ret.setDef(0,ctrl); - ret.setDef(1,mem ); - ret.setDef(2,expr); + ret.setDef(0,ctrl.unkeep()); + ret.setDef(1,mem .unkeep()); + ret.setDef(2,expr.unkeep()); + ret._type = null; // This may LIFT the Return type, from [XCtrl,mem,expr] to [Ctrl,mem,expr] + ret.setType(ret.compute()); return stop; } diff --git a/src/main/java/com/seaofnodes/simple/node/MachConcreteNode.java b/src/main/java/com/seaofnodes/simple/node/MachConcreteNode.java index b01b3308..9440a7ea 100644 --- a/src/main/java/com/seaofnodes/simple/node/MachConcreteNode.java +++ b/src/main/java/com/seaofnodes/simple/node/MachConcreteNode.java @@ -1,7 +1,7 @@ package com.seaofnodes.simple.node; import com.seaofnodes.simple.type.Type; -import com.seaofnodes.simple.Utils; +import com.seaofnodes.simple.util.Utils; import java.io.ByteArrayOutputStream; import java.util.BitSet; diff --git a/src/main/java/com/seaofnodes/simple/node/MachNode.java b/src/main/java/com/seaofnodes/simple/node/MachNode.java index f63b3651..c0b3af66 100644 --- a/src/main/java/com/seaofnodes/simple/node/MachNode.java +++ b/src/main/java/com/seaofnodes/simple/node/MachNode.java @@ -2,6 +2,8 @@ package com.seaofnodes.simple.node; import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; +import com.seaofnodes.simple.util.SB; +import com.seaofnodes.simple.util.Utils; public interface MachNode { diff --git a/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java b/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java index 9f2fdd16..19acc5b9 100644 --- a/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java +++ b/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java @@ -67,9 +67,12 @@ public class MemMergeNode extends Node { // Fold defaults into the default boolean progress=false, allDefault=true; - for( int i=2; i 0 || i._max < 0) ) return TypeInteger.FALSE; diff --git a/src/main/java/com/seaofnodes/simple/node/ParmNode.java b/src/main/java/com/seaofnodes/simple/node/ParmNode.java index 32e41f54..a14a4fb9 100644 --- a/src/main/java/com/seaofnodes/simple/node/ParmNode.java +++ b/src/main/java/com/seaofnodes/simple/node/ParmNode.java @@ -1,6 +1,5 @@ package com.seaofnodes.simple.node; -import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.type.Type; import java.util.BitSet; @@ -13,7 +12,7 @@ public class ParmNode extends PhiNode { super(label,declaredType,inputs); _idx = idx; } - public ParmNode(ParmNode parm) { super(parm, parm._label, parm._declaredType); _idx = parm._idx; } + public ParmNode(ParmNode parm) { super(parm, parm._label, parm._minType ); _idx = parm._idx; } @Override public String label() { return MemOpNode.mlabel(_label); } @@ -37,14 +36,8 @@ public class ParmNode extends PhiNode { } - @Override - public Node idealize() { - if( inProgress() ) return null; - return super.idealize(); - } - // Always in-progress until we run out of unknown callers - @Override public boolean inProgress() { return fun().inProgress(); } + @Override public boolean inProgress() { return in(0) instanceof FunNode fun && fun.inProgress(); } @Override public boolean eq( Node n ) { return ((ParmNode)n)._idx==_idx && super.eq(n); diff --git a/src/main/java/com/seaofnodes/simple/node/PhiNode.java b/src/main/java/com/seaofnodes/simple/node/PhiNode.java index 971b52ae..fcbacbc9 100644 --- a/src/main/java/com/seaofnodes/simple/node/PhiNode.java +++ b/src/main/java/com/seaofnodes/simple/node/PhiNode.java @@ -1,25 +1,34 @@ package com.seaofnodes.simple.node; import com.seaofnodes.simple.*; +import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.type.*; +import com.seaofnodes.simple.util.Utils; import java.util.BitSet; public class PhiNode extends Node { public final String _label; - // The Phi type we compute must stay within the domain of the Phi. - // Example Int stays Int, Ptr stays Ptr, Control stays Control, Mem stays Mem. - final Type _declaredType; - - public PhiNode(String label, Type declaredType, Node... inputs) { super(inputs); _label = label; assert declaredType!=null; _declaredType = declaredType; } - public PhiNode(PhiNode phi, String label, Type declaredType) { super(phi); _label = label; _type = _declaredType = declaredType; } - public PhiNode(PhiNode phi) { super(phi); _label = phi._label; _declaredType = phi._declaredType; } + // The Phi type we compute must stay within the domain of the Phi. Example + // Int stays Int, Ptr stays Ptr, Control stays Control, Mem stays Mem. + Type _minType; + public PhiNode(String label, Type minType, Node... inputs) { + super(inputs); + _label = label; + assert minType!=null; + _minType = minType; + } + // Used by ParmNode + public PhiNode(PhiNode phi, String label, Type minType) { super(phi); _label = label; _type = _minType = minType; } + // Used by instruction Selection + public PhiNode(PhiNode phi) { this(phi,phi._label,phi._minType ); } + // Used by the infinite-loop exit breaker public PhiNode(RegionNode r, Node sample) { super(new Node[]{r}); _label = ""; - _declaredType = sample._type; + _minType = sample._type; while( nIns() < r.nIns() ) addDef(sample); } @@ -44,7 +53,7 @@ public class PhiNode extends Node { } public CFGNode region() { return (CFGNode)in(0); } - @Override public boolean isMem() { return _declaredType instanceof TypeMem; } + @Override public boolean isMem() { return _minType instanceof TypeMem; } @Override public boolean isPinned() { return true; } @Override @@ -52,14 +61,19 @@ public class PhiNode extends Node { if( !(region() instanceof RegionNode r) ) return region()._type==Type.XCONTROL ? (_type instanceof TypeMem ? TypeMem.TOP : Type.TOP) : _type; // During parsing Phis have to be computed type pessimistically. - if( r.inProgress() ) return _declaredType; + if( r.inProgress() ) return _minType; // Set type to local top of the starting type - Type t = _declaredType.glb(false).dual();//Type.TOP; + //Type t = _minType.dual(); + Type t = 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. - if( addDep(r.in(i))._type != Type.XCONTROL ) + if( addDep(r.in(i))._type != Type.XCONTROL ) { + if( in(i)._type==Type.BOTTOM ) + return Type.BOTTOM; t = t.meet(in(i)._type); + } + t = t.join( _minType ); return t; } @@ -67,19 +81,40 @@ public class PhiNode extends Node { public Node idealize() { if( !(region() instanceof RegionNode r ) ) return in(1); // Input has collapse to e.g. starting control. + // Can upgrade minType even while in-progress + if( _minType instanceof TypeMemPtr tmp && _minType.isFRef() ) { + TypeMemPtr tmp2 = (TypeMemPtr)CodeGen.CODE.P.TYPES.get(tmp._obj._name); + if( tmp2!=null && tmp2 != _minType ) { + _minType = tmp2; + return this; + } + } if( r.inProgress() || r.nIns()<=1 ) return null; // Input is in-progress // If we have only a single unique input, become it. Node live = singleUniqueInput(); - if (live != null) - return live; + if( live != null ) { + if( live._type.isa(_type) ) + return live; + // Keep the Phi upcast + return new CastNode(_type,null,live); + } // No bother if region is going to fold dead paths soon for( int i=1; i3 && // No Phi users, just a control user in(1) instanceof CProjNode p1 && in(2) instanceof CProjNode p2 && addDep(p1.in(0))==addDep(p2.in(0)) && diff --git a/src/main/java/com/seaofnodes/simple/node/ReturnNode.java b/src/main/java/com/seaofnodes/simple/node/ReturnNode.java index b4173871..7971733a 100644 --- a/src/main/java/com/seaofnodes/simple/node/ReturnNode.java +++ b/src/main/java/com/seaofnodes/simple/node/ReturnNode.java @@ -1,12 +1,12 @@ package com.seaofnodes.simple.node; import com.seaofnodes.simple.Parser; -import com.seaofnodes.simple.SB; -import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.codegen.CodeGen; -import com.seaofnodes.simple.codegen.RegMask; import com.seaofnodes.simple.codegen.Encoding; +import com.seaofnodes.simple.codegen.RegMask; import com.seaofnodes.simple.type.*; +import com.seaofnodes.simple.util.SB; +import com.seaofnodes.simple.util.Utils; import java.util.BitSet; /** @@ -61,11 +61,10 @@ public class ReturnNode extends CFGNode { // Upgrade signature based on return type Type ret = expr()._type; TypeFunPtr fcn = _fun.sig(); - assert ret.isa(fcn.ret()); - if( ret != fcn.ret() ) + if( ret != fcn.ret() && ret.isa(fcn.ret()) ) _fun.setSig(fcn.makeFrom(ret)); - // If dead (cant be reached; infinite loop), kill the exit values + // If dead (cannot be reached; infinite loop), kill the exit values if( ctrl()._type==Type.XCONTROL && !(mem() instanceof ConstantNode && expr() instanceof ConstantNode) ) { Node top = new ConstantNode(Type.TOP).peephole(); @@ -100,8 +99,8 @@ public class ReturnNode extends CFGNode { // Merge path into the One True Return RegionNode r = (RegionNode)ctrl(); // Assert that the Phis are in particular outputs; not reordered or shuffled - PhiNode mem = (PhiNode)r.out(0); assert mem._declaredType == TypeMem.BOT; - PhiNode rez = (PhiNode)r.out(1); assert rez._declaredType == Type.BOTTOM; + PhiNode mem = (PhiNode)r.out(0); assert mem._minType == TypeMem.BOT; + PhiNode rez = (PhiNode)r.out(1); assert rez._minType == Type.BOTTOM; // Pop "inProgress" null off r ._inputs.pop(); mem._inputs.pop(); diff --git a/src/main/java/com/seaofnodes/simple/node/ScopeNode.java b/src/main/java/com/seaofnodes/simple/node/ScopeNode.java index 3127e491..36746a81 100644 --- a/src/main/java/com/seaofnodes/simple/node/ScopeNode.java +++ b/src/main/java/com/seaofnodes/simple/node/ScopeNode.java @@ -1,8 +1,13 @@ package com.seaofnodes.simple.node; -import com.seaofnodes.simple.*; +import com.seaofnodes.simple.Parser; +import com.seaofnodes.simple.Var; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.type.*; +import com.seaofnodes.simple.util.Ary; +import com.seaofnodes.simple.util.AryInt; +import com.seaofnodes.simple.util.Utils; + import java.util.*; /** @@ -19,18 +24,26 @@ public class ScopeNode extends MemMergeNode { public static final String ARG0 = "arg"; public static final String MEM0 = "$mem"; - // All active/live variables in all nested scopes, all run together + // All active/live variables in all nested scopes, all run together. + // Maps 1-to-1 to the _inputs array. public final Ary _vars; - // Size of each nested lexical scope - public final Ary _lexSize; - // Lexical scope is typed: - // - Block scope - basic block scoping - // - Constructor - struct type is defined, and here we give values to all fields - // - Function - out-of-scope lookups restricted to final constants - public enum Kind { Block, Constructor, Function }; + public static class Kind { + // Basic block scoping + public static class Block extends Kind { } + // Function scope + public static class Func extends Kind { } + // Struct definition, mapping types to fields + public static class Define extends Kind { public Define(TypeMemPtr tmp) { _tmp=tmp; } public final TypeMemPtr _tmp; } + // Struct allocation, mapping values to fields + public static class Alloc extends Kind { public Alloc (TypeMemPtr tmp) { _tmp=tmp; } public final TypeMemPtr _tmp; } + + public int _lexSize; // Number of Vars in this scope + } public final Ary _kinds; + // Lexical scope nesting depth + public int depth() { return _kinds._len; } // Extra guards; tested predicates and casted results private final Ary _guards; @@ -38,10 +51,9 @@ public class ScopeNode extends MemMergeNode { // A new ScopeNode public ScopeNode() { super(true); - _vars = new Ary<>(Var .class); - _lexSize= new Ary<>(Integer.class); - _kinds = new Ary<>(Kind .class); - _guards = new Ary<>(Node .class); + _vars = new Ary<>(Var .class); + _kinds = new Ary<>(Kind.class); + _guards = new Ary<>(Node.class); } @Override public String label() { return "Scope"; } @@ -51,9 +63,9 @@ public class ScopeNode extends MemMergeNode { sb.append("Scope[ "); int j=1; for( int i=0; i=0; i-- ) + if( v._idx >= _kinds.at(i)._lexSize ) + return _kinds.at(i); + throw Utils.TODO(); + } + + // Return the kind for the defining scope, or a function scope if found + // first. Block scopes means the variable can be r/w directly in the + // scope, Function scopes require final constants (no capture), and + // Constructor scopes mean an instance variable reference. + + // Walk up-lexical scope looking for defining lexical Kind. + // - Skip any amount of nested block scopes + // - Walking out of a function requires v be a final constant (for now) - + // and we can stop walking. + + // - Walking out of a method and (skipping Blocks) into the matching struct + // is OK, and this is a instance var load. + + // - Walking out of a method and into the wrong struct is an error; + // including nested structs containing (no nested classes yet) + + // Returns error, forward-ref, ok containing struct, ok containing function/block. - // Is v outside any current function scope? - public boolean outOfFunction( Var v ) { - for( int i=_lexSize._len-1; i>=0 && v._idx<_lexSize.at(i); i-- ) - if( _kinds.at(i)==Kind.Function ) - return true; - return false; + public String outOfFunction( Var v ) { + //if( v==null ) return null; // Prolly forward reference + //int i; for( i=_lexSize._len-1; i>=0 && v._idx<_lexSize.at(i); i-- ) + // if( _kinds.at(i)=="{->}" ) return "{->}"; + //return _kinds.at(i); + throw Utils.TODO(); } @@ -149,9 +185,9 @@ 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 ) { - 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-- ) { + assert _kinds.isEmpty() || name.charAt(0)!='$' ; // Later scopes do not define memory + if( depth() > 0 ) + for( int i=_vars.size()-1; i>=_kinds.last()._lexSize; i-- ) { Var n = var(i); if( n._name.equals(name) ) { if( !n.isFRef() ) return false; // Double define @@ -214,7 +250,7 @@ public class ScopeNode extends MemMergeNode { : 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; + //assert !v._final || st==null; if( st!=null ) setDef(v._idx,st); // Set new value return v; } @@ -240,7 +276,6 @@ public class ScopeNode extends MemMergeNode { // 2) Make the new ScopeNode a user of all the nodes bound // 3) Ensure that the order of defs is the same to allow easy merging dup._vars .addAll(_vars ); - dup._lexSize.addAll(_lexSize); dup._kinds .addAll(_kinds ); dup._guards .addAll(_guards ); // The dup'd guards all need dup'd keepers, to keep proper accounting diff --git a/src/main/java/com/seaofnodes/simple/node/SplitNode.java b/src/main/java/com/seaofnodes/simple/node/SplitNode.java index 3a1ed011..d061cdbd 100644 --- a/src/main/java/com/seaofnodes/simple/node/SplitNode.java +++ b/src/main/java/com/seaofnodes/simple/node/SplitNode.java @@ -1,8 +1,8 @@ package com.seaofnodes.simple.node; -import com.seaofnodes.simple.SB; import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.type.Type; +import com.seaofnodes.simple.util.SB; import java.util.BitSet; public abstract class SplitNode extends MachConcreteNode { diff --git a/src/main/java/com/seaofnodes/simple/node/StartNode.java b/src/main/java/com/seaofnodes/simple/node/StartNode.java index f40203b4..e3806de7 100644 --- a/src/main/java/com/seaofnodes/simple/node/StartNode.java +++ b/src/main/java/com/seaofnodes/simple/node/StartNode.java @@ -6,11 +6,11 @@ import com.seaofnodes.simple.type.*; import java.util.Arrays; import java.util.BitSet; import java.util.HashSet; -import static com.seaofnodes.simple.Utils.TODO; +import static com.seaofnodes.simple.util.Utils.TODO; /** * The Start node represents the start of the function. - * + *

* 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. @@ -19,7 +19,7 @@ public class StartNode extends LoopNode implements MultiNode { final Type _arg; - public StartNode(Type arg) { super((Parser.Lexer)null,null); _arg = arg; _type = compute(); } + public StartNode(Type arg) { super(null,null); _arg = arg; _type = compute(); } public StartNode(StartNode start) { super(start); _arg = start==null ? null : start._arg; } @Override public String label() { return "Start"; } @@ -29,13 +29,12 @@ public class StartNode extends LoopNode implements MultiNode { return sb.append(label()); } - @Override public boolean blockHead() { return true; } - @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" @Override public CFGNode uctrl() { - // Find "main", its the start. + // Find "main", it's the start. CFGNode C = null; for( Node use : _outputs ) if( use instanceof FunNode fun && fun.sig().isa(CodeGen.CODE._main) ) diff --git a/src/main/java/com/seaofnodes/simple/node/StopNode.java b/src/main/java/com/seaofnodes/simple/node/StopNode.java index b65535f1..4b03bf4e 100644 --- a/src/main/java/com/seaofnodes/simple/node/StopNode.java +++ b/src/main/java/com/seaofnodes/simple/node/StopNode.java @@ -1,7 +1,7 @@ package com.seaofnodes.simple.node; -import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.type.Type; +import com.seaofnodes.simple.util.Utils; import java.util.BitSet; public class StopNode extends CFGNode { diff --git a/src/main/java/com/seaofnodes/simple/node/StoreNode.java b/src/main/java/com/seaofnodes/simple/node/StoreNode.java index 9b561bed..5fb274db 100644 --- a/src/main/java/com/seaofnodes/simple/node/StoreNode.java +++ b/src/main/java/com/seaofnodes/simple/node/StoreNode.java @@ -40,14 +40,16 @@ public class StoreNode extends MemOpNode { @Override public Type compute() { Type val = val()._type; - TypeMem mem = (TypeMem)mem()._type; // Invariant + Type mem0 = mem()._type; + if( mem0 == Type.TOP ) return TypeMem.TOP; + TypeMem mem = (TypeMem)mem0; // Invariant if( mem == TypeMem.TOP ) return TypeMem.TOP; Type t = Type.BOTTOM; // No idea on field contents // Same alias, lift val to the declared type and then meet into other fields if( mem._alias == _alias ) { - // Update declared forward ref to the actual - if( _declaredType.isFRef() && val instanceof TypeMemPtr tmp && !tmp.isFRef() ) - _declaredType = tmp; + assert !_declaredType.isFRef(); + // Sharpen memory value; required for narrowing stores where the parser inserts + // zero/sign masking and somebody reads the TypeMem type. val = val.join(_declaredType); t = val.meet(mem._t); } @@ -57,6 +59,11 @@ public class StoreNode extends MemOpNode { @Override public Node idealize() { + if( mem() instanceof CastNode cast ) { + setDef(1,cast.in(1)); + return this; + } + // Simple store-after-store on same address. Should pick up the // required init-store being stomped by a first user store. if( mem() instanceof StoreNode st && diff --git a/src/main/java/com/seaofnodes/simple/node/StructNode.java b/src/main/java/com/seaofnodes/simple/node/StructNode.java index 4efc0de9..b5b59b81 100644 --- a/src/main/java/com/seaofnodes/simple/node/StructNode.java +++ b/src/main/java/com/seaofnodes/simple/node/StructNode.java @@ -1,7 +1,7 @@ package com.seaofnodes.simple.node; -import com.seaofnodes.simple.SB; import com.seaofnodes.simple.type.*; +import com.seaofnodes.simple.util.SB; import java.util.BitSet; /** @@ -9,7 +9,8 @@ import java.util.BitSet; */ public class StructNode extends Node { - public TypeStruct _ts; + public final TypeStruct _ts; + public StructNode(TypeStruct ts) { _ts=ts; assert !ts._open; } @Override public String label() { return _ts==null ? "STRUCT?" : _ts.str(); } @@ -19,7 +20,7 @@ public class StructNode extends Node { sb.append(_ts._name).append(" {"); for( int i=0; i