summaryrefslogtreecommitdiff
path: root/chapter18/src/main/java/com/seaofnodes/simple/CodeGen.java
blob: 4b8a7235d90f0c0079a431e991144c5eefbc9baf (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
 package com.seaofnodes.simple;

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

public class CodeGen {

    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() { return parse(false); }
    public CodeGen parse(boolean disable) {
        assert _phase == null;
        _phase = Phase.Parse;
        _linker.clear();

        P = new Parser(_src,_arg);
        Node._disablePeephole = disable;
        _stop = P.parse();
        _start = Parser.START;   // Capture global start
        JSViewer.show();
        P = null;                // No longer parsing
        return this;
    }

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

        // Optimization
        IterPeeps.iterate(_stop);

        // TODO:
        // Optimistic
        return this;
    }

    public CodeGen typeCheck() {
        // Demand phase Opto for cleaning up dead control flow at least,
        // required for the following GCM.  Note that peeps can be disabled,
        // but still the dead CFG will get cleaned.
        assert _phase == Phase.Opto;
        _phase = Phase.TypeCheck;

        // Type check
        Parser.ParseException err = _stop.walk( Node::err );
        if( err != null )
            throw err;
        return this;
    }


    public CodeGen GCM() { return GCM(false); }
    public CodeGen GCM( boolean show) {
        assert _phase == Phase.TypeCheck;
        _phase = Phase.Schedule;

        // Build the loop tree, fix never-exit loops
        _start.buildLoopTree(_stop);
        if( show )
            System.out.println(new GraphVisualizer().generateDotOutput(_stop,null,null));

        // 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 IRPrinter.prettyPrint(this);
    }

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