From eee5b806fabae0b480ff7d41159369c5a457d014 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Tue, 26 Nov 2024 11:01:47 -0800 Subject: Chapter 18: Functions --- src/main/java/com/seaofnodes/simple/CodeGen.java | 123 +++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 src/main/java/com/seaofnodes/simple/CodeGen.java (limited to 'src/main/java/com/seaofnodes/simple/CodeGen.java') diff --git a/src/main/java/com/seaofnodes/simple/CodeGen.java b/src/main/java/com/seaofnodes/simple/CodeGen.java new file mode 100644 index 00000000..47616b51 --- /dev/null +++ b/src/main/java/com/seaofnodes/simple/CodeGen.java @@ -0,0 +1,123 @@ + package com.seaofnodes.simple; + +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.type.*; +import java.util.HashMap; + +public class CodeGen { + + public enum Phase { + Parse, Opto, TypeCheck, Schedule, LocalSched, RegAlloc; + } + public Phase _phase; + + public final String _src; + // Compile-time known initial argument type + public final TypeInteger _arg; + + public Parser P; + public StartNode _start; + public StopNode _stop ; + + + // "Linker" mapping from constant TypeFunPtrs to heads of function. These + // TFPs all have exact single fidxs and their return is wiped to BOTTOM (so + // the return is not part of the match). + private final HashMap _linker = new HashMap<>(); + + + // Last created CodeGen as a global, for easier debugging prints + public static CodeGen CODE; + + CodeGen( String src, TypeInteger arg ) { _phase = null; _src = src; _arg=arg; CODE=this; } + public CodeGen( String src ) { this(src,TypeInteger.BOT); } + + public CodeGen parse() { return parse(false); } + public CodeGen parse(boolean disable) { + assert _phase == null; + _phase = Phase.Parse; + _linker.clear(); + + P = new Parser(_src,_arg); + Node._disablePeephole = disable; + _stop = P.parse(); + _start = Parser.START; // Capture global start + JSViewer.show(); + P = null; // No longer parsing + return this; + } + + public CodeGen opto() { + assert _phase == Phase.Parse; + _phase = Phase.Opto; + + // Optimization + IterPeeps.iterate(_stop); + + // TODO: + // Optimistic + return this; + } + + public CodeGen typeCheck() { + // Demand phase Opto for cleaning up dead control flow at least, + // required for the following GCM. Note that peeps can be disabled, + // but still the dead CFG will get cleaned. + assert _phase == Phase.Opto; + _phase = Phase.TypeCheck; + + // Type check + Parser.ParseException err = _stop.walk( Node::err ); + if( err != null ) + throw err; + return this; + } + + + public CodeGen GCM() { return GCM(false); } + public CodeGen GCM( boolean show) { + assert _phase == Phase.TypeCheck; + _phase = Phase.Schedule; + + // Build the loop tree, fix never-exit loops + _start.buildLoopTree(_stop); + if( show ) + System.out.println(new GraphVisualizer().generateDotOutput(_stop,null,null)); + + // TODO: + // loop unroll, peel, RCE, etc + GlobalCodeMotion.buildCFG(_start,_stop); + return this; + } + + // Local (basic block) scheduler phase, a classic list scheduler + public CodeGen localSched() { + assert _phase == Phase.Schedule; + _phase = Phase.LocalSched; + ListScheduler.sched(this); + return this; + } + + // Reverse from a constant function pointer to the IR function being called + public FunNode link( TypeFunPtr tfp ) { + assert tfp.isConstant(); + return _linker.get(tfp.makeFrom(Type.BOTTOM)); + } + + public void link(FunNode fun) { + _linker.put(fun.sig().makeFrom(Type.BOTTOM),fun); + } + + // Testing shortcuts + Node ctrl() { return _stop.ret().ctrl(); } + Node expr() { return _stop.ret().expr(); } + String print() { return _stop.print(); } + + // Debugging helper + @Override public String toString() { + return _stop.p(9999); + } + + // Debugging helper + public Node f(int idx) { return _stop.find(idx); } +} -- cgit v1.2.3