summaryrefslogtreecommitdiff
path: root/chapter25/src/main/java/com
diff options
context:
space:
mode:
Diffstat (limited to 'chapter25/src/main/java/com')
-rw-r--r--chapter25/src/main/java/com/seaofnodes/simple/node/FunNode.java17
-rw-r--r--chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java11
-rw-r--r--chapter25/src/main/java/com/seaofnodes/simple/type/TypeInteger.java5
-rw-r--r--chapter25/src/main/java/com/seaofnodes/simple/type/TypeScalar.java12
4 files changed, 22 insertions, 23 deletions
diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/FunNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/FunNode.java
index a9d03543..5018f5d6 100644
--- a/chapter25/src/main/java/com/seaofnodes/simple/node/FunNode.java
+++ b/chapter25/src/main/java/com/seaofnodes/simple/node/FunNode.java
@@ -154,14 +154,14 @@ public class FunNode extends RegionNode {
}
// Attempt to get rid of the unknown caller.
- // - Must be past Parser, which invents new calls "from whole cloth".
+ // - Must be past pessimistic Iter, which discovers and links calls
+ // through class-field loads and other initially imprecise values.
// - FIDX is not in the escape set
// - Not called anywhere else; post Opto called-not-escaped functions need to still be hooked to start
if( in(1) instanceof StartCUNode start ) {
boolean preOpto = CodeGen.CODE._phase == null ||
CodeGen.CODE._phase.ordinal() < CodeGen.Phase.Opto.ordinal();
- if( !start.escapedFIDX(_sig.fidx()) && nIns()<=2 && _ret!=null &&
- !(preOpto && hasFunPtr()) ) {
+ if( !preOpto && !start.escapedFIDX(_sig.fidx()) && nIns()<=2 && _ret!=null ) {
_compunit._stop.delDef(_compunit._stop._inputs.find(ret()));
return removeDeadPath(1);
} else {
@@ -186,17 +186,6 @@ public class FunNode extends RegionNode {
return null;
}
- // Before SCCP has discovered all Call edges, a live function pointer is
- // enough reason to retain the unknown-caller Start edge.
- private boolean hasFunPtr() {
- for( Node use : ret().outs() )
- if( use instanceof FunPtrNode && !use.isDead() ) {
- addDep(use);
- return true;
- }
- return false;
- }
-
// Bypass Region idom, always assume depth == 1, one more than Start,
// unless folding
@Override public int idepth() {
diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java
index cbed5996..8d8d3950 100644
--- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java
+++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/TFPX86.java
@@ -12,13 +12,20 @@ public class TFPX86 extends FunPtrNode implements MachNode, RIPRelSize {
private byte _opLen;
final String _ext; // External name
// Pointer to a Simple function
- TFPX86( FunPtrNode fptr ) { super(fptr); _ext = null; }
+ TFPX86( FunPtrNode fptr ) { this((TypeFunPtr)fptr._type,null); }
+ // Spill clone: copy inputs without registering their reverse edges;
+ // insertBefore will place and register the clone in its use block.
+ private TFPX86( TFPX86 fptr ) { super(fptr); _ext = fptr._ext; }
// Pointer to an Extern "C" function
TFPX86( TypeFunPtr fptr, String ext ) { super(fptr,CodeGen.CODE._start,null); _type = fptr; _ext = ext; }
@Override public String op() { return "ldx"; }
@Override public String label() { return op(); }
+ // The ideal FunPtrNode is pinned because its Return input is a lifetime
+ // hook. After selection this is an ordinary cloneable load-address
+ // instruction and must be scheduled down near its actual use.
+ @Override public boolean isPinned() { return false; }
@Override public boolean isClone() { return true; }
- @Override public TFPX86 copy() { return new TFPX86((TypeFunPtr)_con,_ext); }
+ @Override public TFPX86 copy() { return new TFPX86(this); }
@Override public RegMask regmap(int i) { return null; }
@Override public RegMask outregmap() { return x86_64_v2.WMASK; }
@Override public void encoding( Encoding enc ) {
diff --git a/chapter25/src/main/java/com/seaofnodes/simple/type/TypeInteger.java b/chapter25/src/main/java/com/seaofnodes/simple/type/TypeInteger.java
index 4245626a..25c3fa6f 100644
--- a/chapter25/src/main/java/com/seaofnodes/simple/type/TypeInteger.java
+++ b/chapter25/src/main/java/com/seaofnodes/simple/type/TypeInteger.java
@@ -193,7 +193,8 @@ public class TypeInteger extends TypeScalar {
baos.write(TAGOFFS[_type] + 6);
baos.packed8(_min);
baos.packed8(_max);
- baos.packed1(_widen);
+ assert -3 <= _widen && _widen <= 3;
+ baos.packed1(_widen + 3);
}
}
@@ -205,7 +206,7 @@ public class TypeInteger extends TypeScalar {
case 3 -> BOOL;
case 4 -> ZERO;
case 5 -> constant(bais.packed8());
- case 6 -> make(bais.packed8(),bais.packed8(),(byte)bais.packed1());
+ case 6 -> make(bais.packed8(),bais.packed8(),(byte)(bais.packed1()-3));
default -> throw Utils.TODO();
};
}
diff --git a/chapter25/src/main/java/com/seaofnodes/simple/type/TypeScalar.java b/chapter25/src/main/java/com/seaofnodes/simple/type/TypeScalar.java
index 4fec3c33..7b5d6317 100644
--- a/chapter25/src/main/java/com/seaofnodes/simple/type/TypeScalar.java
+++ b/chapter25/src/main/java/com/seaofnodes/simple/type/TypeScalar.java
@@ -41,14 +41,16 @@ public class TypeScalar extends Type {
@Override boolean _isGLB(boolean mem) { return this == BOT; }
@Override Type _glb(boolean mem) { return BOT; }
- @Override int TAGOFF() { return 1; }
+ // Reserve tags for both lattice endpoints. Unlike most concrete scalar
+ // families, generic scalar TOP can survive into a serialized graph.
+ @Override int TAGOFF() { return 2; }
@Override public void packed(BAOS baos, HashMap<String,Integer> strs) {
- assert this == BOT;
- baos.write(TAGOFFS[_type]);
+ assert this == BOT || this == TOP;
+ baos.write(TAGOFFS[_type] + (this == BOT ? 0 : 1));
}
static TypeScalar packed(int tag) {
- assert tag == 0;
- return BOT;
+ assert tag == 0 || tag == 1;
+ return tag == 0 ? BOT : TOP;
}
@Override public String str() { return isHigh() ? "~scalar" : "scalar"; }