1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
package com.seaofnodes.simple.node;
import com.seaofnodes.print.ExprPrinter;
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeScalar;
import com.seaofnodes.simple.util.BAOS;
import com.seaofnodes.simple.util.Utils;
import java.util.HashMap;
import java.util.IdentityHashMap;
// A branch-proven refinement to zero/null or non-zero/non-null. The value
// family is deliberately taken from the input when it becomes known.
public class GuardNode extends Node {
public final boolean _nonZero;
public GuardNode(boolean nonZero, Node ctrl, Node val) {
super(ctrl,val);
_nonZero = nonZero;
}
public GuardNode(GuardNode guard) {
super(guard);
_nonZero = guard._nonZero;
}
@Override public Tag serialTag() { return Tag.Guard; }
@Override public void packed(BAOS baos, HashMap<String,Integer> strs, HashMap<Type,Integer> types, IdentityHashMap<Node,Integer> anodes) {
baos.write(_nonZero ? 1 : 0);
}
static Node make(BAOS bais) { return new GuardNode(bais.read()!=0,null,null); }
@Override public String label() { return _nonZero ? "(!=0)" : "(==0)"; }
@Override protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
return p.p(label()).n(in(1));
}
@Override public Type compute() {
// Guard is a pinned, path-local fact. If its control path is not
// executable, the fact is not executable either, regardless of how the
// value input sharpens later.
Type c = in(0)._type;
if( c != Type.CONTROL && c != Type.BOTTOM )
return Type.TOP;
Type t = in(1)._type;
if( t==Type.BOTTOM || t==Type.TOP ) return t;
// The scalar envelope does not identify a value family. Preserve it
// until SCCP learns whether this is an int, float, pointer, or fptr;
// choosing generic ptr here can be weaker than a later concrete type.
if( t==TypeScalar.BOT || t==TypeScalar.TOP ) return t;
Type t2 = _nonZero ? t.nonZero() : t.makeZero();
return t2==null ? (_type==null ? Type.TOP : _type) : t2; // No sane answer for e.g. not-zero of a zero
}
@Override public Node idealize() {
if( in(0)._type != Type.CONTROL && in(0)._type != Type.BOTTOM )
return null;
if( in(1)._type==Type.BOTTOM || in(1)._type==Type.TOP ) return null;
if( _type.isHighOrConst() && in(1)._type.isa(_type) )
return in(1);
return null;
}
@Override public boolean eq(Node n) { return _nonZero==((GuardNode)n)._nonZero; }
@Override int hash() { return _nonZero ? 1 : 0; }
}
|