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 IRPrinter.prettyPrint(this);
}
// Debugging helper
public Node f(int idx) { return _stop.find(idx); }
}
|