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); }
}
|