Import Debian changes 20180207-1
[hcoop/debian/mlton.git] / mlton / ssa / direct-exp2.fun
CommitLineData
7f918cf1
CE
1(* Copyright (C) 1999-2006 Henry Cejtin, Matthew Fluet, Suresh
2 * Jagannathan, and Stephen Weeks.
3 * Copyright (C) 1997-2000 NEC Research Institute.
4 *
5 * MLton is released under a BSD-style license.
6 * See the file MLton-LICENSE for details.
7 *)
8
9functor DirectExp2 (S: DIRECT_EXP2_STRUCTS): DIRECT_EXP2 =
10struct
11
12open S
13
14structure DirectExp =
15struct
16
17datatype t =
18 Arith of {prim: Type.t Prim.t,
19 args: t vector,
20 overflow: t,
21 ty: Type.t}
22 | Call of {func: Func.t,
23 args: t vector,
24 ty: Type.t}
25 | Case of {cases: cases,
26 default: t option,
27 test: t,
28 ty: Type.t}
29 | ConApp of {con: Con.t,
30 args: t vector,
31 ty: Type.t}
32 | Const of Const.t
33 | Detuple of {body: Var.t vector -> t,
34 length: int,
35 tuple: t}
36 | DetupleBind of {body: t,
37 components: Var.t vector,
38 tuple: Var.t,
39 tupleTy: Type.t}
40 | Handle of {try: t,
41 catch: Var.t * Type.t,
42 handler: t,
43 ty: Type.t}
44 | Let of {decs: {var: Var.t, exp: t} list,
45 body: t}
46 | Name of t * (Var.t -> t)
47 | PrimApp of {prim: Type.t Prim.t,
48 targs: Type.t vector,
49 args: t vector,
50 ty: Type.t}
51 | Profile of ProfileExp.t
52 | Raise of t
53 | Runtime of {args: t vector,
54 prim: Type.t Prim.t,
55 ty: Type.t}
56 | Select of {tuple: t,
57 offset: int,
58 ty: Type.t}
59 | Seq of t * t
60 | Tuple of {exps: t vector,
61 ty: Type.t}
62 | Var of Var.t * Type.t
63and cases =
64 Con of {con: Con.t,
65 args: (Var.t * Type.t) vector,
66 body: t} vector
67 | Word of WordSize.t * (WordX.t * t) vector
68
69val arith = Arith
70val call = Call
71val casee = Case
72val conApp = ConApp
73val const = Const
74val detuple = Detuple
75val detupleBind = DetupleBind
76val handlee = Handle
77val lett = Let
78val name = Name
79val profile = Profile
80val raisee = Raise
81val select = Select
82val seq = Seq
83val word = Const o Const.word
84
85fun tuple (r as {exps, ...}) =
86 if 1 = Vector.length exps
87 then Vector.first exps
88 else Tuple r
89
90val var = Var
91
92fun primApp {args, prim, targs, ty} =
93 let
94 fun runtime () =
95 Runtime {args = args,
96 prim = prim,
97 ty = ty}
98 in
99 case Prim.name prim of
100 Prim.Name.MLton_halt => runtime ()
101 | Prim.Name.Thread_copyCurrent => runtime ()
102 | _ => PrimApp {args = args,
103 prim = prim,
104 targs = targs,
105 ty = ty}
106 end
107
108local
109 fun make c = conApp {con = c, args = Vector.new0 (), ty = Type.bool}
110in
111 val truee = make Con.truee
112 val falsee = make Con.falsee
113end
114
115fun eq (e1, e2, ty) =
116 primApp {prim = Prim.eq,
117 targs = Vector.new1 ty,
118 args = Vector.new2 (e1, e2),
119 ty = Type.bool}
120
121local
122 open Layout
123 fun lett (decs, body) =
124 align [seq [str "let ", decs],
125 seq [str "in ", body],
126 str "end"]
127in
128 fun layout e : Layout.t =
129 case e of
130 Arith {prim, args, overflow, ...} =>
131 align [Prim.layoutApp (prim, args, layout),
132 seq [str "Overflow => ", layout overflow]]
133 | Call {func, args, ty} =>
134 seq [Func.layout func, str " ", layouts args,
135 str ": ", Type.layout ty]
136 | Case {cases, default, test, ...} =>
137 align
138 [seq [str "case ", layout test, str " of"],
139 indent
140 (align [let
141 fun doit (v, f) =
142 Vector.layout
143 (fn z =>
144 let
145 val (x, e) = f z
146 in
147 seq [str "| ", x, str " => ", layout e]
148 end)
149 v
150 fun simple (v, f) =
151 doit (v, (fn (x, e) => (f x, e)))
152 in
153 case cases of
154 Con v =>
155 doit (v, fn {con, args, body} =>
156 (seq [Con.layout con,
157 Vector.layout (Var.layout o #1) args],
158 body))
159 | Word (_, v) => simple (v, WordX.layout)
160 end,
161 case default of
162 NONE => empty
163 | SOME e => seq [str " _ => ", layout e]],
164 2)]
165 | ConApp {con, args, ty} =>
166 seq [Con.layout con, layouts args, str ": ", Type.layout ty]
167 | Const c => Const.layout c
168 | Detuple {tuple, ...} => seq [str "detuple ", layout tuple]
169 | DetupleBind {body, components, tuple, ...} =>
170 lett (seq [Vector.layout Var.layout components,
171 str " = ", Var.layout tuple],
172 layout body)
173 | Handle {try, catch, handler, ...} =>
174 align [layout try,
175 seq [str "handle ", Var.layout (#1 catch),
176 str " => ", layout handler]]
177 | Let {decs, body} =>
178 lett (align
179 (List.map (decs, fn {var, exp} =>
180 seq [Var.layout var, str " = ", layout exp])),
181 layout body)
182 | Name _ => str "Name"
183 | PrimApp {args, prim, ...} =>
184 Prim.layoutApp (prim, args, layout)
185 | Profile e => ProfileExp.layout e
186 | Raise e => seq [str "raise ", layout e]
187 | Runtime {args, prim, ...} =>
188 Prim.layoutApp (prim, args, layout)
189 | Select {tuple, offset, ...} =>
190 seq [str "#", str (Int.toString (1 + offset)), str " ",
191 layout tuple]
192 | Seq (e1, e2) => seq [layout e1, str "; ", layout e2]
193 | Tuple {exps, ...} => layouts exps
194 | Var (x, t) =>
195 seq [Var.layout x, str ": ", Type.layout t]
196 and layouts es = Vector.layout layout es
197end
198
199structure Res =
200 struct
201 type t = {statements: Statement.t list,
202 transfer: Transfer.t}
203
204 fun layout {statements, transfer} =
205 let
206 open Layout
207 in
208 align [align (List.map (statements, Statement.layout)),
209 Transfer.layout transfer]
210 end
211
212 fun prefix ({statements, transfer}: t, s: Statement.t): t =
213 {statements = s :: statements,
214 transfer = transfer}
215 end
216
217structure Cont:
218 sig
219 type t
220
221 val bind: Var.t * Res.t -> t
222 val goto: Label.t -> t
223 val layout: t -> Layout.t
224 val receiveExp: (Exp.t * Type.t -> Res.t) -> t
225 val receiveVar: (Var.t * Type.t -> Res.t) -> t
226 val return: t
227 val sendExp: t * Type.t * Exp.t -> Res.t
228 val sendVar: t * Type.t * Var.t -> Res.t
229 val toBlock: t * Type.t -> Block.t
230 end =
231 struct
232 type bind = {arg: Var.t,
233 statements: Statement.t list,
234 transfer: Transfer.t}
235
236 datatype t =
237 Bind of bind
238 | Goto of Label.t
239 | Prefix of t * Statement.t
240 | ReceiveExp of Exp.t * Type.t -> Res.t
241 | ReceiveVar of Var.t * Type.t -> Res.t
242 | Return
243
244 fun layout (k: t): Layout.t =
245 let
246 open Layout
247 in
248 case k of
249 Bind {arg, statements, transfer} =>
250 seq [str "Bind ",
251 record [("arg", Var.layout arg),
252 ("statements",
253 List.layout Statement.layout statements),
254 ("transfer", Transfer.layout transfer)]]
255 | Goto l => seq [str "Goto ", Label.layout l]
256 | Prefix (k, s) => seq [str "Prefix ",
257 tuple [layout k, Statement.layout s]]
258 | ReceiveExp _ => str "ReceiveExp"
259 | ReceiveVar _ => str "ReceiveVar"
260 | Return => str "Return"
261 end
262
263 fun bind (arg, {statements, transfer}) =
264 Bind {arg = arg,
265 statements = statements,
266 transfer = transfer}
267
268 val goto = Goto
269 val receiveExp = ReceiveExp
270 val receiveVar = ReceiveVar
271 val return = Return
272
273 fun toBind (k: t, ty: Type.t): bind =
274 case k of
275 Bind b => b
276 | _ =>
277 let
278 val arg = Var.newNoname ()
279 val {statements, transfer} = sendVar (k, ty, arg)
280 in
281 {arg = arg,
282 statements = statements,
283 transfer = transfer}
284 end
285 and sendVar (k: t, ty: Type.t, x: Var.t): Res.t =
286 case k of
287 Bind b => sendBindExp (b, ty, Exp.Var x)
288 | Goto dst => {statements = [],
289 transfer = Transfer.Goto {dst = dst,
290 args = Vector.new1 x}}
291 | ReceiveExp f => f (Exp.Var x, ty)
292 | ReceiveVar f => f (x, ty)
293 | Prefix (k, s) => Res.prefix (sendVar (k, ty, x), s)
294 | Return => {statements = [],
295 transfer = Transfer.Return (Vector.new1 x)}
296 and sendBindExp ({arg, statements, transfer}, ty, e: Exp.t) =
297 {statements = Statement.T {var = SOME arg,
298 ty = ty,
299 exp = e} :: statements,
300 transfer = transfer}
301
302 val sendVar =
303 Trace.trace3 ("DirectExp2.Cont.sendVar", layout, Type.layout, Var.layout,
304 Res.layout)
305 sendVar
306
307 val sendExp: t * Type.t * Exp.t -> Res.t =
308 fn (k, ty, e) =>
309 case k of
310 ReceiveExp f => f (e, ty)
311 | _ => sendBindExp (toBind (k, ty), ty, e)
312
313 val sendExp =
314 Trace.trace3 ("DirectExp2.Cont.sendExp", layout, Type.layout, Exp.layout,
315 Res.layout)
316 sendExp
317
318 fun toBlock (k: t, ty: Type.t): Block.t =
319 let
320 val {arg, statements, transfer} = toBind (k, ty)
321 val label = Label.newNoname ()
322 in
323 Block.T {label = label,
324 args = Vector.new1 (arg, ty),
325 statements = Vector.fromList statements,
326 transfer = transfer}
327 end
328
329 val toBlock =
330 Trace.trace2 ("DirectExp2.Cont.toBlock", layout, Type.layout, Block.layout)
331 toBlock
332 end
333
334fun selects (tuple: Var.t, ty: Type.t, components: Var.t vector)
335 : Statement.t list =
336 let
337 val ts = Type.deTuple ty
338 in
339 Vector.foldi
340 (ts, [], fn (i, t, ss) =>
341 Statement.T {var = SOME (Vector.sub (components, i)),
342 ty = t,
343 exp = Exp.Select {tuple = tuple,
344 offset = i}}
345 :: ss)
346 end
347
348fun linearize' (e: t, h: Handler.t, k: Cont.t): Label.t * Block.t list =
349 let
350 val traceLinearizeLoop =
351 Trace.trace3 ("DirectExp.linearize'.loop", layout, Handler.layout, Cont.layout,
352 Res.layout)
353 val blocks: Block.t list ref = ref []
354 fun newBlock (args: (Var.t * Type.t) vector,
355 {statements: Statement.t list,
356 transfer: Transfer.t}): Label.t =
357 let
358 val label = Label.newNoname ()
359 val _ = List.push (blocks,
360 Block.T {label = label,
361 args = args,
362 statements = Vector.fromList statements,
363 transfer = transfer})
364 in
365 label
366 end
367 fun reify (k: Cont.t, ty: Type.t): Label.t =
368 let
369 val b = Cont.toBlock (k, ty)
370 val _ = List.push (blocks, b)
371 in
372 Block.label b
373 end
374 fun newLabel (args: (Var.t * Type.t) vector,
375 e: t,
376 h: Handler.t,
377 k: Cont.t): Label.t =
378 newBlock (args, loop (e, h, k))
379 and newLabel0 (e, h, k) = newLabel (Vector.new0 (), e, h, k)
380 and loopf (e: t, h: Handler.t, f: Var.t * Type.t -> Res.t) =
381 loop (e, h, Cont.receiveVar f)
382 and loop arg : Res.t =
383 traceLinearizeLoop
384 (fn (e: t, h: Handler.t, k: Cont.t) =>
385 case e of
386 Arith {prim, args, overflow, ty} =>
387 loops
388 (args, h, fn xs =>
389 let
390 val l = reify (k, ty)
391 val k = Cont.goto l
392 in
393 {statements = [],
394 transfer =
395 Transfer.Arith {prim = prim,
396 args = xs,
397 overflow = newLabel0 (overflow, h, k),
398 success = l,
399 ty = ty}}
400 end)
401 | Call {func, args, ty} =>
402 loops
403 (args, h, fn xs =>
404 {statements = [],
405 transfer = (Transfer.Call
406 {func = func,
407 args = xs,
408 return = Return.NonTail {cont = reify (k, ty),
409 handler = h}})})
410 | Case {cases, default, test, ty} =>
411 let
412 val k = Cont.goto (reify (k, ty))
413 in
414 loopf (test, h, fn (x, _) =>
415 {statements = [],
416 transfer =
417 Transfer.Case
418 {test = x,
419 default = Option.map (default, fn e =>
420 newLabel0 (e, h, k)),
421 cases =
422 let
423 fun doit v =
424 Vector.map (v, fn (c, e) =>
425 (c, newLabel0 (e, h, k)))
426 in
427 case cases of
428 Con v =>
429 Cases.Con
430 (Vector.map
431 (v, fn {con, args, body} =>
432 (con,
433 newLabel (args, body, h, k))))
434 | Word (s, v) => Cases.Word (s, doit v)
435 end}})
436 end
437 | ConApp {con, args, ty} =>
438 loops (args, h, fn xs =>
439 Cont.sendExp (k, ty, Exp.ConApp {con = con, args = xs}))
440 | Const c => Cont.sendExp (k, Type.ofConst c, Exp.Const c)
441 | Detuple {tuple, length, body} =>
442 loop (tuple, h,
443 Cont.receiveExp
444 (fn (e, ty) =>
445 let
446 fun doit (tuple: Var.t): Res.t =
447 let
448 val (ss, xs) =
449 case length of
450 0 => ([], Vector.new0 ())
451 | 1 => ([], Vector.new1 tuple)
452 | _ =>
453 let
454 val xs =
455 Vector.tabulate
456 (length, fn _ => Var.newNoname ())
457 in (selects (tuple, ty, xs), xs)
458 end
459 val {statements, transfer} = loop (body xs, h, k)
460 in
461 {statements = List.appendRev (ss, statements),
462 transfer = transfer}
463 end
464 in
465 case e of
466 Exp.Tuple xs => loop (body xs, h, k)
467 | Exp.Var x => doit x
468 | _ =>
469 let
470 val tuple = Var.newNoname ()
471 in
472 Res.prefix (doit tuple,
473 Statement.T {var = SOME tuple,
474 ty = ty,
475 exp = e})
476 end
477 end))
478 | DetupleBind {body, components, tuple, tupleTy} =>
479 let
480 val {statements, transfer} = loop (body, h, k)
481 val ss =
482 case Vector.length components of
483 0 => []
484 | 1 => [Statement.T
485 {var = SOME (Vector.first components),
486 ty = tupleTy,
487 exp = Exp.Var tuple}]
488 | _ => selects (tuple, tupleTy, components)
489 in
490 {statements = List.appendRev (ss, statements),
491 transfer = transfer}
492 end
493 | Handle {try, catch, handler, ty} =>
494 let
495 val k = Cont.goto (reify (k, ty))
496 val hl = Label.newNoname ()
497 val {statements, transfer} = loop (handler, h, k)
498 val _ =
499 List.push (blocks,
500 Block.T {label = hl,
501 args = Vector.new1 catch,
502 statements = Vector.fromList statements,
503 transfer = transfer})
504 in
505 loop (try, Handler.Handle hl, k)
506 end
507 | Let {decs, body} =>
508 let
509 fun each decs =
510 case decs of
511 [] => loop (body, h, k)
512 | {var, exp} :: decs =>
513 loop (exp, h, Cont.bind (var, each decs))
514 in
515 each decs
516 end
517 | Name (e, f) => loopf (e, h, fn (x, _) => loop (f x, h, k))
518 | PrimApp {prim, targs, args, ty} =>
519 loops
520 (args, h, fn xs =>
521 Cont.sendExp (k, ty, Exp.PrimApp {prim = prim,
522 targs = targs,
523 args = xs}))
524 | Profile e => Cont.sendExp (k, Type.unit, Exp.Profile e)
525 | Raise e =>
526 loopf (e, h, fn (x, _) =>
527 {statements = [],
528 transfer =
529 (case h of
530 Handler.Caller => Transfer.Raise (Vector.new1 x)
531 | Handler.Dead => Error.bug "DirectExp2.linearize'.loop: Raise:to dead handler"
532 | Handler.Handle l =>
533 Transfer.Goto {args = Vector.new1 x,
534 dst = l})})
535 | Runtime {args, prim, ty} =>
536 loops
537 (args, h, fn xs =>
538 let
539 val l = reify (k, ty)
540 val k = Cont.goto l
541 val (args, exps) =
542 case Type.deTupleOpt ty of
543 NONE =>
544 let
545 val res = Var.newNoname ()
546 in
547 (Vector.new1 (res, ty),
548 Vector.new1 (Var (res, ty)))
549 end
550 | SOME ts =>
551 if Vector.isEmpty ts
552 then (Vector.new0 (), Vector.new0 ())
553 else
554 Error.bug
555 (concat ["DirectExp2.linearlize'.loop: Runtime:with multiple return values: ",
556 Prim.toString prim])
557 in
558 {statements = [],
559 transfer =
560 Transfer.Runtime
561 {prim = prim,
562 args = xs,
563 return = newLabel (args,
564 tuple {exps = exps,
565 ty = ty},
566 h, k)}}
567 end)
568 | Select {tuple, offset, ty} =>
569 loopf (tuple, h, fn (tuple, _) =>
570 Cont.sendExp (k, ty, Exp.Select {tuple = tuple,
571 offset = offset}))
572 | Seq (e1, e2) => loopf (e1, h, fn _ => loop (e2, h, k))
573 | Tuple {exps, ty} =>
574 loops (exps, h, fn xs => Cont.sendExp (k, ty, Exp.Tuple xs))
575 | Var (x, ty) => Cont.sendVar (k, ty, x)) arg
576 and loops (es: t vector, h: Handler.t, k: Var.t vector -> Res.t): Res.t =
577 let
578 val n = Vector.length es
579 fun each (i, ac) =
580 if i = n
581 then k (Vector.fromListRev ac)
582 else loopf (Vector.sub (es, i), h, fn (x, _) =>
583 each (i + 1, x :: ac))
584 in
585 each (0, [])
586 end
587 val l = newLabel0 (e, h, k)
588 in
589 (l, !blocks)
590 end
591
592fun linearize (e: t, h) = linearize' (e, h, Cont.return)
593
594val linearize =
595 Trace.trace2 ("DirectExp2.linearize", layout, Handler.layout,
596 Layout.tuple2 (Label.layout,
597 List.layout (Label.layout o Block.label)))
598 linearize
599
600fun linearizeGoto (e: t, h, l) = linearize' (e, h, Cont.goto l)
601
602end
603end