SCM Repository
View of /branches/pure-cfg/src/compiler/translate/translate.sml
Parent Directory
|
Revision Log
Revision 500 -
(download)
(annotate)
Tue Feb 1 17:40:24 2011 UTC (11 years, 4 months ago) by jhr
File size: 9306 byte(s)
Tue Feb 1 17:40:24 2011 UTC (11 years, 4 months ago) by jhr
File size: 9306 byte(s)
Made cfg type immutable
(* translate.sml * * COPYRIGHT (c) 2010 The Diderot Project (http://diderot-language.cs.uchicago.edu) * All rights reserved. * * Translate Simple-AST code into the IL representation. This translation is based on the * algorithm described in * * Single-pass generation of static single assignment form for structured languages * ACM TOPLAS, Nov. 1994 * by Brandis and MossenBock. *) structure Translate : sig val translate : Simple.program -> HighIL.program end = struct structure S = Simple structure Ty = Types structure VMap = Var.Map structure VSet = Var.Set structure IL = HighIL structure DstTy = HighILTypes type env = IL.var VMap.map fun lookup env x = (case VMap.find (env, x) of SOME x' => x' | NONE => raise Fail(concat[ "no binding for ", Var.uniqueNameOf x, " in environment" ]) (* end case *)) fun cvtTy ty = (case TypeUtil.prune ty of Ty.T_Bool => DstTy.BoolTy | Ty.T_Int => DstTy.IntTy | Ty.T_String => DstTy.StringTy | Ty.T_Kernel _ => DstTy.KernelTy | Ty.T_Tensor(Ty.Shape dd) => let fun cvtDim (Ty.DimConst 1) = NONE | cvtDim (Ty.DimConst d) = SOME d in DstTy.TensorTy(List.mapPartial cvtDim dd) end | Ty.T_Image _ => DstTy.ImageTy | Ty.T_Field _ => DstTy.FieldTy | ty => raise Fail("cvtTy: unexpected " ^ TypeUtil.toString ty) (* end case *)) (* create a new instance of a variable *) fun newVar x = IL.Var.new (Var.nameOf x, cvtTy(Var.monoTypeOf x)) (* a pending-join node tracks the phi nodes needed to join the assignments * that flow into the join node. *) datatype join = JOIN of { arity : int, (* number of predecessors *) nd : IL.node, (* the CFG node for this pending join *) phiMap : IL.phi VMap.map ref, (* a mapping from Simple AST variables that are assigned *) (* to their phi nodes. *) predKill : int list ref (* killed predecessor edges (because of DIE or STABILIZE *) } (* a stack of pending joins. The first component specifies the path index of the current * path to the join. *) type pending_joins = (int * join) list (* create a new pending-join node *) fun newJoin arity = JOIN{ arity = arity, nd = IL.Node.mkJOIN [], phiMap = ref VMap.empty, predKill = ref [] } fun killPath ((i, JOIN{predKill, ...}) :: _) = predKill := i :: !predKill | killPath _ = () (* record an assignment to the IL variable dstVar (corresponding to the Simple AST variable * srcVar) in the current pending-join node. The predIndex specifies which path into the * JOIN node this assignment occurs on. *) fun recordAssign (_, [], _, _, _) = () | recordAssign (env, (predIndex, JOIN{arity, phiMap, ...})::_, srcVar, dstVar) = let val m = !phiMap val m'= (case VMap.find (m, srcVar) of NONE => let val dstVar' = newVar srcVar val dfltVar = lookup env srcVar val rhs = List.tabulate (arity, fn i => if (i = predIndex) then dstVar else dfltVar) in VMap.insert (m, srcVar, (dstVar', rhs)) end | SOME(lhs, rhs) => let fun update (i, l as x::r) = if (i = predIndex) then dstVar::r else x::update(i+1, r) | update _ = raise Fail "invalid predecessor index" in VMap.insert (m, srcVar, (lhs, update(0, rhs))) end (* end case *)) in phiMap := m' end (* complete a pending join operation by filling in the phi nodes from the phi map and * updating the environment. *) fun commitJoin (env, joinStk, JOIN{nd, phiMap, ...}) = let val IL.ND{kind=IL.JOIN{phis, ...}, ...} = nd fun doVar (srcVar, phi as (dstVar, _), (env, phis)) = ( recordAssign (env, r, srcVar, dstVer); (VMap.insert (env, srcVar, dstVar), phi::phis)) val (env, phis') = VMap.foldli doVar (env, []) (!phiMap) in (* FIXME: prune killed paths. *) phis := phis' (env, SOME nd) end (* expression translation *) fun cvtExp (env, lhs, exp) = (case exp of S.E_Var x => [(lhs, IL.VAR(lookup env x))] | S.E_Lit lit => [(lhs, IL.LIT lit)] | S.E_Tuple xs => raise Fail "E_Tuple not implemeted" | S.E_Apply(f, tyArgs, args, ty) => let val args' = List.map (lookup env) args in TranslateBasis.translate (lhs, f, tyArgs, args') end | S.E_Cons args => [(lhs, IL.CONS(List.map (lookup env) args))] | S.E_Slice(x, indices, ty) => let val x = lookup env x val mask = List.map isSome indices fun cvt NONE = NONE | cvt (SOME x) = SOME(lookup env x) val indices = List.mapPartial cvt indices in if List.all (fn b => b) mask then [(lhs, IL.OP(HighOps.Subscript(IL.Var.ty x), x::indices))] else [(lhs, IL.OP(HighOps.Slice(IL.Var.ty lhs, mask), x::indices))] end | S.E_Input(_, name, NONE) => [(lhs, IL.OP(HighOps.Input(IL.Var.ty lhs, name), []))] | S.E_Input(_, name, SOME dflt) => [(lhs, IL.OP(HighOps.InputWithDefault(IL.Var.ty lhs, name), [lookup env dflt]))] | S.E_Field fld => [(lhs, IL.OP(HighOps.Field fld, []))] | S.E_LoadImage info => [(lhs, IL.OP(HighOps.LoadImage info, []))] (* end case *)) fun cvtBlock (env, joinStk, S.Block stms) = let fun cvt (env, cfg, []) = cfg | cvt (env, cfg, stm::stms) = (case stm of S.S_Assign(lhs, rhs) => let val assigns = cvtExp (env, lhs, rhs) in (* FIXME: need to record assignments *) cvt (env, IL.CFG.concat(cfg, IL.CFG.mkBlock assigns), stms) end | S.S_IfThenElse(x, b0, b1) => let val x' = lookup env x val join = newJoin 2 val cfg0 = cvtBlock (env, (0, join)::joinStk, b0) val cfg1 = cvtBlock (env, (1, join)::joinStk, b1) fun skipEmpty cfg = if IL.CFG.isEmpty cfg then join else IL.CFG.entry cfg val cond = IL.Node.mkCOND { cond = x', trueBranch = skipEmpty cfg0, elseBranch = skipEmpty cfg1 } in case commitJoin (env, joinStk, join) of (env, SOME joinNd) => ( if IL.CFG.isEmpty cfg0 then () else IL.CFG.addEdge (IL.CFG.exit cfg0, joinNd); if IL.CFG.isEmpty cfg1 then () else IL.CFG.addEdge (IL.CFG.exit cfg1, joinNd); cvt ( env, IL.CFG{entry = IL.CFG.entry, exit = joinNd}, stms)) (* the join node has only zero or one predecessors, so * it was killed. *) | (env, NONE) => ?? (* end case *) end | S.S_New(strandId, args) => let val nd = IL.Node.mkNEW{ strand = strandId, args = List.map (lookup env) args } in cvt (env, IL.CFG.appendNode (cfg, nd), stms) end | S.S_Die => ( killPath joinStk; IL.CFG.appendNode (cfg, IL.Node.mkDIE ())) | S.S_Stabilize => ( killPath joinStk; IL.CFG.appendNode (cfg, IL.Node.mkSTABILIZE ())) (* end case *)) in cvt (env, IL.CFG.empty, stms) end fun cvtTopLevelBlock (env, blk) = let fun finish (env, firstNd, lastNd) = let val entry = IL.Node.mkENTRY () val exit = IL.Node.mkEXIT () in IL.Node.addEdge (entry, firstNd); (* NOTE: this addEdge could fail if all control paths end in DIE or STABILIZE, * so we wrap it in a handler *) IL.Node.addEdge (lastNd, exit) handle _ => (); IL.CFG{entry = ref entry, exit = ref exit} end in cvtBlock (env, blk, finish) end (* generate fresh SSA variables and add them to the environment *) fun freshVars (env, xs) = let fun cvtVar (x, (env, xs)) = let val x' = newVar x in (VMap.insert(env, x, x'), x'::xs) end val (env, xs) = List.foldl cvtVar (env, []) xs in (env, List.rev xs) end fun translate (S.Program{globals, globalInit, strands}) = let val (globalInit, env) = cvtTopLevelBlock (VMap.empty, globalInit) (* get the SSA names for the globals and a reduced environment that just defines * the globals. *) val (env, globs) = let val lookup = lookup env fun cvtVar (x, (env, globs)) = let val x' = lookup x in (VMap.insert(env, x, x'), x'::globs) end val (env, globs) = List.foldl cvtVar (VMap.empty, []) globals in (env, List.rev globs) end fun cvtStrand (S.Strand{name, params, state, stateInit, methods}) = let val (env, params) = let fun cvtParam (x, (env, xs)) = let val x' = newVar x in (VMap.insert(env, x, x'), x'::xs) end val (env, params) = List.foldl cvtParam (env, []) params in (env, List.rev params) end val (stateInit, env) = cvtTopLevelBlock (env, stateInit) val state' = List.map (lookup env) state fun cvtMethod (S.Method(name, blk)) = let (* allocate fresh variables for the state variables *) val (env, stateIn) = freshVars (env, state) val (body, env) = cvtTopLevelBlock (env, blk) val stateOut = List.map (lookup env) state in IL.Method{name=name, stateIn=stateIn, stateOut=stateOut, body=body} end in IL.Strand{ name = name, params = params, state = state', stateInit = stateInit, methods = List.map cvtMethod methods } end in IL.Program{ globals = globs, globalInit = globalInit, strands = List.map cvtStrand strands } end end
root@smlnj-gforge.cs.uchicago.edu | ViewVC Help |
Powered by ViewVC 1.0.0 |