Home My Page Projects Code Snippets Project Openings diderot
Summary Activity Tracker Tasks SCM

SCM Repository

[diderot] Diff of /trunk/src/compiler/codegen/codegen-fn.sml
ViewVC logotype

Diff of /trunk/src/compiler/codegen/codegen-fn.sml

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 511, Tue Feb 8 17:01:43 2011 UTC revision 1116, Thu May 5 04:49:02 2011 UTC
# Line 1  Line 1 
1  (* codegen-fn.sml  (* codegen-fn.sml
2   *   *
3   * COPYRIGHT (c) 2010 The Diderot Project (http://diderot-language.cs.uchicago.edu)   * COPYRIGHT (c) 2011 The Diderot Project (http://diderot-language.cs.uchicago.edu)
4   * All rights reserved.   * All rights reserved.
5   *   *
6   * Generic support for translating LowIL code to the target representation.  We   * Generic support for translating LowIL code to the target representation.
7   * assume that the LowIL has first been run through the splitting pass to match   *
8   * the target's vector widths.   * FIXME:
9     *      We need to run the TreeIL through a splitting pass to match the target's vector widths.
10   *)   *)
11    
12  functor CodeGenFn (T : TARGET) : sig  functor CodeGenFn (T : TARGET) : sig
13    
14      val generate : LowIL.program -> T.program      val generate : string * LowIL.program -> unit
15    
16    end = struct    end = struct
17    
18      structure Src = LowIL      structure IL = TreeIL
     structure SrcV = LowIL.Var  
     structure SrcOp = LowOps  
     structure SrcNd = LowIL.Node  
   
   (* a property marking nodes that are directly referenced by statememts. *)  
     local  
       val {getFn, setFn, ...} = SrcNd.newFlag ()  
     in  
     val isFirst = getFn  
     fun markFirst nd = setFn(nd, true)  
     end  
   
   (* walk the statements, marking the first nodes of the statements *)  
     fun markNodes (stm as SrcIL.STM{kind, next}) = (  
           case kind  
            of SrcIL.S_SIMPLE nd => markFirst (nd, stm)  
             | SrcIL.S_IF{cond, thenBranch, elseBranch} => (  
                 markFirst (cond, stm);  
                 markNodes thenBranch;  
                 markNodes elseBranch)  
             | SrcIL.S_LOOP{hdr, cond, body} => (  
                 markNodes hdr;  
                 markFirst (cond, stm);  
                 markNodes body)  
           (* end case *);  
           case next  
            of NONE => ()  
             | SOME stm => markNodes stm  
           (* end case *))  
   
   (* a mapping from LowIL variables to target expressions.  Variables get  
    * removed when the expressions are used as arguments.  
    *)  
     structure VDefTbl : sig  
         type tbl  
   
         val newTbl : unit -> tbl  
         val getDefOf : tbl -> SrcV.var -> T.exp  
         val useDefOf : tbl -> SrcV.var -> T.exp  
         val setDefOf : tbl -> (SrcV.var * T.exp) -> unit  
   
         val clear : tbl -> unit  
   
         val bind : tbl -> (SrcV.var * T.exp) -> T.stm list  
   
       (* force all pending expressions into variables *)  
         val flush : tbl -> T.stm list  
   
       end = struct  
   
         type info = {  
             cnt : int ref,      (* count of oustanding uses (usually 1) *)  
             bind : T.exp  
           }  
   
         type tbl = info SrcV.Tbl.hash_table  
19    
20          fun newTbl () = SrcV.Tbl.mkTable (512, Fail "vtbl")      structure LowToTree = LowToTreeFn(T)
21    
22          fun getDefOf tbl x = (case SrcV.Tbl.find tbl x      fun trMethod (strand, stateVars, env) = let
23                 of NONE => ??            val varyingStateVars = List.mapPartial
24                  | SOME{bind, cnt} => bind                  (fn (IL.SV{varying = true, var, ...}) => SOME var | _ => NONE)
25                (* end case *))                    stateVars
26              val env = T.Env.scopeMethod (env, varyingStateVars)
27          fun useDefOf tbl x = (case SrcV.Tbl.find tbl x            fun tr (IL.Method{name, body}) = let
28                 of NONE => ??                  val body = T.Tr.block (env, body)
29                  | SOME{cnt=ref n, bind} => (                  in
30                      ignore (SrcV.Tbl.remove tbl x);                    T.Strand.method (strand, Atom.toString name, body)
31                      bind)                  end
32                  | SOME{cnt, bind} =>  => (            in
33                      cnt := !cnt - 1;              tr
34                      bind)            end
35                (* end case *))  
36        fun trStrand (prog, env) (IL.Strand{name, params, state, stateInit, methods}) = let
37          fun setDefOf tbl (x, exp) =            val strand = T.Strand.define(prog, name)
38                SrcV.Tbl.insert tbl (x, {cnt = ref(SrcV.useCount x), bind = exp})            val env = T.Env.scopeStrand (env, List.map (fn (IL.SV{var, ...}) => var) state)
39            (* the output state variable *)
40          fun assign tbl (x, exp) = let            val outputVar = ref NONE
41                      val lhs : T.local_var = ??          (* map the state variables to target state variables and extend the environment *)
42                      in            val env = let
43                        SrcV.Tbl.insert tbl                  fun cvtSVar (IL.SV{output, var=x, ...}, env) = let
44                          (x, {cnt = SrcV.useCount x, bind = T.Expr.var lhs});                        val x' = T.Var.state(strand, x)
45                        [T.Stmt.assign(lhs, exp)]                        in
46                            case (output, !outputVar)
47                             of (true, NONE) => outputVar := SOME(IL.Var.ty x, x')
48                              | (false, _) => ()
49                              | _ => raise Fail("multiple outputs in " ^ Atom.toString name)
50                            (* end case *);
51                            T.Env.bind(env, x, x')
52                      end                      end
   
         fun bind tbl (x, exp) = (case SrcV.useCount lhs  
                of 1 => (SrcV.Tbl.insert tbl (x, {cnt = 1, bind = exp}); [])  
                 | n => let (* bind exp to a new target variable *)  
                     val lhs : T.local_var = ??  
53                      in                      in
54                        SrcV.Tbl.insert tbl (x, {cnt = n, bind = T.Expr.var lhs});                  (* note that we folr right-to-left to get the order of state variables in the
55                        [T.Stmt.assign(lhs, exp)]                   * target strand in the right order.
56                     *)
57                      List.foldr cvtSVar env state
58                    end
59            (* define the parameters and add them to the environment *)
60              val params' = List.map T.Var.param params
61              val env = ListPair.foldlEq (fn (x, y, env) => T.Env.bind(env, x, y)) env (params, params')
62              in
63                T.Strand.init (strand, params', T.Tr.block (env, stateInit));
64                case !outputVar
65                 of NONE => raise Fail("no output specified for strand " ^ Atom.toString name)
66                  | SOME(ty, x) => T.Strand.output (strand, ty, x)
67                (* end case *);
68                List.app (trMethod (strand, state, env)) methods
69                      end                      end
               (* end case *))  
70    
71        end (*  VDefTbl *)      fun trInitially (env0, prog, {isArray, iterPrefix, iters, createPrefix, strand, args}) = let
72              val env0 = T.Env.scopeInitially env0
73              fun trIter ((param, lo, hi), (env, iters)) = let
74                    val param' = T.Var.param param
75                    val env = T.Env.bind (env, param, param')
76                    val iter = (param', T.Tr.exp (env0, lo), T.Tr.exp (env0, hi))
77                    in
78                      (env, iter::iters)
79                    end
80              val (env, iters) = List.foldr trIter (env0, []) iters
81              in
82                T.Program.initially {
83                    prog = prog,
84                    isArray = isArray,
85                    iterPrefix = T.Tr.block (env0, iterPrefix),
86                    iters = iters,
87                    createPrefix = T.Tr.block (env, createPrefix),
88                    strand = strand,
89                    args = List.map (fn e => T.Tr.exp(env, e)) args
90                  }
91              end
92    
93  (* FIXME: what about splitting code where the target width doesn't match the      fun generate (fileStem, srcProg) = let
94   * source width?            val treeProg as TreeIL.Program{globals, globalInit, strands, initially} =
95                    PhaseTimer.withTimer Timers.timeLowToTree LowToTree.translate srcProg
96    val _ = (
97    TextIO.output(Log.logFile(), "********** After translation to TreeIL **********\n");
98    TreeILPP.program (Log.logFile(), treeProg))
99              val prog = T.Program.new ()
100              val env = T.Env.new prog
101            (* define the globals and initialize the environment *)
102              val env = let
103                  (* produce a list of target variables for the globals, such that each global
104                   * has a unique name.
105   *)   *)
106      fun doRator (vtbl, lhs, rator, args) = let                  fun genName (x, (cnt, globs)) = let
107            val args' = List.map (VDefTbl.useDefOf vtbl) args                        val name = IL.Var.name x
108            val rhs' = (case rator                        fun uniqueName (name, cnt) =
109  (* ??? *)                              if List.exists (fn (_, y) => (name = T.Var.name y)) globs
110                  (* end case *))                                then uniqueName(name ^ Int.toString cnt, cnt+1)
111            in                                else (name, cnt)
112              VDefTbl.bind vtbl (lhs, rhs')                        val (name, cnt) = uniqueName (IL.Var.name x, cnt)
113            end                        in
114                            (cnt, (x, T.Var.global(prog, name, IL.Var.ty x))::globs)
115    (* translate a LowIL assignment to a list of zero or more target statements *)                        end
116      fun doAssign vtbl (lhs, rhs) = let                  val (_, globs) = List.foldl genName (0, []) globals
117            fun setDef rhs = (VTbl.setDefOf vtbl (lhs, rhs); [])                  fun gvar ((x, x'), env) = T.Env.bind(env, x, x')
118            in                  in
119              case rhs                    List.foldl gvar (T.Env.scopeGlobal env) globs
120               of Src.VAR x => setDef (T.Expr.var(VDefTbl.useDefOf vtbl x))                  end
121                | Src.LIT(Literal.Int n) => setDef (T.Expr.intLit n)            in
122                | Src.LIT(Literal.Bool b) => setDef (T.Expr.boolLit b)            (* global initialization *)
123                | Src.LIT(Literal.Float f) => setDef (T.Expr.floatLit f)              T.Program.init (prog, T.Tr.block (T.Env.scopeGlobal env, globalInit));
124                | Src.LIT(Literal.String s) => setDef (T.Expr.stringLit s)            (* translate strands *)
125                | Src.OP(rator, args) => doRator(vtbl, lhs, rator, args)              List.app (trStrand (prog, env)) strands;
126                | Src.CONS args =>            (* generate the initially function *)
127                    VTbl.assign ctbl (lhs, T.Expr.vector (List.map (VDefTbl.useDefOf vtbl) args))              trInitially (env, prog, initially);
128              (* end case *)            (* output the program *)
129            end              T.Program.generate (fileStem, prog)
   
     fun gen (vtbl, stm) = let  
           val doAssign = doAssign vtbl  
           fun mkBlock [] = ?  
             | mkBlock [s] = s  
             | mkBlock stms = T.Stmt.block stms  
           fun doStmt (SrcIL.STM{kind, next, ...}) = let  
                 val stms = (case kind  
                        of SrcIL.S_SIMPLE nd => doNode nd  
                         | SrcIL.S_IF{cond, thenBranch, elseBranch} => let  
                             val SrcIL.ND{kind=SrcIL.COND{cond, ...}, ...} = cond  
                             val s1 = mkBlock(doStmt thenBranch)  
                             val s2 = mkBlock(doStmt elseBranch)  
                             in  
 (* FIXME: check for empty else branch *)  
                               T.ifthenelse(VDefTbl.useDefOf vtbl cond, s1, s2)  
                             end  
                         | SrcIL.S_LOOP{hdr, cond, body} => raise Fail "LOOP not supported yet"  
                       (* end case *))  
                 val rest = (case next  
                        of NONE => VDefTbl.flush vtbl  
                         | SOME stm = doStmt stm  
                       (* end case *))  
                 in  
                   stms @ rest  
                 end  
           and doNode (SrcIL.ND{kind, ...}) = (case kind  
                  of SrcIL.NULL => ??  
                   | SrcIL.ENTRY{succ} => nextNode succ  
                   | SrcIL.JOIN{succ, ...} =>  
                   | SrcIL.COND{cond, ...} =>  
                   | SrcIL.BLOCK{body, succ, ...} =>  
                       List.app doAssign body @ nextNode succ  
                   | SrcIL.NEW{strand, args, ...} =>  
                   | SrcIL.DIE _ =>  
                   | SrcIL.STABILIZE _ =>  
                   | SrcIL.EXIT _ =>  
                 (* end case *))  
           and nextNode nd = if isFirst nd then [] else doNode nd  
           in  
             mkBlock (doStmt stm)  
130            end            end
131    
132    end    end

Legend:
Removed from v.511  
changed lines
  Added in v.1116

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0