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/compiler/FLINT/main/literals.sml
ViewVC logotype

Annotation of /sml/trunk/compiler/FLINT/main/literals.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2162 - (view) (download)

1 : monnier 251 (* literals.sml
2 :     *
3 :     * COPYRIGHT (c) 1998 Bell Labs, Lucent Technologies.
4 :     * COPYRIGHT (c) 1998 YALE FLINT PROJECT.
5 :     *)
6 : monnier 98
7 :     signature LITERALS =
8 :     sig
9 :     type lit
10 :     val litsplit : CPS.function -> CPS.function * lit
11 : monnier 251 val litToBytes : lit -> Word8Vector.vector
12 :     end;
13 : monnier 98
14 :     structure Literals : LITERALS =
15 :     struct
16 :    
17 : monnier 251 structure W8V = Word8Vector
18 :    
19 : monnier 98 local structure LV = LambdaVar
20 : monnier 504 structure Intset = struct
21 :     type intset = IntRedBlackSet.set ref
22 :     fun new() = ref IntRedBlackSet.empty
23 :     fun add set i = set := IntRedBlackSet.add(!set, i)
24 :     fun mem set i = IntRedBlackSet.member(!set, i)
25 :     fun rmv set i = set := IntRedBlackSet.delete(!set, i)
26 :     end
27 : monnier 98 open CPS
28 :     in
29 :    
30 :     fun bug msg = ErrorMsg.impossible ("Literals: "^msg)
31 :     val ident = fn x => x
32 :     fun mkv _ = LV.mkLvar()
33 :    
34 :     (****************************************************************************
35 :     * A MINI-LITERAL LANGUAGE *
36 :     ****************************************************************************)
37 :     datatype lit_val
38 : monnier 251 = LI_INT of word
39 : monnier 98 | LI_STRING of string
40 :     | LI_VAR of lvar
41 :    
42 : monnier 251 datatype block_kind
43 :     = LI_RECORD (* record of tagged ML values *)
44 :     | LI_VECTOR (* vector of tagged ML values *)
45 :    
46 : monnier 98 datatype lit_exp
47 :     = LI_TOP of lit_val list
48 : monnier 251 | LI_BLOCK of (block_kind * lit_val list * lvar * lit_exp)
49 :     | LI_F64BLOCK of (string list * lvar * lit_exp)
50 :     | LI_I32BLOCK of (Word32.word list * lvar * lit_exp)
51 : monnier 98
52 :     type lit = lit_exp
53 :    
54 : monnier 251 fun rk2bk CPS.RK_VECTOR = LI_VECTOR
55 :     | rk2bk CPS.RK_RECORD = LI_RECORD
56 :     | rk2bk _ = bug "rk2bk: unexpected block kind"
57 :    
58 :     fun val2lit (CPS.VAR v) = LI_VAR v
59 :     | val2lit (CPS.INT i) = LI_INT(Word.fromInt i)
60 :     | val2lit (CPS.STRING s) = LI_STRING s
61 : monnier 98 | val2lit _ = bug "unexpected case in val2lit"
62 :    
63 :     (****************************************************************************
64 : monnier 251 * TRANSLATING THE LITERAL EXP TO BYTES *
65 : monnier 98 ****************************************************************************)
66 :    
67 : monnier 251 (* Literals are encoded as instructions for a "literal machine." The abstract
68 :     * description of these instructions is as follows:
69 :     *
70 :     * INT(i) -- push the int31 literal i on the stack
71 :     * RAW32[i1,...,in] -- form a 32-bit raw data record from the
72 :     * i1..in and push a pointer to it.
73 :     * RAW64[r1,...,rn] -- form a 64-bit raw data record from the
74 :     * r1..rn and push a pointer to it.
75 :     * STR[c1,...,cn] -- form a string from the characters c1..cn
76 :     * and push it on the stack.
77 :     * LIT(k) -- push the contents of the stack element
78 :     * that is k slots from the top of the stack.
79 :     * VECTOR(n) -- pop n elements from the stack, make a vector
80 :     * from them and push a pointer to the vector.
81 :     * RECORD(n) -- pop n elements from the stack, make a record
82 :     * from them and push a pointer.
83 :     * RETURN -- return the literal that is on the top of the
84 :     * stack.
85 :     *)
86 : monnier 98
87 : monnier 251 fun w32ToBytes' (w, l) =
88 :     Word8.fromLargeWord(Word32.>>(w, 0w24)) ::
89 :     Word8.fromLargeWord(Word32.>>(w, 0w16)) ::
90 :     Word8.fromLargeWord(Word32.>>(w, 0w8)) ::
91 :     Word8.fromLargeWord w :: l
92 :     fun w32ToBytes w = w32ToBytes' (w, [])
93 :     fun w31ToBytes w = w32ToBytes(Word31.toLargeWordX w)
94 :     fun intToBytes i = w32ToBytes(Word32.fromInt i)
95 :     fun intToBytes' (i, l) = w32ToBytes'(Word32.fromInt i, l)
96 :     fun strToBytes s = map Byte.charToByte (explode s)
97 : monnier 98
98 : monnier 251 val emit_MAGIC = W8V.fromList[0wx19, 0wx98, 0wx10, 0wx22]
99 :     fun emit_DEPTH n = W8V.fromList(intToBytes n)
100 :     fun emit_INT i = W8V.fromList(0wx01 :: w31ToBytes i)
101 :     fun emit_RAW32 [i] = W8V.fromList(0wx02 :: w32ToBytes i)
102 :     | emit_RAW32 l =
103 :     W8V.fromList(0wx03 :: (intToBytes'(length l, List.foldr w32ToBytes' [] l)))
104 :     fun emit_RAW64 [r] = W8V.fromList(0wx04 :: strToBytes r)
105 :     | emit_RAW64 l = W8V.concat(
106 :     W8V.fromList(0wx05 :: intToBytes(length l)) :: map Byte.stringToBytes l)
107 :     fun emit_STR s = W8V.concat[
108 :     W8V.fromList(0wx06 :: intToBytes(size s)),
109 :     Byte.stringToBytes s
110 :     ]
111 :     fun emit_LIT k = W8V.fromList(0wx07 :: intToBytes k)
112 :     fun emit_VECTOR n = W8V.fromList(0wx08 :: intToBytes n)
113 :     fun emit_RECORD n = W8V.fromList(0wx09 :: intToBytes n)
114 :     val emit_RETURN = W8V.fromList[0wxff]
115 : monnier 98
116 : monnier 251 fun litToBytes (LI_TOP[]) = W8V.fromList[]
117 :     | litToBytes litExp = let
118 :     fun depth (LI_TOP ls, d, maxDepth) = Int.max(maxDepth, d+length ls)
119 :     | depth (LI_BLOCK(_, ls, _, rest), d, maxDepth) =
120 :     depth (rest, d+1, Int.max(maxDepth, d+length ls))
121 :     | depth (LI_F64BLOCK(ls, _, rest), d, maxDepth) =
122 :     depth (rest, d+1, Int.max(maxDepth, d+length ls))
123 :     | depth (LI_I32BLOCK(ls, _, rest), d, maxDepth) =
124 :     depth (rest, d+1, Int.max(maxDepth, d+length ls))
125 :     fun emitLitExp (env, exp, code) = let
126 :     fun emitLitVals ([], _, code) = code
127 :     | emitLitVals (lit::r, d, code) = let
128 :     val instr = (case lit
129 :     of (LI_INT i) => emit_INT i
130 :     | (LI_STRING s) => emit_STR s
131 :     | (LI_VAR v) => let
132 :     fun f ([], _) = bug "unbound lvar"
133 :     | f (v'::r, d) = if (v = v') then d else f(r, d+1)
134 :     in
135 :     emit_LIT(f (env, d))
136 :     end
137 :     (* end case *))
138 :     in
139 :     emitLitVals (r, d+1, instr::code)
140 :     end
141 :     fun emitBlock (LI_RECORD, ls, code) =
142 :     emit_RECORD(length ls) :: emitLitVals(ls, 0, code)
143 :     | emitBlock (LI_VECTOR, ls, code) =
144 :     emit_VECTOR(length ls) :: emitLitVals(ls, 0, code)
145 :     fun emitF64Block (ls, code) =
146 :     emit_RAW64(map IEEERealConst.realconst ls) :: code
147 :     fun emitI32Block (ls, code) = emit_RAW32 ls :: code
148 :     in
149 :     case exp
150 :     of (LI_TOP ls) => emit_RETURN :: emitBlock(LI_RECORD, ls, code)
151 :     | (LI_BLOCK(bk, ls, v, rest)) =>
152 :     emitLitExp (v::env, rest, emitBlock(bk, ls, code))
153 :     | (LI_F64BLOCK(ls, v, rest)) =>
154 :     emitLitExp (v::env, rest, emitF64Block(ls, code))
155 :     | (LI_I32BLOCK(ls, v, rest)) =>
156 :     emitLitExp (v::env, rest, emitI32Block(ls, code))
157 :     (* end case *)
158 :     end
159 :     val maxDepth = depth (litExp, 0, 1)
160 :     val code = emit_MAGIC
161 :     :: emit_DEPTH maxDepth
162 :     :: List.rev(emitLitExp([], litExp, []))
163 :     in
164 :     W8V.concat code
165 :     end
166 : monnier 98
167 : monnier 251
168 : monnier 98 (****************************************************************************
169 :     * LIFTING LITERALS ON FLINT *
170 :     ****************************************************************************)
171 :     (*
172 :     fun liftlits body = bug "FLINT version currently not implemented yet"
173 :    
174 :     fun litsplit (FK_FCT, f, [(v, t)], body) =
175 :     if LT.ltp_str t then
176 : monnier 251 let val (nbody, lit, llt) = liftlits body
177 : monnier 98 val nt = LT.ltc_str ((LT.ltd_str t)@[llt])
178 :     in ((FK_FCT, f, [(v, nt)], body), lit)
179 :     end
180 :     else bug "unexpected FLINT header in litsplit (case 1)"
181 :     | litsplit _ = bug "unexpected FLINT header in litsplit (case 2)"
182 :     *)
183 :    
184 :     (****************************************************************************
185 :     * LIFTING LITERALS ON CPS *
186 :     ****************************************************************************)
187 :     datatype info
188 :     = ZZ_STR of string
189 :     | ZZ_FLT of string
190 :     | ZZ_RCD of record_kind * value list
191 :    
192 :     exception LitInfo
193 :    
194 : monnier 422 datatype rlit = RLIT of string * word
195 :     fun toRlit s = RLIT(s, HashString.hashString s)
196 : monnier 98 fun fromRlit (RLIT(s, _)) = s
197 :     fun rlitcmp (RLIT(s1,i1), RLIT(s2,i2)) =
198 :     if i1 < i2 then LESS
199 :     else if i1 > i2 then GREATER else String.compare(s1, s2)
200 : monnier 504 structure RlitDict = RedBlackMapFn(struct type ord_key = rlit
201 : monnier 477 val compare = rlitcmp
202 :     end)
203 : monnier 98
204 :     (* lifting all literals from a CPS program *)
205 :     fun liftlits (body, root, offset) =
206 :     let (* the list of record, string, or real constants *)
207 : blume 733 val m : info IntHashTable.hash_table = IntHashTable.mkTable(32, LitInfo)
208 : monnier 98 val freevars : lvar list ref = ref []
209 :     fun addv x = (freevars := (x :: (!freevars)))
210 :    
211 :     (* check if an lvar is used by the main program *)
212 :     val refset : Intset.intset = Intset.new()
213 : monnier 477 val used : lvar -> unit = Intset.add refset
214 : monnier 98 val isUsed : lvar -> bool = Intset.mem refset
215 :    
216 :     (* memoize the information on which corresponds to what *)
217 : blume 733 fun enter (v, i) = (IntHashTable.insert m (v, i); addv v)
218 :     fun const (VAR v) = ((IntHashTable.lookup m v; true) handle _ => false)
219 : monnier 98 | const (INT _ | INT32 _ | REAL _ | STRING _) = true
220 :     | const _ = bug "unexpected case in const"
221 :    
222 : blume 733 fun cstlit (VAR v) = ((IntHashTable.lookup m v; true) handle _ => false)
223 : monnier 251 | cstlit (REAL _ | STRING _) = true
224 :     | cstlit _ = false
225 :    
226 : monnier 98 (* register a string literal *)
227 :     local val strs : string list ref = ref []
228 :     val strsN : int ref = ref 0
229 : monnier 422 val sdict = ref (RlitDict.empty)
230 : monnier 98 val srtv = mkv()
231 :     val srtval = VAR srtv
232 :     in
233 :     fun entStr s =
234 :     let val v = mkv() (** should hash to remove duplicates **)
235 :     val sd = !sdict
236 :     val rlit = toRlit s
237 :     val n =
238 : monnier 422 (case RlitDict.find(sd, rlit)
239 : monnier 98 of SOME k => k
240 :     | _ => let val _ = (strs := (s :: (!strs)))
241 :     val k = !strsN
242 :     val _ = (strsN := (k+1))
243 :     val _ = (sdict := (RlitDict.insert(sd, rlit, k)))
244 :     in k
245 :     end)
246 :     in (VAR v, fn ce => SELECT(n, srtval, v, BOGt, ce))
247 :     end
248 :    
249 :     (* old definition of entStr
250 :    
251 :     let val sd = !sdict
252 :     val rlit = toRlit s
253 :     in (case RlitDict.peek(sd, rlit)
254 :     of SOME v => (VAR v, ident)
255 :     | _ => let val v = mkv()
256 :     val _ = (enter(v, ZZ_STR s); used v)
257 :     val _ = (sdict := RlitDict.insert(sd, rlit, v))
258 :     in (VAR v, ident)
259 :     end)
260 :     end
261 :     *)
262 :    
263 :     fun appStr () =
264 :     let fun g (a::r, z) = g(r, (STRING a)::z)
265 :     | g ([], z) = z (* reverse to reflecting the correct order *)
266 :     val allStrs = !strs
267 :     in case !strs
268 :     of [] => ()
269 :     | xs => (enter(srtv, ZZ_RCD(RK_RECORD, g(xs,[]))); used srtv)
270 :     end
271 :     end (* local of processing string literals *)
272 :    
273 :     (** a special treatment of real constants *)
274 :     local val reals : string list ref = ref []
275 :     val realsN : int ref = ref 0
276 : monnier 422 val rdict = ref (RlitDict.empty)
277 : monnier 98 val rrtv = mkv()
278 :     val rrtval = VAR rrtv
279 :     in
280 :     fun entReal s =
281 :     let val v = mkv() (** should hash to remove duplicates **)
282 :     val rd = !rdict
283 :     val rlit = toRlit s
284 :     val n =
285 : monnier 422 (case RlitDict.find(rd, rlit)
286 : monnier 98 of SOME k => k
287 :     | _ => let val _ = (reals := (s :: (!reals)))
288 :     val k = !realsN
289 :     val _ = (realsN := (k+1))
290 :     val _ = (rdict := (RlitDict.insert(rd, rlit, k)))
291 :     in k
292 :     end)
293 :     in (VAR v, fn ce => SELECT(n, rrtval, v, FLTt, ce))
294 :     end
295 :    
296 :     fun appReal () =
297 :     let fun g (a::r, z) = g(r, (REAL a)::z)
298 :     | g ([], z) = z (* reverse to reflecting the correct order *)
299 :     val allReals = !reals
300 :     in case !reals
301 :     of [] => ()
302 :     | xs => (enter(rrtv, ZZ_RCD(RK_FBLOCK, g(xs,[]))); used rrtv)
303 :     end
304 :     end (* local of special treatment of real constants *)
305 :    
306 :     (* translation on the CPS values *)
307 :     fun lpsv u =
308 :     (case u
309 :     of REAL s => entReal s
310 :     | STRING s => entStr s
311 :     | VAR v => (used v; (u, ident))
312 :     | _ => (u, ident))
313 :    
314 :     fun lpvs vs =
315 :     let fun g (u, (xs, hh)) =
316 :     let val (nu, nh) = lpsv u
317 :     in (nu::xs, nh o hh)
318 :     end
319 :     in foldr g ([], ident) vs
320 :     end
321 :    
322 :     (* if all fields of a record are "constant", then we lift it *)
323 :     fun field ul =
324 : monnier 251 let fun h ((x, OFFp 0)::r, z, rsflag) =
325 :     if const x then h(r, x::z, rsflag orelse (cstlit x)) else NONE
326 :     | h ([], z, rsflag) = if rsflag then SOME(rev z) else NONE
327 : monnier 98 | h _ = bug "unexpected case in field"
328 : monnier 251 in h (ul, [], false)
329 : monnier 98 end
330 :    
331 :     (* register a constant record *)
332 :     fun record (rk, ul, v) =
333 :     (case field ul
334 :     of SOME xl => (enter(v, ZZ_RCD(rk, xl)); ident)
335 :     | NONE =>
336 :     let fun g ((u, p as OFFp 0), (r, hh)) =
337 :     let val (nu, nh) = lpsv u
338 :     in ((nu, p)::r, nh o hh)
339 :     end
340 :     | g _ = bug "unexpected non-zero OFFp in record"
341 :     val (nl, hdr) = foldr g ([], ident) ul
342 :     in fn ce => hdr(RECORD(rk, nl, v, ce))
343 :     end)
344 :    
345 :     (* register a wrapped float literal *)
346 :     fun wrapfloat (u, v, t) =
347 :     if const u then (enter(v, ZZ_RCD(RK_FBLOCK, [u])); ident)
348 :     else let val (nu, hh) = lpsv u
349 :     in (fn ce => hh(PURE(P.fwrap, [nu], v, t, ce)))
350 :     end
351 :    
352 :     (* fetch out the literal information *)
353 :     fun getInfo () =
354 :     let val _ = appReal() (* register all Reals as a record *)
355 :     val _ = appStr() (* register all Strings as a record *)
356 :     val allvars = !freevars
357 :     val exports = List.filter isUsed allvars
358 :    
359 :     val toplit =
360 :     let fun g ([], z) = LI_TOP z
361 :     | g (x::r, z) =
362 : blume 733 (case IntHashTable.lookup m x
363 : monnier 98 of ZZ_STR s => g(r, (LI_STRING s)::z)
364 :     | _ => g(r, (LI_VAR x)::z))
365 :     in g(exports, [])
366 :     end
367 :    
368 : blume 773 fun mklit (v, lit) = let
369 :     fun unREAL (CPS.REAL s) = s
370 :     | unREAL _ = bug "unREAL"
371 :     fun unINT32 (CPS.INT32 w) = w
372 :     | unINT32 _ = bug "unINT32"
373 :     in
374 :     case IntHashTable.lookup m v of
375 :     (ZZ_FLT _) => (* float is wrapped *)
376 :     bug "currently we don't expect ZZ_FLT in mklit"
377 :     (* LI_F64BLOCK([s], v, lit) *)
378 :     | (ZZ_STR s) =>
379 :     bug "currently we don't expect ZZ_STR in mklit"
380 :     (* lit --- or we could inline string *)
381 :     | (ZZ_RCD(CPS.RK_FBLOCK, vs)) =>
382 :     LI_F64BLOCK(map unREAL vs, v, lit)
383 :     | (ZZ_RCD(CPS.RK_I32BLOCK, vs)) =>
384 :     LI_I32BLOCK(map unINT32 vs, v, lit)
385 : monnier 251 | (ZZ_RCD(rk, vs)) =>
386 : blume 773 LI_BLOCK(rk2bk rk, map val2lit vs, v, lit)
387 :     end
388 : monnier 98
389 :     (** build up the literal structure *)
390 :     val lit = foldl mklit toplit allvars
391 :    
392 :     val n = length exports
393 :     val hdr =
394 :     if n = 0 then ident
395 :     else let val rv = mkv()
396 :     val rval = VAR rv
397 :     val rhdr =
398 :     fn ce => SELECT(offset, root, rv, PTRt(RPT n), ce)
399 :    
400 :     fun mkhdr (v, (i, hh)) =
401 :     let val nh =
402 : blume 733 (case IntHashTable.lookup m v
403 : monnier 98 of (ZZ_FLT _) => bug "ZZ_FLT in mkhdr"
404 :     (* (fn ce =>
405 :     (SELECT(i, rval, w, PTRt(FPT 1),
406 :     SELECT(0, VAR w, v, FLTt, ce)))) *)
407 :     | (ZZ_STR s) => bug "ZZ_STR in mkhdr"
408 :     (* (fn ce =>
409 :     SELECT(i, rval, v, BOGt, ce)) *)
410 :     | (ZZ_RCD (rk, vs)) =>
411 :     let val n = length vs
412 :     val t =
413 :     case rk
414 :     of RK_FBLOCK => PTRt(FPT n)
415 : monnier 477 | RK_VECTOR => BOGt
416 : monnier 98 | _ => PTRt(RPT n)
417 :     in fn ce => SELECT(i, rval, v, t, ce)
418 :     end)
419 :     in (i+1, hh o nh)
420 :     end
421 :     in #2 (foldr mkhdr (0, rhdr) exports)
422 :     end
423 :     in (lit, hdr)
424 :     end (* function getInfo *)
425 :    
426 :     fun lpfn (fk, f, vl, cl, e) = (fk, f, vl, cl, loop e)
427 :    
428 :     and loop ce =
429 :     (case ce
430 :     of RECORD (rk, ul, v, e) => record (rk, ul, v) (loop e)
431 :     | SELECT (i, u, v, t, e) =>
432 :     let val (nu, hh) = lpsv u
433 :     in hh(SELECT(i, nu, v, t, loop e))
434 :     end
435 :     | OFFSET _ => bug "unexpected OFFSET in loop"
436 :     | APP (u, ul) =>
437 :     let val (nu, h1) = lpsv u
438 :     val (nl, h2) = lpvs ul
439 :     in h1(h2(APP(nu, nl)))
440 :     end
441 :     | FIX (fns, e) => FIX(map lpfn fns, loop e)
442 :     | SWITCH (u, v, es) =>
443 :     let val (nu, hh) = lpsv u
444 :     in hh(SWITCH(nu, v, map loop es))
445 :     end
446 :     | BRANCH (p, ul, v, e1, e2) =>
447 :     let val (nl, hh) = lpvs ul
448 :     in hh(BRANCH(p, nl, v, loop e1, loop e2))
449 :     end
450 :     | SETTER (p, ul, e) =>
451 :     let val (nl, hh) = lpvs ul
452 :     in hh(SETTER(p, nl, loop e))
453 :     end
454 :     | LOOKER (p, ul, v, t, e) =>
455 :     let val (nl, hh) = lpvs ul
456 :     in hh(LOOKER(p, nl, v, t, loop e))
457 :     end
458 :     | ARITH (p, ul, v, t, e) =>
459 :     let val (nl, hh) = lpvs ul
460 :     in hh(ARITH(p, nl, v, t, loop e))
461 :     end
462 :     | PURE (P.fwrap, [u], v, t, e) => wrapfloat (u, v, t) (loop e)
463 :     | PURE (p, ul, v, t, e) =>
464 :     let val (nl, hh) = lpvs ul
465 :     in hh(PURE(p, nl, v, t, loop e))
466 : blume 773 end
467 : mblume 1755 | RCC (k, l, p, ul, vtl, e) =>
468 : blume 773 let val (nl, hh) = lpvs ul
469 : mblume 1755 in hh(RCC(k, l, p, nl, vtl, loop e))
470 : blume 773 end)
471 : monnier 98
472 :     val newbody = loop body
473 :     val (lit, hdr) = getInfo ()
474 :     in (hdr newbody, lit)
475 :     end
476 :    
477 :     (* the main function *)
478 :     fun litsplit (fk, f, vl as [_,x], [CNTt, t as PTRt(RPT n)], body) =
479 :     let val nt = PTRt(RPT (n+1))
480 : monnier 251 val (nbody, lit) = liftlits(body, VAR x, n)
481 : monnier 98 in ((fk, f, vl, [CNTt, nt], nbody), lit)
482 :     end
483 :     | litsplit _ = bug "unexpected CPS header in litsplit"
484 :    
485 :     end (* toplevel local *)
486 :     end (* Literals *)

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