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

SCM Repository

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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 654 - (download) (annotate)
Mon Mar 21 17:10:54 2011 UTC (9 years ago) by jhr
File size: 8836 byte(s)
  Added support for tracking output state variables through ILs and generating
  a print function in the C target.
(* codegen-fn.sml
 *
 * COPYRIGHT (c) 2010 The Diderot Project (http://diderot-language.cs.uchicago.edu)
 * All rights reserved.
 *
 * Generic support for translating LowIL code to the target representation.  We
 * assume that the LowIL has first been run through the splitting pass to match
 * the target's vector widths.
 *)

functor CodeGenFn (T : TARGET) : sig

    val generate : string * LowIL.program -> unit

  end = struct

    structure IL = TreeIL
    structure Ty = IL.Ty
    structure Op = IL.Op
    structure V = IL.Var

  (* convert LowIL types to T types *)
    fun cvtTy ty = (case ty
	   of Ty.BoolTy => T.boolTy
	    | Ty.StringTy => T.stringTy
	    | Ty.IVecTy 1 => T.intTy
	    | Ty.IVecTy n => T.ivecTy n		(* FIXME: what about vector splits? *)
	    | Ty.VecTy 1 => T.realTy
	    | Ty.VecTy n => T.vecTy n		(* FIXME: what about vector splits? *)
	    | Ty.AddrTy info => T.imageDataTy info
	    | Ty.ImageTy info => T.imageTy info
	  (* end case *))

    fun addBindings (env, xs, ys) =
	  ListPair.foldlEq (fn (x, y, env) => V.Map.insert(env, x, y)) env (xs, ys)

    fun lookup (env, x) = (case V.Map.find (env, x)
	   of SOME x' => x'
	    | NONE => raise Fail(concat["lookup(_, ", V.name x, ")"])
	  (* end case *))

    fun trExp (env, e) = (case e
	   of IL.E_Var x => (case V.kind x
		 of IL.VK_Global => T.Expr.global(lookup(env, x))
		  | IL.VK_State strand => T.Expr.getState(lookup(env, x))
		  | IL.VK_Local => T.Expr.var(lookup(env, x))
		(* end case *))
	    | IL.E_Lit(Literal.Int n) => T.Expr.intLit n
	    | IL.E_Lit(Literal.Bool b) => T.Expr.boolLit b
	    | IL.E_Lit(Literal.Float f) => T.Expr.floatLit f
	    | IL.E_Lit(Literal.String s) => T.Expr.stringLit s
	    | IL.E_Op(rator, args) => (case (rator, trExps(env, args))
		 of (Op.Add ty, [a, b])		=> T.Expr.add(a, b)
		  | (Op.Sub ty, [a, b])		=> T.Expr.sub(a, b)
		  | (Op.Mul ty, [a, b])		=> T.Expr.mul(a, b)
		  | (Op.Div ty, [a, b])		=> T.Expr.divide(a, b)
		  | (Op.Neg ty, [a])		=> T.Expr.neg a
		  | (Op.LT ty, [a, b])		=> T.Expr.lt(a, b)
		  | (Op.LTE ty, [a, b])		=> T.Expr.lte(a, b)
		  | (Op.EQ ty, [a, b])		=> T.Expr.equ(a, b)
		  | (Op.NEQ ty, [a, b])		=> T.Expr.neq(a, b)
		  | (Op.GT ty, [a, b])		=> T.Expr.gt(a, b)
		  | (Op.GTE ty, [a, b])		=> T.Expr.gte(a, b)
		  | (Op.Not, [a])		=> T.Expr.not a
		  | (Op.Max, [a, b])		=> T.Expr.max(a, b)
		  | (Op.Min, [a, b])		=> T.Expr.min(a, b)
		  | (Op.Sin, [a])		=> T.Expr.sin a
		  | (Op.Cos, [a])		=> T.Expr.cos a
		  | (Op.Pow, [a, b])		=> T.Expr.pow(a, b)
		  | (Op.Dot d, [a, b])		=> T.Expr.dot(a, b)
		  | (Op.Cross, [a, b])		=> T.Expr.cross(a, b)
		  | (Op.Select(ty, i), [a])	=> T.Expr.select(i, a)
		  | (Op.Norm d, [a])		=> T.Expr.length a
		  | (Op.Scale d, [a, b])	=> T.Expr.mul(a, b)
		  | (Op.InvScale d, [a, b])	=> T.Expr.divide(a, b)
		  | (Op.CL, _)			=> raise Fail "CL unimplemented"
		  | (Op.PrincipleEvec ty, _)	=> raise Fail "PrincipleEvec unimplemented"
(*
		  | (Op.Subscript ty,
*)
		  | (Op.Ceiling d, [a])		=> T.Expr.ceil a
		  | (Op.Floor d, [a])		=> T.Expr.floor a
		  | (Op.Round d, [a])		=> T.Expr.round a
		  | (Op.Trunc d, [a])		=> T.Expr.trunc a
		  | (Op.IntToReal, [a])		=> T.Expr.toReal a
		  | (Op.RealToInt d, [a])	=> T.Expr.toInt a
		  | (Op.ImageAddress d, [a])	=> T.Expr.imageAddr a
		  | (Op.LoadVoxels(info, 1), [a]) => T.Expr.getImgData a
		  | (Op.LoadVoxels _, [a])	=> raise Fail "impossible"
		  | (Op.PosToImgSpace d, [v, x]) => T.Expr.posToImgSpace(v, x)
		  | (Op.GradToWorldSpace d, [v, x]) => T.Expr.intLit 0 (* FIXME *)
		  | (Op.LoadImage info, [a])	=> raise Fail "impossible"
		  | (Op.Inside(d, s), [x, v])	=> T.Expr.inside(x, v, s)
		  | (Op.Input(ty, name), [])	=> raise Fail "impossible"
		  | (Op.InputWithDefault(ty, name), [a]) => T.Expr.intLit 0 (* FIXME *)
		  | _ => raise Fail(concat[
			"incorrect number of arguments for ", Op.toString rator
		      ])
		(* end case *))
	  (* end case *))

    and trExps (env, exps) = List.map (fn exp => trExp(env, exp)) exps

    fun trBlock (env, saveState, blk) = let
	  fun trStmt (env, stm) = (case stm
		 of IL.S_Comment text => [T.Stmt.comment text]
		  | IL.S_Assign(x, exp) => (case V.kind x
		       of IL.VK_Global => [T.Stmt.assign(lookup(env, x), trExp(env, exp))]
			| IL.VK_State strand =>
			    [T.Stmt.assignState(lookup(env, x), trExp(env, exp))]
			| IL.VK_Local => [T.Stmt.assign(lookup(env, x), trExp(env, exp))]
		      (* end case *))
		  | IL.S_IfThen(cond, thenBlk) =>
		      [T.Stmt.ifthen(trExp(env, cond), trBlk(env, thenBlk))]
		  | IL.S_IfThenElse(cond, thenBlk, elseBlk) =>
		      [T.Stmt.ifthenelse(trExp(env, cond),
			trBlk(env, thenBlk),
			trBlk(env, elseBlk))]
		  | IL.S_For(x, e1, e2, blk) => let
		      val x' = T.Var.var(cvtTy(V.ty x), V.name x)
		      val env' = V.Map.insert(env, x, x')
		      in [
			T.Stmt.for(x', trExp(env, e1), trExp(env, e2), trBlk(env', blk))
		      ] end
		  | IL.S_Cons(lhs, args) =>
		      [T.Stmt.cons(lookup(env, lhs), trExps(env, args))]
		  | IL.S_LoadVoxels(lhs, dim, addr) =>
		      T.Stmt.getImgData(lookup(env, lhs), trExp(env, addr))
		  | IL.S_LoadImage(lhs, dim, name) =>
		      T.Stmt.loadImage (lookup(env, lhs), dim, trExp(env, name))
		  | IL.S_Input(lhs, name, optDflt) =>
		      T.Stmt.input(lookup(env, lhs), name, Option.map (fn e => trExp(env, e)) optDflt)
(* FIXME: what about the args? *)
		  | IL.S_Exit args => [T.Stmt.exit()]
		  | IL.S_Active args => saveState (env, args, T.Stmt.active())
		  | IL.S_Stabilize args => saveState (env, args, T.Stmt.stabilize())
		  | IL.S_Die => [T.Stmt.die()]
		(* end case *))
	  and trBlk (env, IL.Block{locals, body}) = let
		val env = List.foldl
		      (fn (x, env) => V.Map.insert(env, x, T.Var.var(cvtTy(V.ty x), V.name x)))
			env locals
		val stms = List.foldr (fn (stm, stms) => trStmt(env, stm)@stms) [] body
		val stms = List.foldr
		      (fn (x, stms) => T.Stmt.decl(lookup(env, x), NONE)::stms)
			stms locals
		in
		  T.Stmt.block stms
		end
	  in
	    trBlk (env, blk)
	  end

    fun trTopBlock (env, blk) = trBlock (env, fn _ => raise Fail "unexpected state save", blk)

    fun trMethod (strand, stateVars, env) (IL.Method{name, body}) = let
	  fun saveState (env, args, stm) =
		ListPair.foldrEq
		  (fn (x, e, stms) => T.Stmt.assignState(x, trExp(env, e))::stms)
		    [stm]
		      (stateVars, args)
	  val body = trBlock (env, saveState, body)
	  in
	    T.Strand.method (strand, Atom.toString name, body)
	  end

    fun trStrand (prog, env) (IL.Strand{name, params, state, stateInit, methods}) = let
	  val strand = T.Strand.define(prog, name)
	(* map the state variables to target state variables, while extending the environment
         * and registering the output variables.
	 *)
	  val (env, state') = let
		fun cvtSVar ((isOut, x), (env, xs)) = let
		      val x' = T.Var.state(strand, cvtTy(V.ty x), V.name x)
		      in
			if isOut then T.Strand.output(strand, x') else ();
			(V.Map.insert(env, x, x'), x'::xs)
		      end
		in
		  List.foldr cvtSVar (env, []) state
		end
	(* define the parameters and add them to the environment *)
	  val params' = List.map (fn x => T.Var.param(cvtTy(V.ty x), V.name x)) params
	  val env = addBindings (env, params, params')
	  in
	    T.Strand.init (strand, params', trTopBlock (env, stateInit));
	    List.app (trMethod (strand, state', env)) methods
	  end

    fun trInitially (env0, prog, {isArray, iterPrefix, iters, createPrefix, strand, args}) = let
	  fun trIter ((param, lo, hi), (env, iters)) = let
		val param' = T.Var.var(cvtTy(V.ty param), V.name param)
		val env = V.Map.insert(env, param, param')
		val iter = (param', trExp (env0, lo), trExp (env0, hi))
		in
		  (env, iter::iters)
		end
	  val (env, iters) = List.foldr trIter (env0, []) iters
	  in
	    T.initially {
		prog = prog,
		isArray = isArray,
		iterPrefix = trTopBlock (env0, iterPrefix),
		iters = iters,
		createPrefix = trTopBlock (env, createPrefix),
		strand = strand,
		args = trExps (env, args)
	      }
	  end

    fun generate (fileStem, srcProg) = let
	  val treeProg as TreeIL.Program{globals, globalInit, strands, initially} = LowToTree.translate srcProg
val _ = (
TextIO.output(Log.logFile(), "********** After translation to TreeIL **********\n");
TreeILPP.program (Log.logFile(), treeProg))
	  val prog = T.newProgram ()
	(* define the globals and initialize the environment *)
	  val env = let
		fun gvar (x, env) =
		      V.Map.insert(env, x, T.Var.global(prog, cvtTy(V.ty x), V.name x))
		in
		  List.foldl gvar V.Map.empty globals
		end
	  in
	  (* global initialization *)
	    T.globalInit (prog, trTopBlock (env, globalInit));
	  (* translate strands *)
	    List.app (trStrand (prog, env)) strands;
	  (* generate the initially function *)
	    trInitially (env, prog, initially);
	  (* output the program *)
	    T.generate (fileStem, prog)
	  end

  end

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