aa
FunPtrNode.java
Go to the documentation of this file.
1 package com.cliffc.aa.node;
2 
3 import com.cliffc.aa.Env;
4 import com.cliffc.aa.GVNGCM;
5 import com.cliffc.aa.Parse;
6 import com.cliffc.aa.type.*;
7 
8 import static com.cliffc.aa.AA.ARG_IDX;
9 import static com.cliffc.aa.Env.GVN;
10 
11 // See CallNode and FunNode comments. The FunPtrNode converts a RetNode into a
12 // TypeFunPtr with a constant fidx and variable displays. Used to allow first
13 // class functions to be passed about.
14 
15 // FIDXs above-center are used by UnresolvedNode to represent choice.
16 // Normal FunPtrs, in both GCP and Opto/Iter, should be a single (low) FIDX.
17 
18 // Display is e.g. *[12] (alias 12 struct), or some other thing to represent an
19 // unused/dead display. I've been using either ANY or XNIL.
20 
21 // There are several invariants we'd like to have:
22 
23 // The FIDX and DISP match sign: so {-15,ANY} and {+15,NIL} are OK, but
24 // {+15,XNIL} and {+15,ANY} are not. This one is in conflict with the others,
25 // and is DROPPED. Instead we allow e.g. {+15,ANY} to indicate a FIDX 15 with
26 // no display.
27 //
28 // FunPtrNodes strictly fall during GCP; lift during Opto.
29 // So e.g. any -> [-15,any] -> [-15,-12] -> [+15,+12] -> [+15,all] -> all.
30 // But need to fall preserving the existing of DISP.
31 // So e.g. any -> [-15,any] -> [-15,xnil] -> [+15,nil] -> [+15,all] -> all.
32 // So e.g. any -> [-15,-12] -> [+15,+12] -> all.
33 //
34 // FunPtrNodes start being passed e.g. [+12], but during GCP can discover DISP
35 // is dead... but then after GCP need to migrate the types from [+15,+12] to
36 // [+15,nil] which is sideways. Has to happen in a single monolithic pass
37 // covering all instances of [+15,+12]. Also may impact mixed +15 and other
38 // FIDXs with unrelated DISPs. Instead a dead display just flips to ANY.
39 
40 public final class FunPtrNode extends UnOrFunPtrNode {
41  public String _name; // Optional for debug only
42  private ErrMsg _referr; // Forward-ref error, cleared after defining
43 
44  // Every var use that results in a function, so actually only these FunPtrs,
45  // needs to make a "fresh" copy before unification. "Fresh" makes a
46  // structural copy of the TVar, keeping TVars from Nodes currently in-scope
47  // as-is, and making structural copies of out-of-scope TVars. The only
48  // interesting thing is when an out-of-scope TVar uses the same TVar
49  // internally in different parts - the copy replicates this structure. When
50  // unified, it forces equivalence in the same places.
51  public FunPtrNode( String name, RetNode ret, Node display ) { this(name,null,ret,display ); }
52  // Explicitly, no display
53  public FunPtrNode( String name, RetNode ret ) { this(name,null,ret, Env.ANY ); }
54  // Display (already fresh-loaded) but no name.
55  public FunPtrNode( RetNode ret, Node display ) { this(null,null,ret,display); }
56  // For forward-refs only; super weak display & function.
57  private FunPtrNode( String name, ErrMsg referr, RetNode ret, Node display ) {
58  super(OP_FUNPTR,ret,display);
59  _name = name;
60  _referr = referr;
61  }
62  public RetNode ret() { return (RetNode)in(0); }
63  public Node display(){ return in(1); }
64  public FunNode fun() { return ret().fun(); }
65  public FunNode xfun() { RetNode ret = ret(); return ret !=null && ret.in(4) instanceof FunNode ? ret.fun() : null; }
66  @Override public int nargs() { return ret()._nargs; }
67  @Override public FunPtrNode funptr() { return this; }
68  @Override public UnresolvedNode unk() { return null; }
69  // Self short name
70  @Override public String xstr() {
71  if( is_dead() || _defs._len==0 || ret()==null) return "*fun";
72  int fidx = ret()._fidx; // Reliably returns a fidx
73  FunNode fun = FunNode.find_fidx(fidx);
74  return "*"+(fun==null ? ""+fidx : fun.name());
75  }
76  // Inline longer name
77  @Override String str() {
78  if( is_dead() ) return "DEAD";
79  if( _defs._len==0 ) return "MAKING";
80  RetNode ret = ret();
81  if( ret==null || ret.is_copy() ) return "gensym:"+xstr();
82  FunNode fun = ret.fun();
83  return fun==null ? xstr() : fun.str();
84  }
85 
86  // Debug only: make an attempt to bind name to a function
87  public void bind( String tok ) {
88  assert _name==null || _name.equals(tok); // Attempt to double-bind
89  _name = tok;
90  fun().bind(tok);
91  }
92 
93  @Override public Node ideal_reduce() {
94  if( is_forward_ref() ) return null;
95 
96  // Display is known dead? Yank it.
97  Node dsp = display();
98  Type tdsp = dsp._val;
99  if( tdsp instanceof TypeMemPtr && ((TypeMemPtr)tdsp)._obj==TypeObj.UNUSED && !(dsp instanceof ConNode) )
100  return set_def(1,Env.ANY); // No display needed
101 
102  // Remove unused displays. Track uses; Calling with no display is OK.
103  // Uses storing the FPTR and passing it along still require a display.
104  if( GVN._opt_mode._CG && !(dsp instanceof ConNode) && !display_used() )
105  return set_def(1,Env.ANY); // No display needed
106  return null;
107  }
108  // Called if Display goes unused
109  @Override public void add_flow_use_extra(Node chg) {
110  Type tdsp = display()._val;
111  if( tdsp instanceof TypeMemPtr && ((TypeMemPtr)tdsp)._obj==TypeObj.UNUSED )
112  Env.GVN.add_reduce(this);
113  }
114 
115  // Is the display used?
116  private boolean display_used() {
117  for( Node call : _uses ) {
118  if( call instanceof CallNode ) {
119  if( call._defs.find(e->e==this) < call._defs._len-1 )
120  return true; // Call-use other than the last position is using the display
121  } else {
122  return true; // Anything other than a Call is using the display
123  }
124  }
125  return false;
126  }
127 
128 
129  @Override public Type value(GVNGCM.Mode opt_mode) {
130  if( !(in(0) instanceof RetNode) )
131  return TypeFunPtr.EMPTY;
132  return TypeFunPtr.make(ret()._fidx,nargs(),display()._val);
133  }
134  @Override public void add_flow_extra(Type old) {
135  if( old==_live ) // live impacts value
136  Env.GVN.add_flow(this);
137  }
138 
139  @Override public TypeMem live(GVNGCM.Mode opt_mode) {
140  // Pre-GCP, might be used anywhere (still finding the CFG)
141  return !opt_mode._CG ? TypeMem.ESCAPE : super.live(opt_mode);
142  }
143  @Override public TypeMem live_use(GVNGCM.Mode opt_mode, Node def ) {
144  return def==ret() ? TypeMem.ANYMEM : (_live==TypeMem.LNO_DISP ? TypeMem.DEAD : TypeMem.ESCAPE);
145  }
146 
147  //@Override public TV2 new_tvar(String alloc_site) {
148  // return TV2.make("Fun",this,alloc_site);
149  //}
150  //
151  //@Override public boolean unify( boolean test ) {
152  // // Build a HM tvar (args->ret), same as HM.java Lambda does.
153  // // FunNodes are just argument collections (no return).
154  // RetNode ret = ret();
155  // FunNode fun = xfun();
156  // if( fun==null ) return false;
157  // TV2 tret = ret.tvar();
158  // if( tret.is_dead() ) return false;
159  // assert tret.isa("Ret"); // Ret is always a Ret
160  //
161  // // Check for progress before allocation
162  // TV2 tvar = tvar();
163  // if( tvar.is_dead() ) return false;
164  // assert tvar.isa("Fun"); // Self is always a Fun
165  // TV2 tvar_args = tvar.get("Args");
166  // TV2 tvar_ret = tvar.get("Ret" );
167  // Node[] parms = fun.parms();
168  // parms[0] = fun;
169  // if( tvar_args!=null && tvar_args.eq(parms) && tvar_ret==tret ) return false; // Equal parts
170  // // Build function arguments; "fun" itself is just control.
171  // TV2 targ = TV2.make("Args",fun,"FunPtr_unify_Args",parms);
172  // NonBlockingHashMap<Comparable,TV2> args = new NonBlockingHashMap<Comparable,TV2>(){{ put("Args",targ); put("Ret",tret); }};
173  // TV2 tfun = TV2.make("Fun",this,"FunPtr_unify_Fun",args);
174  // return tvar.unify(tfun,test);
175  //}
176 
177  // Filter out all the wrong-arg-count functions from Parser.
178  @Override public FunPtrNode filter( int nargs ) {
179  // User-nargs are user-visible #arguments.
180  // Fun-nargs include ctrl, memory & the display, hence the +ARG_IDX.
181  return nargs() == ARG_IDX+nargs ? this : null;
182  }
183 
184  // Return the op_prec of the returned value. Not sensible except when called
185  // on primitives.
186  @Override public byte op_prec() { return fun()._op_prec; }
187 
188  // Instead of returning the pre-call memory on true, returns self.
189  // Changes as the graph changes, because works purely off of graph shape.
190  @Override Node is_pure_call() {
191  // See if the RetNode points to a Parm:mem (so no mods on memory).
192  RetNode ret = ret();
193  if( ret.is_copy() ) return null;
194  FunNode fun = ret.fun();
195  if( fun.noinline() ) return null; // Disallow if no-inline
196  Node mem = ret.mem();
197  if( mem.in(0)==fun && mem instanceof ParmNode ) return this; // Parm:mem on fun, no mods to memory
198  return null;
199  }
200 
201  // A forward-ref is an assumed unknown-function being used before being
202  // declared. Hence we want a callable function pointer, but have no defined
203  // body (yet). Make a function pointer that takes/ignores all args, and
204  // returns a scalar.
205  public static FunPtrNode forward_ref( GVNGCM gvn, String name, Parse unkref, Env e ) {
206  FunNode fun = gvn.init(new FunNode(name)).unkeep(2);
208  gvn.add_flow(fun);
209  gvn.add_flow(ret);
210  // Display is limited to any one of the current lexical scopes.
212  return new FunPtrNode( name, ErrMsg.forward_ref(unkref,name),ret,Node.con(tdisp));
213  }
214 
215  // True if this is a forward_ref
216  @Override public boolean is_forward_ref() { return _referr!=null; }
217 
218  // 'this' is a forward reference, probably with multiple uses (and no inlined
219  // callers). Passed in the matching function definition, which is brand new
220  // and has no uses. Merge the two.
221  public void merge_ref_def( String tok, FunPtrNode def, NewObjNode dsp ) {
222  FunNode rfun = fun();
223  FunNode dfun = def.fun();
224  assert rfun._defs._len==2 && rfun.in(0)==null && rfun.in(1) == Env.ALL_CTRL; // Forward ref has no callers
225  assert dfun._defs._len==2 && dfun.in(0)==null;
226  assert def ._uses._len==0; // Def is brand new, no uses
227 
228  // Make a function pointer based on the original forward-ref fidx, but with
229  // the known types.
230  FunNode.FUNS.setX(dfun._fidx,null); // Untrack dfun by old fidx
231  dfun._fidx = rfun._fidx;
232  FunNode.FUNS.setX(dfun._fidx,dfun); // Track FunNode by new fidx
233 
234  // Update the fidx
235  RetNode dret = def.ret();
236  dret.set_fidx(rfun._fidx);
237  FunPtrNode fptr = dret.funptr();
238  fptr.xval();
239  Env.GVN.add_flow_uses(this);
240 
241  // The existing forward-ref becomes a normal (not f-ref) but internal
242  // FunPtr; the H-M type is NOT Fresh, and forces alignment amongst the
243  // recursive uses. Make a new FunPtr which IS Fresh for future external
244  // uses.
245  _referr = null; // No longer a forward ref
246  set_def(0,def.in(0)); // Same inputs
247  set_def(1,def.in(1));
248  dsp.set_def(NewObjNode.def_idx(dsp._ts.fld_find(tok)),def);
249  dsp.xval();
250 
251  fptr.bind(tok); // Debug only, associate variable name with function
252  Env.GVN.add_reduce_uses(this);
253  assert Env.START.more_flow(true)==0;
255  }
256 
257  @Override public ErrMsg err( boolean fast ) { return is_forward_ref() ? _referr : null; }
258 }
com.cliffc.aa.type.TypeMem.DEAD
static final TypeMem DEAD
Definition: TypeMem.java:226
com.cliffc.aa.type.TypeFunPtr
Definition: TypeFunPtr.java:23
com.cliffc.aa.type.TypeMem
Memory type; the state of all of memory; memory edges order memory ops.
Definition: TypeMem.java:53
com.cliffc.aa.node.Node._live
TypeMem _live
Definition: Node.java:89
com.cliffc.aa.node.FunNode._op_prec
final byte _op_prec
Definition: FunNode.java:65
com.cliffc.aa.GVNGCM.add_flow_uses
void add_flow_uses(Node n)
Definition: GVNGCM.java:55
com.cliffc.aa.type.Type.SCALAR
static final Type SCALAR
Definition: Type.java:328
com.cliffc
com.cliffc.aa.node.FunPtrNode.funptr
FunPtrNode funptr()
Definition: FunPtrNode.java:67
com.cliffc.aa.node.Node
Definition: Node.java:16
com.cliffc.aa.type.TypeRPC.ALL_CALL
static final TypeRPC ALL_CALL
Definition: TypeRPC.java:31
com.cliffc.aa.node.UnOrFunPtrNode
Definition: UnOrFunPtrNode.java:6
com.cliffc.aa.type.TypeMem.ESCAPE
static final TypeMem ESCAPE
Definition: TypeMem.java:227
com.cliffc.aa.node.Node.OP_FUNPTR
static final byte OP_FUNPTR
Definition: Node.java:28
com.cliffc.aa.type.Type
an implementation of language AA
Definition: Type.java:94
com.cliffc.aa.node.FunPtrNode._referr
ErrMsg _referr
Definition: FunPtrNode.java:42
com.cliffc.aa.node.FunPtrNode.bind
void bind(String tok)
Definition: FunPtrNode.java:87
com.cliffc.aa.node.FunNode.str
String str()
Definition: FunNode.java:107
com.cliffc.aa.node.RetNode.mem
Node mem()
Definition: RetNode.java:29
com.cliffc.aa.AA.ARG_IDX
static final int ARG_IDX
Definition: AA.java:17
com.cliffc.aa.node.Node._val
Type _val
Definition: Node.java:88
com.cliffc.aa.node.FunPtrNode.merge_ref_def
void merge_ref_def(String tok, FunPtrNode def, NewObjNode dsp)
Definition: FunPtrNode.java:221
com.cliffc.aa.node.Node.ErrMsg
Definition: Node.java:888
com.cliffc.aa.node.ConNode
Definition: ConNode.java:9
com.cliffc.aa.node.FunPtrNode
Definition: FunPtrNode.java:40
com.cliffc.aa.node.FunPtrNode.xstr
String xstr()
Definition: FunPtrNode.java:70
com.cliffc.aa.node.RetNode
Definition: RetNode.java:19
com.cliffc.aa.node.CallNode
Definition: CallNode.java:86
com.cliffc.aa.node.FunPtrNode.add_flow_use_extra
void add_flow_use_extra(Node chg)
Definition: FunPtrNode.java:109
com.cliffc.aa.type.TypeMem.ANYMEM
static final TypeMem ANYMEM
Definition: TypeMem.java:228
com.cliffc.aa.Env.START
static StartNode START
Definition: Env.java:14
com.cliffc.aa.node.FunPtrNode.ideal_reduce
Node ideal_reduce()
Definition: FunPtrNode.java:93
com.cliffc.aa.node.FunPtrNode.FunPtrNode
FunPtrNode(String name, ErrMsg referr, RetNode ret, Node display)
Definition: FunPtrNode.java:57
com.cliffc.aa.node.RetNode.set_fidx
void set_fidx(int fidx)
Definition: RetNode.java:47
com.cliffc.aa.Env.GVN
static final GVNGCM GVN
Definition: Env.java:13
com.cliffc.aa.type.TypeMem.LNO_DISP
static final TypeMem LNO_DISP
Definition: TypeMem.java:226
com.cliffc.aa.node.FunNode.name
static String name(int fidx, boolean debug)
Definition: FunNode.java:109
com.cliffc.aa.type.TypeObj
Definition: TypeObj.java:15
com.cliffc.aa.node.NewNode.def_idx
static int def_idx(int fld)
Definition: NewNode.java:52
com.cliffc.aa.node.FunPtrNode.xfun
FunNode xfun()
Definition: FunPtrNode.java:65
com.cliffc.aa.node.RetNode.is_copy
Node is_copy(int idx)
Definition: RetNode.java:212
com.cliffc.aa.node.FunNode._fidx
int _fidx
Definition: FunNode.java:61
com.cliffc.aa.node.Node.is_dead
boolean is_dead()
Definition: Node.java:820
com.cliffc.aa.node.FunPtrNode.FunPtrNode
FunPtrNode(RetNode ret, Node display)
Definition: FunPtrNode.java:55
com.cliffc.aa.type.TypeMem.live
TypeLive live()
Definition: TypeMem.java:559
com.cliffc.aa.node.RetNode._fidx
int _fidx
Definition: RetNode.java:20
com.cliffc.aa.node.FunNode.bind
void bind(String tok)
Definition: FunNode.java:172
com.cliffc.aa.GVNGCM.add_reduce_uses
void add_reduce_uses(Node n)
Definition: GVNGCM.java:57
com.cliffc.aa.type.TypeObj.UNUSED
static final TypeObj UNUSED
Definition: TypeObj.java:46
com.cliffc.aa.node.FunPtrNode.nargs
int nargs()
Definition: FunPtrNode.java:66
com.cliffc.aa.node.FunNode.find_fidx
static FunNode find_fidx(int fidx)
Definition: FunNode.java:101
com.cliffc.aa.node.FunPtrNode.is_pure_call
Node is_pure_call()
Definition: FunPtrNode.java:190
com.cliffc.aa.node.FunPtrNode.add_flow_extra
void add_flow_extra(Type old)
Definition: FunPtrNode.java:134
com.cliffc.aa.type.TypeObj.ISUSED
static final TypeObj ISUSED
Definition: TypeObj.java:45
com.cliffc.aa.node.Node.in
Node in(int i)
Definition: Node.java:126
com.cliffc.aa.node.FunPtrNode.filter
FunPtrNode filter(int nargs)
Definition: FunPtrNode.java:178
com.cliffc.aa.node.RetNode._nargs
int _nargs
Definition: RetNode.java:21
com.cliffc.aa.node.FunPtrNode.unk
UnresolvedNode unk()
Definition: FunPtrNode.java:68
com.cliffc.aa.GVNGCM
Definition: GVNGCM.java:12
com.cliffc.aa.type.TypeFunPtr.make
static TypeFunPtr make(BitsFun fidxs, int nargs, Type disp)
Definition: TypeFunPtr.java:67
com.cliffc.aa.node.FunPtrNode.op_prec
byte op_prec()
Definition: FunPtrNode.java:186
com.cliffc.aa.node.FunPtrNode.err
ErrMsg err(boolean fast)
Definition: FunPtrNode.java:257
com.cliffc.aa.node.FunPtrNode.forward_ref
static FunPtrNode forward_ref(GVNGCM gvn, String name, Parse unkref, Env e)
Definition: FunPtrNode.java:205
com.cliffc.aa.node.FunNode.noinline
boolean noinline()
Definition: FunNode.java:179
com.cliffc.aa.node.FunPtrNode.FunPtrNode
FunPtrNode(String name, RetNode ret, Node display)
Definition: FunPtrNode.java:51
com.cliffc.aa.node.FunPtrNode.ret
RetNode ret()
Definition: FunPtrNode.java:62
com.cliffc.aa.node.NewNode._ts
T _ts
Definition: NewNode.java:25
com.cliffc.aa.node.NewObjNode
Definition: NewObjNode.java:20
com.cliffc.aa.node.Node.con
static Node con(Type t)
Definition: Node.java:670
com.cliffc.aa.node.Node._uses
Ary< Node > _uses
Definition: Node.java:245
com.cliffc.aa.AA
an implementation of language AA
Definition: AA.java:9
com.cliffc.aa
Definition: AA.java:1
com.cliffc.aa.node.UnresolvedNode
Definition: UnresolvedNode.java:13
com.cliffc.aa.node.FunPtrNode.live_use
TypeMem live_use(GVNGCM.Mode opt_mode, Node def)
Definition: FunPtrNode.java:143
com.cliffc.aa.node.FunPtrNode.is_forward_ref
boolean is_forward_ref()
Definition: FunPtrNode.java:216
com.cliffc.aa.node.FunPtrNode._name
String _name
Definition: FunPtrNode.java:41
com.cliffc.aa.node.Node.set_def
Node set_def(int idx, Node n)
Definition: Node.java:154
com.cliffc.aa.GVNGCM.add_reduce
public< N extends Node > N add_reduce(N n)
Definition: GVNGCM.java:49
com.cliffc.aa.Env.LEX_DISPLAYS
static BitsAlias LEX_DISPLAYS
Definition: Env.java:31
com.cliffc.aa.node.ParmNode
Definition: ParmNode.java:14
com.cliffc.aa.node.FunPtrNode.FunPtrNode
FunPtrNode(String name, RetNode ret)
Definition: FunPtrNode.java:53
com.cliffc.aa.type.TypeRPC
Definition: TypeRPC.java:7
com.cliffc.aa.node.FunPtrNode.value
Type value(GVNGCM.Mode opt_mode)
Definition: FunPtrNode.java:129
com.cliffc.aa.node.Node.xval
Type xval()
Definition: Node.java:460
com.cliffc.aa.node.RetNode.fun
FunNode fun()
Definition: RetNode.java:32
com.cliffc.aa.GVNGCM.add_flow
public< N extends Node > N add_flow(N n)
Definition: GVNGCM.java:50
com.cliffc.aa.node.RetNode.funptr
FunPtrNode funptr()
Definition: RetNode.java:37
com.cliffc.aa.type.TypeFunPtr.EMPTY
static final TypeFunPtr EMPTY
Definition: TypeFunPtr.java:81
com.cliffc.aa.GVNGCM.iter
void iter(Mode opt_mode)
Definition: GVNGCM.java:147
com.cliffc.aa.node.FunPtrNode.fun
FunNode fun()
Definition: FunPtrNode.java:64
com.cliffc.aa.node.FunNode
Definition: FunNode.java:58
com.cliffc.aa.node.FunPtrNode.display
Node display()
Definition: FunPtrNode.java:63
com.cliffc.aa.node.Node.ErrMsg.forward_ref
static ErrMsg forward_ref(Parse loc, FunPtrNode fun)
Definition: Node.java:896
com.cliffc.aa.node.FunPtrNode.display_used
boolean display_used()
Definition: FunPtrNode.java:116
com.cliffc.aa.node.FunPtrNode.live
TypeMem live(GVNGCM.Mode opt_mode)
Definition: FunPtrNode.java:139
com.cliffc.aa.Env.ANY
static ConNode ANY
Definition: Env.java:24
com
com.cliffc.aa.node.FunPtrNode.str
String str()
Definition: FunPtrNode.java:77
com.cliffc.aa.type.TypeMem.MEM
static final TypeMem MEM
Definition: TypeMem.java:224
com.cliffc.aa.Env
Definition: Env.java:12
com.cliffc.aa.GVNGCM.Mode.Parse
Parse
Definition: GVNGCM.java:15
com.cliffc.aa.node.FunNode.FUNS
static Ary< FunNode > FUNS
Definition: FunNode.java:99
com.cliffc.aa.type
Definition: Bits.java:1
com.cliffc.aa.GVNGCM.init
public< N extends Node > N init(N n)
Definition: GVNGCM.java:99
com.cliffc.aa.node.Node._defs
Ary< Node > _defs
Definition: Node.java:124
com.cliffc.aa.type.TypeMemPtr
Definition: TypeMemPtr.java:14
com.cliffc.aa.Parse
an implementation of language AA
Definition: Parse.java:68
com.cliffc.aa.Env.ALL_CTRL
static ConNode ALL_CTRL
Definition: Env.java:20
com.cliffc.aa.GVNGCM.Mode
Definition: GVNGCM.java:14
com.cliffc.aa.type.TypeMemPtr.make
static TypeMemPtr make(BitsAlias aliases, TypeObj obj)
Definition: TypeMemPtr.java:66