Skip to content

Commit 59b5d14

Browse files
Merge pull request #46 from CompilerProgramming/son21
Sync up with finalized chapter 21
2 parents 790d2aa + 0eaa7bb commit 59b5d14

File tree

120 files changed

+1794
-1491
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

120 files changed

+1794
-1491
lines changed

seaofnodes/src/main/java/com/compilerprogramming/ezlang/compiler/IterPeeps.java

-2
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ public class IterPeeps {
4949

5050
public IterPeeps( long seed ) { _work = new WorkList<>(seed); }
5151

52-
@SuppressWarnings("unchecked")
5352
public <N extends Node> N add( N n ) { return (N)_work.push(n); }
5453

5554
public void addAll( Ary<Node> ary ) { _work.addAll(ary); }
@@ -127,7 +126,6 @@ private boolean progressOnList(CodeGen code) {
127126
* Classic WorkList, with a fast add/remove, dup removal, random pull.
128127
* The Node's nid is used to check membership in the worklist.
129128
*/
130-
@SuppressWarnings("unchecked")
131129
public static class WorkList<E extends Node> {
132130

133131
private Node[] _es;

seaofnodes/src/main/java/com/compilerprogramming/ezlang/compiler/SB.java

+7-16
Original file line numberDiff line numberDiff line change
@@ -29,28 +29,21 @@ else if( Double.isInfinite(s) ) {
2929
public SB p( int s ) { _sb.append(s); return this; }
3030
public SB p( long s ) { _sb.append(s); return this; }
3131
public SB p( boolean s) { _sb.append(s); return this; }
32-
// 1 byte, 2 hex digits, 8 bits
33-
public SB hex1(int s) {
34-
int digit = (s>>4) & 0xf;
35-
_sb.append((char)((digit <= 9 ? '0' : ('A'-10))+digit));
36-
digit = s & 0xf;
37-
_sb.append((char)((digit <= 9 ? '0' : ('A'-10))+digit));
32+
// 4 hex digits
33+
public SB hex4(int s) {
34+
assert (s>>4*4)==0; // Fits in 16 bits
35+
for( int i=0; i<4; i++ ) {
36+
int digit = (s>>((3-i)*4)) & 0xf;
37+
_sb.append((char)((digit <= 9 ? '0' : ('A'-10))+digit));
38+
}
3839
return this;
3940
}
40-
// 2 bytes, 4 hex digits, 16 bits, Big Endian
41-
public SB hex2(int s) { return hex1(s>> 8).hex1(s); }
42-
// 4 bytes, 8 hex digits, 32 bits, Big Endian
43-
public SB hex4(int s) { return hex2(s>>16).hex2(s); }
44-
// 8 bytes, 16 hex digits, 64 bits, Big Endian
45-
public SB hex8(long s) { return hex4((int)(s>>32)).hex4((int)s); }
46-
4741
// Fixed width field
4842
public SB fix( int sz, String s ) {
4943
for( int i=0; i<sz; i++ )
5044
_sb.append( i < s.length() ? s.charAt(i) : ' ');
5145
return this;
5246
}
53-
public char at(int idx ) { return _sb.charAt(idx); }
5447

5548
// Not spelled "p" on purpose: too easy to accidentally say "p(1.0)" and
5649
// suddenly call the autoboxed version.
@@ -90,8 +83,6 @@ public boolean was_nl() {
9083
//
9184
public SB unchar() { return unchar(1); }
9285
public SB unchar(int x) { _sb.setLength(_sb.length()-x); return this; }
93-
public SB setLen(int len) { _sb.setLength(len); return this; }
94-
public String subString(int start, int end ) { return _sb.substring(start,end); }
9586

9687
public SB clear() { _sb.setLength(0); return this; }
9788
public int len() { return _sb.length(); }

seaofnodes/src/main/java/com/compilerprogramming/ezlang/compiler/codegen/BuildLRG.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ public static boolean run(int round, RegAlloc alloc) {
5555
if( n.in(i)!=null ) {
5656
LRG lrg2 = alloc.lrg(n.in(i));
5757
if( lrg2 != null ) { // Anti-dep or other, no LRG
58-
RegMask use_mask = mach.regmap(i);
59-
if( !lrg2.machUse(mach,(short)i,use_mask.size1()).and(use_mask) )
58+
RegMask use_mask = mach.regmap(i); // use_mask is also null for anti-dep
59+
if( use_mask!=null && !lrg2.machUse(mach,(short)i,use_mask.size1()).and(use_mask) )
6060
alloc.fail(lrg2); // Empty register mask, must split
6161
}
6262
}

seaofnodes/src/main/java/com/compilerprogramming/ezlang/compiler/codegen/CodeGen.java

+89-16
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public enum Phase {
2222
Parse, // Parse ASCII text into Sea-of-Nodes IR
2323
Opto, // Run ideal optimizations
2424
TypeCheck, // Last check for bad programs
25+
LoopTree, // Build a loop tree; break infinite loops
2526
InstSelect, // Convert to target hardware nodes
2627
Schedule, // Global schedule (code motion) nodes
2728
LocalSched, // Local schedule
@@ -52,6 +53,27 @@ public CodeGen( String src, SONTypeInteger arg, long workListSeed ) {
5253
}
5354

5455

56+
// All passes up to Phase, except ELF
57+
public CodeGen driver( Phase phase ) { return driver(phase,null,null); }
58+
public CodeGen driver( Phase phase, String cpu, String callingConv ) {
59+
if( _phase==null ) parse();
60+
if( _phase.ordinal() < phase.ordinal() ) opto();
61+
if( _phase.ordinal() < phase.ordinal() ) typeCheck();
62+
if( _phase.ordinal() < phase.ordinal() ) loopTree();
63+
if( _phase.ordinal() < phase.ordinal() && cpu != null ) instSelect(cpu,callingConv);
64+
if( _phase.ordinal() < phase.ordinal() ) GCM();
65+
if( _phase.ordinal() < phase.ordinal() ) localSched();
66+
if( _phase.ordinal() < phase.ordinal() ) regAlloc();
67+
if( _phase.ordinal() < phase.ordinal() ) encode();
68+
return this;
69+
}
70+
71+
// Run all the phases through final ELF emission
72+
public CodeGen driver( String cpu, String callingConv, String obj ) throws IOException {
73+
return driver(Phase.Encoding,cpu,callingConv).exportELF(obj);
74+
}
75+
76+
5577
// ---------------------------
5678
/**
5779
* A counter, for unique node id generation. Starting with value 1, to
@@ -125,6 +147,7 @@ public CodeGen parse() {
125147
assert _phase == null;
126148
_phase = Phase.Parse;
127149
long t0 = System.currentTimeMillis();
150+
128151
P.parse();
129152
_tParse = (int)(System.currentTimeMillis() - t0);
130153
return this;
@@ -180,18 +203,42 @@ public CodeGen typeCheck() {
180203
return this;
181204
}
182205

206+
// ---------------------------
207+
// Build the loop tree; break never-exit loops
208+
public int _tLoopTree;
209+
public CodeGen loopTree() {
210+
assert _phase.ordinal() <= Phase.TypeCheck.ordinal();
211+
_phase = Phase.LoopTree;
212+
long t0 = System.currentTimeMillis();
213+
// Build the loop tree, fix never-exit loops
214+
_start.buildLoopTree(_stop);
215+
_tLoopTree = (int)(System.currentTimeMillis() - t0);
216+
return this;
217+
}
183218

184219
// ---------------------------
185220
// Code generation CPU target
186221
public Machine _mach;
187-
//
222+
// Chosen calling convention (usually either Win64 or SystemV)
188223
public String _callingConv;
224+
// Callee save registers
225+
public RegMask _callerSave;
226+
227+
// All returns have the following inputs:
228+
// 0 - ctrl
229+
// 1 - memory
230+
// 2 - varies with returning GPR,FPR
231+
// 3 - RPC
232+
// 4+- Caller save registers
233+
public RegMask[] _retMasks;
234+
// Return Program Counter
235+
public RegMask _rpcMask;
189236

190237
// Convert to target hardware nodes
191238
public int _tInsSel;
192239
public CodeGen instSelect( String cpu, String callingConv ) { return instSelect(cpu,callingConv,PORTS); }
193240
public CodeGen instSelect( String cpu, String callingConv, String base ) {
194-
assert _phase.ordinal() <= Phase.TypeCheck.ordinal();
241+
assert _phase.ordinal() == Phase.LoopTree.ordinal();
195242
_phase = Phase.InstSelect;
196243

197244
_callingConv = callingConv;
@@ -203,6 +250,27 @@ public CodeGen instSelect( String cpu, String callingConv, String base ) {
203250
try { _mach = ((Class<Machine>) Class.forName( clzFile )).getDeclaredConstructor(new Class[]{CodeGen.class}).newInstance(this); }
204251
catch( Exception e ) { throw new RuntimeException(e); }
205252

253+
// Build global copies of common register masks.
254+
long callerSave = _mach.callerSave();
255+
long neverSave = _mach. neverSave();
256+
int maxReg = Math.min(64,_mach.regs().length);
257+
assert maxReg>=64 || (-1L << maxReg & callerSave)==0; // No stack slots in callerSave
258+
_callerSave = new RegMask(callerSave);
259+
260+
// Build a Return RegMask array. All returns have the following inputs:
261+
// 0 - ctrl
262+
// 1 - memory
263+
// 2 - varies with returning GPR,FPR
264+
// 3 - RPC
265+
// 4+- Caller save registers
266+
_retMasks = new RegMask[(maxReg-_callerSave.size()-Long.bitCount( neverSave ))+4];
267+
for( int reg=0, i=4; reg<maxReg; reg++ )
268+
if( !_callerSave.test(reg) && ((1L<<reg)&neverSave)==0 )
269+
_retMasks[i++] = new RegMask(reg);
270+
_rpcMask = new RegMask(_mach.rpc());
271+
_retMasks[3] = _rpcMask;
272+
273+
206274
// Convert to machine ops
207275
long t0 = System.currentTimeMillis();
208276
_uid = 1; // All new machine nodes reset numbering
@@ -258,7 +326,7 @@ private void _instOuts( Node n, BitSet visit ) {
258326

259327

260328
// ---------------------------
261-
// Control Flow Graph in RPO order.
329+
// Control Flow Graph in Reverse Post Order.
262330
public int _tGCM;
263331
public Ary<CFGNode> _cfg = new Ary<>(CFGNode.class);
264332

@@ -269,8 +337,6 @@ public CodeGen GCM( boolean show) {
269337
_phase = Phase.Schedule;
270338
long t0 = System.currentTimeMillis();
271339

272-
// Build the loop tree, fix never-exit loops
273-
_start.buildLoopTree(_stop);
274340
GlobalCodeMotion.buildCFG(this);
275341
_tGCM = (int)(System.currentTimeMillis() - t0);
276342
if( show )
@@ -305,34 +371,32 @@ public CodeGen regAlloc() {
305371
return this;
306372
}
307373

308-
public String reg(Node n) {
374+
// Human readable register name
375+
public String reg(Node n) { return reg(n,null); }
376+
public String reg(Node n, FunNode fun) {
309377
if( _phase.ordinal() >= Phase.RegAlloc.ordinal() ) {
310-
String s = _regAlloc.reg(n);
378+
String s = _regAlloc.reg(n,fun);
311379
if( s!=null ) return s;
312380
}
313381
return "N"+ n._nid;
314382
}
315383

384+
316385
// ---------------------------
317386
// Encoding
318387
public int _tEncode;
319-
public boolean _JIT;
320-
public Encoding _encoding;
321-
public CodeGen encode(boolean jit) {
388+
public Encoding _encoding; // Encoding object
389+
public void preEncode() { } // overridden by alternative ports
390+
public CodeGen encode() {
322391
assert _phase == Phase.RegAlloc;
323392
_phase = Phase.Encoding;
324393
long t0 = System.currentTimeMillis();
325394
_encoding = new Encoding(this);
326-
_JIT = jit;
395+
preEncode();
327396
_encoding.encode();
328397
_tEncode = (int)(System.currentTimeMillis() - t0);
329398
return this;
330399
}
331-
public CodeGen encode() {
332-
return encode(false);
333-
}
334-
// Encoded binary, no relocation info
335-
public byte[] binary() { return _encoding.bits(); }
336400

337401
// ---------------------------
338402
// Exporting to external formats
@@ -365,6 +429,15 @@ public CodeGen exportELF(String fname) throws IOException {
365429
// Debugging helper
366430
public Node f(int idx) { return _stop.find(idx); }
367431

432+
433+
String printCFG() {
434+
if( _cfg==null ) return "no CFG";
435+
SB sb = new SB();
436+
for( CFGNode cfg : _cfg )
437+
IRPrinter.printLine(cfg,sb);
438+
return sb.toString();
439+
}
440+
368441
public static void print_as_hex(Encoding enc) {
369442
for (byte b : enc._bits.toByteArray()) {
370443
System.out.print(String.format("%02X", b));

0 commit comments

Comments
 (0)