1 (* Copyright (C) 2009 Matthew Fluet.
2 * Copyright (C) 1999-2007 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 SignalCheck (S: RSSA_TRANSFORM_STRUCTS): RSSA_TRANSFORM =
18 open CFunction Type.BuiltInCFunction
21 structure Graph = DirectedGraph
26 structure Forest = LoopForest
29 fun insertInFunction (f: Function.t): Function.t =
31 val {args, blocks, name, raises, returns, start} =
33 val {get = labelIndex: Label.t -> int, set = setLabelIndex, ...} =
35 (Label.plist, Property.initRaise ("index", Label.layout))
37 Vector.foreachi (blocks, fn (i, Block.T {label, ...}) =>
38 setLabelIndex (label, i))
40 val n = Vector.length blocks
41 val {get = nodeIndex: unit Node.t -> int, set = setNodeIndex, ...} =
43 (Node.plist, Property.initRaise ("index", Node.layout))
45 Vector.tabulate (n, fn i =>
47 val n = Graph.newNode g
48 val _ = setNodeIndex (n, i)
52 val isHeader = Array.new (n, false)
53 fun indexNode i = Vector.sub (nodes, i)
54 val labelNode = indexNode o labelIndex
57 (blocks, fn (i, Block.T {transfer, ...}) =>
59 val from = indexNode i
62 Transfer.CCall {func, ...} =>
63 CFunction.maySwitchThreads func
69 (ignore o Graph.addEdge)
70 (g, {from = from, to = labelNode to}))
72 val extra: Block.t list ref = ref []
73 fun addSignalCheck (Block.T {args, kind, label, statements, transfer})
76 val collect = Label.newNoname ()
77 val collectReturn = Label.newNoname ()
78 val dontCollect = Label.newNoname ()
79 val res = Var.newNoname ()
84 (Operand.Runtime Runtime.GCField.Limit,
86 dst = SOME (res, Type.bool),
87 prim = Prim.cpointerEqual})
90 (Operand.Var {var = res, ty = Type.bool},
91 {falsee = dontCollect,
93 val func = CFunction.gc {maySwitchThreads = true}
100 transfer = compareTransfer}
102 {args = Vector.new0 (),
105 statements = Vector.new0 (),
108 {args = Vector.new3 (Operand.GCState,
109 Operand.word (WordX.zero (WordSize.csize ())),
112 return = SOME collectReturn}})
114 {args = Vector.new0 (),
115 kind = Kind.CReturn {func = func},
116 label = collectReturn,
117 statements = Vector.new0 (),
119 Transfer.Goto {dst = dontCollect,
120 args = Vector.new0 ()}})
121 :: Block.T {args = Vector.new0 (),
124 statements = statements,
130 (* Create extra blocks with signal checks for all blocks that are
133 fun loop (f: unit Forest.t) =
135 val {loops, ...} = Forest.dest f
138 (loops, fn {headers, child} =>
145 val _ = Array.update (isHeader, i, true)
147 addSignalCheck (Vector.sub (blocks, i))
154 (* Add a signal check at the function entry. *)
155 val newStart = Label.newNoname ()
158 (Block.T {args = Vector.new0 (),
161 statements = Vector.new0 (),
162 transfer = Transfer.Goto {args = Vector.new0 (),
164 val () = loop (Graph.loopForestSteensgaard (g, {root = labelNode start}))
167 (blocks, fn b as Block.T {label, ...} =>
168 if Array.sub (isHeader, labelIndex label)
171 val blocks = Vector.concat [blocks, Vector.fromList (!extra)]
172 val f = Function.new {args = args,
178 val _ = Function.clear f
185 val Program.T {functions, handlesSignals, main, objectTypes} = p
187 if not handlesSignals
190 Program.T {functions = List.revMap (functions, insertInFunction),
191 handlesSignals = handlesSignals,
193 objectTypes = objectTypes}