1 (* Copyright (C) 2011,2017 Matthew Fluet.
2 * Copyright (C) 1999-2006 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 Analyze (S: ANALYZE_STRUCTS): ANALYZE =
14 datatype z = datatype Exp.t
15 datatype z = datatype Transfer.t
18 {coerce, conApp, const, filter, filterWord, fromType, layout, primApp,
19 program = Program.T {main, globals, functions, ...},
20 select, tuple, useFromTypeOnBinds} =
22 val unit = fromType Type.unit
23 fun coerces (msg, from, to) =
24 if Vector.length from = Vector.length to
25 then Vector.foreach2 (from, to, fn (from, to) =>
26 coerce {from = from, to = to})
27 else Error.bug (concat ["Analyze.coerces (length mismatch: ", msg, ")"])
28 val {get = value: Var.t -> 'a, set = setValue, ...} =
31 Property.initRaise ("Analyze.value", Var.layout))
32 val value = Trace.trace ("Analyze.value", Var.layout, layout) value
33 fun values xs = Vector.map (xs, value)
34 val {get = funcInfo, set = setFuncInfo, ...} =
36 (Func.plist, Property.initRaise ("Analyze.funcInfo", Func.layout))
37 val {get = labelInfo, set = setLabelInfo, ...} =
39 (Label.plist, Property.initRaise ("Analyze.labelInfo", Label.layout))
40 val labelArgs = #args o labelInfo
41 val labelValues = #values o labelInfo
43 Vector.map (args, fn (x, t) =>
44 let val v = fromType t
52 val {args, name, raises, returns, ...} = Function.dest f
54 setFuncInfo (name, {args = loopArgs args,
55 raises = Option.map (raises, fn ts =>
56 Vector.map (ts, fromType)),
57 returns = Option.map (returns, fn ts =>
58 Vector.map (ts, fromType))})
60 fun loopTransfer (t: Transfer.t,
61 shouldReturns: 'a vector option,
62 shouldRaises: 'a vector option): unit =
64 Arith {prim, args, overflow, success, ty} =>
65 (coerces ("arith overflow", Vector.new0 (), labelValues overflow)
66 ; coerce {from = primApp {prim = prim,
67 targs = Vector.new0 (),
71 to = Vector.sub (labelValues success, 0)})
73 | Call {func, args, return, ...} =>
75 val {args = formals, raises, returns} = funcInfo func
76 val _ = coerces ("call args/formals", values args, formals)
78 case (raises, shouldRaises) of
80 | (NONE, SOME _) => ()
82 Error.bug "Analyze.loopTransfer (raise mismatch)"
83 | (SOME vs, SOME vs') => coerces ("call caller/raises", vs, vs')
84 datatype z = datatype Return.t
88 if isSome returns orelse isSome raises
89 then Error.bug "Analyze.loopTransfer (return mismatch at Dead)"
91 | NonTail {cont, handler} =>
92 (Option.app (returns, fn vs =>
93 coerces ("call non-tail/returns", vs, labelValues cont))
95 Handler.Caller => noHandler ()
98 then Error.bug "Analyze.loopTransfer (raise mismatch at NonTail/Dead)"
100 | Handler.Handle h =>
106 coerces ("call handle/raises", vs, labelValues h)
114 case (returns, shouldReturns) of
116 | (NONE, SOME _) => ()
118 Error.bug "Analyze.loopTransfer (return mismatch at Tail)"
119 | (SOME vs, SOME vs') =>
120 coerces ("call tail/returns", vs, vs')
126 | Case {test, cases, default, ...} =>
128 val test = value test
129 fun ensureNullary j =
130 if Vector.isEmpty (labelValues j)
132 else Error.bug (concat ["Analyze.loopTransfer (case ",
134 " must be nullary)"])
135 fun ensureSize (w, s) =
136 if WordSize.equals (s, WordX.size w)
138 else Error.bug (concat ["Analyze.loopTransfer (case ",
143 fun doitWord (s, cs) =
144 (ignore (filterWord (test, s))
145 ; Vector.foreach (cs, fn (w, j) =>
149 Vector.foreach (cs, fn (c, j) =>
150 filter (test, c, labelValues j))
151 datatype z = datatype Cases.t
155 | Word (s, cs) => doitWord (s, cs)
156 val _ = Option.app (default, ensureNullary)
159 | Goto {dst, args} => coerces ("goto", values args, labelValues dst)
161 (case shouldRaises of
162 NONE => Error.bug "Analyze.loopTransfer (raise mismatch at Raise)"
163 | SOME vs => coerces ("raise", values xs, vs))
165 (case shouldReturns of
166 NONE => Error.bug "Analyze.loopTransfer (return mismatch at Return)"
167 | SOME vs => coerces ("return", values xs, vs))
168 | Runtime {prim, args, return} =>
170 val xts = labelArgs return
171 val (resultVar, resultType) =
172 if Vector.isEmpty xts
173 then (NONE, Type.unit)
176 val (x, t) = Vector.first xts
181 primApp {prim = prim,
182 targs = Vector.new0 (),
184 resultType = resultType,
185 resultVar = resultVar}
189 handle exn => Error.reraiseSuffix (exn, concat [" in ", Layout.toString (Transfer.layout t)])
192 ("Analyze.loopTransfer",
194 Option.layout (Vector.layout layout),
195 Option.layout (Vector.layout layout),
198 fun loopStatement (s as Statement.T {var, exp, ty}): unit =
202 ConApp {con, args} => conApp {con = con, args = values args}
204 | PrimApp {prim, targs, args, ...} =>
205 primApp {prim = prim,
211 | Select {tuple, offset} =>
212 select {tuple = value tuple,
216 if 1 = Vector.length xs
217 then Error.bug "Analyze.loopStatement (unary tuple)"
218 else tuple (values xs)
223 if useFromTypeOnBinds
226 val _ = coerce {from = v, to = v'}
227 val _ = setValue (var, v')
231 else setValue (var, v))
233 handle exn => Error.reraiseSuffix (exn, concat [" in ", Layout.toString (Statement.layout s)])
235 Trace.trace ("Analyze.loopStatement", Statement.layout, Unit.layout)
237 val _ = coerces ("main", Vector.new0 (), #args (funcInfo main))
238 val _ = Vector.foreach (globals, loopStatement)
239 handle exn => Error.reraiseSuffix (exn, concat [" in Globals"])
244 val {blocks, name, start, ...} = Function.dest f
247 (blocks, fn b as Block.T {label, args, ...} =>
248 setLabelInfo (label, {args = args,
250 values = loopArgs args,
251 visited = ref false}))
252 val {returns, raises, ...} = funcInfo name
253 fun visit (l: Label.t) =
255 val {block, visited, ...} = labelInfo l
261 val _ = visited := true
262 val Block.T {statements, transfer, ...} = block
263 val _ = (Vector.foreach (statements, loopStatement)
264 ; loopTransfer (transfer, returns, raises))
265 handle exn => Error.reraiseSuffix (exn, concat [" in ", Label.toString l])
267 Transfer.foreachLabel (transfer, visit)
275 handle exn => Error.reraiseSuffix (exn, concat [" in ", Func.toString (Function.name f)]))