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
|
package com.seaofnodes.simple;
import com.seaofnodes.simple.node.*;
import java.util.BitSet;
import java.util.IdentityHashMap;
import com.seaofnodes.simple.node.cpus.x86_64_v2.MemOpX86;
// Replace ideal nodes with machine nodes, then rebuild the copied graph's uses.
class InstSelect {
private final CodeGen _code;
InstSelect(CodeGen code) { _code=code; }
@SuppressWarnings("unchecked")
void run(String cpu, String callingConv, String base) {
_code._callingConv = switch(callingConv) {
case "SystemV" -> CodeGen.CallingConv.SystemV;
case "Win64" -> CodeGen.CallingConv.Win64;
default -> throw Utils.TODO(); // Unknown calling convention
};
// Look for CPU in fixed named place:
// com.seaofnodes.simple.node.cpus."cpu"."cpu.class"
String clzFile = "com.seaofnodes.simple.node.cpus."+cpu+"."+cpu;
try { _code._mach = ((Class<Machine>) Class.forName( clzFile )).getDeclaredConstructor().newInstance(); }
catch( Exception e ) { throw new RuntimeException(e); }
// Convert to machine ops
_code._uid = 1; // All new machine nodes reset numbering
var map = new IdentityHashMap<Node,Node>();
_instSelect( _code._stop, map );
_code._stop = ( StopNode)map.get(_code._stop );
_code._start = (StartNode)map.get(_code._start);
_instOuts(_code._stop,_code.visit());
_code._visit.clear();
}
private Node _instSelect( Node n, IdentityHashMap<Node,Node> map ) {
if( n==null ) return null;
Node x = map.get(n);
if( x !=null ) return x; // Been there, done that
// If n is a MachConcrete, then its part of a multi-node expansion.
// It does not need instruction selection (already selected!)
// but it does need its inputs walked.
if( n instanceof MachConcreteNode || n instanceof MemOpX86) {
for( int i=0; i < n.nIns(); i++ )
n._inputs.set(i, _instSelect(n.in(i),map) );
return n;
}
// Produce a machine node from n; map it to flag as done so stops cycles.
map.put(n, x=_code._mach.instSelect(n) );
// Walk machine op and replace inputs with mapped inputs
for( int i=0; i < x.nIns(); i++ )
x._inputs.set(i, _instSelect(x.in(i),map) );
if( x instanceof MachNode mach )
mach.postSelect(); // Post selection action
// Updates forward edges only.
n._outputs.clear();
return x;
}
private void _instOuts( Node n, BitSet visit ) {
if( visit.get(n._nid) ) return;
visit.set(n._nid);
for( Node in : n._inputs )
if( in!=null ) {
in._outputs.push(n);
_instOuts(in,visit);
}
}
}
|