summaryrefslogtreecommitdiff
path: root/src/main/java/com/seaofnodes/simple/print/SimpleGraphAdapter.java
blob: 9ca0ec51e914ebce36b4e1275352a2bb79e50ff8 (plain)
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
69
70
71
72
73
74
75
76
77
78
79
80
package com.seaofnodes.simple.print;

import com.seaofnodes.graph.GraphAdapter;
import com.seaofnodes.graph.GraphSnapshot.*;
import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.node.*;
import com.seaofnodes.simple.node.Node;
import com.seaofnodes.simple.type.TypeMem;

/** Chapter 25's view of the IR, including partially constructed parse-time graphs. */
public class SimpleGraphAdapter extends GraphAdapter<Node> {

    @Override protected boolean show(Node n) {
        if( n != CodeGen.CODE.ZERO && n != CodeGen.CODE.XCTRL ) return true;
        for( int i=0; i<n.nOuts(); i++ )
            if( n.out(i) != null ) return true;
        return false; // The parser's keep is not a graph use.
    }

    @Override protected String edgeName(Node n, int i) {
        return n instanceof ScopeNode scope && i < scope._vars.size()
                ? scope.var(i)._name : null;
    }
    @Override protected int edgeJump(Node n, int i) {
        return n instanceof CallEndNode && i>0 && n.in(i) instanceof ReturnNode ret
                ? ref(ret.fun()) : 0;
    }
    @Override protected int projectionIndex(Node n) { return n instanceof Proj p ? p.idx() : -1; }

    @Override protected boolean folding(Node n) {
        if( n instanceof FunNode fun ) return fun.folding();
        if( n instanceof ReturnNode ret ) return ret.fun().folding();
        if( n instanceof CallEndNode cend ) return cend.folding();
        if( n instanceof CallNode )
            for( int i=0; i<n.nOuts(); i++ )
                if( n.out(i) instanceof CallEndNode cend && cend.folding() ) return true;
        return false;
    }

    @Override protected Kind kind(Node n) {
        if( n instanceof StopNode ) return Kind.STOP;
        if( n instanceof ScopeNode ) return Kind.SCOPE;
        if( n instanceof StartCUNode ) return Kind.UNIT;
        if( n instanceof FunNode ) return Kind.FUN;
        // Start inherits Loop for whole-program analysis, but is not a source loop.
        if( n instanceof StartNode ) return Kind.START;
        if( n instanceof LoopNode ) return Kind.LOOP;
        if( n instanceof RegionNode ) return Kind.REGION;
        if( n instanceof PhiNode ) return Kind.PHI;
        if( n instanceof CFGNode ) return Kind.CTRL;
        return isMem(n) ? Kind.MEM : Kind.DATA;
    }

    @Override protected Role role(Node n, int i) {
        if( n instanceof ScopeNode || n instanceof ConstantNode || n instanceof FunPtrNode ||
            n instanceof CtrlNode || n instanceof XCtrlNode )
            return Role.ASSOC;
        if( n instanceof PhiNode )
            return i == 0 ? Role.ASSOC : isMem(n) ? Role.MEM : Role.DATA;
        if( n instanceof Proj )
            return n instanceof CFGNode ? Role.CTRL : isMem(n) ? Role.MEM : Role.DATA;
        // StartCU inherits Region, but slot 0 really connects it to Start.
        if( n instanceof StartCUNode && i == 0 ) return Role.CTRL;
        if( n instanceof RegionNode && i == 0 ) return Role.ASSOC;
        // Preserve known slot roles even when an input is not attached/typed yet.
        if( i == 0 || n instanceof RegionNode || n instanceof StopNode ) return Role.CTRL;
        if( n instanceof MemMergeNode ||
            (i == 1 && (n instanceof MemOpNode || n instanceof ReturnNode || n instanceof CallNode)) ||
            (n instanceof EscapeNode && i >= 2) ) return Role.MEM;
        Node def = n.in(i);
        if( def instanceof CFGNode ) return Role.CTRL;
        if( def != null && isMem(def) ) return Role.MEM;
        return Role.DATA;
    }

    private boolean isMem(Node n) {
        // These Phi subclasses are memory even before their first type computation.
        return n instanceof MemPhiNode || n instanceof BulkMemPhiNode || n.isMem() || n._type instanceof TypeMem;
    }
}