1 (* Copyright (C) 2009,2014,2017 Matthew Fluet.
2 * Copyright (C) 1999-2008 Henry Cejtin, Matthew Fluet, Suresh
3 * Jagannathan, and Stephen Weeks.
4 * Copyright (C) 1997-2000 NEC Research Institute.
6 * MLton is released under a BSD-style license.
7 * See the file MLton-LICENSE for details.
10 functor SsaTree2 (S: SSA_TREE2_STRUCTS): SSA_TREE2 =
17 datatype 'a t = T of {elt: 'a, isMutable: bool} vector
23 fun empty () = T (Vector.new0 ())
26 Vector.fold (dest p, b, fn ({elt, ...}, b) => f (elt, b))
28 fun foreach (p, f) = Vector.foreach (dest p, f o #elt)
30 fun isEmpty p = Vector.isEmpty (dest p)
32 fun allAreImmutable (T v) = Vector.forall (v, not o #isMutable)
33 fun allAreMutable (T v) = Vector.forall (v, #isMutable)
34 fun someIsImmutable (T v) = Vector.exists (v, not o #isMutable)
35 fun someIsMutable (T v) = Vector.exists (v, #isMutable)
37 fun sub (T p, i) = Vector.sub (p, i)
39 fun elt (p, i) = #elt (sub (p, i))
41 fun length p = Vector.length (dest p)
43 val equals: 'a t * 'a t * ('a * 'a -> bool) -> bool =
44 fn (p1, p2, equals) =>
45 Vector.equals (dest p1, dest p2,
46 fn ({elt = e1, isMutable = m1},
47 {elt = e2, isMutable = m2}) =>
48 m1 = m2 andalso equals (e1, e2))
50 fun layout (p, layout) =
52 then Layout.str "unit"
57 (mayAlign o separateRight)
58 (Vector.toListMap (dest p, fn {elt, isMutable} =>
60 then seq [layout elt, str " ref"]
66 val map: 'a t * ('a -> 'b) -> 'b t =
68 make (Vector.map (dest p, fn {elt, isMutable} =>
70 isMutable = isMutable}))
72 val keepAllMap: 'a t * ('a -> 'b option) -> 'b t =
74 make (Vector.keepAllMap (dest p, fn {elt, isMutable} =>
75 Option.map (f elt, fn elt =>
77 isMutable = isMutable})))
87 val equals: t * t -> bool =
88 fn (Con c, Con c') => Con.equals (c, c')
89 | (Tuple, Tuple) => true
90 | (Vector, Vector) => true
93 val isVector: t -> bool =
97 val layout: t -> Layout.t =
103 Con c => Con.layout c
104 | Tuple => str "Tuple"
105 | Vector => str "Vector"
109 datatype z = datatype ObjectCon.t
115 plist: PropertyList.t,
119 | Datatype of Tycon.t
121 | Object of {args: t Prod.t,
129 fun make f (T r) = f r
131 val hash = make #hash
132 val plist = make #plist
133 val tree = make #tree
136 datatype dest = datatype tree
140 fun equals (t, t') = PropertyList.equals (plist t, plist t')
142 val deVectorOpt: t -> t Prod.t option =
145 Object {args, con = Vector} => SOME args
148 val deVector1: t -> t =
150 case deVectorOpt t of
152 if Prod.length args = 1
153 then Prod.elt (args, 0)
154 else Error.bug "SsaTree2.Type.deVector1"
155 | _ => Error.bug "SsaTree2.Type.deVector1"
157 val isVector: t -> bool = isSome o deVectorOpt
159 val deWeakOpt: t -> t option =
165 val deWeak: t -> t = valOf o deWeakOpt
168 val same: tree * tree -> bool =
169 fn (CPointer, CPointer) => true
170 | (Datatype t1, Datatype t2) => Tycon.equals (t1, t2)
171 | (IntInf, IntInf) => true
172 | (Object {args = a1, con = c1}, Object {args = a2, con = c2}) =>
173 ObjectCon.equals (c1, c2)
174 andalso Prod.equals (a1, a2, equals)
175 | (Real s1, Real s2) => RealSize.equals (s1, s2)
176 | (Thread, Thread) => true
177 | (Weak t1, Weak t2) => equals (t1, t2)
178 | (Word s1, Word s2) => WordSize.equals (s1, s2)
180 val table: t HashSet.t = HashSet.new {hash = hash}
182 fun lookup (hash, tr) =
183 HashSet.lookupOrInsert (table, hash,
184 fn t => same (tr, tree t),
185 fn () => T {hash = hash,
186 plist = PropertyList.new (),
191 in align [seq [str "num types in hash table = ",
192 Int.layout (HashSet.size table)],
193 Control.sizeMessage ("types hash table", lookup)]
197 val newHash = Random.word
200 fun make f : t -> t =
204 fn t => lookup (Word.xorb (w, hash t), f t)
210 val datatypee: Tycon.t -> t =
211 fn t => lookup (Tycon.hash t, Datatype t)
213 val bool = datatypee Tycon.bool
215 val isBool: t -> bool =
218 Datatype t => Tycon.equals (t, Tycon.bool)
222 fun make (tycon, tree) = lookup (Tycon.hash tycon, tree)
224 val cpointer = make (Tycon.cpointer, CPointer)
225 val intInf = make (Tycon.intInf, IntInf)
226 val thread = make (Tycon.thread, Thread)
229 val real: RealSize.t -> t =
230 fn s => lookup (Tycon.hash (Tycon.real s), Real s)
232 val word: WordSize.t -> t =
233 fn s => lookup (Tycon.hash (Tycon.word s), Word s)
236 val generator: Word.t = 0wx5555
237 val tuple = newHash ()
238 val vector = newHash ()
239 fun hashProd (p, base) =
240 Vector.fold (Prod.dest p, base, fn ({elt, ...}, w) =>
241 Word.xorb (w * generator, hash elt))
243 fun object {args, con}: t =
250 val hash = hashProd (args, base)
252 lookup (hash, Object {args = args, con = con})
256 fun vector p = object {args = p, con = Vector}
259 fun make isMutable t =
260 vector (Prod.make (Vector.new1 {elt = t, isMutable = isMutable}))
262 val array1 = make true
263 val vector1 = make false
268 datatype z = datatype Const.t
273 | Real r => real (RealX.size r)
274 | Word w => word (WordX.size w)
275 | WordVector v => vector1 (word (WordXVector.elementSize v))
278 fun conApp (con, args) = object {args = args, con = Con con}
280 fun tuple ts = object {args = ts, con = Tuple}
283 object {args = Prod.make (Vector.new1 {elt = t, isMutable = true}),
286 val unit: t = tuple (Prod.empty ())
288 val isUnit: t -> bool =
291 Object {args, con = Tuple} => Prod.isEmpty args
297 val {get = layout, ...} =
303 CPointer => str "cpointer"
304 | Datatype t => Tycon.layout t
305 | IntInf => str "intInf"
306 | Object {args, con} =>
311 val args = Prod.layout (args, layout)
314 Con c => seq [Con.layout c, str " of ", args]
316 | Vector => seq [args, str " vector"]
318 | Real s => str (concat ["real", RealSize.toString s])
319 | Thread => str "thread"
320 | Weak t => seq [layout t, str " weak"]
321 | Word s => str (concat ["word", WordSize.toString s])))
324 fun checkPrimApp {args, prim, result}: bool =
334 typeOps = {deArray = fn _ => raise BadPrimApp,
335 deArrow = fn _ => raise BadPrimApp,
336 deRef = fn _ => raise BadPrimApp,
337 deVector = fn _ => raise BadPrimApp,
345 typeOps = {array = array1,
346 arrow = fn _ => raise BadPrimApp,
353 reff = fn _ => raise BadPrimApp,
360 val default = fn () =>
361 (default ()) handle BadPrimApp => false
363 datatype z = datatype Prim.Name.t
364 fun arg i = Vector.sub (args, i)
365 fun oneArg f = 1 = Vector.length args andalso f (arg 0)
366 fun twoArgs f = 2 = Vector.length args andalso f (arg 0, arg 1)
367 fun fiveArgs f = 5 = Vector.length args andalso f (arg 0, arg 1, arg 2, arg 3, arg 4)
368 val seqIndex = word (WordSize.seqIndex ())
370 case Prim.name prim of
374 case deVectorOpt result of
376 Prod.allAreMutable resp
377 andalso equals (n, seqIndex)
381 (fn (dst, di, src, si, len) =>
382 case (deVectorOpt dst, deVectorOpt src) of
383 (SOME dstp, SOME srcp) =>
384 Vector.equals (Prod.dest dstp, Prod.dest srcp,
385 fn ({elt = dstElt, isMutable = dstIsMutable},
386 {elt = srcElt, isMutable = srcIsMutable}) =>
387 dstIsMutable andalso srcIsMutable
388 andalso equals (dstElt, srcElt))
389 andalso equals (di, seqIndex)
390 andalso equals (si, seqIndex)
391 andalso equals (len, seqIndex)
392 andalso isUnit result
394 | Array_copyVector =>
396 (fn (dst, di, src, si, len) =>
397 case (deVectorOpt dst, deVectorOpt src) of
398 (SOME dstp, SOME srcp) =>
399 Vector.equals (Prod.dest dstp, Prod.dest srcp,
400 fn ({elt = dstElt, isMutable = dstIsMutable},
401 {elt = srcElt, ...}) =>
403 andalso equals (dstElt, srcElt))
404 andalso equals (di, seqIndex)
405 andalso equals (si, seqIndex)
406 andalso equals (len, seqIndex)
407 andalso isUnit result
412 isVector a andalso equals (result, seqIndex))
416 case (deVectorOpt arr, deVectorOpt result) of
417 (SOME arrp, SOME resp) =>
418 Vector.equals (Prod.dest arrp, Prod.dest resp,
419 fn ({elt = arrElt, isMutable = arrIsMutable},
420 {elt = resElt, isMutable = resIsMutable}) =>
421 arrIsMutable andalso resIsMutable
422 andalso equals (arrElt, resElt))
427 case (deVectorOpt arr, deVectorOpt result) of
428 (SOME arrp, SOME resp) =>
429 Vector.equals (Prod.dest arrp, Prod.dest resp,
430 fn ({elt = arrElt, isMutable = arrIsMutable},
431 {elt = resElt, ...}) =>
433 andalso equals (arrElt, resElt))
438 case deVectorOpt arr of
440 Prod.allAreMutable arrp
441 andalso equals (i, seqIndex)
442 andalso isUnit result
444 | Array_uninitIsNop =>
447 case deVectorOpt arr of
449 Prod.allAreMutable arrp
450 andalso isBool result
459 Con of (Con.t * Label.t) vector
460 | Word of WordSize.t * (WordX.t * Label.t) vector
462 fun equals (c1: t, c2: t): bool =
464 fun doit (l1, l2, eq') =
466 (l1, l2, fn ((x1, a1), (x2, a2)) =>
467 eq' (x1, x2) andalso Label.equals (a1, a2))
470 (Con l1, Con l2) => doit (l1, l2, Con.equals)
471 | (Word (_, l1), Word (_, l2)) => doit (l1, l2, WordX.equals)
475 fun hd (c: t): Label.t =
478 if Vector.length v >= 1
479 then let val (_, a) = Vector.first v
482 else Error.bug "SsaTree2.Cases.hd"
486 | Word (_, cs) => doit cs
489 fun isEmpty (c: t): bool =
491 fun doit v = Vector.isEmpty v
495 | Word (_, cs) => doit cs
498 fun fold (c: t, b, f) =
500 fun doit l = Vector.fold (l, b, fn ((_, a), b) => f (a, b))
504 | Word (_, l) => doit l
507 fun map (c: t, f): t =
509 fun doit l = Vector.map (l, fn (i, x) => (i, f x))
512 Con l => Con (doit l)
513 | Word (s, l) => Word (s, doit l)
516 fun forall (c: t, f: Label.t -> bool): bool =
518 fun doit l = Vector.forall (l, fn (_, x) => f x)
522 | Word (_, l) => doit l
525 fun foreach (c, f) = fold (c, (), fn (x, ()) => f x)
532 | VectorSub of {index: 'a,
535 fun layout (b: 'a t, layoutX: 'a -> Layout.t): Layout.t =
540 Object x => layoutX x
541 | VectorSub {index, vector} =>
542 seq [str "$", Vector.layout layoutX (Vector.new2 (vector, index))]
545 val equals: 'a t * 'a t * ('a * 'a -> bool) -> bool =
546 fn (b1, b2, equalsX) =>
548 (Object x1, Object x2) => equalsX (x1, x2)
549 | (VectorSub {index = i1, vector = v1},
550 VectorSub {index = i2, vector = v2}) =>
551 equalsX (i1, i2) andalso equalsX (v1, v2)
554 fun object (b: 'a t): 'a =
557 | VectorSub {vector = x, ...} => x
560 val newHash = Random.word
561 val object = newHash ()
562 val vectorSub = newHash ()
564 val hash: 'a t * ('a -> word) -> word =
567 Object x => Word.xorb (object, hashX x)
568 | VectorSub {index, vector} =>
569 Word.xorb (Word.xorb (hashX index, hashX vector),
573 fun foreach (b: 'a t, f: 'a -> unit): unit =
576 | VectorSub {index, vector} => (f index; f vector)
578 fun map (b: 'a t, f: 'a -> 'b): 'b t =
580 Object x => Object (f x)
581 | VectorSub {index, vector} => VectorSub {index = f index,
589 | Inject of {sum: Tycon.t,
591 | Object of {con: Con.t option,
593 | PrimApp of {prim: Type.t Prim.t,
595 | Select of {base: Var.t Base.t,
599 val unit = Object {con = NONE, args = Vector.new0 ()}
601 fun foreachVar (e, v) =
603 fun vs xs = Vector.foreach (xs, v)
607 | Inject {variant, ...} => v variant
608 | Object {args, ...} => vs args
609 | PrimApp {args, ...} => vs args
610 | Select {base, ...} => Base.foreach (base, v)
614 fun replaceVar (e, fx) =
616 fun fxs xs = Vector.map (xs, fx)
620 | Inject {sum, variant} => Inject {sum = sum, variant = fx variant}
621 | Object {con, args} => Object {con = con, args = fxs args}
622 | PrimApp {prim, args} => PrimApp {args = fxs args, prim = prim}
623 | Select {base, offset} =>
624 Select {base = Base.map (base, fx), offset = offset}
625 | Var x => Var (fx x)
628 fun layout' (e, layoutVar) =
631 fun layoutArgs xs = Vector.layout layoutVar xs
634 Const c => Const.layout c
635 | Inject {sum, variant} =>
636 seq [paren (layoutVar variant), str ": ", Tycon.layout sum]
637 | Object {con, args} =>
640 | SOME c => seq [Con.layout c, str " "]),
642 | PrimApp {args, prim} =>
643 seq [Prim.layout prim, str " ", layoutArgs args]
644 | Select {base, offset} =>
645 seq [str "#", Int.layout offset, str " ",
646 paren (Base.layout (base, layoutVar))]
647 | Var x => layoutVar x
650 fun layout e = layout' (e, Var.layout)
652 fun maySideEffect (e: t): bool =
657 | PrimApp {prim,...} => Prim.maySideEffect prim
661 fun varsEquals (xs, xs') = Vector.equals (xs, xs', Var.equals)
663 fun equals (e: t, e': t): bool =
665 (Const c, Const c') => Const.equals (c, c')
666 | (Object {con, args}, Object {con = con', args = args'}) =>
667 Option.equals (con, con', Con.equals)
668 andalso varsEquals (args, args')
669 | (PrimApp {prim, args, ...},
670 PrimApp {prim = prim', args = args', ...}) =>
671 Prim.equals (prim, prim') andalso varsEquals (args, args')
672 | (Select {base = b1, offset = i1}, Select {base = b2, offset = i2}) =>
673 Base.equals (b1, b2, Var.equals) andalso i1 = i2
674 | (Var x, Var x') => Var.equals (x, x')
676 (* quell unused warning *)
680 val newHash = Random.word
681 val inject = newHash ()
682 val primApp = newHash ()
683 val select = newHash ()
684 val tuple = newHash ()
685 fun hashVars (xs: Var.t vector, w: Word.t): Word.t =
686 Vector.fold (xs, w, fn (x, w) => Word.xorb (w, Var.hash x))
688 val hash: t -> Word.t =
689 fn Const c => Const.hash c
690 | Inject {sum, variant} =>
692 Word.xorb (Tycon.hash sum, Var.hash variant))
693 | Object {con, args, ...} =>
697 | SOME c => Con.hash c)
698 | PrimApp {args, ...} => hashVars (args, primApp)
699 | Select {base, offset} =>
701 Base.hash (base, Var.hash) + Word.fromInt offset)
702 | Var x => Var.hash x
704 (* quell unused warning *)
707 datatype z = datatype Exp.t
709 structure Statement =
712 Bind of {var: Var.t option,
715 | Profile of ProfileExp.t
716 | Update of {base: Var.t Base.t,
720 fun layout' (s: t, layoutVar): Layout.t =
725 Bind {var, ty, exp} =>
728 if !Control.showTypes
729 then (str ":", indent (seq [Type.layout ty, str " ="], 2))
730 else (str " =", empty)
732 mayAlign [mayAlign [seq [case var of
734 | SOME var => Var.layout var,
737 indent (Exp.layout' (exp, layoutVar), 2)]
739 | Profile p => ProfileExp.layout p
740 | Update {base, offset, value} =>
741 mayAlign [seq [Exp.layout' (Exp.Select {base = base,
747 fun layout s = layout' (s, Var.layout)
749 val profile = Profile
751 fun foreachDef (s: t, f: Var.t * Type.t -> unit): unit =
753 Bind {ty, var, ...} => Option.app (var, fn x => f (x, ty))
756 fun clear s = foreachDef (s, Var.clear o #1)
758 fun prettifyGlobals (v: t vector): Var.t -> Layout.t =
760 val {get = global: Var.t -> Layout.t, set = setGlobal, ...} =
761 Property.getSet (Var.plist, Property.initFun Var.layout)
766 Bind {var, exp, ...} =>
772 val s = Layout.toString (Exp.layout' (exp, global))
775 val dotsSize = String.size dots
776 val frontSize = 2 * (maxSize - dotsSize) div 3
777 val backSize = maxSize - dotsSize - frontSize
779 if String.size s > maxSize
780 then concat [String.prefix (s, frontSize),
782 String.suffix (s, backSize)]
785 setGlobal (var, Layout.seq [Var.layout var,
786 Layout.str (" (*" ^ s ^ "*)")])
791 | Object {con, args, ...} =>
793 NONE => if Vector.isEmpty args then set () else ()
802 fun foreachUse (s: t, f: Var.t -> unit): unit =
804 Bind {exp, ...} => Exp.foreachVar (exp, f)
806 | Update {base, value, ...} => (Base.foreach (base, f); f value)
808 fun replaceDefsUses (s: t, {def: Var.t -> Var.t, use: Var.t -> Var.t}): t =
810 Bind {exp, ty, var} =>
811 Bind {exp = Exp.replaceVar (exp, use),
813 var = Option.map (var, def)}
815 | Update {base, offset, value} =>
816 Update {base = Base.map (base, use),
820 fun replaceUses (s, f) = replaceDefsUses (s, {def = fn x => x, use = f})
823 datatype z = datatype Statement.t
827 structure Label = Label
834 fun layout (h: t): Layout.t =
839 Caller => str "Caller"
841 | Handle l => seq [str "Handle ", Label.layout l]
845 fn (Caller, Caller) => true
846 | (Dead, Dead) => true
847 | (Handle l, Handle l') => Label.equals (l, l')
850 fun foldLabel (h: t, a: 'a, f: Label.t * 'a -> 'a): 'a =
854 | Handle l => f (l, a)
856 fun foreachLabel (h, f) = foldLabel (h, (), f o #1)
862 | Handle l => Handle (f l)
865 val newHash = Random.word
866 val caller = newHash ()
867 val dead = newHash ()
868 val handlee = newHash ()
870 fun hash (h: t): word =
874 | Handle l => Word.xorb (handlee, Label.hash l)
880 structure Label = Label
881 structure Handler = Handler
885 | NonTail of {cont: Label.t,
895 | NonTail {cont, handler} =>
898 [("cont", Label.layout cont),
899 ("handler", Handler.layout handler)]]
903 fun equals (r, r'): bool =
906 | (NonTail {cont = c, handler = h},
907 NonTail {cont = c', handler = h'}) =>
908 Label.equals (c, c') andalso Handler.equals (h, h')
909 | (Tail, Tail) => true
912 fun foldLabel (r: t, a, f) =
915 | NonTail {cont, handler} =>
916 Handler.foldLabel (handler, f (cont, a), f)
919 fun foreachLabel (r, f) = foldLabel (r, (), f o #1)
921 fun foreachHandler (r, f) =
924 | NonTail {handler, ...} => Handler.foreachLabel (handler, f)
930 | NonTail {cont, handler} =>
931 NonTail {cont = f cont,
932 handler = Handler.map (handler, f)}
935 fun compose (r, r') =
938 | NonTail {cont, handler} =>
941 handler = (case handler of
944 Dead => Handler.Caller
945 | NonTail {handler, ...} => handler
946 | Tail => Handler.Caller)
947 | Handler.Dead => handler
948 | Handler.Handle _ => handler)}
950 (* quell unused warning *)
954 val newHash = Random.word
955 val dead = newHash ()
956 val nonTail = newHash ()
957 val tail = newHash ()
962 | NonTail {cont, handler} =>
963 Word.xorb (Word.xorb (nonTail, Label.hash cont),
964 Handler.hash handler)
972 Arith of {prim: Type.t Prim.t,
974 overflow: Label.t, (* Must be nullary. *)
975 success: Label.t, (* Must be unary. *)
977 | Bug (* MLton thought control couldn't reach here. *)
978 | Call of {args: Var.t vector,
981 | Case of {test: Var.t,
983 default: Label.t option} (* Must be nullary. *)
984 | Goto of {dst: Label.t,
986 | Raise of Var.t vector
987 | Return of Var.t vector
988 | Runtime of {prim: Type.t Prim.t,
990 return: Label.t} (* Must be nullary. *)
992 fun foreachFuncLabelVar (t, func: Func.t -> unit, label: Label.t -> unit, var) =
994 fun vars xs = Vector.foreach (xs, var)
997 Arith {args, overflow, success, ...} =>
1002 | Call {func = f, args, return, ...} =>
1004 ; Return.foreachLabel (return, label)
1006 | Case {test, cases, default, ...} =>
1008 ; Cases.foreach (cases, label)
1009 ; Option.app (default, label))
1010 | Goto {dst, args, ...} => (vars args; label dst)
1011 | Raise xs => vars xs
1012 | Return xs => vars xs
1013 | Runtime {args, return, ...} =>
1018 fun foreachFunc (t, func) =
1019 foreachFuncLabelVar (t, func, fn _ => (), fn _ => ())
1020 (* quell unused warning *)
1023 fun foreachLabelVar (t, label, var) =
1024 foreachFuncLabelVar (t, fn _ => (), label, var)
1026 fun foreachLabel (t, j) = foreachLabelVar (t, j, fn _ => ())
1027 fun foreachVar (t, v) = foreachLabelVar (t, fn _ => (), v)
1029 fun replaceLabelVar (t, fl, fx) =
1031 fun fxs xs = Vector.map (xs, fx)
1034 Arith {prim, args, overflow, success, ty} =>
1037 overflow = fl overflow,
1038 success = fl success,
1041 | Call {func, args, return} =>
1044 return = Return.map (return, fl)}
1045 | Case {test, cases, default} =>
1046 Case {test = fx test,
1047 cases = Cases.map(cases, fl),
1048 default = Option.map(default, fl)}
1049 | Goto {dst, args} =>
1052 | Raise xs => Raise (fxs xs)
1053 | Return xs => Return (fxs xs)
1054 | Runtime {prim, args, return} =>
1055 Runtime {prim = prim,
1060 fun replaceLabel (t, f) = replaceLabelVar (t, f, fn x => x)
1061 (* quell unused warning *)
1062 val _ = replaceLabel
1063 fun replaceVar (t, f) = replaceLabelVar (t, fn l => l, f)
1066 fun layoutCase ({test, cases, default}, layoutVar) =
1069 fun doit (l, layout) =
1072 seq [layout i, str " => ", Label.layout l])
1073 datatype z = datatype Cases.t
1076 Con l => doit (l, Con.layout)
1077 | Word (_, l) => doit (l, WordX.layout)
1082 cases @ [seq [str "_ => ", Label.layout j]]
1084 align [seq [str "case ", layoutVar test, str " of"],
1085 indent (alignPrefix (cases, "| "), 2)]
1088 fun layout' (t, layoutVar) =
1091 fun layoutArgs xs = Vector.layout layoutVar xs
1092 fun layoutPrim {prim, args} =
1094 (Exp.PrimApp {prim = prim,
1099 Arith {prim, args, overflow, success, ...} =>
1100 seq [Label.layout success, str " ",
1101 tuple [layoutPrim {prim = prim, args = args}],
1102 str " handle Overflow => ", Label.layout overflow]
1104 | Call {func, args, return} =>
1106 val call = seq [Func.layout func, str " ", layoutArgs args]
1109 Return.Dead => seq [str "dead ", paren call]
1110 | Return.NonTail {cont, handler} =>
1111 seq [Label.layout cont, str " ",
1113 str " handle _ => ",
1115 Handler.Caller => str "raise"
1116 | Handler.Dead => str "dead"
1117 | Handler.Handle l => Label.layout l]
1118 | Return.Tail => seq [str "return ", paren call]
1120 | Case arg => layoutCase (arg, layoutVar)
1121 | Goto {dst, args} =>
1122 seq [Label.layout dst, str " ", layoutArgs args]
1123 | Raise xs => seq [str "raise ", layoutArgs xs]
1124 | Return xs => seq [str "return ", layoutArgs xs]
1125 | Runtime {prim, args, return} =>
1126 seq [Label.layout return, str " ",
1127 tuple [layoutPrim {prim = prim, args = args}]]
1130 fun layout t = layout' (t, Var.layout)
1132 fun varsEquals (xs, xs') = Vector.equals (xs, xs', Var.equals)
1134 fun equals (e: t, e': t): bool =
1136 (Arith {prim, args, overflow, success, ...},
1137 Arith {prim = prim', args = args',
1138 overflow = overflow', success = success', ...}) =>
1139 Prim.equals (prim, prim') andalso
1140 varsEquals (args, args') andalso
1141 Label.equals (overflow, overflow') andalso
1142 Label.equals (success, success')
1143 | (Bug, Bug) => true
1144 | (Call {func, args, return},
1145 Call {func = func', args = args', return = return'}) =>
1146 Func.equals (func, func') andalso
1147 varsEquals (args, args') andalso
1148 Return.equals (return, return')
1149 | (Case {test, cases, default},
1150 Case {test = test', cases = cases', default = default'}) =>
1151 Var.equals (test, test')
1152 andalso Cases.equals (cases, cases')
1153 andalso Option.equals (default, default', Label.equals)
1154 | (Goto {dst, args}, Goto {dst = dst', args = args'}) =>
1155 Label.equals (dst, dst') andalso
1156 varsEquals (args, args')
1157 | (Raise xs, Raise xs') => varsEquals (xs, xs')
1158 | (Return xs, Return xs') => varsEquals (xs, xs')
1159 | (Runtime {prim, args, return},
1160 Runtime {prim = prim', args = args', return = return'}) =>
1161 Prim.equals (prim, prim') andalso
1162 varsEquals (args, args') andalso
1163 Label.equals (return, return')
1165 (* quell unused warning *)
1169 val newHash = Random.word
1170 val bug = newHash ()
1171 val raisee = newHash ()
1172 val return = newHash ()
1173 fun hashVars (xs: Var.t vector, w: Word.t): Word.t =
1174 Vector.fold (xs, w, fn (x, w) => Word.xorb (w, Var.hash x))
1175 fun hash2 (w1: Word.t, w2: Word.t) = Word.xorb (w1, w2)
1177 val hash: t -> Word.t =
1178 fn Arith {args, overflow, success, ...} =>
1179 hashVars (args, hash2 (Label.hash overflow,
1180 Label.hash success))
1182 | Call {func, args, return} =>
1183 hashVars (args, hash2 (Func.hash func, Return.hash return))
1184 | Case {test, cases, default} =>
1185 hash2 (Var.hash test,
1189 (default, 0wx55555555,
1191 hash2 (Label.hash l, w)),
1193 hash2 (Label.hash l, w)))
1194 | Goto {dst, args} =>
1195 hashVars (args, Label.hash dst)
1196 | Raise xs => hashVars (xs, raisee)
1197 | Return xs => hashVars (xs, return)
1198 | Runtime {args, return, ...} => hashVars (args, Label.hash return)
1200 (* quell unused warning *)
1203 datatype z = datatype Transfer.t
1208 fun layoutFormals (xts: (Var.t * Type.t) vector) =
1209 Vector.layout (fn (x, t) =>
1211 if !Control.showTypes
1212 then seq [str ": ", Type.layout t]
1220 T of {args: (Var.t * Type.t) vector,
1222 statements: Statement.t vector,
1223 transfer: Transfer.t}
1226 fun make f (T r) = f r
1228 val args = make #args
1229 val label = make #label
1230 val transfer = make #transfer
1233 fun layout' (T {label, args, statements, transfer}, layoutVar) =
1236 fun layoutStatement s = Statement.layout' (s, layoutVar)
1237 fun layoutTransfer t = Transfer.layout' (t, layoutVar)
1239 align [seq [Label.layout label, str " ",
1240 layoutFormals args],
1243 (Vector.toListMap (statements, layoutStatement)),
1244 layoutTransfer transfer],
1247 fun layout b = layout' (b, Var.layout)
1249 fun clear (T {label, args, statements, ...}) =
1251 ; Vector.foreach (args, Var.clear o #1)
1252 ; Vector.foreach (statements, Statement.clear))
1255 structure Datatype =
1258 T of {cons: {args: Type.t Prod.t,
1262 fun layout (T {cons, tycon}) =
1266 seq [Tycon.layout tycon,
1270 (cons, fn {con, args} =>
1271 seq [Con.layout con, str " of ",
1272 Prod.layout (args, Type.layout)]),
1276 fun clear (T {cons, tycon}) =
1278 ; Vector.foreach (cons, Con.clear o #con))
1281 structure Function =
1283 structure CPromise = ClearablePromise
1285 type dest = {args: (Var.t * Type.t) vector,
1286 blocks: Block.t vector,
1289 raises: Type.t vector option,
1290 returns: Type.t vector option,
1293 (* There is a messy interaction between the laziness used in controlFlow
1294 * and the property lists on labels because the former stores
1295 * stuff on the property lists. So, if you force the laziness, then
1296 * clear the property lists, then try to use the lazy stuff, you will
1297 * get screwed with undefined properties. The right thing to do is reset
1298 * the laziness when the properties are cleared.
1302 {dfsTree: unit -> Block.t Tree.t,
1303 dominatorTree: unit -> Block.t Tree.t,
1304 graph: unit DirectedGraph.t,
1305 labelNode: Label.t -> unit DirectedGraph.Node.t,
1306 nodeBlock: unit DirectedGraph.Node.t -> Block.t} CPromise.t,
1310 fun make f (T {dest, ...}) = f dest
1312 val blocks = make #blocks
1313 val dest = make (fn d => d)
1314 val name = make #name
1317 fun foreachVar (f: t, fx: Var.t * Type.t -> unit): unit =
1319 val {args, blocks, ...} = dest f
1320 val _ = Vector.foreach (args, fx)
1323 (blocks, fn Block.T {args, statements, ...} =>
1324 (Vector.foreach (args, fx)
1325 ; Vector.foreach (statements, fn s =>
1326 Statement.foreachDef (s, fx))))
1331 fun controlFlow (T {controlFlow, ...}) =
1333 val {graph, labelNode, nodeBlock, ...} = CPromise.force controlFlow
1335 {graph = graph, labelNode = labelNode, nodeBlock = nodeBlock}
1340 fn T {controlFlow, ...} => sel (CPromise.force controlFlow) ()
1342 val dominatorTree = make #dominatorTree
1347 val {blocks, start, ...} = dest f
1348 val numBlocks = Vector.length blocks
1349 val {get = labelIndex, set = setLabelIndex, rem, ...} =
1350 Property.getSetOnce (Label.plist,
1351 Property.initRaise ("index", Label.layout))
1352 val _ = Vector.foreachi (blocks, fn (i, Block.T {label, ...}) =>
1353 setLabelIndex (label, i))
1354 val visited = Array.array (numBlocks, false)
1355 fun visit (l: Label.t): unit =
1357 val i = labelIndex l
1359 if Array.sub (visited, i)
1363 val _ = Array.update (visited, i, true)
1364 val b as Block.T {transfer, ...} =
1365 Vector.sub (blocks, i)
1367 val _ = Transfer.foreachLabel (transfer, visit)
1374 val _ = Vector.foreach (blocks, rem o Block.label)
1380 structure Graph = DirectedGraph
1381 structure Node = Graph.Node
1382 structure Edge = Graph.Edge
1384 fun determineControlFlow ({blocks, start, ...}: dest) =
1387 val g = Graph.new ()
1388 fun newNode () = Graph.newNode g
1389 val {get = labelNode, ...} =
1391 (Label.plist, Property.initFun (fn _ => newNode ()))
1392 val {get = nodeInfo: unit Node.t -> {block: Block.t},
1393 set = setNodeInfo, ...} =
1395 (Node.plist, Property.initRaise ("info", Node.layout))
1398 (blocks, fn b as Block.T {label, transfer, ...} =>
1400 val from = labelNode label
1401 val _ = setNodeInfo (from, {block = b})
1403 Transfer.foreachLabel
1405 (ignore o Graph.addEdge)
1406 (g, {from = from, to = labelNode to}))
1410 val root = labelNode start
1414 Graph.dfsTree (g, {root = root,
1415 nodeValue = #block o nodeInfo}))
1419 Graph.dominatorTree (g, {root = root,
1420 nodeValue = #block o nodeInfo}))
1423 dominatorTree = dominatorTree,
1425 labelNode = labelNode,
1426 nodeBlock = #block o nodeInfo}
1429 fun layoutDot (f, layoutVar) =
1431 fun toStringStatement s = Layout.toString (Statement.layout' (s, layoutVar))
1432 fun toStringTransfer t =
1436 Layout.seq [Layout.str "case ", layoutVar test]
1437 | _ => Transfer.layout' (t, layoutVar))
1438 fun toStringFormals args = Layout.toString (layoutFormals args)
1439 fun toStringHeader (name, args) = concat [name, " ", toStringFormals args]
1440 val {name, args, start, blocks, returns, raises, ...} = dest f
1442 val graph = Graph.new ()
1443 val {get = nodeOptions, ...} =
1444 Property.get (Node.plist, Property.initFun (fn _ => ref []))
1445 fun setNodeText (n: unit Node.t, l): unit =
1446 List.push (nodeOptions n, NodeOption.Label l)
1447 fun newNode () = Graph.newNode graph
1448 val {destroy, get = labelNode} =
1449 Property.destGet (Label.plist,
1450 Property.initFun (fn _ => newNode ()))
1451 val {get = edgeOptions, set = setEdgeOptions, ...} =
1452 Property.getSetOnce (Edge.plist, Property.initConst [])
1453 fun edge (from, to, label: string, style: style): unit =
1455 val e = Graph.addEdge (graph, {from = from,
1457 val _ = setEdgeOptions (e, [EdgeOption.label label,
1458 EdgeOption.Style style])
1464 (blocks, fn Block.T {label, args, statements, transfer} =>
1466 val from = labelNode label
1467 val edge = fn (to, label, style) =>
1468 edge (from, labelNode to, label, style)
1471 Arith {overflow, success, ...} =>
1472 (edge (success, "", Solid)
1473 ; edge (overflow, "Overflow", Dashed))
1475 | Call {return, ...} =>
1480 | Return.NonTail {cont, handler} =>
1481 (edge (cont, "", Dotted)
1482 ; (Handler.foreachLabel
1484 edge (l, "Handle", Dashed))))
1489 | Case {cases, default, ...} =>
1491 fun doit (v, toString) =
1494 edge (j, toString x, Solid))
1498 doit (v, Con.toString)
1499 | Cases.Word (_, v) =>
1500 doit (v, WordX.toString)
1505 edge (j, "Default", Solid)
1509 | Goto {dst, ...} => edge (dst, "", Solid)
1512 | Runtime {return, ...} => edge (return, "", Dotted)
1514 [(toStringTransfer transfer, Left)]
1517 (statements, lab, fn (s, ac) =>
1518 (toStringStatement s, Left) :: ac)
1520 (toStringHeader (Label.toString label, args), Left)::lab
1521 val _ = setNodeText (from, lab)
1525 val startNode = labelNode start
1528 val funNode = newNode ()
1529 val _ = edge (funNode, startNode, "Start", Solid)
1531 [(toStringTransfer (Transfer.Goto {dst = start, args = Vector.new0 ()}), Left)]
1533 if !Control.showTypes
1534 then ((Layout.toString o Layout.seq)
1536 Layout.record [("returns",
1538 (Vector.layout Type.layout)
1542 (Vector.layout Type.layout)
1547 (toStringHeader ("fun " ^ Func.toString name, args), Left)::
1549 val _ = setNodeText (funNode, lab)
1553 val controlFlowGraphLayout =
1555 (graph, fn {nodeName} =>
1556 {title = concat [Func.toString name, " control-flow graph"],
1557 options = [GraphOption.Rank (Min, [{nodeName = nodeName funNode}])],
1558 edgeOptions = edgeOptions,
1561 val l = ! (nodeOptions n)
1563 in FontColor Black :: Shape Box :: l
1565 val () = Graph.removeNode (graph, funNode)
1566 fun dominatorTreeLayout () =
1568 val {get = nodeOptions, set = setNodeOptions, ...} =
1569 Property.getSetOnce (Node.plist, Property.initConst [])
1572 (blocks, fn Block.T {label, ...} =>
1573 setNodeOptions (labelNode label,
1574 [NodeOption.label (Label.toString label)]))
1575 val dominatorTreeLayout =
1577 (Graph.dominatorTree (graph,
1579 nodeValue = fn n => n}),
1580 {title = concat [Func.toString name, " dominator tree"],
1582 nodeOptions = nodeOptions})
1586 fun loopForestLayout () =
1588 val {get = nodeName, set = setNodeName, ...} =
1589 Property.getSetOnce (Node.plist, Property.initConst "")
1592 (blocks, fn Block.T {label, ...} =>
1593 setNodeName (labelNode label, Label.toString label))
1594 val loopForestLayout =
1595 Graph.LoopForest.layoutDot
1596 (Graph.loopForestSteensgaard (graph,
1597 {root = startNode}),
1598 {title = concat [Func.toString name, " loop forest"],
1600 nodeName = nodeName})
1606 controlFlowGraph = controlFlowGraphLayout,
1607 dominatorTree = dominatorTreeLayout,
1608 loopForest = loopForestLayout}
1612 fun new (dest: dest) =
1614 val controlFlow = CPromise.delay (fn () => determineControlFlow dest)
1616 T {controlFlow = controlFlow,
1620 fun clear (T {controlFlow, dest, ...}) =
1622 val {args, blocks, ...} = dest
1623 val _ = (Vector.foreach (args, Var.clear o #1)
1624 ; Vector.foreach (blocks, Block.clear))
1625 val _ = CPromise.clear controlFlow
1630 fun layoutHeader (f: t): Layout.t =
1632 val {args, name, raises, returns, start, ...} = dest f
1635 if !Control.showTypes
1637 indent (seq [record [("returns",
1639 (Vector.layout Type.layout)
1643 (Vector.layout Type.layout)
1647 else (str " =", empty)
1649 mayAlign [mayAlign [seq [str "fun ",
1655 Transfer.layout (Transfer.Goto {dst = start, args = Vector.new0 ()})]
1658 fun layout' (f: t, layoutVar) =
1660 val {blocks, ...} = dest f
1662 fun layoutBlock b = Block.layout' (b, layoutVar)
1664 align [layoutHeader f,
1665 indent (align (Vector.toListMap (blocks, layoutBlock)), 2)]
1667 fun layout f = layout' (f, Var.layout)
1669 fun layouts (f: t, layoutVar, output: Layout.t -> unit): unit =
1671 val {blocks, name, ...} = dest f
1672 val _ = output (layoutHeader f)
1676 output (Layout.indent (Block.layout' (b, layoutVar), 2)))
1678 if not (!Control.keepDot)
1682 val {destroy, controlFlowGraph, dominatorTree, loopForest} =
1683 layoutDot (f, layoutVar)
1684 val name = Func.toString name
1690 ({suffix = concat [name, ".", s, ".dot"]},
1691 Dot, (), Layout (fn () => g))
1693 val _ = doit ("cfg", controlFlowGraph)
1694 handle _ => Error.warning "SsaTree2.layouts: couldn't layout cfg"
1695 val _ = doit ("dom", dominatorTree ())
1696 handle _ => Error.warning "SsaTree2.layouts: couldn't layout dom"
1697 val _ = doit ("lf", loopForest ())
1698 handle _ => Error.warning "SsaTree2.layouts: couldn't layout lf"
1710 fun make (new, plist) =
1712 val {get, set, destroy, ...} =
1713 Property.destGetSetOnce (plist, Property.initConst NONE)
1717 val _ = set (x, SOME x')
1725 in (bind, lookup, destroy)
1728 val (bindVar, lookupVar, destroyVar) =
1729 make (Var.new, Var.plist)
1730 val (bindLabel, lookupLabel, destroyLabel) =
1731 make (Label.new, Label.plist)
1733 val {args, blocks, mayInline, name, raises, returns, start, ...} =
1735 val args = Vector.map (args, fn (x, ty) => (bindVar x, ty))
1736 val bindLabel = ignore o bindLabel
1737 val bindVar = ignore o bindVar
1740 (blocks, fn Block.T {label, args, statements, ...} =>
1742 ; Vector.foreach (args, fn (x, _) => bindVar x)
1743 ; Vector.foreach (statements, fn s =>
1744 Statement.foreachDef (s, bindVar o #1))))
1747 (blocks, fn Block.T {label, args, statements, transfer} =>
1748 Block.T {label = lookupLabel label,
1749 args = Vector.map (args, fn (x, ty) =>
1751 statements = (Vector.map
1752 (statements, fn s =>
1753 Statement.replaceDefsUses
1754 (s, {def = lookupVar,
1755 use = lookupVar}))),
1756 transfer = Transfer.replaceLabelVar
1757 (transfer, lookupLabel, lookupVar)})
1758 val start = lookupLabel start
1759 val _ = destroyVar ()
1760 val _ = destroyLabel ()
1764 mayInline = mayInline,
1770 (* quell unused warning *)
1773 fun profile (f: t, sourceInfo): t =
1774 if !Control.profile = Control.ProfileNone
1775 orelse !Control.profileIL <> Control.ProfileSource
1779 val _ = Control.diagnostic (fn () => layout f)
1780 val {args, blocks, mayInline, name, raises, returns, start} = dest f
1781 val extraBlocks = ref []
1782 val {get = labelBlock, set = setLabelBlock, rem} =
1784 (Label.plist, Property.initRaise ("block", Label.layout))
1787 (blocks, fn block as Block.T {label, ...} =>
1788 setLabelBlock (label, block))
1791 (blocks, fn Block.T {args, label, statements, transfer} =>
1794 if Label.equals (label, start)
1797 (Profile (ProfileExp.Enter sourceInfo)),
1800 fun leave () = Profile (ProfileExp.Leave sourceInfo)
1801 fun prefix (l: Label.t,
1802 statements: Statement.t vector): Label.t =
1804 val Block.T {args, ...} = labelBlock l
1805 val c = Label.newNoname ()
1806 val xs = Vector.map (args, fn (x, _) => Var.new x)
1811 {args = Vector.map2 (xs, args, fn (x, (_, t)) =>
1814 statements = statements,
1815 transfer = Goto {args = xs,
1820 fun genHandler (cont: Label.t)
1821 : Statement.t vector * Label.t * Handler.t =
1823 NONE => (statements, cont, Handler.Caller)
1826 val xs = Vector.map (ts, fn _ => Var.newNoname ())
1827 val l = Label.newNoname ()
1832 {args = Vector.zip (xs, ts),
1834 statements = Vector.new1 (leave ()),
1835 transfer = Transfer.Raise xs})
1838 prefix (cont, Vector.new0 ()),
1842 (Vector.concat [statements,
1843 Vector.new1 (leave ())],
1845 val (statements, transfer) =
1847 Call {args, func, return} =>
1849 datatype z = datatype Return.t
1852 Dead => (statements, transfer)
1853 | NonTail {cont, handler} =>
1855 Handler.Dead => (statements, transfer)
1858 val (statements, cont, handler) =
1870 | Handler.Handle _ =>
1871 (statements, transfer))
1872 | Tail => addLeave ()
1874 | Raise _ => addLeave ()
1875 | Return _ => addLeave ()
1876 | _ => (statements, transfer)
1878 Block.T {args = args,
1880 statements = statements,
1881 transfer = transfer}
1883 val _ = Vector.foreach (blocks, rem o Block.label)
1884 val blocks = Vector.concat [Vector.fromList (!extraBlocks), blocks]
1888 mayInline = mayInline,
1893 val _ = Control.diagnostic (fn () => layout f)
1899 Trace.trace2 ("SsaTree2.Function.profile", layout, SourceInfo.layout, layout)
1907 datatypes: Datatype.t vector,
1908 globals: Statement.t vector,
1909 functions: Function.t list,
1919 structure Graph = DirectedGraph
1920 structure Node = Graph.Node
1921 structure Edge = Graph.Edge
1923 fun layoutCallGraph (T {functions, main, ...},
1924 title: string): Layout.t =
1927 val graph = Graph.new ()
1928 val {get = nodeOptions, set = setNodeOptions, ...} =
1930 (Node.plist, Property.initRaise ("options", Node.layout))
1931 val {get = funcNode, destroy} =
1933 (Func.plist, Property.initFun
1936 val n = Graph.newNode graph
1941 in [FontColor Black, label (Func.toString f)]
1946 val {get = edgeOptions, set = setEdgeOptions, ...} =
1947 Property.getSetOnce (Edge.plist, Property.initConst [])
1952 val {name, blocks, ...} = Function.dest f
1953 val from = funcNode name
1954 val {get, destroy} =
1957 Property.initFun (fn _ => {nontail = ref false,
1961 (blocks, fn Block.T {transfer, ...} =>
1963 Call {func, return, ...} =>
1965 val to = funcNode func
1966 val {tail, nontail} = get to
1967 datatype z = datatype Return.t
1973 val r = if is then nontail else tail
1980 (graph, {from = from, to = to}),
1983 else [EdgeOption.Style Dotted])))
1990 val root = funcNode main
1993 (graph, fn {nodeName} =>
1995 options = [GraphOption.Rank (Min, [{nodeName = nodeName root}])],
1996 edgeOptions = edgeOptions,
1997 nodeOptions = nodeOptions})
2004 fun layouts (p as T {datatypes, globals, functions, main},
2005 output': Layout.t -> unit) =
2007 val layoutVar = Statement.prettifyGlobals globals
2009 (* Layout includes an output function, so we need to rebind output
2012 val output = output'
2014 output (str "\n\nDatatypes:")
2015 ; Vector.foreach (datatypes, output o Datatype.layout)
2016 ; output (str "\n\nGlobals:")
2017 ; Vector.foreach (globals, output o (fn s => Statement.layout' (s, layoutVar)))
2018 ; output (seq [str "\n\nMain: ", Func.layout main])
2019 ; output (str "\n\nFunctions:")
2020 ; List.foreach (functions, fn f =>
2021 Function.layouts (f, layoutVar, output))
2022 ; if not (!Control.keepDot)
2029 ({suffix = "call-graph.dot"},
2030 Dot, (), Layout (fn () =>
2031 layoutCallGraph (p, !Control.inputFile)))
2035 fun layoutStats (T {datatypes, globals, functions, main, ...}) =
2037 val (mainNumVars, mainNumBlocks) =
2038 case List.peek (functions, fn f =>
2039 Func.equals (main, Function.name f)) of
2040 NONE => Error.bug "SsaTree2.Program.layoutStats: no main"
2044 val _ = Function.foreachVar (f, fn _ => Int.inc numVars)
2045 val {blocks, ...} = Function.dest f
2046 val numBlocks = Vector.length blocks
2048 (!numVars, numBlocks)
2050 val numTypes = ref 0
2051 val {get = countType, destroy} =
2055 (fn (t, countType) =>
2057 datatype z = datatype Type.dest
2063 | Object {args, ...} => Prod.foreach (args, countType)
2066 | Weak t => countType t
2068 val _ = Int.inc numTypes
2074 (datatypes, fn Datatype.T {cons, ...} =>
2075 Vector.foreach (cons, fn {args, ...} =>
2076 Prod.foreach (args, countType)))
2077 val numStatements = ref (Vector.length globals)
2078 val numBlocks = ref 0
2083 val {args, blocks, ...} = Function.dest f
2084 val _ = Vector.foreach (args, countType o #2)
2087 (blocks, fn Block.T {args, statements, ...} =>
2089 val _ = Int.inc numBlocks
2090 val _ = Vector.foreach (args, countType o #2)
2093 (statements, fn stmt =>
2095 val _ = Int.inc numStatements
2096 datatype z = datatype Statement.t
2099 Bind {ty, ...} => countType ty
2104 val numFunctions = List.length functions
2109 [seq [str "num vars in main = ", Int.layout mainNumVars],
2110 seq [str "num blocks in main = ", Int.layout mainNumBlocks],
2111 seq [str "num functions in program = ", Int.layout numFunctions],
2112 seq [str "num blocks in program = ", Int.layout (!numBlocks)],
2113 seq [str "num statements in program = ", Int.layout (!numStatements)],
2114 seq [str "num types in program = ", Int.layout (!numTypes)],
2118 (* clear all property lists reachable from program *)
2119 fun clear (T {datatypes, globals, functions, ...}) =
2120 ((* Can't do Type.clear because it clears out the info needed for
2123 Vector.foreach (datatypes, Datatype.clear)
2124 ; Vector.foreach (globals, Statement.clear)
2125 ; List.foreach (functions, Function.clear))
2127 fun clearGlobals (T {globals, ...}) =
2128 Vector.foreach (globals, Statement.clear)
2130 fun clearTop (p as T {datatypes, functions, ...}) =
2131 (Vector.foreach (datatypes, Datatype.clear)
2132 ; List.foreach (functions, Func.clear o Function.name)
2135 fun foreachVar (T {globals, functions, ...}, f) =
2136 (Vector.foreach (globals, fn s => Statement.foreachDef (s, f))
2137 ; List.foreach (functions, fn g => Function.foreachVar (g, f)))
2139 fun foreachPrimApp (T {globals, functions, ...}, f) =
2141 fun loopStatement (s: Statement.t) =
2143 Bind {exp = PrimApp {args, prim}, ...} =>
2144 f {args = args, prim = prim}
2146 fun loopTransfer t =
2148 Arith {args, prim, ...} => f {args = args, prim = prim}
2149 | Runtime {args, prim, ...} => f {args = args, prim = prim}
2151 val _ = Vector.foreach (globals, loopStatement)
2156 (Function.blocks f, fn Block.T {statements, transfer, ...} =>
2157 (Vector.foreach (statements, loopStatement);
2158 loopTransfer transfer)))
2163 fun hasPrim (p, f) =
2166 (foreachPrimApp (p, fn {prim, ...} =>
2167 if f prim then escape true else ())
2172 val T {functions, main, ...} = p
2173 val functions = Vector.fromList functions
2174 val numFunctions = Vector.length functions
2175 val {get = funcIndex, set = setFuncIndex, rem, ...} =
2176 Property.getSetOnce (Func.plist,
2177 Property.initRaise ("index", Func.layout))
2178 val _ = Vector.foreachi (functions, fn (i, f) =>
2179 setFuncIndex (#name (Function.dest f), i))
2180 val visited = Array.array (numFunctions, false)
2181 fun visit (f: Func.t): unit =
2185 if Array.sub (visited, i)
2189 val _ = Array.update (visited, i, true)
2190 val f = Vector.sub (functions, i)
2192 val _ = Function.dfs
2193 (f, fn Block.T {transfer, ...} =>
2194 (Transfer.foreachFunc (transfer, visit)
2202 val _ = Vector.foreach (functions, rem o Function.name)