package com.seaofnodes.simple.node;
import com.seaofnodes.print.ExprPrinter;
import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeFunPtr;
import com.seaofnodes.simple.util.BAOS;
import java.util.HashMap;
import java.util.IdentityHashMap;
/**
* A Constant node represents a constant value.
*
* 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
* meaning, and it is present solely to allow visitation.
*
* The Constant's value is the value stored in it.
*/
public class ConstantNode extends TypeNode {
public ConstantNode( Type type ) {
this(type,false);
}
protected ConstantNode( Type type, boolean raw ) {
super(type,new Node[]{CodeGen.CODE._start});
assert raw || !(type instanceof TypeFunPtr tfp && tfp.isConstant()) :
"Unique function identities require a Return-linked FunPtrNode";
_type = type;
}
public ConstantNode( ConstantNode con ) { super(con); }
@Override public Tag serialTag() { return Tag.Con; }
@Override public void packed( BAOS baos, HashMap strs, HashMap types, IdentityHashMap anodes ) {
baos.packed2(types.get(_con)); // NPE if fails lookup
}
static Node make( BAOS bais, Type[] types) { return raw(types[bais.packed2()]); }
// Semantic constant construction through Opto. A unique internal
// function identity carries a lifetime edge to the function's Return.
public static Node make( Type type ) {
if( type==Type. CONTROL ) return new CtrlNode();
if( type==Type.XCONTROL ) return new XCtrlNode();
if( CodeGen.CODE._phase != null &&
CodeGen.CODE._phase.ordinal() > CodeGen.Phase.Opto.ordinal() )
return raw(type);
if( type instanceof TypeFunPtr tfp && tfp.isConstant() ) {
FunNode fun = CodeGen.CODE._link(tfp);
if( fun != null )
return new FunPtrNode(tfp,CodeGen.CODE._start,fun.ret()).init();
// TODO: A singleton FIDX can also emerge after merging and
// guarding several function pointers. Preserve that identity
// even if its internal Return is no longer available.
return raw(type);
}
return new ConstantNode(type);
}
// Exact construction for deserialization and graph-incomplete machine
// selection. No semantic classification, compute, idealize, or GVN.
public static ConstantNode raw( Type type ) { return new ConstantNode(type,true); }
public static ConstantNode raw( ConstantNode con ) { return new ConstantNode(con); }
// Analysis input created from whole cloth, rather than a first-class
// runtime value. In particular, a constructor call descriptor does not
// own the constructor function; the class FunPtr does.
public static ConstantNode seed( Type type ) { return new ConstantNode(type,true); }
@Override protected String repeatName() {
return _con==null || _con.toString().length()<=32 ? null : uniqueName();
}
@Override public String label() { return "Con"; }
@Override public Node copy() { return raw(this); }
@Override
protected ExprPrinter _print1(ExprPrinter p) {
if( _con instanceof TypeFunPtr tfp && tfp._isConstant() && tfp.notNull() ) {
FunNode fun = CodeGen.CODE._link(tfp);
if( fun!=null && fun._name != null )
return p.p("{ ").p(fun._name).p("}");
}
return p.p(_con==null ? "---" : _con.toString());
}
@Override public boolean isConst() { return true; }
@Override public Type compute() { return _con; }
@Override public Node idealize() { return null; }
}