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 531 - (download) (annotate)
Mon Feb 14 17:45:57 2011 UTC (8 years, 6 months ago) by jhr
File size: 6522 byte(s)
  Working on code generation
(* 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 Ty = TreeIL.Ty

  (* convert LowIL types to T types *)
    fun cvtTy ty = (case ty
	   of Ty.BoolTy => T.boolTy
	    | Ty.StringTy => raise Fail "FIXME: 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 => raise Fail "FIXME: AddrTy"
	    | Ty.ImageTy =>  raise Fail "FIXME: ImageTy"
	  (* end case *))

(*
(* FIXME: what about splitting code where the target width doesn't match the
 * source width?
 *)
    fun doRator vtbl = let
	  val exp = VDefTbl.useDefOf vtbl
	  val bind = VDefTbl.bind vtbl
	  fun f (lhs, rator, args) = (case (rator, args)
		 of (Op.Add ty, [a, b])		=> bind (lhs, T.Expr.add(exp a, exp b))
		  | (Op.Sub ty, [a, b])		=> bind (lhs, T.Expr.sub(exp a, exp b))
		  | (Op.Mul ty, [a, b])		=> bind (lhs, T.Expr.mul(exp a, exp b))
		  | (Op.Div ty, [a, b])		=> bind (lhs, T.Expr.divide(exp a, exp b))
		  | (Op.Neg ty, [a])		=> bind (lhs, T.Expr.neg(exp a))
		  | (Op.LT ty, [a, b])		=> bind (lhs, T.Expr.lt(exp a, exp b))
		  | (Op.LTE ty, [a, b])		=> bind (lhs, T.Expr.lte(exp a, exp b))
		  | (Op.EQ ty, [a, b])		=> bind (lhs, T.Expr.equ(exp a, exp b))
		  | (Op.NEQ ty, [a, b])		=> bind (lhs, T.Expr.neq(exp a, exp b))
		  | (Op.GT ty, [a, b])		=> bind (lhs, T.Expr.gt(exp a, exp b))
		  | (Op.GTE ty, [a, b])		=> bind (lhs, T.Expr.gte(exp a, exp b))
		  | (Op.Not, [a])		=> bind (lhs, T.Expr.not(exp a))
		  | (Op.Max, [a, b])		=> bind (lhs, T.Expr.max(exp a, exp b))
		  | (Op.Min, [a, b])		=> bind (lhs, T.Expr.min(exp a, exp b))
		  | (Op.Sin, [a])		=> bind (lhs, T.Expr.sin(exp a))
		  | (Op.Cos, [a])		=> bind (lhs, T.Expr.cos(exp a))
		  | (Op.Pow, [a, b])		=> bind (lhs, T.Expr.pow(exp a, exp b))
		  | (Op.Dot d, [a, b])		=> bind (lhs, T.Expr.dot(exp a, exp b))
		  | (Op.Cross, [a, b])		=> bind (lhs, T.Expr.cross(exp a, exp b))
		  | (Op.Select(ty, i), [a])	=> bind (lhs, T.Expr.select(i, exp a))
		  | (Op.Norm d, [a])		=> bind (lhs, T.Expr.length(exp a))
		  | (Op.Scale d, [a, b])	=> bind (lhs, T.Expr.mul(exp a, exp b))
		  | (Op.InvScale d, [a, b])	=> bind (lhs, T.Expr.divide(exp a, exp b))
		  | (Op.CL, _)			=> raise Fail "CL unimplemented"
		  | (Op.PrincipleEvec ty, _)	=> raise Fail "PrincipleEvec unimplemented"
(*
		  | (Op.Subscript ty,
*)
		  | (Op.Floor d, [a])		=> bind (lhs, T.Expr.floor(exp a))
		  | (Op.IntToReal, [a])		=> bind (lhs, T.Expr.toReal(exp a))
		  | (Op.TruncToInt d, [a])	=> bind (lhs, T.Expr.truncToInt(exp a))
		  | (Op.RoundToInt d, [a])	=> bind (lhs, T.Expr.roundToInt(exp a))
		  | (Op.CeilToInt d, [a])	=> bind (lhs, T.Expr.ceilToInt(exp a))
		  | (Op.FloorToInt d, [a])	=> bind (lhs, T.Expr.floorToInt(exp a))
		  | (Op.ImageAddress, [a])	=> bind (lhs, T.Expr.imageAddr(exp a))
		  | (Op.LoadVoxels(rTy, n), [a]) => [] (* FIXME *)
		  | (Op.PosToImgSpace d, [v, x]) => [] (* FIXME *)
		  | (Op.GradToWorldSpace d, [v, x]) => [] (* FIXME *)
		  | (Op.LoadImage info, [a]) => [] (* FIXME *)
		  | (Op.Inside d, [v, x]) => [] (* FIXME *)
		  | (Op.Input(ty, name), []) => [] (* FIXME *)
		  | (Op.InputWithDefault(ty, name), [a]) => [] (* FIXME *)
		  | _ => raise Fail(concat[
			"incorrect number of arguments for ", Op.toString rator
		      ])
		(* end case *))
	  in
	    f
	  end

  (* translate a LowIL assignment to a list of zero or more target statements *)
    fun doAssign vtbl = let
	  val setDefOf = VDefTbl.setDefOf vtbl
	  val doRator = doRator vtbl
	  fun assign (lhs, rhs) = let
		fun setDef rhs = (setDefOf (lhs, rhs); [])
		in
		  case rhs
		   of IL.VAR x => setDef (VDefTbl.useDefOf vtbl x)
		    | IL.LIT(Literal.Int n) => setDef (T.Expr.intLit n)
		    | IL.LIT(Literal.Bool b) => setDef (T.Expr.boolLit b)
		    | IL.LIT(Literal.Float f) => setDef (T.Expr.floatLit f)
		    | IL.LIT(Literal.String s) => setDef (T.Expr.stringLit s)
		    | IL.OP(rator, args) => doRator(lhs, rator, args)
		    | IL.CONS args =>
			VDefTbl.assign vtbl
			  (lhs, T.Expr.vector (List.map (VDefTbl.useDefOf vtbl) args))
		  (* end case *)
		end
	  in
	    assign
	  end

    fun gen (vtbl, cfg) = let
	  val doAssign = doAssign vtbl
	  fun doNode (vtbl, ifCont, stms, nd) = (case Nd.kind nd
		 of IL.NULL => raise Fail "unexpected NULL"
		  | IL.ENTRY{succ} => doNode (vtbl, ifCont, stms, !succ)
		  | IL.JOIN{phis, succ, ...} => ifCont (stms, Nd.kind nd)
		  | IL.COND{cond, trueBranch, falseBranch, ...} => let
		      fun kThen (stms', _) = let
			    val thenBlk = T.Stmt.block (List.rev stms')
			    fun kElse (stms', IL.JOIN{phis, succ, ...}) = let
				  val stm = T.Stmt.ifthenelse (
					VDefTbl.useDefOf vtbl cond,
					thenBlk,
					T.Stmt.block (List.rev stms'))
				  in
(* FIXME: what do we do about phis? *)
				    doNode (vtbl, ifCont, stm::stms, !succ)
				  end
			    in
			      doNode (vtbl, kElse, [], !falseBranch)
			    end
		      in
			doNode (vtbl, kThen, [], !trueBranch)
		      end
		  | IL.COM {text, succ, ...} =>
		      doNode (vtbl, ifCont, T.Stmt.comment text :: stms, !succ)
		  | IL.ASSIGN{stm, succ, ...} =>
		      doNode (vtbl, ifCont, doAssign stm @ stms, !succ)
		  | IL.NEW{strand, args, succ, ...} => raise Fail "NEW unimplemented"
		  | IL.DIE _ =>
		      T.Stmt.block (List.rev (T.Stmt.die() :: stms))
		  | IL.STABILIZE _ =>
		      T.Stmt.block (List.rev stms)
		  | IL.EXIT _ => T.Stmt.block (List.rev (T.Stmt.stabilize() :: stms))
		(* end case *))
	  in
	    doNode (vtbl, fn _ => raise Fail "bogus ifCont at JOIN node", [], CFG.entry cfg)
	  end

  (* generate the global-variable declarations and initialization code *)
    fun genGlobals (vtbl, prog, globals, globalInit) = let
(* FIXME: we should put the initialization code in a function! *)
	  in
	    List.app markGlobal globals;
	    gen (vtbl, globalInit)
	  end
*)

    fun generate (fileStem, srcProg) = let
	  val TreeIL.Program{globals, globalInit, strands} = LowToTree.translate srcProg
	  val prog = T.newProgram ()
	  in
	  (* output the program *)
	    T.generate (fileStem, prog)
	  end

  end

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