Commit | Line | Data |
---|---|---|
7f918cf1 CE |
1 | (* c-int.sml |
2 | * 2005 Matthew Fluet (mfluet@acm.org) | |
3 | * Adapted for MLton. | |
4 | *) | |
5 | ||
6 | (* | |
7 | * The implementation of the interface that encodes C's type system | |
8 | * in ML. This implementation includes its "private" extensions. | |
9 | * | |
10 | * (C) 2001, Lucent Technologies, Bell Laboratories | |
11 | * | |
12 | * author: Matthias Blume (blume@research.bell-labs.com) | |
13 | *) | |
14 | local | |
15 | (* We play some games here with first calling C_Int simply C and then | |
16 | * renaming it because they result in saner printing behavior. *) | |
17 | structure C :> C_INT = struct | |
18 | ||
19 | exception OutOfMemory = CMemory.OutOfMemory | |
20 | ||
21 | fun bug m = raise Fail ("impossible: " ^ m) | |
22 | ||
23 | type addr = CMemory.addr | |
24 | val null = CMemory.null | |
25 | ||
26 | local | |
27 | datatype 'f objt = | |
28 | BASE of word | |
29 | | PTR of 'f | |
30 | | FPTR of addr -> 'f | |
31 | | ARR of { typ: 'f objt, n: word, esz: word, asz: word } | |
32 | ||
33 | (* Bitfield: b bits wide, l bits from left corner, r bits from right. | |
34 | * The word itself is CMemory.int_bits wide and located at address a. | |
35 | * | |
36 | * MSB LSB | |
37 | * V |<---b--->| V | |
38 | * |<---l---> ......... <---r--->| | |
39 | * |<----------wordsize--------->| | |
40 | * | |
41 | * 0.......0 1.......1 0.......0 = m | |
42 | * 1.......1 0.......0 1.......1 = im | |
43 | * | |
44 | * l + r = lr *) | |
45 | type cword = MLRep.Int.Unsigned.word | |
46 | type bf = { a: addr, l: word, r: word, lr: word, m: cword, im: cword } | |
47 | ||
48 | (* | |
49 | fun pair_type_addr (t: 'f objt) (a: addr) = (a, t) | |
50 | *) | |
51 | fun strip_type (a: addr, _: 'f objt) = a | |
52 | fun p_strip_type (a: addr, _: 'f objt) = a | |
53 | fun strip_fun (a: addr, _: 'f) = a | |
54 | fun addr_type_id (x: addr * 'f objt) = x | |
55 | fun addr_id (x: addr) = x | |
56 | ||
57 | infix -- ++ | |
58 | val op -- = CMemory.-- | |
59 | val op ++ = CMemory.++ | |
60 | ||
61 | infix << >> ~>> && || ^^ | |
62 | val op << = MLRep.Int.Unsigned.<< | |
63 | val op >> = MLRep.Int.Unsigned.>> | |
64 | val op ~>> = MLRep.Int.Unsigned.~>> | |
65 | val op && = MLRep.Int.Unsigned.andb | |
66 | val op || = MLRep.Int.Unsigned.orb | |
67 | (* | |
68 | val op ^^ = MLRep.Int.Unsigned.xorb | |
69 | *) | |
70 | val ~~ = MLRep.Int.Unsigned.notb | |
71 | in | |
72 | ||
73 | type ('t, 'c) obj = addr * 't objt (* RTTI for stored value *) | |
74 | type ('t, 'c) obj' = addr | |
75 | type ro = unit | |
76 | type rw = unit | |
77 | ||
78 | type 'o ptr = addr * 'o objt (* RTTI for target value *) | |
79 | type 'o ptr' = addr | |
80 | ||
81 | type ('t, 'n) arr = 't | |
82 | ||
83 | type 'f fptr = addr * 'f | |
84 | type 'f fptr' = addr | |
85 | ||
86 | type void = unit | |
87 | type voidptr = void ptr' | |
88 | ||
89 | type 'tag su = unit | |
90 | ||
91 | type 'tag enum = MLRep.Int.Signed.int | |
92 | ||
93 | type schar = MLRep.Char.Signed.int | |
94 | type uchar = MLRep.Char.Unsigned.word | |
95 | type sshort = MLRep.Short.Signed.int | |
96 | type ushort = MLRep.Short.Unsigned.word | |
97 | type sint = MLRep.Int.Signed.int | |
98 | type uint = MLRep.Int.Unsigned.word | |
99 | type slong = MLRep.Long.Signed.int | |
100 | type ulong = MLRep.Long.Unsigned.word | |
101 | type slonglong = MLRep.LongLong.Signed.int | |
102 | type ulonglong = MLRep.LongLong.Unsigned.word | |
103 | type float = MLRep.Float.real | |
104 | type double = MLRep.Double.real | |
105 | ||
106 | type 'c schar_obj = ( schar, 'c) obj | |
107 | type 'c uchar_obj = ( uchar, 'c) obj | |
108 | type 'c sshort_obj = ( sshort, 'c) obj | |
109 | type 'c ushort_obj = ( ushort, 'c) obj | |
110 | type 'c sint_obj = ( sint, 'c) obj | |
111 | type 'c uint_obj = ( uint, 'c) obj | |
112 | type 'c slong_obj = ( slong, 'c) obj | |
113 | type 'c ulong_obj = ( ulong, 'c) obj | |
114 | type 'c slonglong_obj = (slonglong, 'c) obj | |
115 | type 'c ulonglong_obj = (ulonglong, 'c) obj | |
116 | type 'c float_obj = ( float, 'c) obj | |
117 | type 'c double_obj = ( double, 'c) obj | |
118 | type 'c voidptr_obj = ( voidptr, 'c) obj | |
119 | type ('e, 'c) enum_obj = ( 'e enum, 'c) obj | |
120 | type ('f, 'c) fptr_obj = ( 'f fptr, 'c) obj | |
121 | type ('s, 'c) su_obj = ( 's su, 'c) obj | |
122 | ||
123 | type 'c schar_obj' = ( schar, 'c) obj' | |
124 | type 'c uchar_obj' = ( uchar, 'c) obj' | |
125 | type 'c sshort_obj' = ( sshort, 'c) obj' | |
126 | type 'c ushort_obj' = ( ushort, 'c) obj' | |
127 | type 'c sint_obj' = ( sint, 'c) obj' | |
128 | type 'c uint_obj' = ( uint, 'c) obj' | |
129 | type 'c slong_obj' = ( slong, 'c) obj' | |
130 | type 'c ulong_obj' = ( ulong, 'c) obj' | |
131 | type 'c slonglong_obj' = (slonglong, 'c) obj' | |
132 | type 'c ulonglong_obj' = (ulonglong, 'c) obj' | |
133 | type 'c float_obj' = ( float, 'c) obj' | |
134 | type 'c double_obj' = ( double, 'c) obj' | |
135 | type 'c voidptr_obj' = ( voidptr, 'c) obj' | |
136 | type ('e, 'c) enum_obj' = ( 'e enum, 'c) obj' | |
137 | type ('f, 'c) fptr_obj' = ( 'f fptr, 'c) obj' | |
138 | type ('s, 'c) su_obj' = ( 's su, 'c) obj' | |
139 | ||
140 | type 'c ubf = bf | |
141 | type 'c sbf = bf | |
142 | ||
143 | structure W = struct | |
144 | type ('from, 'to) witness = 'from -> 'to | |
145 | ||
146 | fun convert (w : 's -> 't) (x : 's objt) : 't objt = | |
147 | case x of | |
148 | BASE b => BASE b | |
149 | | PTR x => PTR (w x) | |
150 | | FPTR f => FPTR (fn a => w (f a)) | |
151 | | ARR {typ, n, esz, asz} => | |
152 | ARR {typ = convert w typ, | |
153 | n = n, esz = esz, asz = asz} | |
154 | ||
155 | val trivial : ('t, 't) witness = | |
156 | fn x => x | |
157 | ||
158 | val pointer : ('from, 'to) witness -> ('from ptr, 'to ptr) witness = | |
159 | fn w => fn (a, t) => (a, convert w t) | |
160 | val object : ('from, 'to) witness -> (('from, 'c) obj, ('to, 'c) obj) witness = | |
161 | fn w => fn (a, t) => (a, convert w t) | |
162 | val arr : ('from, 'to) witness -> (('from, 'n) arr, ('to, 'n) arr) witness = | |
163 | fn w => w | |
164 | val ro : ('from, 'to) witness -> (('from, 'fc) obj, ('to, ro) obj) witness = | |
165 | fn w => fn (a, t) => (a, convert w t) | |
166 | val rw : ('from, 'to) witness -> (('from, 'fc) obj, ('to, 'tc) obj) witness = | |
167 | fn w => fn (a, t) => (a, convert w t) | |
168 | end | |
169 | ||
170 | val convert : (('st, 'sc) obj, ('tt, 'tc) obj) W.witness -> | |
171 | ('st, 'sc) obj -> ('tt, 'tc) obj = | |
172 | fn w => fn x => w x | |
173 | val convert' : (('st, 'sc) obj, ('tt, 'tc) obj) W.witness -> | |
174 | ('st, 'sc) obj' -> ('tt, 'tc) obj' = | |
175 | fn _ => fn x => x | |
176 | ||
177 | (* | |
178 | * A family of types and corresponding values representing natural numbers. | |
179 | * (An encoding in SML without using dependent types.) | |
180 | * This is the full implementation including an unsafe extension | |
181 | * ("fromInt"). *) | |
182 | ||
183 | structure Dim = struct | |
184 | ||
185 | type ('a, 'z) dim0 = int | |
186 | fun toInt d = d | |
187 | fun fromInt d = d | |
188 | ||
189 | type dec = unit | |
190 | type 'a dg0 = unit | |
191 | type 'a dg1 = unit | |
192 | type 'a dg2 = unit | |
193 | type 'a dg3 = unit | |
194 | type 'a dg4 = unit | |
195 | type 'a dg5 = unit | |
196 | type 'a dg6 = unit | |
197 | type 'a dg7 = unit | |
198 | type 'a dg8 = unit | |
199 | type 'a dg9 = unit | |
200 | ||
201 | type zero = unit | |
202 | type nonzero = unit | |
203 | ||
204 | type 'a dim = ('a, nonzero) dim0 | |
205 | ||
206 | local | |
207 | fun dg n d = 10 * d + n | |
208 | in | |
209 | val dec' = 0 | |
210 | val (dg0', dg1', dg2', dg3', dg4', dg5', dg6', dg7', dg8', dg9') = | |
211 | (dg 0, dg 1, dg 2, dg 3, dg 4, dg 5, dg 6, dg 7, dg 8, dg 9) | |
212 | ||
213 | fun dec k = k dec' | |
214 | fun dg0 d k = k (dg0' d) | |
215 | fun dg1 d k = k (dg1' d) | |
216 | fun dg2 d k = k (dg2' d) | |
217 | fun dg3 d k = k (dg3' d) | |
218 | fun dg4 d k = k (dg4' d) | |
219 | fun dg5 d k = k (dg5' d) | |
220 | fun dg6 d k = k (dg6' d) | |
221 | fun dg7 d k = k (dg7' d) | |
222 | fun dg8 d k = k (dg8' d) | |
223 | fun dg9 d k = k (dg9' d) | |
224 | fun dim d = d | |
225 | end | |
226 | end | |
227 | ||
228 | structure S = struct | |
229 | ||
230 | type 't size = word | |
231 | ||
232 | fun toWord (s: 't size) = s | |
233 | ||
234 | val schar = CMemory.char_size | |
235 | val uchar = CMemory.char_size | |
236 | val sint = CMemory.int_size | |
237 | val uint = CMemory.int_size | |
238 | val sshort = CMemory.short_size | |
239 | val ushort = CMemory.short_size | |
240 | val slong = CMemory.long_size | |
241 | val ulong = CMemory.long_size | |
242 | val slonglong = CMemory.longlong_size | |
243 | val ulonglong = CMemory.longlong_size | |
244 | val float = CMemory.float_size | |
245 | val double = CMemory.double_size | |
246 | ||
247 | val voidptr = CMemory.addr_size | |
248 | val ptr = CMemory.addr_size | |
249 | val fptr = CMemory.addr_size | |
250 | val enum = CMemory.int_size | |
251 | end | |
252 | ||
253 | structure T = struct | |
254 | ||
255 | type 't typ = 't objt | |
256 | ||
257 | val typeof : ('t, 'c) obj -> 't typ = | |
258 | fn (_, t) => t | |
259 | ||
260 | val sizeof : 't typ -> 't S.size = | |
261 | fn BASE b => b | |
262 | | PTR _ => S.ptr | |
263 | | FPTR _ => S.fptr | |
264 | | ARR a => #asz a | |
265 | ||
266 | (* use private (and unsafe) extension to Dim module here... *) | |
267 | val dim : ('t, 'n) arr typ -> 'n Dim.dim = | |
268 | fn ARR { n, ... } => Dim.fromInt (Word.toInt n) | |
269 | | _ => bug "T.dim (non-array type)" | |
270 | ||
271 | val pointer : 't typ -> ('t, rw) obj ptr typ = | |
272 | fn t => PTR (null, PTR (null, t)) | |
273 | val target : ('t, 'c) obj ptr typ -> 't typ = | |
274 | fn PTR (_, PTR (_, t)) => t | |
275 | | _ => bug "T.target (non-pointer type)" | |
276 | val arr : 't typ * 'n Dim.dim -> ('t, 'n) arr typ = | |
277 | fn (t, d) => | |
278 | let | |
279 | val n = Word.fromInt (Dim.toInt d) | |
280 | val s = sizeof t | |
281 | in | |
282 | ARR { typ = t, n = n, esz = s, asz = n * s } | |
283 | end | |
284 | val elem : ('t, 'n) arr typ -> 't typ = | |
285 | fn ARR a => #typ a | |
286 | | _ => bug "T.elem (non-array type)" | |
287 | val ro : ('t, 'c) obj ptr typ -> ('t, ro) obj ptr typ = | |
288 | fn t => t | |
289 | ||
290 | val schar : schar typ = BASE S.schar | |
291 | val uchar : uchar typ = BASE S.uchar | |
292 | val sshort : sshort typ = BASE S.sshort | |
293 | val ushort : ushort typ = BASE S.ushort | |
294 | val sint : sint typ = BASE S.sint | |
295 | val uint : uint typ = BASE S.uint | |
296 | val slong : slong typ = BASE S.slong | |
297 | val ulong : ulong typ = BASE S.ulong | |
298 | val slonglong : slonglong typ = BASE S.slonglong | |
299 | val ulonglong : ulonglong typ = BASE S.ulonglong | |
300 | val float : float typ = BASE S.float | |
301 | val double : double typ = BASE S.double | |
302 | ||
303 | val voidptr : voidptr typ = BASE S.voidptr | |
304 | ||
305 | val enum : 'tag enum typ = BASE S.sint | |
306 | end | |
307 | ||
308 | structure Light = struct | |
309 | val obj : ('t, 'c) obj -> ('t, 'c) obj' = | |
310 | fn (a, _) => a | |
311 | val ptr : 'o ptr -> 'o ptr' = | |
312 | fn (a, _) => a | |
313 | val fptr : 'f fptr -> 'f fptr' = | |
314 | fn (a, _) => a | |
315 | end | |
316 | ||
317 | structure Heavy = struct | |
318 | val obj : 't T.typ -> ('t, 'c) obj' -> ('t, 'c) obj = | |
319 | fn t => fn a => (a, t) | |
320 | val ptr : 'o ptr T.typ -> 'o ptr' -> 'o ptr = | |
321 | fn PTR (_, t) => (fn a => (a, t)) | |
322 | | _ => bug "Heavy.ptr (non-object-pointer-type)" | |
323 | val fptr : 'f fptr T.typ -> 'f fptr' -> 'f fptr = | |
324 | fn (FPTR mkf) => (fn a => (a, #2 (mkf a))) | |
325 | | _ => bug "Heavy.fptr (non-function-pointer-type)" | |
326 | end | |
327 | ||
328 | val sizeof : ('t, 'c) obj -> 't S.size = | |
329 | fn (_, t) => T.sizeof t | |
330 | ||
331 | structure Cvt = struct | |
332 | (* going between abstract and concrete; these are all identities *) | |
333 | fun c_schar (c: schar) = c | |
334 | fun c_uchar (c: uchar) = c | |
335 | fun c_sshort (s: sshort) = s | |
336 | fun c_ushort (s: ushort) = s | |
337 | fun c_sint (i: sint) = i | |
338 | fun c_uint (i: uint) = i | |
339 | fun c_slong (l: slong) = l | |
340 | fun c_ulong (l: ulong) = l | |
341 | fun c_slonglong (ll: slonglong) = ll | |
342 | fun c_ulonglong (ll: ulonglong) = ll | |
343 | fun c_float (f: float) = f | |
344 | fun c_double (d: double) = d | |
345 | fun i2c_enum (e: 'e enum) = e | |
346 | ||
347 | val ml_schar = c_schar | |
348 | val ml_uchar = c_uchar | |
349 | val ml_sshort = c_sshort | |
350 | val ml_ushort = c_ushort | |
351 | val ml_sint = c_sint | |
352 | val ml_uint = c_uint | |
353 | val ml_slong = c_slong | |
354 | val ml_ulong = c_ulong | |
355 | val ml_slonglong = c_slonglong | |
356 | val ml_ulonglong = c_ulonglong | |
357 | val ml_float = c_float | |
358 | val ml_double = c_double | |
359 | val c2i_enum = i2c_enum | |
360 | end | |
361 | ||
362 | structure Get = struct | |
363 | val uchar' = CMemory.load_uchar | |
364 | val schar' = CMemory.load_schar | |
365 | val uint' = CMemory.load_uint | |
366 | val sint' = CMemory.load_sint | |
367 | val ushort' = CMemory.load_ushort | |
368 | val sshort' = CMemory.load_sshort | |
369 | val ulong' = CMemory.load_ulong | |
370 | val slong' = CMemory.load_slong | |
371 | val ulonglong' = CMemory.load_ulonglong | |
372 | val slonglong' = CMemory.load_slonglong | |
373 | val float' = CMemory.load_float | |
374 | val double' = CMemory.load_double | |
375 | val enum' = CMemory.load_sint | |
376 | ||
377 | val ptr' = CMemory.load_addr | |
378 | val fptr' = CMemory.load_addr | |
379 | val voidptr' = CMemory.load_addr | |
380 | ||
381 | val uchar = uchar' o strip_type | |
382 | val schar = schar' o strip_type | |
383 | val uint = uint' o strip_type | |
384 | val sint = sint' o strip_type | |
385 | val ushort = ushort' o strip_type | |
386 | val sshort = sshort' o strip_type | |
387 | val ulong = ulong' o strip_type | |
388 | val slong = slong' o strip_type | |
389 | val ulonglong = ulonglong' o strip_type | |
390 | val slonglong = slonglong' o strip_type | |
391 | val float = float' o strip_type | |
392 | val double = double' o strip_type | |
393 | val voidptr = voidptr' o strip_type | |
394 | val enum = enum' o strip_type | |
395 | ||
396 | val ptr : ('o ptr, 'c) obj -> 'o ptr = | |
397 | fn (a, PTR (_, t)) => (ptr' a, t) | |
398 | | _ => bug "Get.ptr (non-pointer)" | |
399 | val fptr : ('f, 'c) fptr_obj -> 'f fptr = | |
400 | fn (a, FPTR mkf) => let val fa = fptr' a in (fa, #2 (mkf fa)) end | |
401 | | _ => bug "Get.fptr (non-function-pointer)" | |
402 | ||
403 | local | |
404 | val u2s = MLRep.Int.Signed.fromLarge o MLRep.Int.Unsigned.toLargeIntX | |
405 | in | |
406 | fun ubf ({ a, l, r=_, lr, m=_, im=_ } : bf) = | |
407 | (CMemory.load_uint a << l) >> lr | |
408 | fun sbf ({ a, l, r=_, lr, m=_, im=_ } : bf) = | |
409 | u2s ((CMemory.load_uint a << l) ~>> lr) | |
410 | end | |
411 | end | |
412 | ||
413 | structure Set = struct | |
414 | val uchar' = CMemory.store_uchar | |
415 | val schar' = CMemory.store_schar | |
416 | val uint' = CMemory.store_uint | |
417 | val sint' = CMemory.store_sint | |
418 | val ushort' = CMemory.store_ushort | |
419 | val sshort' = CMemory.store_sshort | |
420 | val ulong' = CMemory.store_ulong | |
421 | val slong' = CMemory.store_slong | |
422 | val ulonglong' = CMemory.store_ulonglong | |
423 | val slonglong' = CMemory.store_slonglong | |
424 | val float' = CMemory.store_float | |
425 | val double' = CMemory.store_double | |
426 | val enum' = CMemory.store_sint | |
427 | ||
428 | val ptr' = CMemory.store_addr | |
429 | val fptr' = CMemory.store_addr | |
430 | val voidptr' = CMemory.store_addr | |
431 | ||
432 | val ptr_voidptr' = CMemory.store_addr | |
433 | ||
434 | local | |
435 | infix $ | |
436 | fun (f $ g) (x, y) = f (g x, y) | |
437 | in | |
438 | val uchar = uchar' $ strip_type | |
439 | val schar = schar' $ strip_type | |
440 | val uint = uint' $ strip_type | |
441 | val sint = sint' $ strip_type | |
442 | val ushort = ushort' $ strip_type | |
443 | val sshort = sshort' $ strip_type | |
444 | val ulong = ulong' $ strip_type | |
445 | val slong = slong' $ strip_type | |
446 | val ulonglong = ulonglong' $ strip_type | |
447 | val slonglong = slonglong' $ strip_type | |
448 | val float = float' $ strip_type | |
449 | val double = double' $ strip_type | |
450 | val enum = enum' $ strip_type | |
451 | ||
452 | val ptr : ('o ptr, rw) obj * 'o ptr -> unit = | |
453 | fn (x, p) => ptr' (p_strip_type x, p_strip_type p) | |
454 | val voidptr = voidptr' $ strip_type | |
455 | val fptr : ('f, rw) fptr_obj * 'f fptr -> unit = | |
456 | fn (x, f) => fptr' (p_strip_type x, strip_fun f) | |
457 | ||
458 | val ptr_voidptr : ('o ptr, rw) obj * voidptr -> unit = | |
459 | fn (x, p) => ptr_voidptr' (p_strip_type x, p) | |
460 | end | |
461 | ||
462 | fun ubf ({ a, l=_, r, lr=_, m, im }, x) = | |
463 | CMemory.store_uint (a, (CMemory.load_uint a && im) || | |
464 | ((x << r) && m)) | |
465 | ||
466 | local | |
467 | val s2u = MLRep.Int.Unsigned.fromLargeInt o MLRep.Int.Signed.toLarge | |
468 | in | |
469 | fun sbf (f, x) = ubf (f, s2u x) | |
470 | end | |
471 | end | |
472 | ||
473 | fun copy' bytes { from, to } = | |
474 | CMemory.bcopy { from = from, to = to, bytes = bytes } | |
475 | fun copy { from = (from, t), to = (to, _: 'f objt) } = | |
476 | copy' (T.sizeof t) { from = from, to = to } | |
477 | ||
478 | val ro = addr_type_id | |
479 | val rw = addr_type_id | |
480 | ||
481 | val ro' = addr_id | |
482 | val rw' = addr_id | |
483 | ||
484 | structure Ptr = struct | |
485 | val |&| : ('t, 'c) obj -> ('t, 'c) obj ptr = | |
486 | fn (a, t) => (a, PTR (null, t)) | |
487 | val |*| : ('t, 'c) obj ptr -> ('t, 'c) obj = | |
488 | fn (a, PTR (_, t)) => (a, t) | |
489 | | _ => bug "Ptr.* (non-pointer)" | |
490 | ||
491 | val |&! : ('t, 'c) obj' -> ('t, 'c) obj ptr' = | |
492 | addr_id | |
493 | val |*! : ('t, 'c) obj ptr' -> ('t, 'c) obj' = | |
494 | addr_id | |
495 | ||
496 | fun compare (p, p') = CMemory.compare (p_strip_type p, p_strip_type p') | |
497 | ||
498 | val compare' = CMemory.compare | |
499 | ||
500 | val inject' = addr_id | |
501 | val cast' = addr_id | |
502 | ||
503 | val inject : 'o ptr -> voidptr = p_strip_type | |
504 | val cast : 'o ptr T.typ -> voidptr -> 'o ptr = | |
505 | fn PTR (_, t) => (fn p => (p, t)) | |
506 | | _ => bug "Ptr.cast (non-pointer-type)" | |
507 | ||
508 | val vnull : voidptr = CMemory.null | |
509 | val null : 'o ptr T.typ -> 'o ptr = | |
510 | fn t => cast t vnull | |
511 | val null' : 'o ptr' = vnull | |
512 | ||
513 | val fnull' : 'f ptr' = CMemory.null | |
514 | val fnull : 'f fptr T.typ -> 'f fptr = | |
515 | fn t => Heavy.fptr t fnull' | |
516 | ||
517 | val isVNull : voidptr -> bool = CMemory.isNull | |
518 | val isNull : 'o ptr -> bool = | |
519 | fn p => isVNull (inject p) | |
520 | val isNull' = CMemory.isNull | |
521 | ||
522 | val isFNull : 'f fptr -> bool = | |
523 | fn (a,_) => CMemory.isNull a | |
524 | val isFNull' = CMemory.isNull | |
525 | ||
526 | fun |+! s (p, i) = p ++ (Word.toInt s * i) | |
527 | fun |-! s (p, p') = (p -- p') div Word.toInt s | |
528 | ||
529 | val |+| : ('t, 'c) obj ptr * int -> ('t, 'c) obj ptr = | |
530 | fn ((p, t as PTR (_, t')), i) => (|+! (T.sizeof t') (p, i), t) | |
531 | | _ => bug "Ptr.|+| (non-pointer-type)" | |
532 | val |-| : ('t, 'c) obj ptr * ('t, 'c) obj ptr -> int = | |
533 | fn ((p, PTR (_, t')), (p', _)) => |-! (T.sizeof t') (p, p') | |
534 | | _ => bug "Ptr.|-| (non-pointer-type" | |
535 | ||
536 | val sub : ('t, 'c) obj ptr * int -> ('t, 'c) obj = | |
537 | fn (p, i) => |*| (|+| (p, i)) | |
538 | ||
539 | fun sub' t (p, i) = |*! (|+! t (p, i)) | |
540 | ||
541 | val convert : (('st, 'sc) obj ptr, ('tt, 'tc) obj ptr) W.witness -> | |
542 | ('st, 'sc) obj ptr -> ('tt, 'tc) obj ptr = | |
543 | fn w => fn x => w x | |
544 | val convert' : (('st, 'sc) obj ptr, ('tt, 'tc) obj ptr) W.witness -> | |
545 | ('st, 'sc) obj ptr' -> ('tt, 'tc) obj ptr' = | |
546 | fn _ => fn x => x | |
547 | ||
548 | val ro : ('t, 'c) obj ptr -> ('t, ro) obj ptr = | |
549 | fn x => convert (W.pointer (W.ro W.trivial)) x | |
550 | val rw : ('t, 'sc) obj ptr -> ('t, 'tc) obj ptr = | |
551 | fn x => convert (W.pointer (W.rw W.trivial)) x | |
552 | ||
553 | val ro' : ('t, 'c) obj ptr' -> ('t, ro) obj ptr' = | |
554 | addr_id | |
555 | val rw' : ('t, 'sc) obj ptr' -> ('t, 'tc) obj ptr' = | |
556 | addr_id | |
557 | end | |
558 | ||
559 | structure Arr = struct | |
560 | local | |
561 | fun asub (a, i, n, esz) = | |
562 | (* take advantage of wrap-around to avoid the >= 0 test... *) | |
563 | if Word.fromInt i < n then a ++ (Word.toIntX esz * i) | |
564 | else raise General.Subscript | |
565 | in | |
566 | val sub : (('t, 'n) arr, 'c) obj * int -> ('t, 'c) obj = | |
567 | fn ((a, ARR { typ, n, esz, ... }), i) => (asub (a, i, n, esz), typ) | |
568 | | _ => bug "Arr.sub (non-array)" | |
569 | val sub' : 't S.size * 'n Dim.dim -> | |
570 | (('t, 'n) arr, 'c) obj' * int -> ('t, 'c) obj' = | |
571 | fn (s, d) => fn (a, i) => asub (a, i, Word.fromInt (Dim.toInt d), s) | |
572 | end | |
573 | ||
574 | val decay : (('t, 'n) arr, 'c) obj -> ('t, 'c) obj ptr = | |
575 | fn (a, ARR { typ, ... }) => (a, PTR (null, typ)) | |
576 | | _ => bug "Arr.decay (non-array)" | |
577 | ||
578 | val decay' = addr_id | |
579 | ||
580 | val reconstruct : ('t, 'c) obj ptr * 'n Dim.dim -> (('t, 'n) arr, 'c) obj = | |
581 | fn ((a, PTR (_, t)), d) => (a, T.arr (t, d)) | |
582 | | _ => bug "Arr.reconstruct (non-pointer)" | |
583 | ||
584 | fun reconstruct' (a: addr, _: 'n Dim.dim) = a | |
585 | ||
586 | fun dim (_: addr, t) = T.dim t | |
587 | end | |
588 | ||
589 | fun new' s = CMemory.alloc s | |
590 | val new : 't T.typ -> ('t, 'c) obj = | |
591 | fn t => (new' (T.sizeof t), t) | |
592 | ||
593 | val discard' = CMemory.free | |
594 | val discard : ('t, 'c) obj -> unit = | |
595 | fn x => discard' (p_strip_type x) | |
596 | ||
597 | fun alloc' s i = CMemory.alloc (s * i) | |
598 | val alloc : 't T.typ -> word -> ('t, 'c) obj ptr = | |
599 | fn t => fn i => (alloc' (T.sizeof t) i, PTR (null, t)) | |
600 | ||
601 | val free' = CMemory.free | |
602 | val free : 'o ptr -> unit = | |
603 | fn x => free' (p_strip_type x) | |
604 | ||
605 | val call : ('a -> 'b) fptr * 'a -> 'b = | |
606 | fn ((_, f), x) => f x | |
607 | ||
608 | val call' : ('a -> 'b) fptr T.typ -> ('a -> 'b) fptr' * 'a -> 'b = | |
609 | fn (FPTR mkf) => (fn (a, x) => (#2 (mkf a)) x) | |
610 | | _ => bug "call' (non-function-pointer-type)" | |
611 | ||
612 | structure U = struct | |
613 | fun fcast (f : 'fa fptr') : 'fb fptr' = f | |
614 | fun p2i (a : 'o ptr') : ulong = CMemory.p2i a | |
615 | fun i2p (a : ulong) : 'o ptr' = CMemory.i2p a | |
616 | end | |
617 | ||
618 | (* ------------- internal stuff ------------- *) | |
619 | ||
620 | fun mk_obj' (a : addr) = a | |
621 | val mk_voidptr : addr -> voidptr = fn a => a | |
622 | ||
623 | local | |
624 | fun mk_field (t: 'f objt, i, (a, _)) = (a ++ i, t) | |
625 | in | |
626 | val mk_rw_field : 'm T.typ * int * ('s, 'c) su_obj -> ('m, 'c) obj = mk_field | |
627 | val mk_ro_field : 'm T.typ * int * ('s, 'c) su_obj -> ('m, ro) obj = mk_field | |
628 | fun mk_field' (i, a) = a ++ i | |
629 | end | |
630 | ||
631 | local | |
632 | fun mk_bf' (offset, bits, shift) a = let | |
633 | val a = a ++ offset | |
634 | val l = shift | |
635 | val lr = CMemory.int_bits - bits | |
636 | val r = lr - l | |
637 | val m = (~~0w0 << lr) >> l | |
638 | val im = ~~ m | |
639 | in | |
640 | { a = a, l = l, r = r, lr = lr, m = m, im = im } : bf | |
641 | end | |
642 | fun mk_bf acc (a, _) = mk_bf' acc a | |
643 | in | |
644 | val mk_rw_ubf = mk_bf | |
645 | val mk_ro_ubf = mk_bf | |
646 | val mk_rw_ubf' = mk_bf' | |
647 | val mk_ro_ubf' = mk_bf' | |
648 | ||
649 | val mk_rw_sbf = mk_bf | |
650 | val mk_ro_sbf = mk_bf | |
651 | val mk_rw_sbf' = mk_bf' | |
652 | val mk_ro_sbf' = mk_bf' | |
653 | end | |
654 | ||
655 | val mk_su_size : word -> 's S.size = | |
656 | fn sz => sz | |
657 | val mk_su_typ : 's su S.size -> 's su T.typ = | |
658 | fn sz => BASE sz | |
659 | val mk_fptr : (addr -> 'a -> 'b) * addr -> ('a -> 'b) fptr = | |
660 | fn (mkf, a) => (a, mkf a) | |
661 | val mk_fptr_typ : (addr -> 'a -> 'b) -> ('a -> 'b) fptr T.typ = | |
662 | fn mkf => FPTR (fn a => (null, mkf a)) | |
663 | ||
664 | val reveal : voidptr -> addr = addr_id | |
665 | val freveal : 'f fptr' -> addr = addr_id | |
666 | ||
667 | val vcast : addr -> voidptr = addr_id | |
668 | val pcast : addr -> 'o ptr' = addr_id | |
669 | val fcast : addr -> 'f fptr' = addr_id | |
670 | ||
671 | fun unsafe_sub esz (a, i) = a ++ esz * i | |
672 | end (* local *) | |
673 | end | |
674 | in | |
675 | structure C_Int = C | |
676 | end |