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

SCM Repository

[diderot] View of /branches/vis12-cl/src/compiler/IL/dom-tree-fn.sml
ViewVC logotype

View of /branches/vis12-cl/src/compiler/IL/dom-tree-fn.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2999 - (download) (annotate)
Sat Mar 7 15:47:33 2015 UTC (4 years, 6 months ago) by jhr
File size: 4088 byte(s)
  porting changes from vis12 branch
(* dom-tree-fn.sml
 *
 * COPYRIGHT (c) 2011 The Diderot Project (http://diderot-language.cs.uchicago.edu)
 * All rights reserved.
 *)

signature DOMINANCE_TREE =
  sig

    structure IL : SSA

  (* compute the dominance-tree information for a CFG *)
    val computeTree : IL.cfg -> unit

  (* return the dominance-tree children associated with a given node.
   * For a conditional, the true child proceeds the false child (if
   * both are dominance-tree children)
   *)
    val children : IL.node -> IL.node list

  (* cleanup the node properties used to store information about the tree *)
    val clear : IL.cfg -> unit

  end

functor DomTreeFn (IL : SSA) : DOMINANCE_TREE = struct

    structure IL = IL
    structure Nd = IL.Node

  (* a property for COND nodes that maps them to their associated JOIN node
   * (if one exists).
   *)
    val {
	  peekFn = getJoin : IL.node -> IL.node option,
	  setFn = setJoin, clrFn = clrJoin, ...
	} = Nd.newProp (fn _ => raise Fail "join property")

  (* an element on the stack of open COND nodes. *)
    datatype open_if
      = THEN_BR of {cond : IL.node, elseBr : IL.node}
      | ELSE_BR of {cond : IL.node}

  (* compute the dominance-tree information for a CFG.  Most of the immediate
   * dominator info is already present in the tree, since JOIN nodes are the
   * only ones with multiple predecessors, but we also need tree edges from
   * COND nodes to their matching JOIN (it it exists).  We use properties
   * to implemented these edges
   *)
    fun computeTree cfg = let
	  fun walk (ifStk : open_if list, nd) = (case Nd.kind nd
		 of IL.NULL => raise Fail "unexpected NULL node"
		  | IL.ENTRY{succ} => walk (ifStk, !succ)
		  | IL.JOIN{preds, succ, ...} =>
		      if (List.length(!preds) > 1)
			then (case ifStk
			   of [] => raise Fail "unmatched JOIN"
			    | THEN_BR{cond, elseBr}::r => (
				setJoin(cond, nd);
				walk (ELSE_BR{cond=cond}::r, elseBr))
			    | ELSE_BR{cond}::r => (
				walk (r, !succ))
			  (* end case *))
			else walk(List.tl ifStk, !succ)
		  | IL.COND{trueBranch, falseBranch, ...} =>
		      walk (THEN_BR{cond=nd, elseBr = !falseBranch}::ifStk, !trueBranch)
		  | IL.COM{succ, ...} => walk (ifStk, !succ)
		  | IL.ASSIGN{succ, ...} => walk (ifStk, !succ)
		  | IL.MASSIGN{succ, ...} => walk (ifStk, !succ)
                  | IL.GASSIGN{succ, ...} => walk (ifStk, !succ)
		  | IL.NEW{succ, ...} => walk (ifStk, !succ)
                  | IL.SAVE{succ, ...} => walk (ifStk, !succ)
		  | IL.EXIT _ => resume ifStk
		(* end case *))
	  and resume [] = ()
	    | resume (THEN_BR{cond, elseBr}::r) = walk (ELSE_BR{cond=cond}::r, elseBr)
	    | resume (ELSE_BR{cond}::r) = (case getJoin cond
		 of NONE => resume r
		  | SOME nd' => walk(r, nd')
		(* end case *))
	  in
	    walk ([], IL.CFG.entry cfg)
	  end

  (* get the dominance-tree children associated with a given node *)
    fun children nd = let
	(* check to see if a successor node is immediately dominated by nd. *)
	  fun maybeSucc (ref nd') = (case Nd.kind nd'
		 of IL.JOIN{preds, ...} => (case !preds
		       of [_] => [nd'] (* JOIN with single predecessor *)
			| _ => []
		      (* end case *))
		  | IL.COM{succ, ...} => maybeSucc succ (* skip comments *)
		  | _ => [nd']
		(* end case *))
	  in
	    case Nd.kind nd
	     of IL.NULL => raise Fail "unexpected NULL node"
	      | IL.ENTRY{succ} => maybeSucc succ
	      | IL.JOIN{succ, ...} => maybeSucc succ
	      | IL.COND{trueBranch, falseBranch, ...} => (case getJoin nd
		   of SOME nd' => maybeSucc trueBranch @ maybeSucc falseBranch @ [nd']
		    | NONE => [!trueBranch, !falseBranch]
		  (* end case *))
	      | IL.COM{succ, ...} => maybeSucc succ
	      | IL.ASSIGN{succ, ...} => maybeSucc succ
	      | IL.MASSIGN{succ, ...} => maybeSucc succ
	      | IL.GASSIGN{succ, ...} => maybeSucc succ
	      | IL.NEW{succ, ...} => maybeSucc succ
	      | IL.SAVE{succ, ...} => maybeSucc succ
	      | IL.EXIT _ => []
	    (* end case *)
	  end

  (* cleanup the node properties used to store information about the tree *)
    fun clear cfg = IL.CFG.apply clrJoin cfg

  end

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