1 (* Copyright (C) 2017 Matthew Fluet.
2 * Copyright (C) 1999-2005, 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.
11 * All local variables in the Sxml are renamed to new variables in Ssa,
12 * unless they are global, as determined by the Globalization pass.
13 * Renaming must happen because an Sxml variable will be bound in the Ssa
14 * once for each lambda it occurs in. The main trickiness is caused because a
15 * property is used to implement the renamer map. Hence, a variable binding
16 * must always be visited with "newVar" or "newScope" before it is looked up
17 * with "getNewVar". "newScope" also handles resetting the variable to its
18 * old value once the processing of the lambda is done.
20 functor ClosureConvert (S: CLOSURE_CONVERT_STRUCTS): CLOSURE_CONVERT =
25 structure Globalize = Globalize (open Sxml)
29 structure Scases = Cases
32 structure Slambda = Lambda
34 structure SprimExp = PrimExp
35 structure SvarExp = VarExp
36 structure Stype = Type
43 structure Block = Block
44 structure Datatype = Datatype
45 structure Dexp = DirectExp
47 structure Function = Function
48 structure SourceInfo = SourceInfo
52 structure Value = AbstractValue (structure Ssa = Ssa
53 structure Sxml = Sxml)
55 in structure Lambdas = Lambdas
58 (* Accum.t is one of the results returned internally by the converter -- an
59 * accumulation of toplevel Ssa globals and function declarations.
63 structure AL = AppendList
65 datatype t = T of {globals: {var: Var.t,
68 functions: Function.t list}
70 val empty = T {globals = AL.empty, functions = []}
72 fun addGlobals (T {globals, functions}, gs) =
73 T {globals = AL.append (globals, AL.fromList gs),
74 functions = functions}
76 fun addGlobal (ac, g) = addGlobals (ac, [g])
78 fun addFunc (T {globals, functions}, f) =
79 T {globals = globals, functions = f :: functions}
81 fun done (T {globals, functions}) =
82 {functions = functions,
85 (* Must shrink because coercions may be inserted at constructor
86 * applications. I'm pretty sure the shrinking will eliminate
87 * any case expressions/local functions.
88 * We must rebind eliminated variables because the shrinker is
89 * just processing globals and hence cannot safely delete a
90 * variable that has no occurrences, since there may still be
91 * occurrences in functions.
93 val globals = AL.toList globals
94 val vars = Vector.fromListMap (globals, #var)
95 val tys = Vector.fromListMap (globals, #ty)
99 {decs = List.map (globals, fn {var, exp, ...} =>
100 {var = var, exp = exp}),
101 body = Dexp.tuple {exps = (Vector.fromListMap
102 (globals, fn {var, ty, ...} =>
103 Dexp.var (var, ty))),
104 ty = Type.tuple tys}},
109 {globals = Vector.new0 ()}
110 (Function.new {args = Vector.new0 (),
111 blocks = Vector.fromList blocks,
112 mayInline = false, (* doesn't matter *)
113 name = Func.newNoname (),
115 returns = SOME (Vector.new1 (Type.tuple tys)),
118 if 1 <> Vector.length blocks
119 then Error.bug (concat ["ClosureConvert.Accum.done: ",
120 "shrinker didn't completely simplify"])
123 val ss = Block.statements (Vector.first blocks)
125 case Ssa.Statement.exp (Vector.last ss) of
127 if Vector.length vars = Vector.length vs
129 else Error.bug (concat ["ClosureConvert.Accum.done: ",
130 "shrinker didn't simplify right"])
131 | _ => Error.bug (concat ["ClosureConvert.Accum.done: ",
132 "shrinker didn't produce tuple"])
133 val ss = Vector.dropSuffix (ss, 1)
137 if Var.equals (v, Vector.sub (vars, i))
139 else SOME (Ssa.Statement.T
140 {exp = Ssa.Exp.Var v,
141 ty = Vector.sub (tys, i),
142 var = SOME (Vector.sub (vars, i))}))
144 Vector.concat [ss, rebinds]
150 val traceConvertExp =
152 ("ClosureConvert.convertExp",
153 Sexp.layout, Instance.layout, Dexp.layout)
156 val convertPrimExpInfo = Trace.info "ClosureConvert.convertPrimExp"
157 val valueTypeInfo = Trace.info "ClosureConvert.valueType"
159 structure LambdaFree = LambdaFree (Sxml)
164 structure Status = Status
167 structure LambdaInfo =
172 frees: Var.t vector ref,
173 (* name is the original name in the source (i.e. SXML) program,
174 * so the closure conversion output has some readability.
177 recs: Var.t vector ref,
178 (* The type of its environment record. *)
179 ty: Type.t option ref
182 fun frees (T {frees, ...}) = !frees
187 type t = {frees: Var.t list ref ref,
189 lambda: Slambda.t option,
190 replacement: Var.t ref,
191 status: Status.t ref,
195 fun make sel (r: t) = sel r
197 val lambda = valOf o make #lambda
198 val value = make #value
204 ("ClosureConvert.loopBind",
205 fn {exp, ty = _: Stype.t, var} =>
206 Layout.record [("var", Var.layout var),
207 ("exp", SprimExp.layout exp)],
211 (program as Sxml.Program.T {datatypes, body, overflow}): Ssa.Program.t =
213 val {get = conArg: Con.t -> Value.t option, set = setConArg, ...} =
214 Property.getSetOnce (Con.plist,
215 Property.initRaise ("conArg", Con.layout))
216 val {get = varInfo: Var.t -> VarInfo.t, set = setVarInfo, ...} =
218 (Var.plist, Property.initRaise ("closure convert info", Var.layout))
221 ("ClosureConvert.varInfo", Var.layout, Layout.ignore)
223 val varExpInfo = varInfo o SvarExp.var
224 val isGlobal = ! o #isGlobal o varInfo
227 ("ClosureConvert.isGlobal", Var.layout, Bool.layout)
229 val value = #value o varInfo
230 val varExp = value o SvarExp.var
231 val expValue = varExp o Sexp.result
232 (* ---------------------------------- *)
234 (* ---------------------------------- *)
235 val {get = lambdaInfo: Slambda.t -> LambdaInfo.t,
236 set = setLambdaInfo, ...} =
239 Property.initRaise ("closure convert info", Layout.ignore))
240 val allLambdas: Slambda.t list ref = ref []
241 (* Do the flow analysis.
242 * Initialize lambdaInfo and varInfo.
246 (datatypes, fn {cons, ...} =>
248 (cons, fn {con, arg} =>
249 setConArg (con, (case arg of
251 | SOME t => SOME (Value.fromType t)))))
255 val bogusFrees = ref []
256 fun newVar' (x, v, lambda) =
257 setVarInfo (x, {frees = ref bogusFrees,
258 isGlobal = ref false,
261 status = ref Status.init,
263 fun newVar (x, v) = newVar' (x, v, NONE)
266 ("ClosureConvert.newVar",
267 Var.layout, Layout.ignore, Unit.layout)
269 fun varExps xs = Vector.map (xs, varExp)
270 fun loopExp (e: Exp.t): Value.t =
272 val {decs, result} = Exp.dest e
273 val () = List.foreach (decs, loopDec)
277 and loopDec (d: Dec.t): unit =
279 datatype z = datatype Dec.t
283 (Vector.foreach (decs, fn {var, lambda, ty, ...} =>
284 newVar' (var, Value.fromType ty,
287 (decs, fn {var, lambda, ...} =>
288 Value.unify (value var,
289 loopLambda (lambda, var)))))
290 | MonoVal b => loopBind b
291 | _ => Error.bug "ClosureConvert.loopDec: strange dec"
295 (fn {var, ty, exp} =>
297 fun set v = newVar (var, v)
299 let val v = Value.fromType ty
302 val new' = ignore o new
303 datatype z = datatype PrimExp.t
307 let val arg = varExp arg
310 (varExp func, fn l =>
312 val lambda = Value.Lambda.dest l
313 val {arg = formal, body, ...} =
315 in Value.coerce {from = arg,
317 ; Value.coerce {from = expValue body,
321 | Case {cases, default, ...} =>
325 Value.coerce {from = loopExp e, to = result}
326 fun handlePat (Pat.T {con, arg, ...}) =
327 case (arg, conArg con) of
329 | (SOME (x, _), SOME v) => newVar (x, v)
330 | _ => Error.bug "ClosureConvert.loopBind: Case"
331 val _ = Cases.foreach' (cases, branch, handlePat)
332 val _ = Option.app (default, branch o #1)
335 | ConApp {con, arg, ...} =>
336 (case (arg, conArg con) of
338 | (SOME x, SOME v) =>
339 Value.coerce {from = varExp x, to = v}
340 | _ => Error.bug "ClosureConvert.loopBind: ConApp"
343 | Handle {try, catch = (x, t), handler} =>
346 in Value.coerce {from = loopExp try, to = result}
347 ; newVar (x, Value.fromType t)
348 ; Value.coerce {from = loopExp handler, to = result}
350 | Lambda l => set (loopLambda (l, var))
351 | PrimApp {prim, args, ...} =>
352 set (Value.primApply {prim = prim,
355 | Profile _ => new' ()
357 | Select {tuple, offset} =>
358 set (Value.select (varExp tuple, offset))
360 if Value.typeIsFirstOrder ty
362 else set (Value.tuple (Vector.map (xs, varExp)))
363 | Var x => set (varExp x)
365 and loopLambda (lambda: Lambda.t, x: Var.t): Value.t =
367 val _ = List.push (allLambdas, lambda)
368 val {arg, argType, body, ...} = Lambda.dest lambda
372 LambdaInfo.T {con = ref Con.bogus,
373 frees = ref (Vector.new0 ()),
374 name = Func.newString (Var.originalName x),
375 recs = ref (Vector.new0 ()),
377 val _ = newVar (arg, Value.fromType argType)
379 Value.lambda (lambda,
380 Type.arrow (argType, Value.ty (loopExp body)))
383 Control.trace (Control.Pass, "flow analysis")
391 (body, fn (x, _, _) => display (let open Layout
392 in seq [Var.layout x,
394 Value.layout (value x)]
396 val overflow = valOf overflow
398 Control.trace (Control.Pass, "free variables")
399 LambdaFree.lambdaFree
402 varInfo = fn x => let val {frees, status, ...} = varInfo x
403 in {frees = frees, status = status}
405 lambdaInfo = fn l => let val LambdaInfo.T {frees, recs, ...} = lambdaInfo l
406 in {frees = frees, recs = recs}
409 if !Control.closureConvertGlobalize
410 then Control.trace (Control.Pass, "globalize")
411 Globalize.globalize {program = program,
412 lambdaFree = LambdaInfo.frees o lambdaInfo,
413 varGlobal = #isGlobal o varInfo}
416 fun removeGlobal v = Vector.keepAll (v, not o isGlobal)
418 List.foreach (!allLambdas, fn l =>
420 val LambdaInfo.T {frees, recs, ...} = lambdaInfo l
422 frees := removeGlobal (!frees)
423 ; recs := removeGlobal (!recs)
427 val {get = lambdasInfoOpt, ...} =
428 Property.get (Lambdas.plist, Property.initFun (fn _ => ref NONE))
429 val (convertType, destroyConvertType) =
431 val {get, set, destroy, ...} =
432 Property.destGetSetOnce (Tycon.plist, Property.initConst NONE)
437 else Error.bug "ClosureConvert.convertType.nullary: bogus application of nullary tycon"
440 if 1 = Vector.length v
441 then make (Vector.first v)
442 else Error.bug "ClosureConvert.convertType.unary: bogus application of unary tycon"
444 [(Tycon.arrow, fn _ => Error.bug "ClosureConvert.convertType.array"),
445 (Tycon.array, unary Type.array),
446 (Tycon.cpointer, nullary Type.cpointer),
447 (Tycon.intInf, nullary Type.intInf),
448 (Tycon.reff, unary Type.reff),
449 (Tycon.thread, nullary Type.thread),
450 (Tycon.tuple, Type.tuple),
451 (Tycon.vector, unary Type.vector),
452 (Tycon.weak, unary Type.weak)]
453 @ Vector.toListMap (Tycon.reals, fn (t, s) => (t, nullary (Type.real s)))
454 @ Vector.toListMap (Tycon.words, fn (t, s) => (t, nullary (Type.word s)))
456 val _ = List.foreach (tycons, fn (tycon, f) => set (tycon, SOME f))
458 val {hom = convertType, destroy = destroyConvertType} =
460 {con = fn (_, tycon, ts) =>
462 NONE => nullary (Type.datatypee tycon) ts
466 fn () => (destroy () ; destroyConvertType ()))
468 (* newDatatypes accumulates the new datatypes built for sets of lambdas. *)
469 val newDatatypes: Datatype.t list ref = ref []
470 fun valueType arg: Type.t =
471 Trace.traceInfo (valueTypeInfo,
477 val r = Value.ssaType v
485 Value.Array v => Type.array (valueType v)
486 | Value.Lambdas ls => #ty (lambdasInfo ls)
487 | Value.Ref v => Type.reff (valueType v)
488 | Value.Type t => convertType t
490 Type.tuple (Vector.map (vs, valueType))
491 | Value.Vector v => Type.vector (valueType v)
492 | Value.Weak v => Type.weak (valueType v)
496 and lambdasInfo (ls: Lambdas.t): {cons: {lambda: Slambda.t,
500 val r = lambdasInfoOpt ls
506 val tycon = Tycon.newString "lambdas"
509 (Lambdas.toList ls, fn l =>
510 {lambda = Value.Lambda.dest l,
511 con = Con.newString "Env"})
512 val ty = Type.datatypee tycon
513 val info = {ty = ty, cons = cons}
514 val _ = r := SOME info
515 (* r must be set before the following, because calls to
516 * lambdaInfoType may refer to the type of this lambdasInfo.
520 (cons, fn {con, lambda} =>
522 args = Vector.new1 (lambdaInfoType
523 (lambdaInfo lambda))})
524 val _ = List.push (newDatatypes,
525 Datatype.T {tycon = tycon,
531 and varInfoType ({value, ...}: VarInfo.t) = valueType value
532 and lambdaInfoType (LambdaInfo.T {frees, ty, ...}): Type.t =
535 let val t = Type.tuple (Vector.map
536 (!frees, varInfoType o varInfo))
540 fun valueLambdasInfo v =
542 Value.Lambdas l => lambdasInfo l
543 | _ => Error.bug "ClosureConvert.valueLambdasInfo: non-lambda"
544 val varLambdasInfo = valueLambdasInfo o value
545 val emptyTypes = Vector.new0 ()
548 (datatypes, fn {tycon, cons, ...} =>
552 (cons, fn {con, ...} =>
554 args = (case conArg con of
556 | SOME v => Vector.new1 (valueType v))}))})
557 (* Variable renaming *)
558 fun newVarInfo (x: Var.t, {isGlobal, replacement, ...}: VarInfo.t): Var.t =
561 else let val x' = Var.new x
562 in replacement := x'; x'
564 fun newVar x = newVarInfo (x, varInfo x)
565 val newVar = Trace.trace ("ClosureConvert.newVar", Var.layout, Var.layout) newVar
566 fun newScope (xs: Var.t vector, f: Var.t vector -> 'a): 'a =
568 val old = Vector.map (xs, ! o #replacement o varInfo)
569 val res = f (Vector.map (xs, newVar))
570 val _ = Vector.foreach2 (xs, old, fn (x, x') =>
571 #replacement (varInfo x) := x')
575 (*------------------------------------*)
577 (*------------------------------------*)
580 ("ClosureConvert.coerce",
581 Dexp.layout, Value.layout, Value.layout, Dexp.layout)
582 (* val traceCoerceTuple =
583 * let val layoutValues = List.layout (", ", Value.layout)
584 * in Trace.trace3 ("ClosureConvert.coerceTuple", Dexp.layout,
585 * layoutValues, layoutValues, Dexp.layout)
588 fun coerce arg: Dexp.t =
590 (fn (e: Dexp.t, from: Value.t, to: Value.t) =>
591 if Value.equals (from, to)
594 case (Value.dest from, Value.dest to) of
595 (Value.Tuple vs, Value.Tuple vs') =>
596 coerceTuple (e, valueType from, vs, valueType to, vs')
597 | (Value.Lambdas ls, Value.Lambdas ls') =>
598 if Lambdas.equals (ls, ls')
602 val {cons, ...} = lambdasInfo ls
603 val {cons = cons', ty, ...} = lambdasInfo ls'
606 (cons', fn {lambda, con, ...} =>
608 val LambdaInfo.T {con = r, ...} =
620 (cons, fn {lambda, con} =>
622 val info as LambdaInfo.T {con = r, ...} =
624 val tuple = (Var.newNoname (),
627 args = Vector.new1 tuple,
632 Vector.new1 (Dexp.var tuple)})}
636 | _ => Error.bug "ClosureConvert.coerce") arg
637 and coerceTuple arg =
638 (* traceCoerceTuple *)
640 ty: Type.t, vs: Value.t vector,
641 ty': Type.t, vs': Value.t vector) =>
642 if Type.equals (ty, ty')
647 length = Vector.length vs,
651 {exps = Vector.map3 (components, vs, vs',
653 coerce (Dexp.var (x, valueType v), v, v')),
655 fun convertVarInfo (info as {replacement, ...}: VarInfo.t) =
656 Dexp.var (!replacement, varInfoType info)
657 val convertVar = convertVarInfo o varInfo
658 val convertVarExp = convertVar o SvarExp.var
660 Sexp.hasPrim (body, fn p =>
662 Prim.Name.MLton_installSignalHandler => true
664 (*------------------------------------*)
666 (*------------------------------------*)
667 fun apply {func, arg, resultVal}: Dexp.t =
669 val func = varExpInfo func
670 val arg = varExpInfo arg
671 val funcVal = VarInfo.value func
672 val argVal = VarInfo.value arg
673 val argExp = convertVarInfo arg
674 val ty = valueType resultVal
675 val {cons, ...} = valueLambdasInfo funcVal
677 {test = convertVarInfo func,
683 (cons, fn {lambda, con} =>
685 val {arg = param, body, ...} = Slambda.dest lambda
686 val info as LambdaInfo.T {name, ...} = lambdaInfo lambda
687 val result = expValue body
688 val env = (Var.newString "env", lambdaInfoType info)
690 args = Vector.new1 env,
691 body = coerce (Dexp.call
693 args = Vector.new2 (Dexp.var env,
694 coerce (argExp, argVal,
696 ty = valueType result},
700 (*------------------------------------*)
702 (*------------------------------------*)
703 fun lambdaInfoTuple (info as LambdaInfo.T {frees, ...}): Dexp.t =
704 Dexp.tuple {exps = Vector.map (!frees, convertVar),
705 ty = lambdaInfoType info}
706 fun recursives (old: Var.t vector, new: Var.t vector, env) =
708 (old, new, [], fn (old, new, ac) =>
710 val {cons, ty, ...} = varLambdasInfo old
711 val l = VarInfo.lambda (varInfo old)
713 case Vector.peek (cons, fn {lambda = l', ...} =>
714 Slambda.equals (l, l')) of
715 NONE => Error.bug "ClosureConvert.recursives: lambda must exist in its own set"
719 exp = Dexp.conApp {con = con, ty = ty,
720 args = Vector.new1 (Dexp.var env)}}
724 Trace.trace ("ClosureConvert.recursives",
726 Layout.tuple [Vector.layout Var.layout a,
727 Vector.layout Var.layout b],
730 val raises: Type.t vector option =
732 exception Yes of Type.t vector
735 (body, fn (_, _, e) =>
737 SprimExp.Handle {catch = (x, _), ...} =>
738 raise (Yes (Vector.new1 (varInfoType (varInfo x))))
741 handle Yes ts => SOME ts
744 if !Control.closureConvertShrink
745 then Ssa.shrinkFunction {globals = Vector.new0 ()}
747 fun addFunc (ac, {args, body, isMain, mayInline, name, returns}) =
749 val (start, blocks) =
750 Dexp.linearize (body, Ssa.Handler.Caller)
753 (Function.new {args = args,
754 blocks = Vector.fromList blocks,
755 mayInline = mayInline,
760 returns = SOME returns,
764 then Function.profile (f, SourceInfo.main)
767 Accum.addFunc (ac, f)
769 (* Closure convert an expression, returning:
770 * - the target ssa expression
771 * - a list of global declarations (in order)
772 * - a list of function declarations
773 * Accumulate the globals onto the end of the given ones.
775 fun convertExp (e: Sexp.t, ac: Accum.t): Dexp.t * Accum.t =
777 val {decs, result} = Sexp.dest e
778 (* Process decs left to right, since bindings of variables
779 * must be visited before uses.
783 (decs, ([], ac), fn (d, (binds, ac)) =>
785 Sdec.MonoVal {exp, var, ...} =>
787 val info as {isGlobal, value, ...} = varInfo var
788 val (exp, ac) = convertPrimExp (exp, value, ac)
789 val bind = {var = newVarInfo (var, info),
790 ty = valueType value,
793 then (binds, Accum.addGlobal (ac, bind))
794 else (bind :: binds, ac)
796 | Sdec.Fun {decs, ...} =>
797 if Vector.isEmpty decs
801 val {lambda, var, ...} = Vector.first decs
802 val info = lambdaInfo lambda
803 val tupleVar = Var.newString "tuple"
804 val tupleTy = lambdaInfoType info
808 exp = lambdaInfoTuple info}
810 (Vector.map (decs, #var),
811 Vector.map (decs, newVar o #var),
812 (tupleVar, tupleTy)))
815 then (binds, Accum.addGlobals (ac, binds'))
816 else (List.fold (binds', binds, op ::), ac)
818 Vector.fold (decs, ac, fn ({lambda, ...}, ac) =>
819 convertLambda (lambda,
823 | _ => Error.bug "ClosureConvert.convertExp: strange dec")
824 in (Dexp.lett {decs = List.fold (decs, [], fn ({var, exp, ...}, ac) =>
825 {var = var, exp = exp} :: ac),
826 body = convertVarExp result},
829 and convertPrimExp arg : Dexp.t * Accum.t =
830 Trace.traceInfo (convertPrimExpInfo,
831 SprimExp.layout o #1,
834 (fn (e: SprimExp.t, v: Value.t, ac: Accum.t) =>
837 fun convertJoin (e, ac) =
838 let val (e', ac) = convertExp (e, ac)
839 in (coerce (e', expValue e, v), ac)
841 fun simple e = (e, ac)
844 SprimExp.App {func, arg} =>
845 (apply {func = func, arg = arg, resultVal = v},
847 | SprimExp.Case {test, cases, default} =>
853 val (e, ac) = convertJoin (e, ac)
857 fun doCases (cases, finish, make) =
861 (cases, ac, fn ((x, e), ac) =>
864 val (body, ac) = convertJoin (e, ac)
867 in (finish cases, ac)
874 fn Spat.T {con, arg, ...} =>
877 case (conArg con, arg) of
878 (NONE, NONE) => Vector.new0 ()
879 | (SOME v, SOME (arg, _)) =>
880 Vector.new1 (newVar arg, valueType v)
881 | _ => Error.bug "ClosureConvert.convertPrimExp: Case,constructor mismatch"
883 fn body => {args = args,
887 | Scases.Word (s, cs) =>
888 doCases (cs, fn cs => Dexp.Word (s, cs),
889 fn i => fn e => (i, e))
891 {test = convertVarExp test,
892 ty = ty, cases = cases, default = default},
895 | SprimExp.ConApp {con = con, arg, ...} =>
900 args = (case (arg, conArg con) of
901 (NONE, NONE) => Vector.new0 ()
902 | (SOME arg, SOME conArg) =>
904 val arg = varExpInfo arg
905 val argVal = VarInfo.value arg
906 val arg = convertVarInfo arg
907 in if Value.equals (argVal, conArg)
909 else Vector.new1 (coerce (arg, argVal, conArg))
911 | _ => Error.bug "ClosureConvert.convertPrimExp: ConApp,constructor mismatch")})
912 | SprimExp.Const c => simple (Dexp.const c)
913 | SprimExp.Handle {try, catch = (catch, _), handler} =>
915 val catchInfo = varInfo catch
916 val (try, ac) = convertJoin (try, ac)
917 val catch = (newVarInfo (catch, catchInfo),
918 varInfoType catchInfo)
919 val (handler, ac) = convertJoin (handler, ac)
920 in (Dexp.handlee {try = try, ty = ty,
921 catch = catch, handler = handler},
924 | SprimExp.Lambda l =>
926 val info = lambdaInfo l
927 val ac = convertLambda (l, info, ac)
928 val {cons, ...} = valueLambdasInfo v
929 in case Vector.peek (cons, fn {lambda = l', ...} =>
930 Slambda.equals (l, l')) of
931 NONE => Error.bug "ClosureConvert.convertPrimExp: Lambda,lambda must exist in its own set"
933 (Dexp.conApp {con = con, ty = ty,
934 args = Vector.new1 (lambdaInfoTuple info)},
937 | SprimExp.PrimApp {prim, targs, args} =>
939 val prim = Prim.map (prim, convertType)
941 fun arg i = Vector.sub (args, i)
945 fun primApp (targs, args) =
946 Dexp.primApp {args = args,
951 if Prim.mayOverflow prim
952 then simple (Dexp.arith
953 {args = Vector.map (args, convertVarExp),
954 overflow = Dexp.raisee (convertVar overflow),
959 datatype z = datatype Prim.Name.t
962 (case Prim.name prim of
965 val a = varExpInfo (arg 0)
966 val y = varExpInfo (arg 2)
967 val v = Value.deArray (VarInfo.value a)
969 primApp (v1 (valueType v),
970 v3 (convertVarInfo a,
971 convertVarExp (arg 1),
972 coerce (convertVarInfo y,
973 VarInfo.value y, v)))
977 val a0 = varExpInfo (arg 0)
978 val a1 = varExpInfo (arg 1)
980 primApp (v1 (valueType (VarInfo.value a0)),
981 v2 (convertVarInfo a0,
984 case (Value.dest (VarInfo.value a0),
985 Value.dest (VarInfo.value a1)) of
986 (Value.Lambdas l, Value.Lambdas l') =>
987 if Lambdas.equals (l, l')
994 val a0 = varExpInfo (arg 0)
995 val a1 = varExpInfo (arg 1)
997 primApp (v1 (valueType (VarInfo.value a0)),
998 v2 (convertVarInfo a0,
1001 case (Value.dest (VarInfo.value a0),
1002 Value.dest (VarInfo.value a1)) of
1003 (Value.Lambdas l, Value.Lambdas l') =>
1004 if Lambdas.equals (l, l')
1009 | MLton_handlesSignals =>
1015 val r = varExpInfo (arg 0)
1016 val y = varExpInfo (arg 1)
1017 val v = Value.deRef (VarInfo.value r)
1019 primApp (v1 (valueType v),
1020 v2 (convertVarInfo r,
1021 coerce (convertVarInfo y,
1022 VarInfo.value y, v)))
1026 val y = varExpInfo (arg 0)
1027 val v = Value.deRef v
1029 primApp (v1 (valueType v),
1030 v1 (coerce (convertVarInfo y,
1031 VarInfo.value y, v)))
1033 | MLton_serialize =>
1035 val y = varExpInfo (arg 0)
1037 Value.serialValue (Vector.first targs)
1039 primApp (v1 (valueType v),
1040 v1 (coerce (convertVarInfo y,
1041 VarInfo.value y, v)))
1045 val ys = Vector.map (args, varExpInfo)
1046 val v = Value.deVector v
1048 primApp (v1 (valueType v),
1049 Vector.map (ys, fn y =>
1050 coerce (convertVarInfo y,
1051 VarInfo.value y, v)))
1055 val y = varExpInfo (arg 0)
1056 val v = Value.deWeak v
1058 primApp (v1 (valueType v),
1059 v1 (coerce (convertVarInfo y,
1060 VarInfo.value y, v)))
1064 val args = Vector.map (args, varExpInfo)
1069 {args = Vector.map (args, varInfoType),
1071 typeOps = {deArray = Type.deArray,
1072 deArrow = fn _ => Error.bug "ClosureConvert.convertPrimExp: deArrow",
1074 deVector = Type.deVector,
1075 deWeak = Type.deWeak}}),
1076 Vector.map (args, convertVarInfo))
1080 | SprimExp.Profile e => simple (Dexp.profile e)
1081 | SprimExp.Raise {exn, ...} =>
1082 simple (Dexp.raisee (convertVarExp exn))
1083 | SprimExp.Select {offset, tuple} =>
1084 simple (Dexp.select {offset = offset,
1085 tuple = convertVarExp tuple,
1087 | SprimExp.Tuple xs =>
1088 simple (Dexp.tuple {exps = Vector.map (xs, convertVarExp),
1090 | SprimExp.Var y => simple (convertVarExp y)
1092 and convertLambda (lambda: Slambda.t,
1093 info as LambdaInfo.T {frees, name, recs, ...},
1094 ac: Accum.t): Accum.t =
1096 val {arg = argVar, body, mayInline, ...} = Slambda.dest lambda
1097 val argVarInfo = varInfo argVar
1098 val env = Var.newString "env"
1099 val envType = lambdaInfoType info
1100 val args = Vector.new2 ((env, envType),
1101 (newVarInfo (argVar, argVarInfo),
1102 varInfoType argVarInfo))
1103 val returns = Vector.new1 (valueType (expValue body))
1107 (!frees, fn components =>
1111 val decs = recursives (recs, recs', (env, envType))
1112 val (body, ac) = convertExp (body, ac)
1115 {decs = List.fold (decs, [], fn ({var, exp, ...}, ac) =>
1116 {var = var, exp = exp} :: ac),
1117 body = Dexp.detupleBind {tuple = env,
1119 components = components,
1122 addFunc (ac, {args = args,
1125 mayInline = mayInline,
1130 (*------------------------------------*)
1131 (* main body of closure convert *)
1132 (*------------------------------------*)
1133 val main = Func.newString "main"
1134 val {functions, globals} =
1135 Control.trace (Control.Pass, "convert")
1138 val (body, ac) = convertExp (body, Accum.empty)
1139 val ac = addFunc (ac, {args = Vector.new0 (),
1144 returns = Vector.new1 Type.unit})
1147 val datatypes = Vector.concat [datatypes, Vector.fromList (!newDatatypes)]
1149 Ssa.Program.T {datatypes = datatypes,
1151 functions = functions,
1153 val _ = destroyConvertType ()
1154 val _ = Value.destroy ()
1155 val _ = Ssa.Program.clear program