summaryrefslogtreecommitdiff
path: root/chapter18/src/main/java/com/seaofnodes/simple/CodeGen.java
blob: a9dfe47612a989039b34c257144693e675d7bd34 (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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
 package com.seaofnodes.simple;

import com.seaofnodes.graph.GraphObserver;

import com.seaofnodes.simple.node.*;
import com.seaofnodes.simple.type.*;
import java.util.HashMap;

public class CodeGen {
    public GraphObserver<Node> _obs;

    // Inlining can insert CFG edges and invalidate cached depth ordering.
    private char _iDepthVersion;
    public char iDepthVersion() { return _iDepthVersion; }
    public void invalidateIDepthCaches() {
        assert _iDepthVersion < Character.MAX_VALUE : "Dominator cache version exceeds 65535";
        ++_iDepthVersion;
    }



    public enum Phase {
        Parse, Opto, TypeCheck, Schedule, LocalSched, RegAlloc;
    }
    public Phase _phase;

    public final String _src;
    // Compile-time known initial argument type
    public final TypeInteger _arg;

    public Parser P;
    public StartNode _start;
    public  StopNode _stop ;


    // "Linker" mapping from constant TypeFunPtrs to heads of function.  These
    // TFPs all have exact single fidxs and their return is wiped to BOTTOM (so
    // the return is not part of the match).
    private final HashMap<TypeFunPtr,FunNode> _linker = new HashMap<>();


    // Last created CodeGen as a global, for easier debugging prints
    public static CodeGen CODE;

    CodeGen( String src, TypeInteger arg ) { _phase = null; _src = src; _arg=arg; CODE=this; }
    public CodeGen( String src ) { this(src,TypeInteger.BOT); }

    public CodeGen parse() {
        assert _phase == null;
        _phase = Phase.Parse;
        _linker.clear();

        P = new Parser(_src,_arg);
        _stop = P.parse();
        _start = Parser.START;   // Capture global start
        if( _obs != null ) _obs.phase("Parse");
        P = null;                // No longer parsing
        return this;
    }

    public CodeGen opto() {
        assert _phase == Phase.Parse;
        _phase = Phase.Opto;

        // Optimization
        IterPeeps.iterate(_stop);

        // TODO:
        // Optimistic
        if( _obs != null ) _obs.phase("Opto");
        return this;
    }

    public CodeGen typeCheck() {
        // Demand phase Opto for cleaning up dead control flow at least,
        // required for the following GCM.
        assert _phase == Phase.Opto;
        _phase = Phase.TypeCheck;

        // Type check
        Parser.ParseException err = _stop.walk(n -> {
            Parser.ParseException msg = n.err();
            if( msg != null && _obs != null ) _obs.error(n, msg.getMessage());
            return msg;
        });
        if( err != null )
            throw err;
        if( _obs != null ) _obs.phase("TypeCheck");
        return this;
    }


    public CodeGen GCM() {
        assert _phase == Phase.TypeCheck;
        _phase = Phase.Schedule;

        // Build the loop tree, fix never-exit loops
        _start.buildLoopTree(_stop);


        // TODO:
        // loop unroll, peel, RCE, etc
        GlobalCodeMotion.buildCFG(_start,_stop);
        return this;
    }

    // Local (basic block) scheduler phase, a classic list scheduler
    public CodeGen localSched() {
        assert _phase == Phase.Schedule;
        _phase = Phase.LocalSched;
        ListScheduler.sched(this);
        return this;
     }

    // Reverse from a constant function pointer to the IR function being called
    public FunNode link( TypeFunPtr tfp ) {
        assert tfp.isConstant();
        return _linker.get(tfp.makeFrom(Type.BOTTOM));
    }

    public void link(FunNode fun) {
        _linker.put(fun.sig().makeFrom(Type.BOTTOM),fun);
    }

    // Testing shortcuts
    Node ctrl() { return _stop.ret().ctrl(); }
    Node expr() { return _stop.ret().expr(); }
    String print() { return _stop.print(); }

    // Debugging helper
    @Override public String toString() {
        return _stop.p(9999);
    }

    // Debugging helper
    public Node f(int idx) { return _stop.find(idx); }
}