Commit | Line | Data |
---|---|---|
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 | ||
9 | functor ImplementHandlers (S: RSSA_TRANSFORM_STRUCTS): RSSA_TRANSFORM = | |
10 | struct | |
11 | ||
12 | open S | |
13 | open Rssa | |
14 | datatype z = datatype Statement.t | |
15 | datatype z = datatype Transfer.t | |
16 | ||
17 | structure 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 | ||
36 | structure HandlerLat = FlatLattice (structure Point = Label) | |
37 | ||
38 | structure 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 | ||
62 | fun 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 | ||
212 | fun 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 | ||
218 | end |