@@ -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