Home My Page Projects Code Snippets Project Openings SML/NJ
Summary Activity Forums Tracker Lists Tasks Docs Surveys News SCM Files

SCM Repository

[smlnj] Annotation of /sml/trunk/src/cm/bootstrap/btcompile.sml
ViewVC logotype

Annotation of /sml/trunk/src/cm/bootstrap/btcompile.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 537 - (view) (download)

1 : blume 327 (*
2 :     * The bootstrap compiler.
3 :     * (Formerly known as "batch" compiler.)
4 :     *
5 :     * (C) 1999 Lucent Technologies, Bell Laboratories
6 :     *
7 :     * Author: Matthias Blume (blume@kurims.kyoto-u.ac.jp)
8 :     *)
9 : blume 452 functor BootstrapCompileFn (structure MachDepVC : MACHDEP_VC
10 : blume 518 val os : SMLofNJ.SysInfo.os_kind
11 :     val load_plugin : string -> bool) :> sig
12 : blume 364 val make' : string option -> bool
13 :     val make : unit -> bool
14 : blume 362 val deliver' : string option -> bool
15 :     val deliver : unit -> bool
16 :     val reset : unit -> unit
17 : blume 434 val symval : string -> { get: unit -> int option, set: int option -> unit }
18 : blume 357 end = struct
19 :    
20 : blume 327 structure EM = GenericVC.ErrorMsg
21 :     structure E = GenericVC.Environment
22 :     structure SE = GenericVC.CMStaticEnv
23 :     structure BE = GenericVC.BareEnvironment
24 :     structure PS = GenericVC.PersStamps
25 :     structure CoerceEnv = GenericVC.CoerceEnv
26 : blume 336 structure SSV = SpecificSymValFn (structure MachDepVC = MachDepVC
27 :     val os = os)
28 : blume 364 structure P = OS.Path
29 :     structure F = OS.FileSys
30 : blume 403 structure BF = MachDepVC.Binfile
31 : blume 327
32 : blume 452 val arch = MachDepVC.architecture
33 :     val osname = FilenamePolicy.kind2name os
34 :     val archos = concat [arch, "-", osname]
35 :    
36 : blume 456 fun init_servers (GroupGraph.GROUP { grouppath, ... }) =
37 : blume 464 Servers.cmb { archos = archos,
38 :     root = SrcPath.descr grouppath }
39 : blume 456
40 : blume 448 structure Compile = CompileFn (structure MachDepVC = MachDepVC
41 : blume 464 val compile_there =
42 :     Servers.compile o SrcPath.descr)
43 : blume 360
44 : blume 403 structure BFC = BfcFn (structure MachDepVC = MachDepVC)
45 :    
46 : blume 327 (* instantiate Stabilize... *)
47 : blume 329 structure Stabilize =
48 : blume 537 StabilizeFn (structure MachDepVC = MachDepVC
49 : blume 399 fun recomp gp g = let
50 : blume 403 val { store, get } = BFC.new ()
51 : blume 456 val _ = init_servers g
52 : blume 399 val { group, ... } =
53 : blume 403 Compile.newTraversal (fn _ => fn _ => (),
54 :     store, g)
55 : blume 399 in
56 : blume 450 case Servers.withServers (fn () => group gp) of
57 : blume 403 NONE => NONE
58 :     | SOME _ => SOME get
59 :     end
60 :     val getII = Compile.getII)
61 : blume 398
62 : blume 327 (* ... and Parse *)
63 : blume 362 structure Parse = ParseFn (structure Stabilize = Stabilize
64 : blume 537 val evictStale = Compile.evictStale
65 : blume 372 fun pending () = SymbolMap.empty)
66 : blume 327
67 : blume 537 fun mkBootList g = let
68 :     fun listName p =
69 :     case P.fromString p of
70 :     { vol = "", isAbs = false, arcs = _ :: arc1 :: arcn } => let
71 :     fun win32name () =
72 :     concat (arc1 ::
73 :     foldr (fn (a, r) => "\\" :: a :: r) [] arcn)
74 :     in
75 :     case os of
76 :     SMLofNJ.SysInfo.WIN32 => win32name ()
77 :     | _ => P.toString { isAbs = false, vol = "",
78 :     arcs = arc1 :: arcn }
79 :     end
80 :     | _ => raise Fail ("BootstrapCompile:listName: bad name: " ^ p)
81 : blume 364 in
82 : blume 537 MkBootList.group listName g
83 : blume 364 end
84 : blume 327
85 : blume 456 fun mk_compile deliver root dbopt = let
86 : blume 358
87 : blume 360 val dirbase = getOpt (dbopt, BtNames.dirbaseDefault)
88 :     val pcmodespec = BtNames.pcmodespec
89 :     val initgspec = BtNames.initgspec
90 :     val maingspec = BtNames.maingspec
91 :    
92 : blume 537 val bindir = concat [dirbase, BtNames.bin_infix, archos]
93 :     val bootdir = concat [dirbase, BtNames.boot_infix, archos]
94 : blume 357
95 : blume 433 val keep_going = #get StdConfig.keep_going ()
96 : blume 329
97 : blume 354 val ctxt = SrcPath.cwdContext ()
98 : blume 329
99 : blume 537 val listfile = P.joinDirFile { dir = bootdir, file = BtNames.bootlist }
100 :     val pidmapfile = P.joinDirFile { dir = bootdir, file = BtNames.pidmap }
101 : blume 329
102 : blume 361 val pcmode = PathConfig.new ()
103 :     val _ = PathConfig.processSpecFile (pcmode, pcmodespec)
104 : blume 329
105 : blume 354 fun stdpath s = SrcPath.standard pcmode { context = ctxt, spec = s }
106 : blume 352
107 :     val initgspec = stdpath initgspec
108 : blume 456 val maingspec =
109 :     case root of
110 :     NONE => stdpath maingspec
111 : blume 457 | SOME r => SrcPath.fromDescr pcmode r
112 : blume 352
113 : blume 364 val fnpolicy =
114 : blume 357 FilenamePolicy.separate { bindir = bindir, bootdir = bootdir }
115 :     { arch = arch, os = os }
116 :    
117 : blume 537 fun mkParam corenv =
118 :     { fnpolicy = fnpolicy,
119 : blume 349 pcmode = pcmode,
120 : blume 433 symval = SSV.symval,
121 : blume 349 keep_going = keep_going,
122 : blume 537 corenv = corenv }
123 : blume 349
124 : blume 327 val emptydyn = E.dynamicPart E.emptyEnv
125 :    
126 :     (* first, build an initial GeneralParam.info, so we can
127 :     * deal with the pervasive env and friends... *)
128 :    
129 : blume 537 val param_nocore = mkParam BE.emptyEnv
130 : blume 327
131 :     val groupreg = GroupReg.new ()
132 :     val errcons = EM.defaultConsumer ()
133 : blume 329 val ginfo_nocore = { param = param_nocore, groupreg = groupreg,
134 :     errcons = errcons }
135 : blume 327
136 : blume 449 fun mk_main_compile arg = let
137 : blume 450
138 : blume 537 val { core = core_n, pervasive = perv_n, others, src } = arg
139 : blume 327
140 : blume 329 val ovldR = GenericVC.Control.overloadKW
141 :     val savedOvld = !ovldR
142 :     val _ = ovldR := true
143 : blume 400 val sbnode = Compile.newSbnodeTraversal ()
144 : blume 329
145 : blume 327 (* here we build a new gp -- the one that uses the freshly
146 :     * brewed pervasive env, core env, and primitives *)
147 : blume 537 val core = valOf (sbnode ginfo_nocore core_n)
148 :     val corenv =
149 :     BE.mkenv { static = CoerceEnv.es2bs (#env (#statenv core ())),
150 :     symbolic = #symenv core (),
151 :     dynamic = BE.dynamicPart BE.emptyEnv }
152 : blume 329
153 :     (* The following is a bit of a hack (but corenv is a hack anyway):
154 :     * As soon as we have core available, we have to patch the
155 :     * ginfo to include the correct corenv (because virtually
156 :     * everybody else needs access to corenv). *)
157 : blume 537 val param = mkParam corenv
158 :     val ginfo =
159 :     { param = param, groupreg = groupreg, errcons = errcons }
160 : blume 329
161 : blume 537 val perv_fsbnode = (NONE, perv_n)
162 : blume 327
163 : blume 537 fun rt n = valOf (sbnode ginfo n)
164 :     val pervasive = rt perv_n
165 :    
166 :     fun rt2ie (n, ii: IInfo.info) = let
167 :     val bs = CoerceEnv.es2bs (#env (#statenv ii ()))
168 :     val (dae, mkDomain) = Statenv2DAEnv.cvt bs
169 : blume 327 in
170 : blume 537 { ie = ((NONE, n), dae), mkDomain = mkDomain }
171 : blume 327 end
172 : blume 537
173 :     fun add_exports (n, exports) = let
174 :     val { ie, mkDomain } = rt2ie (n, rt n)
175 :     fun ins_ie (sy, m) = SymbolMap.insert (m, sy, ie)
176 :     in
177 :     SymbolSet.foldl ins_ie exports (mkDomain ())
178 :     end
179 : blume 327
180 : blume 537 val special_exports = let
181 :     fun mkie (n, rtn) = #ie (rt2ie (n, rtn))
182 :     in
183 :     foldl SymbolMap.insert' SymbolMap.empty
184 :     [(PervCoreAccess.pervStrSym, mkie (perv_n, pervasive)),
185 :     (PervCoreAccess.coreStrSym, mkie (core_n, core))]
186 :     end
187 : blume 327
188 : blume 537 val init_group = GroupGraph.GROUP
189 :     { exports = foldl add_exports special_exports others,
190 :     kind = GroupGraph.LIB (StringSet.empty, []),
191 :     required = StringSet.singleton "primitive",
192 :     grouppath = initgspec,
193 :     sublibs = [] }
194 :    
195 : blume 329 val _ = ovldR := savedOvld
196 :    
197 : blume 537 (* At this point we check if there is a usable stable version
198 :     * of the init group. If so, we continue to use that. *)
199 :     val (stab, init_group, deliver) = let
200 :     fun nostabinit () =
201 :     if deliver then
202 :     let val stabarg = { group = init_group,
203 :     anyerrors = ref false }
204 :     in
205 :     case Stabilize.stabilize ginfo stabarg of
206 :     SOME g => (SOME true, g, true)
207 :     (* if we cannot stabilize the init group, then
208 :     * as a first remedy we turn delivery off *)
209 :     | NONE => (NONE, init_group, false)
210 :     end
211 :     else (NONE, init_group, false)
212 :     in
213 :     if VerifyStable.verify ginfo init_group then let
214 :     fun load () =
215 :     Stabilize.loadStable ginfo
216 :     { getGroup = fn _ =>
217 :     raise Fail "CMB: initial getGroup",
218 :     anyerrors = ref false }
219 :     initgspec
220 :     in
221 :     case load () of
222 :     NONE => nostabinit ()
223 :     | SOME g =>
224 :     (if deliver then SOME true else NONE, g, deliver)
225 :     end
226 :     else nostabinit ()
227 :     end
228 : blume 356
229 : blume 537 val gr = GroupReg.new ()
230 :     val _ = GroupReg.register gr (initgspec, src)
231 :    
232 :     val parse_arg =
233 :     { load_plugin = load_plugin,
234 :     gr = gr,
235 :     param = param,
236 :     stabflag = stab,
237 :     group = maingspec,
238 :     init_group = init_group,
239 :     paranoid = true }
240 : blume 327 in
241 : blume 456 Servers.dirbase dirbase;
242 : blume 537 Parse.reset ();
243 :     case Parse.parse parse_arg of
244 : blume 449 NONE => NONE
245 : blume 399 | SOME (g, gp) => let
246 : blume 449 fun thunk () = let
247 : blume 456 val _ = init_servers g
248 : blume 449 fun store _ = ()
249 :     val { group = recomp, ... } =
250 :     Compile.newTraversal (fn _ => fn _ => (), store, g)
251 : blume 450 val res =
252 :     Servers.withServers (fn () => recomp gp)
253 : blume 449 in
254 : blume 450 if isSome res then let
255 : blume 537 val { l = bootitems, ss } = mkBootList g
256 :     val stablelibs = Reachable.stableLibsOf g
257 :     fun inSet bi = StableSet.member (ss, bi)
258 :     val frontiers =
259 :     SrcPathMap.map (Reachable.frontier inSet)
260 :     stablelibs
261 :     fun writeBootList s = let
262 :     fun wr str = TextIO.output (s, str ^ "\n")
263 : blume 364 in
264 : blume 537 app wr bootitems
265 : blume 364 end
266 : blume 537 fun writePid s i = let
267 :     val sn = BinInfo.stablename i
268 :     val os = BinInfo.offset i
269 :     val descr = BinInfo.describe i
270 :     val bfc = BFC.getStable
271 :     { stable = sn, offset = os, descr = descr }
272 :     in
273 :     case BF.exportPidOf bfc of
274 :     NONE => ()
275 :     | SOME pid =>
276 :     (TextIO.output (s, " ");
277 :     TextIO.output (s, PS.toHex pid))
278 :     end
279 :     fun writePidLine s (p, set) =
280 :     if StableSet.isEmpty set then ()
281 :     else (TextIO.output (s, SrcPath.descr p);
282 :     StableSet.app (writePid s) set;
283 :     TextIO.output (s, "\n"))
284 :     fun writePidMap s =
285 :     SrcPathMap.appi (writePidLine s) frontiers
286 : blume 349 in
287 : blume 449 if deliver then
288 :     (SafeIO.perform
289 :     { openIt = fn () =>
290 : blume 537 AutoDir.openTextOut listfile,
291 : blume 449 closeIt = TextIO.closeOut,
292 : blume 537 work = writeBootList,
293 : blume 459 cleanup = fn _ =>
294 : blume 537 OS.FileSys.remove listfile
295 : blume 449 handle _ => () };
296 :     SafeIO.perform
297 :     { openIt = fn () =>
298 : blume 537 AutoDir.openTextOut pidmapfile,
299 : blume 449 closeIt = TextIO.closeOut,
300 : blume 537 work = writePidMap,
301 : blume 459 cleanup = fn _ =>
302 : blume 537 OS.FileSys.remove pidmapfile
303 : blume 449 handle _ => () };
304 : blume 537 Say.say
305 :     ["New boot directory has been built.\n"])
306 : blume 449 else ();
307 :     true
308 : blume 349 end
309 : blume 449 else false
310 : blume 349 end
311 : blume 449 in
312 : blume 457 SOME ((g, gp, pcmode), thunk)
313 : blume 399 end
314 : blume 449 end handle Option => (Compile.reset (); NONE)
315 : blume 330 (* to catch valOf failures in "rt" *)
316 : blume 327 in
317 : blume 329 case BuildInitDG.build ginfo_nocore initgspec of
318 : blume 449 SOME x => mk_main_compile x
319 :     | NONE => NONE
320 : blume 327 end
321 : blume 362
322 : blume 449 fun compile deliver dbopt =
323 : blume 456 case mk_compile deliver NONE dbopt of
324 : blume 450 NONE => false
325 : blume 459 | SOME (_, thunk) => thunk ()
326 : blume 449
327 :     local
328 : blume 456 fun slave (dirbase, root) =
329 :     case mk_compile false (SOME root) (SOME dirbase) of
330 : blume 449 NONE => NONE
331 : blume 457 | SOME ((g, gp, pcmode), _) => let
332 : blume 449 val trav = Compile.newSbnodeTraversal () gp
333 :     fun trav' sbn = isSome (trav sbn)
334 :     in
335 : blume 457 SOME (g, trav', pcmode)
336 : blume 449 end
337 :     in
338 : blume 452 val _ = CMBSlaveHook.init archos slave
339 : blume 449 end
340 :    
341 : blume 362 fun reset () =
342 : blume 398 (Compile.reset ();
343 : blume 367 Parse.reset ())
344 : blume 377
345 :     val make' = compile false
346 :     fun make () = make' NONE
347 :     fun deliver' arg =
348 :     SafeIO.perform { openIt = fn () => (),
349 :     closeIt = reset,
350 :     work = fn () => compile true arg,
351 : blume 459 cleanup = fn _ => () }
352 : blume 377 fun deliver () = deliver' NONE
353 : blume 434 val symval = SSV.symval
354 : blume 327 end

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0