Skip to content

Commit bd293df

Browse files
Merge pull request #50 from CompilerProgramming/son21
Apply fixes from Simple project
2 parents 0e1fdbb + b07a059 commit bd293df

File tree

7 files changed

+419
-1218
lines changed

7 files changed

+419
-1218
lines changed

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

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

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

52+
@SuppressWarnings("unchecked")
5253
public <N extends Node> N add( N n ) { return (N)_work.push(n); }
5354

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

131133
private Node[] _es;

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

+16-7
Original file line numberDiff line numberDiff line change
@@ -29,21 +29,28 @@ 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-
// 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-
}
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));
3938
return this;
4039
}
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+
4147
// Fixed width field
4248
public SB fix( int sz, String s ) {
4349
for( int i=0; i<sz; i++ )
4450
_sb.append( i < s.length() ? s.charAt(i) : ' ');
4551
return this;
4652
}
53+
public char at(int idx ) { return _sb.charAt(idx); }
4754

4855
// Not spelled "p" on purpose: too easy to accidentally say "p(1.0)" and
4956
// suddenly call the autoboxed version.
@@ -83,6 +90,8 @@ public boolean was_nl() {
8390
//
8491
public SB unchar() { return unchar(1); }
8592
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); }
8695

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

seaofnodes/src/main/java/com/compilerprogramming/ezlang/compiler/print/ASMPrinter.java

+173-49
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import com.compilerprogramming.ezlang.compiler.nodes.*;
77
import com.compilerprogramming.ezlang.compiler.sontypes.*;
88

9+
import java.util.HashSet;
10+
911
public abstract class ASMPrinter {
1012

1113
public static SB print(SB sb, CodeGen code) {
@@ -17,118 +19,190 @@ public static SB print(SB sb, CodeGen code) {
1719
for( int i=0; i<code._cfg._len; i++ )
1820
if( code._cfg.at(i) instanceof FunNode fun )
1921
iadr = print(iadr,sb,code,fun,i);
22+
23+
// Skip padding
24+
while( ((iadr+7) & -8) > iadr )
25+
iadr++;
26+
27+
// constant pool
28+
Encoding enc = code._encoding;
29+
if( enc!=null && !enc._bigCons.isEmpty() ) {
30+
iadr = (iadr+15)&-16; // pad to 16
31+
HashSet<SONType> targets = new HashSet<>();
32+
sb.p("--- Constant Pool ------").nl();
33+
// By log size
34+
for( int log = 3; log >= 0; log-- ) {
35+
for( Node op : enc._bigCons.keySet() ) {
36+
Encoding.Relo relo = enc._bigCons.get(op);
37+
if( targets.contains(relo._t) ) continue;
38+
targets.add(relo._t);
39+
if( relo._t.log_size()==log ) {
40+
sb.hex2(iadr).p(" ");
41+
if( relo._t instanceof SONTypeTuple tt ) {
42+
for( SONType tx : tt._types ) {
43+
switch( log ) {
44+
case 0: sb.hex1(enc.read1(iadr)); break;
45+
case 1: sb.hex2(enc.read2(iadr)); break;
46+
case 2: sb.hex4(enc.read4(iadr)); break;
47+
case 3: sb.hex8(enc.read8(iadr)); break;
48+
}
49+
iadr += (1<<log);
50+
sb.p(" ");
51+
}
52+
} else {
53+
switch( log ) {
54+
case 0: sb.hex1(enc.read1(iadr)).fix(9-1,""); break;
55+
case 1: sb.hex2(enc.read2(iadr)).fix(9-2,""); break;
56+
case 2: sb.hex4(enc.read4(iadr)).fix(9-4,""); break;
57+
case 3: sb.hex8(enc.read8(iadr)).p(" "); break;
58+
}
59+
iadr += (1<<log);
60+
}
61+
relo._t.print(sb).nl();
62+
}
63+
}
64+
}
65+
}
66+
67+
2068
return sb;
2169
}
2270

2371
private static int print(int iadr, SB sb, CodeGen code, FunNode fun, int cfgidx) {
72+
FunNode old=null;
73+
if( code._encoding!=null ) {
74+
old = code._encoding._fun;
75+
code._encoding._fun = fun; // Useful printing after RA
76+
}
2477
// Function header
2578
sb.nl().p("---");
2679
if( fun._name != null ) sb.p(fun._name).p(" ");
2780
fun.sig().print(sb);
2881
sb.p("---------------------------").nl();
82+
iadr = (iadr + 15)&-16; // All function entries padded to 16 align
2983

30-
84+
if( fun._frameAdjust != 0 )
85+
iadr = doInst(iadr,sb,code,fun,cfgidx,fun,true,true);
3186
while( !(code._cfg.at(cfgidx) instanceof ReturnNode) )
3287
iadr = doBlock(iadr,sb,code,fun,cfgidx++);
3388

3489
// Function separator
3590
sb.p("---");
3691
fun.sig().print(sb);
3792
sb.p("---------------------------").nl();
93+
if( code._encoding != null )
94+
code._encoding._fun = old;
3895
return iadr;
3996
}
4097

41-
static private final int encWidth = 8;
4298
static private final int opWidth = 5;
4399
static private final int argWidth = 30;
44100
static int doBlock(int iadr, SB sb, CodeGen code, FunNode fun, int cfgidx) {
101+
final int encWidth = code._mach==null ? 2 : code._mach.defaultOpSize()*2;
45102
CFGNode bb = code._cfg.at(cfgidx);
46103
if( bb != fun && !(bb instanceof IfNode) && !(bb instanceof CallEndNode) && !(bb instanceof CallNode) && !(bb instanceof CProjNode && bb.in(0) instanceof CallEndNode ))
47-
sb.p(bb instanceof LoopNode ? "LOOP" : "L").p(bb._nid).p(":").nl();
104+
sb.p(label(bb)).p(":").nl();
48105
if( bb instanceof CallNode ) return iadr;
49106
final boolean postAlloc = code._phase.ordinal() > CodeGen.Phase.RegAlloc.ordinal();
107+
final boolean postEncode= code._phase.ordinal() >=CodeGen.Phase.Encoding.ordinal();
50108

51-
// Count Phis
52-
int nPhi=0;
53-
for( ; nPhi<bb.nOuts(); nPhi++ )
54-
if( !(bb.out(nPhi) instanceof PhiNode) )
55-
break;
56-
57-
if( nPhi>0 ) {
58-
// Post-alloc phi prints all on one line
109+
boolean once=false;
110+
for( Node n : bb.outs() ) {
111+
if( !(n instanceof PhiNode phi) ) continue;
112+
if( phi._type instanceof SONTypeMem || phi._type instanceof SONTypeRPC ) continue; // Nothing for the hidden ones
113+
// Post-RegAlloc phi prints all on one line
59114
if( postAlloc ) {
60-
sb.fix(4," ").p(" ").fix(encWidth,"").p(" ");
61-
for( int i=0; i<nPhi; i++ ) {
62-
PhiNode phi = (PhiNode)bb.out(i);
63-
if( !(phi._type instanceof SONTypeMem || phi._type instanceof SONTypeRPC) ) // Nothing for the hidden ones
64-
sb.p(phi._label).p(':').p(code.reg(phi)).p(',');
65-
}
66-
sb.unchar().nl();
67-
115+
if( !once ) { once=true; sb.fix(4," ").p(" ").fix(encWidth,"").p(" "); }
116+
sb.p(phi._label).p(':').p(code.reg(phi,fun)).p(',');
68117
} else {
69-
for( int j=0; j<nPhi; j++ ) {
70-
PhiNode phi = (PhiNode)bb.out(j);
71-
if( phi._type instanceof SONTypeMem || phi._type instanceof SONTypeRPC ) continue; // Nothing for the hidden ones
72-
sb.fix(4," ").p(" ").fix(encWidth,"").p(" ").fix(opWidth,phi._label).p(" ");
73-
sb.p(code.reg(phi));
74-
if( !(phi instanceof ParmNode) ) {
75-
sb.p(" = phi( ");
76-
for( int i=1; i<phi.nIns(); i++ )
77-
sb.p("N").p(phi.in(i)._nid).p(",");
78-
sb.unchar().p(" )");
79-
}
80-
sb.nl();
118+
// Pre-RegAlloc phi prints one line per
119+
sb.fix(4," ").p(" ").fix(encWidth,"").p(" ").fix(opWidth,phi._label).p(" ").p(code.reg(phi,fun));
120+
if( phi.getClass() == PhiNode.class ) {
121+
sb.p(" = phi( ");
122+
for( int i=1; i<phi.nIns(); i++ )
123+
sb.p("N").p(phi.in(i)._nid).p(",");
124+
sb.unchar().p(" )");
81125
}
126+
sb.nl();
82127
}
83128
}
129+
if( once ) sb.unchar().nl();
84130

85131
// All the non-phis
86-
for( int i=nPhi; i<bb.nOuts(); i++ )
87-
iadr = doInst(iadr, sb,code,fun,bb,bb.out(i),postAlloc );
132+
for( int i=0; i<bb.nOuts(); i++ )
133+
if( !(bb.out(i) instanceof PhiNode) )
134+
iadr = doInst(iadr, sb,code, fun, cfgidx, bb.out(i),postAlloc, postEncode );
88135

89136
return iadr;
90137
}
91138

92-
static int doInst(int iadr, SB sb, CodeGen code, FunNode fun, CFGNode bb, Node n, boolean postAlloc ) {
93-
if( n instanceof CProjNode ) return iadr;
94-
if( n instanceof CalleeSaveNode && postAlloc ) return iadr;
139+
static int doInst( int iadr, SB sb, CodeGen code, FunNode fun, int cfgidx, Node n, boolean postAlloc, boolean postEncode ) {
140+
if( n==null || n instanceof CProjNode ) return iadr;
141+
if( postAlloc && n instanceof CalleeSaveNode ) return iadr;
142+
if( postEncode && n instanceof ProjNode ) return iadr;
143+
if( n instanceof MemMergeNode ) return iadr;
144+
if( n.getClass() == ConstantNode.class ) return iadr; // Default placeholders
145+
final int dopz = code._mach==null ? 2 : code._mach.defaultOpSize();
146+
final int encWidth = dopz*2;
95147

96148
// All blocks ending in a Region will need to either fall into or jump
97149
// to this block. Until the post-reg-alloc block layout cleanup, we
98150
// need to assume a jump. There's no real hardware op here, yet.
99-
if( n instanceof RegionNode && !(n instanceof FunNode) ) {
100-
sb.hex4(iadr++).p(" ").fix(encWidth,"??").p(" ").fix(opWidth,"JMP").p(" ").fix(argWidth,"L"+n._nid).nl();
151+
if( n instanceof RegionNode cfg && !(n instanceof FunNode) ) {
152+
if( postEncode ) return iadr; // All jumps inserted already
153+
while( cfgidx < code._cfg._len-1 ) {
154+
CFGNode next = code._cfg.at(++cfgidx);
155+
if( next == n ) return iadr; // Fall-through, no branch
156+
if( next.nOuts()>1 )
157+
break; // Has code in the block, need to jump around
158+
// No code in the block, can fall through it
159+
}
160+
sb.hex2(iadr++).p(" ").fix(encWidth,"??").p(" ").fix(opWidth,"JMP").p(" ").fix(argWidth,label(cfg)).nl();
101161
return iadr;
102162
}
103163

104164
// ProjNodes following a multi (e.g. Call or New results),
105165
// get indent slightly and just print their index & node#
106166
if( n instanceof ProjNode proj ) {
107167
if( proj._type instanceof SONTypeMem ) return iadr; // Nothing for the hidden ones
108-
sb.fix(4," ").p(" ").fix(encWidth,"").p(" ").fix(opWidth,proj._label==null ? "---" : proj._label).p(" ").p(code.reg(n)).nl();
168+
sb.fix(4," ").p(" ").fix(encWidth,"").p(" ").fix(opWidth,proj._label==null ? "---" : proj._label).p(" ").p(code.reg(n,fun)).nl();
109169
return iadr;
110170
}
111171

112172
// ADDR ENCODING Op--- dst = src op src // Comment
113173
// 1234 abcdefgh ld4 RAX = [Rbase + off] // Comment
114-
sb.hex4(iadr);
115-
sb.p(" ");
174+
sb.hex2(iadr).p(" ");
116175

117176
// Encoding
118-
int size = 1; // TODO: Fake encoding size
119-
iadr += size;
120-
sb.fix(encWidth,"??");
177+
int fatEncoding = 0;
178+
if( code._encoding != null ) {
179+
int size = code._encoding._opLen[n._nid];
180+
if( code._asmLittle )
181+
for( int i=0; i<Math.min(size,dopz); i++ )
182+
sb.hex1(code._encoding._bits.buf()[iadr++]);
183+
else {
184+
iadr += Math.min(size,dopz);
185+
for( int i=0; i<Math.min(size,dopz); i++ )
186+
sb.hex1(code._encoding._bits.buf()[iadr-i-1]);
187+
}
188+
for( int i=size*2; i<encWidth; i++ )
189+
sb.p(" ");
190+
fatEncoding = size - (encWidth>>1); // Not-printed parts of encoding
191+
} else
192+
sb.fix(encWidth,"");
121193
sb.p(" ");
122194

123195
// Op; generally "ld4" or "call"
124-
sb.fix(opWidth, n instanceof MachNode mach ? mach.op() : n.label());
125-
sb.p(" ");
196+
sb.fix(opWidth, n instanceof MachNode mach ? mach.op() : n.label()).p(" ");
126197

127198
// General asm args
199+
String isMultiOp = null;
128200
if( n instanceof MachNode mach ) {
129201
int old = sb.len();
130202
mach.asm(code,sb);
131-
sb.fix(argWidth-(sb.len()-old),""); // Pad out
203+
int len = sb.len();
204+
isMultiOp = isMultiOp(sb,old,len);
205+
sb.fix(argWidth-(len-old),""); // Pad out
132206

133207
} else if( !(n._type instanceof SONTypeMem) ) {
134208
// Room for some inputs
@@ -149,14 +223,64 @@ static int doInst(int iadr, SB sb, CodeGen code, FunNode fun, CFGNode bb, Node n
149223

150224
sb.nl();
151225

226+
// Printing more op bits than fit
227+
if( isMultiOp != null && code._encoding != null ) {
228+
// Multiple ops, template style, no RA, no scheduling. Print out
229+
// one-line-per-newline, with encoding bits up front.
230+
int size = code._encoding._opLen[n._nid];
231+
int off = Math.min(size,dopz);
232+
while( isMultiOp!=null ) {
233+
sb.hex2(iadr).p(" ");
234+
int len = Math.min(size-off,dopz);
235+
for( int i=0; i<len; i++ )
236+
sb.hex1(code._encoding._bits.buf()[iadr++]);
237+
off += len;
238+
for( int i=len; i<dopz; i++ ) sb.p(" ");
239+
sb.p(" ");
240+
int x = isMultiOp.indexOf('\n');
241+
if( x== -1 ) { // Last line
242+
sb.p(isMultiOp).nl();
243+
isMultiOp = null;
244+
} else {
245+
sb.p(isMultiOp.substring(0,x+1)); // Includes the newline
246+
isMultiOp = isMultiOp.substring(x+1);
247+
}
248+
249+
}
250+
251+
} else if( fatEncoding > 0 ) {
252+
// Extra bytes past the default encoding width, all put on a line by
253+
// themselves. X86 special for super long encodings
254+
sb.hex2(iadr).p(" ");
255+
for( int i=0; i<fatEncoding; i++ )
256+
sb.hex1(code._encoding._bits.buf()[iadr++]);
257+
sb.nl();
258+
}
259+
260+
152261
// MultiNodes are immediately followed by projection(s)
153262
if( !(n instanceof CFGNode) && n instanceof MultiNode ) {
154263
for( Node proj : n._outputs ) {
155-
assert proj instanceof ProjNode;
156-
doInst(iadr,sb,code,fun,bb,proj,postAlloc);
264+
if( proj instanceof ProjNode ) // it could also be an ante-dep
265+
doInst(iadr,sb,code,fun, cfgidx, proj,postAlloc,postEncode);
157266
}
158267
}
159268

160269
return iadr;
161270
}
271+
272+
private static String label( CFGNode bb ) {
273+
return (bb instanceof LoopNode ? "LOOP" : "L")+bb._nid;
274+
}
275+
276+
private static String isMultiOp(SB sb, int old, int len) {
277+
for( int i=old; i<len; i++ )
278+
if( sb.at(i)=='\n' ) {
279+
String s = sb.subString(i+1,len);
280+
sb.setLen(i);
281+
return s;
282+
}
283+
return null;
284+
}
285+
162286
}

0 commit comments

Comments
 (0)