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 370 - (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 329 functor BootstrapCompileFn (structure MachDepVC: MACHDEP_VC
10 : blume 357 val os: SMLofNJ.SysInfo.os_kind) :> sig
11 : blume 364 val make' : string option -> bool
12 :     val make : unit -> bool
13 : blume 362 val deliver' : string option -> bool
14 :     val deliver : unit -> bool
15 :     val reset : unit -> unit
16 : blume 357 end = struct
17 :    
18 : blume 327 structure EM = GenericVC.ErrorMsg
19 :     structure E = GenericVC.Environment
20 :     structure SE = GenericVC.CMStaticEnv
21 :     structure BE = GenericVC.BareEnvironment
22 :     structure PS = GenericVC.PersStamps
23 :     structure CoerceEnv = GenericVC.CoerceEnv
24 : blume 336 structure SSV = SpecificSymValFn (structure MachDepVC = MachDepVC
25 :     val os = os)
26 : blume 364 structure P = OS.Path
27 :     structure F = OS.FileSys
28 : blume 327
29 :     (* Since the bootstrap compiler never executes any of the code
30 :     * it produces, we don't need any dynamic values. Therefore,
31 :     * we create RecompPersstate (but not FullPersstate!) and
32 :     * instantiate Recomp as well as RecompTraversal.
33 :     * Since RecompPersstate is not part of any surrounding FullPersstate,
34 :     * function "discard_value" simply does nothing. *)
35 :     structure RecompPersstate =
36 :     RecompPersstateFn (structure MachDepVC = MachDepVC
37 :     val discard_code = true
38 : blume 362 fun stable_value_present i = false
39 :     fun new_smlinfo i = ())
40 : blume 360
41 : blume 327 structure Recomp = RecompFn (structure PS = RecompPersstate)
42 : blume 370 structure RT = CompileGenericFn (structure CT = Recomp
43 :     val thinTraversal = false)
44 : blume 327
45 :     fun recomp gp g = isSome (RT.group gp g)
46 :    
47 :     (* instantiate Stabilize... *)
48 : blume 329 structure Stabilize =
49 :     StabilizeFn (fun bn2statenv gp i = #1 (#stat (valOf (RT.bnode gp i)))
50 : blume 357 fun warmup (i, p) = ()
51 : blume 363 val recomp = recomp
52 :     val transfer_state = RecompPersstate.transfer_state)
53 : blume 327 (* ... and Parse *)
54 : blume 362 structure Parse = ParseFn (structure Stabilize = Stabilize
55 :     val pending = AutoLoad.getPending)
56 : blume 327
57 : blume 366 (* copying an input file to an output file safely... *)
58 : blume 368 fun copyFile (oi, ci, oo, co, inp, outp, eof) (inf, outf) = let
59 :     fun workIn is = let
60 :     fun workOut os = let
61 : blume 366 val N = 4096
62 :     fun loop () =
63 : blume 368 if eof is then () else (outp (os, inp (is, N)); loop ())
64 : blume 366 in
65 :     loop ()
66 :     end
67 :     in
68 : blume 368 SafeIO.perform { openIt = fn () => oo outf,
69 :     closeIt = co,
70 : blume 366 work = workOut,
71 :     cleanup = fn () =>
72 :     (F.remove outf handle _ => ()) }
73 :     end
74 : blume 364 in
75 : blume 368 SafeIO.perform { openIt = fn () => oi inf,
76 :     closeIt = ci,
77 : blume 366 work = workIn,
78 :     cleanup = fn () => () }
79 : blume 364 end
80 : blume 327
81 : blume 368 val copyTextFile =
82 :     copyFile (TextIO.openIn, TextIO.closeIn,
83 :     AutoDir.openTextOut, TextIO.closeOut,
84 :     TextIO.inputN, TextIO.output, TextIO.endOfStream)
85 :    
86 :     val copyBinFile =
87 :     copyFile (BinIO.openIn, BinIO.closeIn,
88 :     AutoDir.openBinOut, BinIO.closeOut,
89 :     BinIO.inputN, BinIO.output, BinIO.endOfStream)
90 :    
91 : blume 362 fun compile deliver dbopt = let
92 : blume 358
93 : blume 360 val dirbase = getOpt (dbopt, BtNames.dirbaseDefault)
94 :     val pcmodespec = BtNames.pcmodespec
95 :     val initgspec = BtNames.initgspec
96 :     val maingspec = BtNames.maingspec
97 :    
98 : blume 357 val arch = MachDepVC.architecture
99 :     val osname = FilenamePolicy.kind2name os
100 :     val bindir = concat [dirbase, ".bin.", arch, "-", osname]
101 :     val bootdir = concat [dirbase, ".boot.", arch, "-", osname]
102 :    
103 : blume 364 fun listName (p, copy) =
104 :     case P.fromString p of
105 :     { vol = "", isAbs = false, arcs = arc0 :: arc1 :: arcn } => let
106 :     fun win32name () =
107 :     concat (arc1 ::
108 :     foldr (fn (a, r) => "\\" :: a :: r) [] arcn)
109 :     fun doCopy () = let
110 :     val bootpath =
111 :     P.toString { isAbs = false, vol = "",
112 :     arcs = bootdir :: arc1 :: arcn }
113 :     in
114 : blume 368 copyBinFile (p, bootpath)
115 : blume 364 end
116 :     in
117 :     if copy andalso arc0 = bindir then doCopy () else ();
118 :     case os of
119 :     SMLofNJ.SysInfo.WIN32 => win32name ()
120 :     | _ => P.toString { isAbs = false, vol = "",
121 :     arcs = arc1 :: arcn }
122 :     end
123 :     | _ => raise Fail "BootstrapCompile:listName: bad name"
124 :    
125 : blume 329 val keep_going = EnvConfig.getSet StdConfig.keep_going NONE
126 :    
127 : blume 354 val ctxt = SrcPath.cwdContext ()
128 : blume 329
129 : blume 364 val pidfile = P.joinDirFile { dir = bootdir, file = "RTPID" }
130 :     val listfile = P.joinDirFile { dir = bootdir, file = "BOOTLIST" }
131 : blume 329
132 : blume 361 val pcmode = PathConfig.new ()
133 :     val _ = PathConfig.processSpecFile (pcmode, pcmodespec)
134 : blume 329
135 : blume 354 fun stdpath s = SrcPath.standard pcmode { context = ctxt, spec = s }
136 : blume 352
137 :     val initgspec = stdpath initgspec
138 :     val maingspec = stdpath maingspec
139 :    
140 : blume 360 val cmifile = valOf (SrcPath.reAnchoredName (initgspec, bootdir))
141 :     handle Option => raise Fail "BootstrapCompile: cmifile"
142 :    
143 : blume 364 val fnpolicy =
144 : blume 357 FilenamePolicy.separate { bindir = bindir, bootdir = bootdir }
145 :     { arch = arch, os = os }
146 :    
147 : blume 364 fun mkParam { primconf, pervasive, pervcorepids }
148 : blume 357 { corenv } =
149 : blume 349 { primconf = primconf,
150 :     fnpolicy = fnpolicy,
151 :     pcmode = pcmode,
152 :     symenv = SSV.env,
153 :     keep_going = keep_going,
154 :     pervasive = pervasive,
155 :     corenv = corenv,
156 :     pervcorepids = pervcorepids }
157 :    
158 : blume 327 val emptydyn = E.dynamicPart E.emptyEnv
159 :    
160 :     (* first, build an initial GeneralParam.info, so we can
161 :     * deal with the pervasive env and friends... *)
162 :    
163 : blume 360 val primconf = Primitive.primEnvConf
164 : blume 349 val mkInitParam = mkParam { primconf = primconf,
165 :     pervasive = E.emptyEnv,
166 : blume 364 pervcorepids = PidSet.empty }
167 : blume 327
168 : blume 349 val param_nocore = mkInitParam { corenv = BE.staticPart BE.emptyEnv }
169 :    
170 : blume 327 val groupreg = GroupReg.new ()
171 :     val errcons = EM.defaultConsumer ()
172 : blume 329 val ginfo_nocore = { param = param_nocore, groupreg = groupreg,
173 :     errcons = errcons }
174 : blume 327
175 :     fun main_compile arg = let
176 : blume 335 val { rts, core, pervasive, primitives, binpaths } = arg
177 : blume 327
178 : blume 329 val ovldR = GenericVC.Control.overloadKW
179 :     val savedOvld = !ovldR
180 :     val _ = ovldR := true
181 :    
182 : blume 327 (* here we build a new gp -- the one that uses the freshly
183 :     * brewed pervasive env, core env, and primitives *)
184 : blume 358 val core = valOf (RT.sbnode ginfo_nocore core)
185 : blume 329 val corenv = CoerceEnv.es2bs (#1 (#stat core))
186 : blume 356 val core_sym = #1 (#sym core)
187 : blume 329
188 :     (* The following is a bit of a hack (but corenv is a hack anyway):
189 :     * As soon as we have core available, we have to patch the
190 :     * ginfo to include the correct corenv (because virtually
191 :     * everybody else needs access to corenv). *)
192 : blume 349 val param_justcore = mkInitParam { corenv = corenv }
193 : blume 329 val ginfo_justcore = { param = param_justcore, groupreg = groupreg,
194 :     errcons = errcons }
195 :    
196 : blume 358 fun rt n = valOf (RT.sbnode ginfo_justcore n)
197 : blume 327 val rts = rt rts
198 :     val pervasive = rt pervasive
199 :    
200 :     fun sn2pspec (name, n) = let
201 : blume 369 val { stat = (s, sp), sym = (sy, syp), ctxt, bfc } = rt n
202 : blume 327 val env =
203 :     E.mkenv { static = s, symbolic = sy, dynamic = emptydyn }
204 :     val pidInfo = { statpid = sp, sympid = syp, ctxt = ctxt }
205 :     in
206 :     { name = name, env = env, pidInfo = pidInfo }
207 :     end
208 :    
209 :     val pspecs = map sn2pspec primitives
210 :    
211 : blume 329 val _ = ovldR := savedOvld
212 :    
213 : blume 356 (* This is a hack but must be done for both the symbolic
214 :     * and later the dynamic part of the core environment:
215 :     * we must include these parts in the pervasive env. *)
216 :     val perv_sym = E.layerSymbolic (#1 (#sym pervasive), core_sym)
217 :    
218 : blume 349 val param =
219 :     mkParam { primconf = Primitive.configuration pspecs,
220 : blume 327 pervasive = E.mkenv { static = #1 (#stat pervasive),
221 : blume 356 symbolic = perv_sym,
222 : blume 327 dynamic = emptydyn },
223 :     pervcorepids =
224 :     PidSet.addList (PidSet.empty,
225 :     [#2 (#stat pervasive),
226 :     #2 (#sym pervasive),
227 : blume 364 #2 (#stat core)]) }
228 : blume 349 { corenv = corenv }
229 : blume 362 val stab =
230 :     if deliver then SOME true else NONE
231 : blume 327 in
232 : blume 362 case Parse.parse NONE param stab maingspec of
233 : blume 349 NONE => false
234 : blume 329 | SOME (g, gp) =>
235 : blume 349 if recomp gp g then let
236 :     val rtspid = PS.toHex (#2 (#stat rts))
237 :     fun writeList s = let
238 : blume 364 fun add ((p, flag), l) = let
239 :     val n = listName (p, true)
240 :     in
241 :     if flag then n :: l else l
242 :     end
243 :     fun transcribe (p, NONE) = listName (p, true)
244 :     | transcribe (p, SOME (off, desc)) =
245 :     concat [listName (p, false),
246 :     "@", Int.toString off, ":", desc]
247 :     val bootstrings =
248 :     foldr add (map transcribe (MkBootList.group g))
249 :     binpaths
250 :     fun show str =
251 :     (TextIO.output (s, str);
252 :     TextIO.output (s, "\n"))
253 : blume 349 in
254 : blume 364 app show bootstrings
255 : blume 349 end
256 :     in
257 : blume 362 if deliver then
258 :     (SafeIO.perform { openIt = fn () =>
259 : blume 354 AutoDir.openTextOut pidfile,
260 : blume 349 closeIt = TextIO.closeOut,
261 :     work = fn s =>
262 :     TextIO.output (s, rtspid ^ "\n"),
263 :     cleanup = fn () =>
264 : blume 354 OS.FileSys.remove pidfile
265 :     handle _ => () };
266 : blume 349 SafeIO.perform { openIt = fn () =>
267 : blume 354 AutoDir.openTextOut listfile,
268 : blume 349 closeIt = TextIO.closeOut,
269 :     work = writeList,
270 :     cleanup = fn () =>
271 : blume 354 OS.FileSys.remove listfile
272 :     handle _ => () };
273 : blume 368 copyTextFile (SrcPath.osstring initgspec, cmifile);
274 : blume 366 Say.say ["Runtime System PID is: ", rtspid, "\n"])
275 : blume 362 else ();
276 :     true
277 : blume 349 end
278 :     else false
279 : blume 351 end handle Option => (RT.reset (); false)
280 : blume 330 (* to catch valOf failures in "rt" *)
281 : blume 327 in
282 : blume 329 case BuildInitDG.build ginfo_nocore initgspec of
283 : blume 327 SOME x => main_compile x
284 : blume 349 | NONE => false
285 : blume 327 end
286 : blume 362
287 : blume 364 val make' = compile false
288 :     fun make () = make' NONE
289 : blume 362 val deliver' = compile true
290 :     fun deliver () = deliver' NONE
291 :     fun reset () =
292 :     (RecompPersstate.reset ();
293 :     RT.resetAll ();
294 : blume 367 Recomp.reset ();
295 :     Parse.reset ())
296 : blume 327 end

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