Import Debian changes 20180207-1
[hcoop/debian/mlton.git] / mlton / backend / implement-handlers.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 ImplementHandlers (S: RSSA_TRANSFORM_STRUCTS): RSSA_TRANSFORM =
10struct
11
12open S
13open Rssa
14datatype z = datatype Statement.t
15datatype z = datatype Transfer.t
16
17structure Function =
18 struct
19 open Function
20
21 fun hasHandler (f: t): bool =
22 let
23 val {blocks, ...} = dest f
24 in
25 Vector.exists
26 (blocks, fn Block.T {transfer, ...} =>
27 case transfer of
28 Transfer.Call
29 {return = (Return.NonTail
30 {handler = Handler.Handle _, ...}), ...} =>
31 true
32 | _ => false)
33 end
34 end
35
36structure HandlerLat = FlatLattice (structure Point = Label)
37
38structure ExnStack =
39 struct
40 local
41 structure ZPoint =
42 struct
43 datatype t = Local | Slot
44
45 val equals: t * t -> bool = op =
46
47 val toString =
48 fn Local => "Local"
49 | Slot => "Slot"
50
51 val layout = Layout.str o toString
52 end
53 structure L = FlatLattice (structure Point = ZPoint)
54 in
55 open L
56 structure Point = ZPoint
57 val locall = point Point.Local
58 val slot = point Point.Slot
59 end
60 end
61
62fun flow (f: Function.t): Function.t =
63 if not (Function.hasHandler f)
64 then f
65 else
66 let
67 val debug = false
68 val {args, blocks, name, raises, returns, start} =
69 Function.dest f
70 val {get = labelInfo: Label.t -> {global: ExnStack.t,
71 handler: HandlerLat.t},
72 rem, ...} =
73 Property.get (Label.plist,
74 Property.initFun (fn _ =>
75 {global = ExnStack.new (),
76 handler = HandlerLat.new ()}))
77 val _ =
78 Vector.foreach
79 (blocks, fn Block.T {label, transfer, ...} =>
80 let
81 val {global, handler} = labelInfo label
82 val _ =
83 if Label.equals (label, start)
84 then let
85 val _ = ExnStack.<= (ExnStack.slot, global)
86 val _ = HandlerLat.forceTop handler
87 in
88 ()
89 end
90 else ()
91 fun goto' {global = g, handler = h}: unit =
92 let
93 val _ = ExnStack.<= (global, g)
94 val _ = HandlerLat.<= (handler, h)
95 in
96 ()
97 end
98 val goto = goto' o labelInfo
99 in
100 case transfer of
101 Call {return, ...} =>
102 (case return of
103 Return.Dead => ()
104 | Return.NonTail {cont, handler = h} =>
105 let
106 val li as {global = g', handler = h'} =
107 labelInfo cont
108 in
109 case h of
110 Handler.Caller =>
111 let
112 val _ = ExnStack.<= (ExnStack.slot, g')
113 val _ = HandlerLat.<= (handler, h')
114 in
115 ()
116 end
117 | Handler.Dead => goto' li
118 | Handler.Handle l =>
119 let
120 fun doit {global = g'', handler = h''} =
121 let
122 val _ = ExnStack.<= (ExnStack.locall, g'')
123 val _ = HandlerLat.<= (HandlerLat.point l, h'')
124 in
125 ()
126 end
127 in
128 doit (labelInfo l)
129 ; doit li
130 end
131 end
132 | Return.Tail => ())
133 | _ => Transfer.foreachLabel (transfer, goto)
134 end)
135 val _ =
136 if debug
137 then
138 Layout.outputl
139 (Vector.layout
140 (fn Block.T {label, ...} =>
141 let
142 val {global, handler} = labelInfo label
143 in
144 Layout.record [("label", Label.layout label),
145 ("global", ExnStack.layout global),
146 ("handler", HandlerLat.layout handler)]
147 end)
148 blocks,
149 Out.error)
150 else ()
151 val blocks =
152 Vector.map
153 (blocks,
154 fn Block.T {args, kind, label, statements, transfer} =>
155 let
156 val {global, handler} = labelInfo label
157 fun setExnStackSlot () =
158 if ExnStack.isPointEq (global, ExnStack.Point.Slot)
159 then Vector.new0 ()
160 else Vector.new1 SetExnStackSlot
161 fun setExnStackLocal () =
162 if ExnStack.isPointEq (global, ExnStack.Point.Local)
163 then Vector.new0 ()
164 else Vector.new1 SetExnStackLocal
165 fun setHandler (l: Label.t) =
166 if HandlerLat.isPointEq (handler, l)
167 then Vector.new0 ()
168 else Vector.new1 (SetHandler l)
169 val post =
170 case transfer of
171 Call {return, ...} =>
172 (case return of
173 Return.Dead => Vector.new0 ()
174 | Return.NonTail {handler, ...} =>
175 (case handler of
176 Handler.Caller => setExnStackSlot ()
177 | Handler.Dead => Vector.new0 ()
178 | Handler.Handle l =>
179 Vector.concat
180 [setHandler l, setExnStackLocal ()])
181 | Return.Tail => setExnStackSlot ())
182 | Raise _ => setExnStackSlot ()
183 | Return _ => setExnStackSlot ()
184 | _ => Vector.new0 ()
185 val statements = Vector.concat [statements, post]
186 in
187 Block.T {args = args,
188 kind = kind,
189 label = label,
190 statements = statements,
191 transfer = transfer}
192 end)
193 val newStart = Label.newNoname ()
194 val startBlock =
195 Block.T {args = Vector.new0 (),
196 kind = Kind.Jump,
197 label = newStart,
198 statements = Vector.new1 SetSlotExnStack,
199 transfer = Goto {args = Vector.new0 (),
200 dst = start}}
201 val blocks = Vector.concat [blocks, Vector.new1 startBlock]
202 val () = Vector.foreach (blocks, rem o Block.label)
203 in
204 Function.new {args = args,
205 blocks = blocks,
206 name = name,
207 raises = raises,
208 returns = returns,
209 start = newStart}
210 end
211
212fun transform (Program.T {functions, handlesSignals, main, objectTypes}) =
213 Program.T {functions = List.revMap (functions, flow),
214 handlesSignals = handlesSignals,
215 main = flow main,
216 objectTypes = objectTypes}
217
218end