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
138
139
140
|
package com.seaofnodes.simple;
import com.seaofnodes.simple.node.*;
import com.seaofnodes.simple.SB;
import com.seaofnodes.simple.type.TypeFunPtr;
import com.seaofnodes.simple.type.TypeMem;
import com.seaofnodes.simple.type.TypeRPC;
public abstract class ASMPrinter {
public static SB print(SB sb, CodeGen code) {
if( code._cfg==null )
return sb.p("Need _cfg set, run after GCM");
// instruction address
int iadr = 0;
for( int i=0; i<code._cfg._len; i++ )
if( code._cfg.at(i) instanceof FunNode fun )
iadr = print(iadr,sb,code,fun,i);
return sb;
}
private static int print(int iadr, SB sb, CodeGen code, FunNode fun, int cfgidx) {
// Function header
sb.nl().p("---");
fun.sig().print(sb);
sb.p("---------------------------").nl();
while( !(code._cfg.at(cfgidx) instanceof ReturnNode) )
iadr = doBlock(iadr,sb,code,fun,cfgidx++);
// Function separator
sb.p("---");
fun.sig().print(sb);
sb.p("---------------------------").nl();
return iadr;
}
static int doBlock(int iadr, SB sb, CodeGen code, FunNode fun, int cfgidx) {
CFGNode bb = code._cfg.at(cfgidx);
if( bb != fun && !(bb instanceof IfNode) && !(bb instanceof CallEndNode) && !(bb instanceof CallNode) && !(bb instanceof CProjNode && bb.in(0) instanceof CallEndNode ))
sb.p("L").p(bb._nid).p(":").nl();
if( !(bb instanceof CallNode) )
for( Node n : bb._outputs )
iadr = doInst(iadr, sb,code,fun,bb,n);
return iadr;
}
static int doInst(int iadr, SB sb, CodeGen code, FunNode fun, CFGNode bb, Node n) {
final int encWidth = 8;
final int opWidth = 5;
final int argWidth = 30;
if( n instanceof CProjNode ) return iadr;
// Phis are useful before (and during) reg alloc
if( n instanceof PhiNode phi ) {
if( phi._type instanceof TypeMem || phi._type instanceof TypeRPC ) return iadr; // Nothing for the hidden ones
sb.fix(4," ").p(" ").fix(encWidth,"").p(" ").fix(opWidth,phi._label).p(" ");
sb.p(code.reg(n));
if( !(n instanceof ParmNode) ) {
sb.p(" = phi( ");
for( int i=1; i<n.nIns(); i++ )
sb.p("N").p(n.in(i)._nid).p(",");
sb.unchar().p(" )");
}
sb.nl();
return iadr;
}
// All blocks ending in a Region will need to either fall into or jump
// to this block. Until the post-reg-alloc block layout cleanup, we
// need to assume a jump. There's no real hardware op here, yet.
if( n instanceof RegionNode && !(n instanceof FunNode) ) {
sb.hex4(iadr++).p(" ").fix(encWidth,"??").p(" ").fix(opWidth,"JMP").p(" ").fix(argWidth,"L"+n._nid).nl();
return iadr;
}
// ProjNodes following a multi (e.g. Call or New results),
// get indent slightly and just print their index & node#
if( n instanceof ProjNode proj ) {
if( proj._type instanceof TypeMem ) return iadr; // Nothing for the hidden ones
sb.fix(4," ").p(" ").fix(encWidth,"").p(" ").fix(opWidth,proj._label==null ? "---" : proj._label).p(" ").p(code.reg(n)).nl();
return iadr;
}
// ADDR ENCODING Op--- dst = src op src // Comment
// 1234 abcdefgh ld4 RAX = [Rbase + off] // Comment
sb.hex4(iadr);
sb.p(" ");
// Encoding
int size = 1; // TODO: Fake encoding size
iadr += size;
sb.fix(encWidth,"??");
sb.p(" ");
// Op; generally "ld4" or "call"
sb.fix(opWidth, n instanceof MachNode mach ? mach.op() : n.label());
sb.p(" ");
// General asm args
if( n instanceof MachNode mach ) {
int old = sb.len();
mach.asm(code,sb);
sb.fix(argWidth-(sb.len()-old),""); // Pad out
} else if( !(n._type instanceof TypeMem) ) {
// Room for some inputs
sb.fix(5, n._nid+":" );
int off = 0;
for( int i=0; i<n.nIns(); i++ ) {
sb.fix(5, n.in(i) == null ? "___" : String.valueOf(n.in(i)._nid));
off += 5;
if( off >= argWidth ) break;
}
if( off < argWidth ) sb.fix(argWidth-off,"");
}
sb.p(" ");
// Comment
String comment = n.comment();
if( comment!=null ) sb.p("// ").p(comment);
sb.nl();
// MultiNodes are immediately followed by projection(s)
if( !(n instanceof CFGNode) && n instanceof MultiNode ) {
for( Node proj : n._outputs ) {
assert proj instanceof ProjNode;
doInst(iadr,sb,code,fun,bb,proj);
}
}
return iadr;
}
}
|