1 /* pvm.h - PVM values  */
2 
3 /* Copyright (C) 2019, 2020, 2021 Jose E. Marchesi */
4 
5 /* This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifndef PVM_VAL_H
20 #define PVM_VAL_H
21 
22 #include <config.h>
23 #include <stdint.h>
24 
25 /* The least-significative bits of pvm_val are reserved for the tag,
26    which specifies the type of the value.  */
27 
28 #define PVM_VAL_TAG(V) ((V) & 0x7)
29 
30 #define PVM_VAL_TAG_INT   0x0
31 #define PVM_VAL_TAG_UINT  0x1
32 #define PVM_VAL_TAG_LONG  0x2
33 #define PVM_VAL_TAG_ULONG 0x3
34 #define PVM_VAL_TAG_BIG   0x4
35 #define PVM_VAL_TAG_UBIG  0x5
36 #define PVM_VAL_TAG_BOX   0x6
37 /* Note that there is no tag 0x7.  It is used to implement PVM_NULL
38    below.  */
39 /* Note also that the tags below are stored in the box, not in
40    PVM_VAL_TAG.  See below in this file.  */
41 #define PVM_VAL_TAG_STR 0x8
42 #define PVM_VAL_TAG_OFF 0x9
43 #define PVM_VAL_TAG_ARR 0xa
44 #define PVM_VAL_TAG_SCT 0xb
45 #define PVM_VAL_TAG_TYP 0xc
46 #define PVM_VAL_TAG_CLS 0xd
47 
48 #define PVM_VAL_BOXED_P(V) (PVM_VAL_TAG((V)) > 1)
49 
50 /* Integers up to 32-bit are unboxed and encoded the following way:
51 
52               val                   bits  tag
53               ---                   ----  ---
54       vvvv vvvv vvvv vvvv xxxx xxxx bbbb bttt
55 
56    BITS+1 is the size of the integral value in bits, from 0 to 31.
57 
58    VAL is the value of the integer, sign- or zero-extended to 32 bits.
59    Bits marked with `x' are unused and should be always 0.  */
60 
61 #define PVM_VAL_INT_SIZE(V) (((int) (((V) >> 3) & 0x1f)) + 1)
62 #define PVM_VAL_INT(V) (((int32_t) ((V) >> 32))                \
63                         << (32 - PVM_VAL_INT_SIZE ((V)))       \
64                         >> (32 - PVM_VAL_INT_SIZE ((V))))
65 #define PVM_MAKE_INT(V,S)                       \
66   (((((int64_t) (V)) & 0xffffffff) << 32)       \
67    | ((((S) - 1) & 0x1f) << 3)                  \
68    | PVM_VAL_TAG_INT)
69 
70 #define PVM_VAL_UINT_SIZE(V) (((int) (((V) >> 3) & 0x1f)) + 1)
71 #define PVM_VAL_UINT(V) (((uint32_t) ((V) >> 32)) \
72                          & ((uint32_t) (~( ((~0ul) << ((PVM_VAL_UINT_SIZE ((V)))-1)) << 1 ))))
73 #define PVM_MAKE_UINT(V,S)                      \
74   (((((uint64_t) (V)) & 0xffffffff) << 32)      \
75    | ((((S) - 1) & 0x1f) << 3)                  \
76    | PVM_VAL_TAG_UINT)
77 
78 #define PVM_MAX_UINT(size) ((1U << (size)) - 1)
79 
80 /* Long integers, wider than 32-bit and up to 64-bit, are boxed.  A
81    pointer
82                                              tag
83                                              ---
84          pppp pppp pppp pppp pppp pppp pppp pttt
85 
86    points to a pair of 64-bit words:
87 
88                            val
89                            ---
90    [0]   vvvv vvvv vvvv vvvv vvvv vvvv vvvv vvvv
91                                            bits
92                                            ----
93    [1]   xxxx xxxx xxxx xxxx xxxx xxxx xxbb bbbb
94 
95    BITS+1 is the size of the integral value in bits, from 0 to 63.
96 
97    VAL is the value of the integer, sign- or zero-extended to 64 bits.
98    Bits marked with `x' are unused.  */
99 
100 #define _PVM_VAL_LONG_ULONG_VAL(V) (((int64_t *) ((((uintptr_t) V) & ~0x7)))[0])
101 #define _PVM_VAL_LONG_ULONG_SIZE(V) ((int) (((int64_t *) ((((uintptr_t) V) & ~0x7)))[1]) + 1)
102 
103 #define PVM_MAKE_LONG_ULONG(V,S,T)                       \
104   ({ uint64_t *ll = pvm_alloc (sizeof (uint64_t) * 2);   \
105     ll[0] = (V);                                         \
106     ll[1] = ((S) - 1) & 0x3f;                            \
107     ((uint64_t) (uintptr_t) ll) | (T); })
108 
109 #define PVM_VAL_LONG_SIZE(V) (_PVM_VAL_LONG_ULONG_SIZE (V))
110 #define PVM_VAL_LONG(V) (_PVM_VAL_LONG_ULONG_VAL ((V))           \
111                          << (64 - PVM_VAL_LONG_SIZE ((V)))      \
112                          >> (64 - PVM_VAL_LONG_SIZE ((V))))
113 #define PVM_MAKE_LONG(V,S)                              \
114   (PVM_MAKE_LONG_ULONG ((V),(S),PVM_VAL_TAG_LONG))
115 
116 #define PVM_VAL_ULONG_SIZE(V) (_PVM_VAL_LONG_ULONG_SIZE (V))
117 #define PVM_VAL_ULONG(V) (_PVM_VAL_LONG_ULONG_VAL ((V))                 \
118                           & ((uint64_t) (~( ((~0ull) << ((PVM_VAL_ULONG_SIZE ((V)))-1)) << 1 ))))
119 #define PVM_MAKE_ULONG(V,S)                             \
120   (PVM_MAKE_LONG_ULONG ((V),(S),PVM_VAL_TAG_ULONG))
121 
122 #define PVM_MAX_ULONG(size) ((1LU << (size)) - 1)
123 
124 /* Big integers, wider than 64-bit, are boxed.  They are implemented
125    using the GNU mp library.  */
126 
127 /* XXX: implement big integers.  */
128 
129 /* A pointer to a boxed value is encoded in the most significative 61
130    bits of pvm_val (32 bits for 32-bit hosts).  Note that this assumes
131    all pointers are aligned to 8 bytes.  The allocator for the boxed
132    values makes sure this is always the case.  */
133 
134 #define PVM_VAL_BOX(V) ((pvm_val_box) ((((uintptr_t) V) & ~0x7)))
135 
136 /* This constructor should be used in order to build boxes.  */
137 
138 #define PVM_BOX(PTR) (((uint64_t) (uintptr_t) PTR) | PVM_VAL_TAG_BOX)
139 
140 /* A box is a header for a boxed value, plus that value.  It is of
141    type `pvm_val_box'.  */
142 
143 #define PVM_VAL_BOX_TAG(B) ((B)->tag)
144 #define PVM_VAL_BOX_STR(B) ((B)->v.string)
145 #define PVM_VAL_BOX_ARR(B) ((B)->v.array)
146 #define PVM_VAL_BOX_SCT(B) ((B)->v.sct)
147 #define PVM_VAL_BOX_TYP(B) ((B)->v.type)
148 #define PVM_VAL_BOX_CLS(B) ((B)->v.cls)
149 #define PVM_VAL_BOX_OFF(B) ((B)->v.offset)
150 
151 struct pvm_val_box
152 {
153   uint8_t tag;
154   union
155   {
156     char *string;
157     struct pvm_array *array;
158     struct pvm_struct *sct;
159     struct pvm_type *type;
160     struct pvm_off *offset;
161     struct pvm_cls *cls;
162   } v;
163 };
164 
165 typedef struct pvm_val_box *pvm_val_box;
166 
167 /* Strings are boxed.  */
168 
169 #define PVM_VAL_STR(V) (PVM_VAL_BOX_STR (PVM_VAL_BOX ((V))))
170 
171 /* Map-able values share a set of properties/attributes, which are
172    stored in `mapinfo' structures.
173 
174    These common properties are:
175 
176    MAPPED_P is 0 if the value is not mapped, or has any other value if
177    it is mapped.
178 
179    STRICT_P is 0 if data integrity shouldn't be enforced in the value,
180    or has any other value if data integrity should be enforced.
181 
182    IOS is an int<32> value that identifies the IO space where the
183    value is mapped.  If the value si not mapped then this is PVM_NULL.
184 
185    OFFSET is an ulong<64> value with the bit offset in the current IO
186    space where the value is mapped.  If the value is not mapped then
187    this holds 0UL by convention.
188 
189    Note that other properties related to mapping that are not shared
190    among the different kind of map-able values are not stored in this
191    struct.  */
192 
193 #define PVM_MAPINFO_MAPPED_P(MINFO) ((MINFO).mapped_p)
194 #define PVM_MAPINFO_STRICT_P(MINFO) ((MINFO).strict_p)
195 #define PVM_MAPINFO_IOS(MINFO) ((MINFO).ios)
196 #define PVM_MAPINFO_OFFSET(MINFO) ((MINFO).offset)
197 
198 struct pvm_mapinfo
199 {
200   int mapped_p;
201   int strict_p;
202   pvm_val ios;
203   pvm_val offset;
204 };
205 
206 struct pvm_mapinfo pvm_make_mapinfo (int mapped_p, pvm_val ios,
207                                      pvm_val offset);
208 
209 /* Arrays values are boxed, and store sequences of homogeneous values
210    called array "elements".  They can be mapped in IO, or unmapped.
211 
212    MAPINFO contains the mapping info for the value.  See the
213    definition of the struct above in this file for more information.
214 
215    MAPINFO_BACK is a backup are used by the relocation instructions.
216    See pvm_val_reloc and pvm_val_ureloc in pvm-val.c
217 
218    If the array is mapped, ELEMS_BOUND is an unsigned long containing
219    the number of elements to which the map is bounded.  Similarly,
220    SIZE_BOUND is an offset indicating the size to which the map is
221    bounded.  If the array is not mapped, both ELEMS_BOUND and
222    SIZE_BOUND are PVM_NULL.  Note that these two boundaries are
223    mutually exclusive, i.e. an array mapped value can be bounded by
224    either a given number of elements, or a given size, but not both.
225 
226    MAPPER is a closure that gets an offset as an argument and, when
227    executed, maps an array from IO.  This field is PVM_NULL if the
228    array is not mapped.
229 
230    WRITER is a closure that gets an offset and an array of this type
231    as arguments and, when executed, writes the array contents to IO.
232    This writer can raise PVM_E_CONSTRAINT if some constraint is
233    violated during the write.  This field is PVM_NULL if the array is
234    not mapped.
235 
236    TYPE is the type of the array.  This includes the type of the
237    elements of the array and the boundaries of the array, in case it
238    is bounded.
239 
240    NELEM is the number of elements contained in the array.
241 
242    NALLOCATED is the number of elements allocated in the array.
243 
244    ELEMS is a list of elements.  The order of the elements is
245    relevant.  */
246 
247 #define PVM_VAL_ARR(V) (PVM_VAL_BOX_ARR (PVM_VAL_BOX ((V))))
248 #define PVM_VAL_ARR_MAPINFO(V) (PVM_VAL_ARR(V)->mapinfo)
249 #define PVM_VAL_ARR_MAPINFO_BACK(V) (PVM_VAL_ARR(V)->mapinfo_back)
250 #define PVM_VAL_ARR_MAPPED_P(V) (PVM_MAPINFO_MAPPED_P (PVM_VAL_ARR_MAPINFO ((V))))
251 #define PVM_VAL_ARR_STRICT_P(V) (PVM_MAPINFO_STRICT_P (PVM_VAL_ARR_MAPINFO ((V))))
252 #define PVM_VAL_ARR_IOS(V) (PVM_MAPINFO_IOS (PVM_VAL_ARR_MAPINFO ((V))))
253 #define PVM_VAL_ARR_OFFSET(V) (PVM_MAPINFO_OFFSET (PVM_VAL_ARR_MAPINFO ((V))))
254 #define PVM_VAL_ARR_ELEMS_BOUND(V) (PVM_VAL_ARR(V)->elems_bound)
255 #define PVM_VAL_ARR_SIZE_BOUND(V) (PVM_VAL_ARR(V)->size_bound)
256 #define PVM_VAL_ARR_MAPPER(V) (PVM_VAL_ARR(V)->mapper)
257 #define PVM_VAL_ARR_WRITER(V) (PVM_VAL_ARR(V)->writer)
258 #define PVM_VAL_ARR_TYPE(V) (PVM_VAL_ARR(V)->type)
259 #define PVM_VAL_ARR_NELEM(V) (PVM_VAL_ARR(V)->nelem)
260 #define PVM_VAL_ARR_NALLOCATED(V) (PVM_VAL_ARR(V)->nallocated)
261 #define PVM_VAL_ARR_ELEMS(V) (PVM_VAL_ARR(V)->elems)
262 #define PVM_VAL_ARR_ELEM(V,I) (PVM_VAL_ARR(V)->elems[(I)])
263 
264 struct pvm_array
265 {
266   struct pvm_mapinfo mapinfo;
267   struct pvm_mapinfo mapinfo_back;
268   pvm_val elems_bound;
269   pvm_val size_bound;
270   pvm_val mapper;
271   pvm_val writer;
272   pvm_val type;
273   pvm_val nelem;
274   uint64_t nallocated;
275   struct pvm_array_elem *elems;
276 };
277 
278 typedef struct pvm_array *pvm_array;
279 
280 /* Array elements hold the data of the arrays, and/or information on
281    how to obtain these values.
282 
283    OFFSET is an ulong<64> value holding the bit offset of the element,
284    relative to the begginnig of the IO space.  If the array is not
285    mapped then this is PVM_NULL.
286 
287    OFFSET_BACK is a backup area used by the reloc instructions.
288 
289    VALUE is the value contained in the element.  If the array is
290    mapped this is the cached value, which is returned by `aref'.  */
291 
292 #define PVM_VAL_ARR_ELEM_OFFSET(V,I) (PVM_VAL_ARR_ELEM((V),(I)).offset)
293 #define PVM_VAL_ARR_ELEM_OFFSET_BACK(V,I) (PVM_VAL_ARR_ELEM((V),(I)).offset_back)
294 #define PVM_VAL_ARR_ELEM_VALUE(V,I) (PVM_VAL_ARR_ELEM((V),(I)).value)
295 
296 
297 struct pvm_array_elem
298 {
299   pvm_val offset;
300   pvm_val offset_back;
301   pvm_val value;
302 };
303 
304 /* Struct values are boxed, and store collections of named values
305    called structure "elements".  They can be mapped in IO, or
306    unmapped.
307 
308    MAPINFO contains the mapping info for the value.  See the
309    definition of the struct above in this file for more information.
310 
311    MAPINFO_BACK is a backup are used by the relocation instructions.
312    See pvm_val_reloc and pvm_val_ureloc in pvm-val.c
313 
314    TYPE is the type of the struct.  This includes the types of the
315    struct fields.
316 
317    NFIELDS is the number of fields conforming the structure.
318 
319    FIELDS is a list of fields.  The order of the fields is
320    relevant.
321 
322    NMETHODS is the number of methods defined in the structure.
323 
324    METHODS is a list of methods.  The order of the methods is
325    irrelevant.  */
326 
327 #define PVM_VAL_SCT(V) (PVM_VAL_BOX_SCT (PVM_VAL_BOX ((V))))
328 #define PVM_VAL_SCT_MAPINFO(V) (PVM_VAL_SCT((V))->mapinfo)
329 #define PVM_VAL_SCT_MAPINFO_BACK(V) (PVM_VAL_SCT((V))->mapinfo_back)
330 #define PVM_VAL_SCT_MAPPED_P(V) (PVM_MAPINFO_MAPPED_P (PVM_VAL_SCT_MAPINFO ((V))))
331 #define PVM_VAL_SCT_STRICT_P(V) (PVM_MAPINFO_STRICT_P (PVM_VAL_SCT_MAPINFO ((V))))
332 #define PVM_VAL_SCT_IOS(V) (PVM_MAPINFO_IOS (PVM_VAL_SCT_MAPINFO ((V))))
333 #define PVM_VAL_SCT_OFFSET(V) (PVM_MAPINFO_OFFSET (PVM_VAL_SCT_MAPINFO ((V))))
334 #define PVM_VAL_SCT_MAPPER(V) (PVM_VAL_SCT((V))->mapper)
335 #define PVM_VAL_SCT_WRITER(V) (PVM_VAL_SCT((V))->writer)
336 #define PVM_VAL_SCT_TYPE(V) (PVM_VAL_SCT((V))->type)
337 #define PVM_VAL_SCT_NFIELDS(V) (PVM_VAL_SCT((V))->nfields)
338 #define PVM_VAL_SCT_FIELD(V,I) (PVM_VAL_SCT((V))->fields[(I)])
339 #define PVM_VAL_SCT_NMETHODS(V) (PVM_VAL_SCT((V))->nmethods)
340 #define PVM_VAL_SCT_METHOD(V,I) (PVM_VAL_SCT((V))->methods[(I)])
341 
342 struct pvm_struct
343 {
344   struct pvm_mapinfo mapinfo;
345   struct pvm_mapinfo mapinfo_back;
346   pvm_val mapper;
347   pvm_val writer;
348   pvm_val type;
349   pvm_val nfields;
350   struct pvm_struct_field *fields;
351   pvm_val nmethods;
352   struct pvm_struct_method *methods;
353 };
354 
355 /* Struct fields hold the data of the fields, and/or information on
356    how to obtain these values.
357 
358    OFFSET is an ulong<64> value containing the bit-offset,
359    relative to the beginning of the struct, where the struct field
360    resides when stored.
361 
362    NAME is a string containing the name of the struct field.  This
363    name should be unique in the struct.
364 
365    VALUE is the value contained in the field.  If the struct is
366    mapped then this is the cached value, which is returned by
367    `sref'.
368 
369    If both NAME and FIELD are PVM_NULL, the field is absent in the
370    struct.
371 
372    MODIFIED is a C boolean indicating whether the field value has
373    been modified since struct creation, or since last mapping if the
374    struct is mapped.
375 
376    MODIFIED_BACK and OFFSET_BACK are backup storage used by the
377    relocation instructions.  */
378 
379 #define PVM_VAL_SCT_FIELD_OFFSET(V,I) (PVM_VAL_SCT_FIELD((V),(I)).offset)
380 #define PVM_VAL_SCT_FIELD_NAME(V,I) (PVM_VAL_SCT_FIELD((V),(I)).name)
381 #define PVM_VAL_SCT_FIELD_VALUE(V,I) (PVM_VAL_SCT_FIELD((V),(I)).value)
382 #define PVM_VAL_SCT_FIELD_MODIFIED(V,I) (PVM_VAL_SCT_FIELD((V),(I)).modified)
383 #define PVM_VAL_SCT_FIELD_MODIFIED_BACK(V,I) (PVM_VAL_SCT_FIELD((V),(I)).modified_back)
384 #define PVM_VAL_SCT_FIELD_OFFSET_BACK(V,I) (PVM_VAL_SCT_FIELD((V),(I)).offset_back)
385 #define PVM_VAL_SCT_FIELD_ABSENT_P(V,I)         \
386   (PVM_VAL_SCT_FIELD_NAME ((V),(I)) == PVM_NULL \
387    && PVM_VAL_SCT_FIELD_VALUE ((V),(I)) == PVM_NULL)
388 
389 struct pvm_struct_field
390 {
391   pvm_val offset;
392   pvm_val offset_back;
393   pvm_val name;
394   pvm_val value;
395   pvm_val modified;
396   pvm_val modified_back;
397 };
398 
399 /* Struct methods are closures associated with the struct, which can
400    be invoked as functions.
401 
402    NAME is a string containing the name of the method.  This name
403    should be unique in the struct.
404 
405    VALUE is a PVM closure.  */
406 
407 #define PVM_VAL_SCT_METHOD_NAME(V,I) (PVM_VAL_SCT_METHOD((V),(I)).name)
408 #define PVM_VAL_SCT_METHOD_VALUE(V,I) (PVM_VAL_SCT_METHOD((V),(I)).value)
409 
410 struct pvm_struct_method
411 {
412   pvm_val name;
413   pvm_val value;
414 };
415 
416 typedef struct pvm_struct *pvm_struct;
417 
418 /* Types are also boxed.  */
419 
420 #define PVM_VAL_TYP(V) (PVM_VAL_BOX_TYP (PVM_VAL_BOX ((V))))
421 
422 #define PVM_VAL_TYP_CODE(V) (PVM_VAL_TYP((V))->code)
423 #define PVM_VAL_TYP_I_SIZE(V) (PVM_VAL_TYP((V))->val.integral.size)
424 #define PVM_VAL_TYP_I_SIGNED_P(V) (PVM_VAL_TYP((V))->val.integral.signed_p)
425 #define PVM_VAL_TYP_A_BOUND(V) (PVM_VAL_TYP((V))->val.array.bound)
426 #define PVM_VAL_TYP_A_ETYPE(V) (PVM_VAL_TYP((V))->val.array.etype)
427 #define PVM_VAL_TYP_S_NAME(V) (PVM_VAL_TYP((V))->val.sct.name)
428 #define PVM_VAL_TYP_S_NFIELDS(V) (PVM_VAL_TYP((V))->val.sct.nfields)
429 #define PVM_VAL_TYP_S_FNAMES(V) (PVM_VAL_TYP((V))->val.sct.fnames)
430 #define PVM_VAL_TYP_S_FTYPES(V) (PVM_VAL_TYP((V))->val.sct.ftypes)
431 #define PVM_VAL_TYP_S_FNAME(V,I) (PVM_VAL_TYP_S_FNAMES((V))[(I)])
432 #define PVM_VAL_TYP_S_FTYPE(V,I) (PVM_VAL_TYP_S_FTYPES((V))[(I)])
433 #define PVM_VAL_TYP_O_UNIT(V) (PVM_VAL_TYP((V))->val.off.unit)
434 #define PVM_VAL_TYP_O_BASE_TYPE(V) (PVM_VAL_TYP((V))->val.off.base_type)
435 #define PVM_VAL_TYP_C_RETURN_TYPE(V) (PVM_VAL_TYP((V))->val.cls.return_type)
436 #define PVM_VAL_TYP_C_NARGS(V) (PVM_VAL_TYP((V))->val.cls.nargs)
437 #define PVM_VAL_TYP_C_ATYPES(V) (PVM_VAL_TYP((V))->val.cls.atypes)
438 #define PVM_VAL_TYP_C_ATYPE(V,I) (PVM_VAL_TYP_C_ATYPES((V))[(I)])
439 
440 enum pvm_type_code
441 {
442   PVM_TYPE_INTEGRAL,
443   PVM_TYPE_STRING,
444   PVM_TYPE_ARRAY,
445   PVM_TYPE_STRUCT,
446   PVM_TYPE_OFFSET,
447   PVM_TYPE_CLOSURE,
448   PVM_TYPE_ANY,
449   PVM_TYPE_VOID
450 };
451 
452 struct pvm_type
453 {
454   enum pvm_type_code code;
455 
456   union
457   {
458     struct
459     {
460       pvm_val size;
461       pvm_val signed_p;
462     } integral;
463 
464     struct
465     {
466       pvm_val bound;
467       pvm_val etype;
468     } array;
469 
470     struct
471     {
472       pvm_val name;
473       pvm_val nfields;
474       pvm_val *fnames;
475       pvm_val *ftypes;
476     } sct;
477 
478     struct
479     {
480       pvm_val base_type;
481       pvm_val unit;
482     } off;
483 
484     struct
485     {
486       pvm_val nargs;
487       pvm_val return_type;
488       pvm_val *atypes;
489     } cls;
490   } val;
491 };
492 
493 typedef struct pvm_type *pvm_type;
494 
495 /* Closures are also boxed.  */
496 
497 #define PVM_VAL_CLS(V) (PVM_VAL_BOX_CLS (PVM_VAL_BOX ((V))))
498 
499 #define PVM_VAL_CLS_PROGRAM(V) (PVM_VAL_CLS((V))->program)
500 #define PVM_VAL_CLS_ENTRY_POINT(V) (PVM_VAL_CLS((V))->entry_point)
501 #define PVM_VAL_CLS_ENV(V) (PVM_VAL_CLS((V))->env)
502 
503 typedef struct pvm_program *pvm_program;
504 typedef void *pvm_program_program_point;
505 
506 struct pvm_cls
507 {
508   pvm_program program;
509   pvm_program_program_point entry_point;
510   struct pvm_env *env;
511 };
512 
513 typedef struct pvm_cls *pvm_cls;
514 
515 /* Offsets are boxed values.  */
516 
517 #define PVM_VAL_OFF(V) (PVM_VAL_BOX_OFF (PVM_VAL_BOX ((V))))
518 
519 #define PVM_VAL_OFF_MAGNITUDE(V) (PVM_VAL_OFF((V))->magnitude)
520 #define PVM_VAL_OFF_UNIT(V) (PVM_VAL_OFF((V))->unit)
521 #define PVM_VAL_OFF_BASE_TYPE(V) (PVM_VAL_OFF((V))->base_type)
522 
523 #define PVM_VAL_OFF_UNIT_BITS 1
524 #define PVM_VAL_OFF_UNIT_NIBBLES 4
525 #define PVM_VAL_OFF_UNIT_BYTES (2 * PVM_VAL_OFF_UNIT_NIBBLES)
526 
527 #define PVM_VAL_OFF_UNIT_KILOBITS (1000 * PVM_VAL_OFF_UNIT_BITS)
528 #define PVM_VAL_OFF_UNIT_KILOBYTES (1000 * PVM_VAL_OFF_UNIT_BYTES)
529 #define PVM_VAL_OFF_UNIT_MEGABITS (1000 * PVM_VAL_OFF_UNIT_KILOBITS)
530 #define PVM_VAL_OFF_UNIT_MEGABYTES (1000 * PVM_VAL_OFF_UNIT_KILOBYTES)
531 #define PVM_VAL_OFF_UNIT_GIGABITS (1000 * PVM_VAL_OFF_UNIT_MEGABITS)
532 #define PVM_VAL_OFF_UNIT_GIGABYTES (1000LU * PVM_VAL_OFF_UNIT_MEGABYTES)
533 
534 #define PVM_VAL_OFF_UNIT_KIBIBITS (1024 * PVM_VAL_OFF_UNIT_BITS)
535 #define PVM_VAL_OFF_UNIT_KIBIBYTES (1024 * PVM_VAL_OFF_UNIT_BYTES)
536 #define PVM_VAL_OFF_UNIT_MEBIBITS (1024 * PVM_VAL_OFF_UNIT_KIBIBITS)
537 #define PVM_VAL_OFF_UNIT_MEBIBYTES (1024 * PVM_VAL_OFF_UNIT_KIBIBYTES)
538 #define PVM_VAL_OFF_UNIT_GIGIBITS (1024 * PVM_VAL_OFF_UNIT_MEBIBITS)
539 #define PVM_VAL_OFF_UNIT_GIGIBYTES (1024LU * PVM_VAL_OFF_UNIT_MEBIBYTES)
540 
541 struct pvm_off
542 {
543   pvm_val base_type;
544   pvm_val magnitude;
545   pvm_val unit;
546 };
547 
548 typedef struct pvm_off *pvm_off;
549 
550 #define PVM_IS_INT(V) (PVM_VAL_TAG(V) == PVM_VAL_TAG_INT)
551 #define PVM_IS_UINT(V) (PVM_VAL_TAG(V) == PVM_VAL_TAG_UINT)
552 #define PVM_IS_LONG(V) (PVM_VAL_TAG(V) == PVM_VAL_TAG_LONG)
553 #define PVM_IS_ULONG(V) (PVM_VAL_TAG(V) == PVM_VAL_TAG_ULONG)
554 #define PVM_IS_STR(V)                                                   \
555   (PVM_VAL_TAG(V) == PVM_VAL_TAG_BOX                                    \
556    && PVM_VAL_BOX_TAG (PVM_VAL_BOX ((V))) == PVM_VAL_TAG_STR)
557 #define PVM_IS_ARR(V)                                                   \
558   (PVM_VAL_TAG(V) == PVM_VAL_TAG_BOX                                    \
559    && PVM_VAL_BOX_TAG (PVM_VAL_BOX ((V))) == PVM_VAL_TAG_ARR)
560 #define PVM_IS_SCT(V)                                                   \
561   (PVM_VAL_TAG(V) == PVM_VAL_TAG_BOX                                    \
562    && PVM_VAL_BOX_TAG (PVM_VAL_BOX ((V))) == PVM_VAL_TAG_SCT)
563 #define PVM_IS_TYP(V)                                                   \
564   (PVM_VAL_TAG(V) == PVM_VAL_TAG_BOX                                    \
565    && PVM_VAL_BOX_TAG (PVM_VAL_BOX ((V))) == PVM_VAL_TAG_TYP)
566 #define PVM_IS_CLS(V)                                                   \
567   (PVM_VAL_TAG(V) == PVM_VAL_TAG_BOX                                    \
568    && PVM_VAL_BOX_TAG (PVM_VAL_BOX ((V))) == PVM_VAL_TAG_CLS)
569 #define PVM_IS_OFF(V)                                                   \
570   (PVM_VAL_TAG(V) == PVM_VAL_TAG_BOX                                    \
571    && PVM_VAL_BOX_TAG (PVM_VAL_BOX ((V))) == PVM_VAL_TAG_OFF)
572 
573 
574 #define PVM_IS_INTEGRAL(V)                                      \
575   (PVM_IS_INT (V) || PVM_IS_UINT (V)                            \
576    || PVM_IS_LONG (V) || PVM_IS_ULONG (V))
577 
578 #define PVM_VAL_INTEGRAL(V)                      \
579   (PVM_IS_INT ((V)) ? PVM_VAL_INT ((V))          \
580    : PVM_IS_UINT ((V)) ? PVM_VAL_UINT ((V))      \
581    : PVM_IS_LONG ((V)) ? PVM_VAL_LONG ((V))      \
582    : PVM_IS_ULONG ((V)) ? PVM_VAL_ULONG ((V))    \
583    : 0)
584 
585 /* The following macros allow to handle map-able PVM values (such as
586    arrays and structs) polymorphically.
587 
588    It is important for the PVM_VAL_SET_{IO,OFFSET,MAPPER,WRITER} to work
589    for non-mappeable values, as nops, as they are used in the
590    implementation of the `unmap' operator.  */
591 
592 #define PVM_VAL_OFFSET(V)                               \
593   (PVM_IS_ARR ((V)) ? PVM_VAL_ARR_OFFSET ((V))          \
594    : PVM_IS_SCT ((V)) ? PVM_VAL_SCT_OFFSET ((V))        \
595    : PVM_NULL)
596 
597 #define PVM_VAL_SET_OFFSET(V,O)                 \
598   do                                            \
599     {                                           \
600       if (PVM_IS_ARR ((V)))                     \
601         PVM_VAL_ARR_OFFSET ((V)) = (O);         \
602       else if (PVM_IS_SCT ((V)))                \
603         PVM_VAL_SCT_OFFSET ((V)) = (O);         \
604     } while (0)
605 
606 #define PVM_VAL_IOS(V)                          \
607   (PVM_IS_ARR ((V)) ? PVM_VAL_ARR_IOS ((V))     \
608    : PVM_IS_SCT ((V)) ? PVM_VAL_SCT_IOS ((V))   \
609    : PVM_NULL)
610 
611 #define PVM_VAL_SET_IOS(V,I)                     \
612   do                                             \
613     {                                            \
614       if (PVM_IS_ARR ((V)))                      \
615         PVM_VAL_ARR_IOS ((V)) = (I);             \
616       else if (PVM_IS_SCT (V))                   \
617         PVM_VAL_SCT_IOS ((V)) = (I);             \
618     } while (0)
619 
620 #define PVM_VAL_MAPPED_P(V)                             \
621   (PVM_IS_ARR ((V)) ? PVM_VAL_ARR_MAPPED_P ((V))        \
622    : PVM_IS_SCT ((V)) ? PVM_VAL_SCT_MAPPED_P ((V))      \
623    : 0)
624 
625 #define PVM_VAL_SET_MAPPED_P(V,I)               \
626   do                                            \
627     {                                           \
628       if (PVM_IS_ARR ((V)))                     \
629         PVM_VAL_ARR_MAPPED_P ((V)) = (I);       \
630       else if (PVM_IS_SCT ((V)))                \
631         PVM_VAL_SCT_MAPPED_P ((V)) = (I);       \
632     }                                           \
633   while (0)
634 
635 #define PVM_VAL_STRICT_P(V)                             \
636   (PVM_IS_ARR ((V)) ? PVM_VAL_ARR_STRICT_P ((V))        \
637    : PVM_IS_SCT ((V)) ? PVM_VAL_SCT_STRICT_P ((V))      \
638    : 0)
639 
640 #define PVM_VAL_SET_STRICT_P(V,I)               \
641   do                                            \
642     {                                           \
643       if (PVM_IS_ARR ((V)))                     \
644         PVM_VAL_ARR_STRICT_P ((V)) = (I);       \
645       else if (PVM_IS_SCT ((V)))                \
646         PVM_VAL_SCT_STRICT_P ((V)) = (I);       \
647     }                                           \
648   while (0)
649 
650 #define PVM_VAL_MAPPER(V)                               \
651   (PVM_IS_ARR ((V)) ? PVM_VAL_ARR_MAPPER ((V))          \
652    : PVM_IS_SCT ((V)) ? PVM_VAL_SCT_MAPPER ((V))        \
653    : PVM_NULL)
654 
655 #define PVM_VAL_ELEMS_BOUND(V)                          \
656   (PVM_IS_ARR ((V)) ? PVM_VAL_ARR_ELEMS_BOUND ((V))     \
657    : PVM_NULL)
658 
659 #define PVM_VAL_SIZE_BOUND(V)                           \
660   (PVM_IS_ARR ((V)) ? PVM_VAL_ARR_SIZE_BOUND ((V))      \
661    : PVM_NULL)
662 
663 #define PVM_VAL_SET_MAPPER(V,O)                 \
664   do                                            \
665     {                                           \
666       if (PVM_IS_ARR ((V)))                     \
667         PVM_VAL_ARR_MAPPER ((V)) = (O);         \
668       else if (PVM_IS_SCT ((V)))                \
669         PVM_VAL_SCT_MAPPER ((V)) = (O);         \
670     } while (0)
671 
672 #define PVM_VAL_WRITER(V)                               \
673   (PVM_IS_ARR ((V)) ? PVM_VAL_ARR_WRITER ((V))          \
674    : PVM_IS_SCT ((V)) ? PVM_VAL_SCT_WRITER ((V))        \
675    : PVM_NULL)
676 
677 #define PVM_VAL_SET_WRITER(V,O)                 \
678   do                                            \
679     {                                           \
680       if (PVM_IS_ARR ((V)))                     \
681         PVM_VAL_ARR_WRITER ((V)) = (O);         \
682       else if (PVM_IS_SCT ((V)))                \
683         PVM_VAL_SCT_WRITER ((V)) = (O);         \
684     } while (0)
685 
686 #define PVM_VAL_SET_ELEMS_BOUND(V,O)            \
687   do                                            \
688     {                                           \
689       if (PVM_IS_ARR ((V)))                     \
690         PVM_VAL_ARR_ELEMS_BOUND ((V)) = (O);    \
691     } while (0)
692 
693 #define PVM_VAL_SET_SIZE_BOUND(V,O)             \
694   do                                            \
695     {                                           \
696       if (PVM_IS_ARR ((V)))                     \
697         PVM_VAL_ARR_SIZE_BOUND ((V)) = (O);     \
698     } while (0)
699 
700 void pvm_allocate_struct_attrs (pvm_val nfields, pvm_val **fnames,
701                                 pvm_val **ftypes);
702 void pvm_allocate_closure_attrs (pvm_val nargs, pvm_val **atypes);
703 
704 void pvm_val_initialize (void);
705 void pvm_val_finalize (void);
706 
707 #endif /* ! PVM_VAL_H */
708