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 CommonBlock (S: SSA_TRANSFORM_STRUCTS): SSA_TRANSFORM = | |
10 | struct | |
11 | ||
12 | open S | |
13 | open Exp Transfer | |
14 | ||
15 | fun transform (Program.T {globals, datatypes, functions, main}) = | |
16 | let | |
17 | val shrink = shrinkFunction {globals = globals} | |
18 | ||
19 | local | |
20 | fun make transfer = let | |
21 | val l = Label.newNoname () | |
22 | in | |
23 | Block.T {label = l, | |
24 | args = Vector.new0 (), | |
25 | statements = Vector.new0 (), | |
26 | transfer = transfer} | |
27 | end | |
28 | in | |
29 | fun makeRaise var = make (Raise (Vector.new1 var)) | |
30 | fun makeReturn var = make (Return (Vector.new1 var)) | |
31 | fun makeGoto (dst, var) = make (Goto {dst = dst, args = Vector.new1 var}) | |
32 | end | |
33 | fun makeNullaryGoto dst = Goto {dst = dst, args = Vector.new0 ()} | |
34 | ||
35 | val {get = varInfo: | |
36 | Var.t -> {returner: (Func.t * Label.t) option ref, | |
37 | raiser: (Func.t * Label.t) option ref, | |
38 | gotoers: (Func.t * (Label.t * Label.t) list ref) option ref} option, | |
39 | set = setVarInfo, ...} = | |
40 | Property.getSetOnce | |
41 | (Var.plist, Property.initConst NONE) | |
42 | ||
43 | val _ = | |
44 | Vector.foreach | |
45 | (globals, fn Statement.T {var, ...} => | |
46 | setVarInfo(valOf var, SOME {returner = ref NONE, | |
47 | raiser = ref NONE, | |
48 | gotoers = ref NONE})) | |
49 | ||
50 | fun eliminateFunction f = | |
51 | let | |
52 | val {args, blocks, mayInline, name, returns, raises, start} = | |
53 | Function.dest f | |
54 | val newBlocks = ref [] | |
55 | local | |
56 | fun common (sel, make) var = | |
57 | case varInfo var of | |
58 | NONE => NONE | |
59 | | SOME varInfo => | |
60 | let | |
61 | val c = sel varInfo | |
62 | ||
63 | fun install () = | |
64 | let | |
65 | val b = make var | |
66 | val l = Block.label b | |
67 | in | |
68 | List.push(newBlocks, b) ; | |
69 | c := SOME (name, l) ; | |
70 | SOME l | |
71 | end | |
72 | in | |
73 | case !c of | |
74 | NONE => install () | |
75 | | SOME (name', l') => | |
76 | if Func.equals(name, name') | |
77 | then SOME l' | |
78 | else install () | |
79 | end | |
80 | in | |
81 | val commonReturner = common (#returner, makeReturn) | |
82 | val commonRaiser = common (#raiser, makeRaise) | |
83 | end | |
84 | fun commonGotoers (k, var) = | |
85 | case varInfo var of | |
86 | NONE => NONE | |
87 | | SOME {gotoers, ...} => | |
88 | let | |
89 | fun install info = | |
90 | let | |
91 | val b = makeGoto (k, var) | |
92 | val l = Block.label b | |
93 | in | |
94 | List.push(newBlocks, b) ; | |
95 | List.push(info, (k, l)) ; | |
96 | SOME l | |
97 | end | |
98 | fun install' () = | |
99 | let | |
100 | val info = ref [] | |
101 | in | |
102 | gotoers := SOME (name, info); | |
103 | install info | |
104 | end | |
105 | in | |
106 | case !gotoers of | |
107 | NONE => install' () | |
108 | | SOME (name', info') => | |
109 | if Func.equals(name, name') | |
110 | then case List.peek (!info', fn (k', _) => | |
111 | Label.equals(k', k)) of | |
112 | NONE => install info' | |
113 | | SOME (_, l') => SOME l' | |
114 | else install' () | |
115 | end | |
116 | ||
117 | val blocks = | |
118 | Vector.map | |
119 | (blocks, fn Block.T {label, args, statements, transfer} => | |
120 | let | |
121 | val doit = fn SOME l => makeNullaryGoto l | |
122 | | NONE => transfer | |
123 | val transfer = | |
124 | if Vector.isEmpty statements | |
125 | then case transfer of | |
126 | Goto {dst, args = xs} => | |
127 | if Vector.length xs = 1 | |
128 | then doit (commonGotoers | |
129 | (dst, Vector.first xs)) | |
130 | else transfer | |
131 | | Return xs => | |
132 | if Vector.length xs = 1 | |
133 | then doit (commonReturner | |
134 | (Vector.first xs)) | |
135 | else transfer | |
136 | | Raise xs => | |
137 | if Vector.length xs = 1 | |
138 | then doit (commonRaiser | |
139 | (Vector.first xs)) | |
140 | else transfer | |
141 | | _ => transfer | |
142 | else transfer | |
143 | in | |
144 | Block.T {label = label, | |
145 | args = args, | |
146 | statements = statements, | |
147 | transfer = transfer} | |
148 | end) | |
149 | val blocks = Vector.concat [Vector.fromList (!newBlocks), blocks] | |
150 | in | |
151 | shrink (Function.new {args = args, | |
152 | blocks = blocks, | |
153 | mayInline = mayInline, | |
154 | name = name, | |
155 | raises = raises, | |
156 | returns = returns, | |
157 | start = start}) | |
158 | end | |
159 | ||
160 | val program = | |
161 | Program.T {datatypes = datatypes, | |
162 | globals = globals, | |
163 | functions = List.revMap (functions, eliminateFunction), | |
164 | main = main} | |
165 | val _ = Program.clearTop program | |
166 | in | |
167 | program | |
168 | end | |
169 | end |