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