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

SCM Repository

[diderot] Annotation of /branches/pure-cfg/src/compiler/codegen/codegen-fn.sml
ViewVC logotype

Annotation of /branches/pure-cfg/src/compiler/codegen/codegen-fn.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 529 - (view) (download)

1 : jhr 454 (* codegen-fn.sml
2 :     *
3 :     * COPYRIGHT (c) 2010 The Diderot Project (http://diderot-language.cs.uchicago.edu)
4 :     * All rights reserved.
5 : jhr 455 *
6 :     * Generic support for translating LowIL code to the target representation. We
7 :     * assume that the LowIL has first been run through the splitting pass to match
8 :     * the target's vector widths.
9 : jhr 454 *)
10 :    
11 :     functor CodeGenFn (T : TARGET) : sig
12 :    
13 : jhr 518 val generate : string * LowIL.program -> unit
14 : jhr 454
15 :     end = struct
16 :    
17 : jhr 512 structure IL = LowIL
18 : jhr 525 structure Ty = LowILTypes
19 : jhr 512 structure V = LowIL.Var
20 :     structure Op = LowOps
21 :     structure Nd = LowIL.Node
22 : jhr 514 structure CFG = LowIL.CFG
23 : jhr 454
24 : jhr 525 (* convert LowIL types to T types *)
25 :     fun cvtTy ty = (case ty
26 :     of Ty.BoolTy => T.boolTy
27 :     | Ty.StringTy => raise Fail "FIXME: StringTy"
28 :     | Ty.IVecTy 1 => T.intTy
29 :     | Ty.IVecTy n => T.ivecTy n (* FIXME: what about vector splits? *)
30 :     | Ty.VecTy 1 => T.realTy
31 :     | Ty.VecTy n => T.vecTy n (* FIXME: what about vector splits? *)
32 :     | Ty.AddrTy => raise Fail "FIXME: AddrTy"
33 :     | Ty.ImageTy => raise Fail "FIXME: ImageTy"
34 :     (* end case *))
35 :    
36 : jhr 529 (* a flag to mark global IL variables, since they need to be treated differently *)
37 :     local
38 :     val {getFn, setFn} = V.newFlag ()
39 :     in
40 :     val isGlobal = getFn
41 :     fun markGlobal x = setFn(x, true)
42 :     end
43 :    
44 : jhr 454 (* a mapping from LowIL variables to target expressions. Variables get
45 :     * removed when the expressions are used as arguments.
46 :     *)
47 :     structure VDefTbl : sig
48 :     type tbl
49 :    
50 : jhr 529 val newTbl : T.program -> tbl
51 : jhr 518 val getDefOf : tbl -> IL.var -> T.exp
52 :     val useDefOf : tbl -> IL.var -> T.exp
53 : jhr 514 val setDefOf : tbl -> (IL.var * T.exp) -> unit
54 : jhr 454
55 :     val clear : tbl -> unit
56 :    
57 : jhr 514 val assign : tbl -> (IL.var * T.exp) -> T.stm list
58 :     val bind : tbl -> (IL.var * T.exp) -> T.stm list
59 : jhr 454
60 : jhr 455 (* force all pending expressions into variables *)
61 :     val flush : tbl -> T.stm list
62 :    
63 : jhr 454 end = struct
64 :    
65 : jhr 455 type info = {
66 :     cnt : int ref, (* count of oustanding uses (usually 1) *)
67 : jhr 518 bind : T.exp
68 : jhr 455 }
69 :    
70 : jhr 529 datatype tbl = VT of
71 :     prog : T.program,
72 :     defs : info V.Tbl.hash_table
73 :     }
74 : jhr 455
75 : jhr 529 fun newTbl prog = VT{
76 :     prog = prog,
77 :     defs = V.Tbl.mkTable (512, Fail "vtbl")
78 :     }
79 : jhr 455
80 : jhr 529 fun getDefOf (VT{defs, ...}) x = (case V.Tbl.find defs x
81 : jhr 514 of NONE => raise Fail(concat["getDefOf(", V.toString x, ")"])
82 : jhr 455 | SOME{bind, cnt} => bind
83 :     (* end case *))
84 :    
85 : jhr 529 fun useDefOf (VT{defs, ...}) x = (case V.Tbl.find defs x
86 : jhr 514 of NONE => raise Fail(concat["useDefOf(", V.toString x, ")"])
87 : jhr 512 | SOME{cnt=ref 1, bind} => (
88 : jhr 529 ignore (V.Tbl.remove defs x);
89 : jhr 455 bind)
90 : jhr 514 | SOME{cnt, bind} => (
91 : jhr 455 cnt := !cnt - 1;
92 :     bind)
93 :     (* end case *))
94 :    
95 : jhr 529 fun defineGlobal ((VT{prog, defs}), x, rhs) = let
96 :     val x' = T.Var.global (prog, cvtTy(V.ty x), V.name x)
97 :     in
98 :    
99 : jhr 455 fun setDefOf tbl (x, exp) =
100 : jhr 518 V.Tbl.insert tbl (x, {cnt = ref(V.useCount x), bind = exp})
101 : jhr 455
102 :     fun assign tbl (x, exp) = let
103 : jhr 525 val lhs = T.Var.tmp(cvtTy(V.ty x))
104 : jhr 455 in
105 : jhr 512 V.Tbl.insert tbl
106 : jhr 518 (x, {cnt = ref(V.useCount x), bind = T.Expr.var lhs});
107 : jhr 455 [T.Stmt.assign(lhs, exp)]
108 :     end
109 :    
110 : jhr 529 fun bind tbl (x, exp) = if isGlobal x
111 :     then
112 :     else (case V.useCount x
113 :     of 1 => (V.Tbl.insert tbl (x, {cnt = ref 1, bind = exp}); [])
114 :     | n => let (* bind exp to a new target variable *)
115 :     val lhs = T.Var.tmp(cvtTy(V.ty x))
116 :     in
117 :     V.Tbl.insert tbl (x, {cnt = ref n, bind = T.Expr.var lhs});
118 :     [T.Stmt.assign(lhs, exp)]
119 :     end
120 :     (* end case *))
121 : jhr 455
122 : jhr 514 val clear = V.Tbl.clear
123 :    
124 :     fun flush tbl = raise Fail "flush"
125 :    
126 : jhr 454 end (* VDefTbl *)
127 :    
128 : jhr 455 (* FIXME: what about splitting code where the target width doesn't match the
129 :     * source width?
130 :     *)
131 : jhr 514 fun doRator vtbl = let
132 : jhr 518 val exp = VDefTbl.useDefOf vtbl
133 : jhr 514 val bind = VDefTbl.bind vtbl
134 : jhr 518 fun f (lhs, rator, args) = (case (rator, args)
135 :     of (Op.Add ty, [a, b]) => bind (lhs, T.Expr.add(exp a, exp b))
136 :     | (Op.Sub ty, [a, b]) => bind (lhs, T.Expr.sub(exp a, exp b))
137 :     | (Op.Mul ty, [a, b]) => bind (lhs, T.Expr.mul(exp a, exp b))
138 :     | (Op.Div ty, [a, b]) => bind (lhs, T.Expr.divide(exp a, exp b))
139 :     | (Op.Neg ty, [a]) => bind (lhs, T.Expr.neg(exp a))
140 :     | (Op.LT ty, [a, b]) => bind (lhs, T.Expr.lt(exp a, exp b))
141 :     | (Op.LTE ty, [a, b]) => bind (lhs, T.Expr.lte(exp a, exp b))
142 :     | (Op.EQ ty, [a, b]) => bind (lhs, T.Expr.equ(exp a, exp b))
143 :     | (Op.NEQ ty, [a, b]) => bind (lhs, T.Expr.neq(exp a, exp b))
144 :     | (Op.GT ty, [a, b]) => bind (lhs, T.Expr.gt(exp a, exp b))
145 :     | (Op.GTE ty, [a, b]) => bind (lhs, T.Expr.gte(exp a, exp b))
146 :     | (Op.Not, [a]) => bind (lhs, T.Expr.not(exp a))
147 :     | (Op.Max, [a, b]) => bind (lhs, T.Expr.max(exp a, exp b))
148 :     | (Op.Min, [a, b]) => bind (lhs, T.Expr.min(exp a, exp b))
149 :     | (Op.Sin, [a]) => bind (lhs, T.Expr.sin(exp a))
150 :     | (Op.Cos, [a]) => bind (lhs, T.Expr.cos(exp a))
151 :     | (Op.Pow, [a, b]) => bind (lhs, T.Expr.pow(exp a, exp b))
152 :     | (Op.Dot d, [a, b]) => bind (lhs, T.Expr.dot(exp a, exp b))
153 :     | (Op.Cross, [a, b]) => bind (lhs, T.Expr.cross(exp a, exp b))
154 :     | (Op.Select(ty, i), [a]) => bind (lhs, T.Expr.select(i, exp a))
155 :     | (Op.Norm d, [a]) => bind (lhs, T.Expr.length(exp a))
156 :     | (Op.Scale d, [a, b]) => bind (lhs, T.Expr.mul(exp a, exp b))
157 :     | (Op.InvScale d, [a, b]) => bind (lhs, T.Expr.divide(exp a, exp b))
158 :     | (Op.CL, _) => raise Fail "CL unimplemented"
159 :     | (Op.PrincipleEvec ty, _) => raise Fail "PrincipleEvec unimplemented"
160 : jhr 514 (*
161 : jhr 518 | (Op.Subscript ty,
162 : jhr 514 *)
163 : jhr 518 | (Op.Floor d, [a]) => bind (lhs, T.Expr.floor(exp a))
164 :     | (Op.IntToReal, [a]) => bind (lhs, T.Expr.toReal(exp a))
165 :     | (Op.TruncToInt d, [a]) => bind (lhs, T.Expr.truncToInt(exp a))
166 :     | (Op.RoundToInt d, [a]) => bind (lhs, T.Expr.roundToInt(exp a))
167 :     | (Op.CeilToInt d, [a]) => bind (lhs, T.Expr.ceilToInt(exp a))
168 :     | (Op.FloorToInt d, [a]) => bind (lhs, T.Expr.floorToInt(exp a))
169 :     | (Op.ImageAddress, [a]) => bind (lhs, T.Expr.imageAddr(exp a))
170 : jhr 528 | (Op.LoadVoxels(rTy, n), [a]) => [] (* FIXME *)
171 :     | (Op.PosToImgSpace d, [v, x]) => [] (* FIXME *)
172 :     | (Op.GradToWorldSpace d, [v, x]) => [] (* FIXME *)
173 :     | (Op.LoadImage info, [a]) => [] (* FIXME *)
174 :     | (Op.Inside d, [v, x]) => [] (* FIXME *)
175 :     | (Op.Input(ty, name), []) => [] (* FIXME *)
176 :     | (Op.InputWithDefault(ty, name), [a]) => [] (* FIXME *)
177 :     | _ => raise Fail(concat[
178 :     "incorrect number of arguments for ", Op.toString rator
179 :     ])
180 : jhr 518 (* end case *))
181 : jhr 455 in
182 : jhr 514 f
183 : jhr 455 end
184 : jhr 454
185 : jhr 455 (* translate a LowIL assignment to a list of zero or more target statements *)
186 : jhr 518 fun doAssign vtbl = let
187 : jhr 514 val setDefOf = VDefTbl.setDefOf vtbl
188 :     val doRator = doRator vtbl
189 :     fun assign (lhs, rhs) = let
190 :     fun setDef rhs = (setDefOf (lhs, rhs); [])
191 :     in
192 :     case rhs
193 : jhr 518 of IL.VAR x => setDef (VDefTbl.useDefOf vtbl x)
194 : jhr 514 | IL.LIT(Literal.Int n) => setDef (T.Expr.intLit n)
195 :     | IL.LIT(Literal.Bool b) => setDef (T.Expr.boolLit b)
196 :     | IL.LIT(Literal.Float f) => setDef (T.Expr.floatLit f)
197 :     | IL.LIT(Literal.String s) => setDef (T.Expr.stringLit s)
198 :     | IL.OP(rator, args) => doRator(lhs, rator, args)
199 :     | IL.CONS args =>
200 :     VDefTbl.assign vtbl
201 :     (lhs, T.Expr.vector (List.map (VDefTbl.useDefOf vtbl) args))
202 :     (* end case *)
203 :     end
204 : jhr 455 in
205 : jhr 514 assign
206 : jhr 455 end
207 :    
208 : jhr 512 fun gen (vtbl, cfg) = let
209 :     val doAssign = doAssign vtbl
210 : jhr 513 fun doNode (vtbl, ifCont, stms, nd) = (case Nd.kind nd
211 :     of IL.NULL => raise Fail "unexpected NULL"
212 : jhr 514 | IL.ENTRY{succ} => doNode (vtbl, ifCont, stms, !succ)
213 : jhr 518 | IL.JOIN{phis, succ, ...} => ifCont (stms, Nd.kind nd)
214 : jhr 512 | IL.COND{cond, trueBranch, falseBranch, ...} => let
215 :     fun kThen (stms', _) = let
216 :     val thenBlk = T.Stmt.block (List.rev stms')
217 : jhr 513 fun kElse (stms', IL.JOIN{phis, succ, ...}) = let
218 : jhr 512 val stm = T.Stmt.ifthenelse (
219 :     VDefTbl.useDefOf vtbl cond,
220 :     thenBlk,
221 :     T.Stmt.block (List.rev stms'))
222 :     in
223 : jhr 513 (* FIXME: what do we do about phis? *)
224 : jhr 514 doNode (vtbl, ifCont, stm::stms, !succ)
225 : jhr 512 end
226 :     in
227 : jhr 514 doNode (vtbl, kElse, [], !falseBranch)
228 : jhr 512 end
229 :     in
230 : jhr 514 doNode (vtbl, kThen, [], !trueBranch)
231 : jhr 512 end
232 :     | IL.COM {text, succ, ...} =>
233 : jhr 514 doNode (vtbl, ifCont, T.Stmt.comment text :: stms, !succ)
234 : jhr 512 | IL.ASSIGN{stm, succ, ...} =>
235 : jhr 518 doNode (vtbl, ifCont, doAssign stm @ stms, !succ)
236 : jhr 513 | IL.NEW{strand, args, succ, ...} => raise Fail "NEW unimplemented"
237 : jhr 512 | IL.DIE _ =>
238 : jhr 514 T.Stmt.block (List.rev (T.Stmt.die() :: stms))
239 : jhr 512 | IL.STABILIZE _ =>
240 : jhr 514 T.Stmt.block (List.rev stms)
241 :     | IL.EXIT _ => T.Stmt.block (List.rev (T.Stmt.stabilize() :: stms))
242 : jhr 512 (* end case *))
243 :     in
244 : jhr 513 doNode (vtbl, fn _ => raise Fail "bogus ifCont at JOIN node", [], CFG.entry cfg)
245 : jhr 512 end
246 :    
247 : jhr 528 (* generate the global-variable declarations and initialization code *)
248 :     fun genGlobals (vtbl, prog, globals, globalInit) = let
249 :     (* FIXME: we should put the initialization code in a function! *)
250 :     in
251 : jhr 529 List.app markGlobal globals;
252 : jhr 528 gen (vtbl, globalInit)
253 :     end
254 :    
255 : jhr 527 fun generate (fileStem, IL.Program{globals, globalInit, strands}) = let
256 :     val prog = T.newProgram ()
257 : jhr 529 val vtbl = VDefTbl.newTbl prog
258 : jhr 527 in
259 : jhr 528 genGlobals (vtbl, prog, globals, globalInit);
260 :     (* output the program *)
261 : jhr 527 T.generate (fileStem, prog)
262 :     end
263 : jhr 518
264 : jhr 454 end

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