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