4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1994, by Sun Microsytems, Inc.
26 #pragma ident "%Z%%M% %I% %E% SMI"
31 * Operations based on ABI bootstrap assumptions
34 #define _GET_TAG(tnf, p) \
37 #define _GET_TAG_ARG(tnf, p) \
40 #define _GET_SELF_SIZE(tnf, p) \
41 _GET_UINT32(tnf, &((struct tnf_array_hdr *)(p))->self_size)
43 #define _GET_NAME(tnf, p) \
44 _GET_REF32(tnf, &((struct tnf_type_hdr *)(p))->name)
46 #define _GET_PROPERTIES(tnf, p) \
47 _GET_REF32(tnf, &((struct tnf_type_hdr *)(p))->properties)
49 #define _GET_SLOT_TYPES(tnf, p) \
50 _GET_REF32(tnf, &((struct tnf_struct_type_hdr *)(p))->slot_types)
52 #define _GET_TYPE_SIZE(tnf, p) \
53 _GET_UINT32(tnf, &((struct tnf_struct_type_hdr *)(p))->type_size)
55 #define _GET_HEADER_SIZE(tnf, p) \
56 _GET_UINT32(tnf, &((struct tnf_array_type_hdr *)(p))->header_size)
58 #define _GET_DERIVED_BASE(tnf, p) \
59 _GET_REF32(tnf, &((struct tnf_derived_type_hdr *)(p))->derived_base)
65 static caddr_t
fetch_slot(TNF
*, caddr_t
, tnf_ref32_t
*);
68 * retrieve tag slot from a record
72 _tnf_get_tag(TNF
*tnf
, tnf_ref32_t
*record
)
74 return (_GET_TAG(tnf
, record
));
78 * Retrieve tag_arg from tag slot of a record
82 _tnf_get_tag_arg(TNF
*tnf
, tnf_ref32_t
*record
)
84 return (_GET_TAG_ARG(tnf
, record
));
88 * Retrieve the self_size slot of an ABI array record
92 _tnf_get_self_size(TNF
*tnf
, tnf_ref32_t
*array
)
94 return (_GET_SELF_SIZE(tnf
, array
));
98 * Calculate the number of elements in ABI array record
102 _tnf_get_element_count(TNF
*tnf
, tnf_ref32_t
*array
, unsigned eltsize
)
104 size_t size
, hdrsize
;
105 #ifdef INFINITE_RECURSION_ARRAY
106 tnf_ref32_t
*base_tag
;
108 size
= _tnf_get_self_size(tnf
, array
);
109 base_tag
= _tnf_get_base_tag(tnf
, _tnf_get_tag(tnf
, array
));
110 hdrsize
= _tnf_get_header_size(tnf
, base_tag
);
111 return (((size
- hdrsize
) / eltsize
));
113 size
= _tnf_get_self_size(tnf
, array
);
114 hdrsize
= sizeof (struct tnf_array_hdr
);
115 return (((size
- hdrsize
) / eltsize
));
120 * Retrieve the base pointer of an ABI array record
125 _tnf_get_elements(TNF
*tnf
, tnf_ref32_t
*array
)
127 #ifdef INFINITE_RECURSION_ARRAY
129 tnf_ref32_t
*base_tag
;
131 base_tag
= _tnf_get_base_tag(tnf
, _tnf_get_tag(tnf
, array
));
132 hdrsize
= _tnf_get_header_size(tnf
, base_tag
);
133 return ((caddr_t
)((char *)array
+ hdrsize
));
135 return ((caddr_t
)((char *)array
+ sizeof (struct tnf_array_hdr
)));
140 * Retrieve the chars in an ABI string record
144 _tnf_get_chars(TNF
*tnf
, tnf_ref32_t
*string
)
146 return ((char *)_tnf_get_elements(tnf
, string
));
150 * Retrieve the string in the name slot of a type record
154 _tnf_get_name(TNF
*tnf
, tnf_ref32_t
*tag
)
156 return (_tnf_get_chars(tnf
, _GET_NAME(tnf
, tag
)));
160 * Retrieve the properties array slot of a type record
164 _tnf_get_properties(TNF
*tnf
, tnf_ref32_t
*tag
)
166 return (_GET_PROPERTIES(tnf
, tag
));
170 * Retrieve the slot_types slot of struct_type or array_type record
174 _tnf_get_slot_types(TNF
*tnf
, tnf_ref32_t
*tag
)
176 return (_GET_SLOT_TYPES(tnf
, tag
));
180 * Retrieve the header_size slot of an array_type record
184 _tnf_get_header_size(TNF
*tnf
, tnf_ref32_t
*tag
)
186 return (_GET_HEADER_SIZE(tnf
, tag
));
190 * Retrieve the derived_base slot of a derived_type record
194 _tnf_get_derived_base(TNF
*tnf
, tnf_ref32_t
*tag
)
196 return (_GET_DERIVED_BASE(tnf
, tag
));
201 * Find the root (self-tagged) type record
205 _tnf_get_root_tag(TNF
*tnf
, tnf_ref32_t
*record
)
208 return (tnf
->root_tag
);
210 tnf_ref32_t
*p1
, *p2
;
212 while ((p2
= _tnf_get_tag(tnf
, p1
)) != p1
)
220 * Search ABI type array for a type named name
224 _tnf_get_element_named(TNF
*tnf
, tnf_ref32_t
*array
, char *name
)
229 count
= _tnf_get_element_count(tnf
, array
, sizeof (tnf_ref32_t
));
230 /* LINTED pointer cast may result in improper alignment */
231 elts
= (tnf_ref32_t
*)_tnf_get_elements(tnf
, array
);
233 for (i
= 0; i
< count
; i
++) {
234 tnf_ref32_t
*type_elt
;
236 if ((type_elt
= _GET_REF32(tnf
, &elts
[i
])) == TNF_NULL
) {
237 /* Can't have missing type records */
238 _tnf_error(tnf
, TNF_ERR_BADTNF
);
242 if (strcmp(name
, _tnf_get_name(tnf
, type_elt
)) == 0)
243 /* Found a type record named name */
250 * Look in type record's properties for named type.
251 * Recursively look at derived_base properties as well.
255 _tnf_get_property(TNF
*tnf
, tnf_ref32_t
*tag
, char *name
)
257 tnf_ref32_t
*properties
, *property
;
259 if (strcmp(name
, _tnf_get_name(tnf
, tag
)) == 0)
260 /* name is type name */
263 if ((properties
= _tnf_get_properties(tnf
, tag
)) == TNF_NULL
)
267 if ((property
= _tnf_get_element_named(tnf
, properties
, name
))
269 /* found property named name */
273 * Recursively check base type of derived types
275 if (_tnf_get_element_named(tnf
, properties
, TNF_N_DERIVED
)
277 /* tag is a derived type: check its derived_base */
278 tnf_ref32_t
*base_tag
;
280 base_tag
= _tnf_get_derived_base(tnf
, tag
);
281 /* tnf_derived has derived_base == TNF_NULL */
282 if (base_tag
!= TNF_NULL
)
283 return (_tnf_get_property(tnf
, base_tag
, name
));
290 * Get the ultimate base type of a type record
294 _tnf_get_base_tag(TNF
*tnf
, tnf_ref32_t
*tag
)
296 tnf_ref32_t
*properties
;
298 if ((properties
= _tnf_get_properties(tnf
, tag
)) == TNF_NULL
)
302 if (_tnf_get_element_named(tnf
, properties
, TNF_N_DERIVED
)
304 tnf_ref32_t
*base_tag
;
306 if ((base_tag
= _tnf_get_derived_base(tnf
, tag
)) != TNF_NULL
)
307 return (_tnf_get_base_tag(tnf
, base_tag
));
314 * Calculate the reference size of an object with type==tag
318 _tnf_get_ref_size(TNF
*tnf
, tnf_ref32_t
*tag
)
320 if (HAS_PROPERTY(tnf
, tag
, TNF_N_TAGGED
)) {
321 /* Tagged objects occupy 4 bytes for reference */
322 return ((sizeof (tnf_ref32_t
)));
323 } else if (HAS_PROPERTY(tnf
, tag
, TNF_N_INLINE
)) {
324 /* Inline slots cannot be self sized */
325 return (_tnf_get_storage_size(tnf
, tag
));
327 /* Illegal to have references to abstract objects */
328 _tnf_error(tnf
, TNF_ERR_BADTNF
);
334 * Calculate storage size of an object with type==tag
338 _tnf_get_storage_size(TNF
*tnf
, tnf_ref32_t
*tag
)
340 if (_tnf_get_tag(tnf
, tag
) == _tnf_get_root_tag(tnf
, tag
))
341 return (_GET_TYPE_SIZE(tnf
, tag
));
343 tnf_ref32_t
*base_tag
; /* implementation tag */
345 tnf_ref32_t
*slot_types
;
347 #ifndef INFINITE_RECURSION_SIZE
353 { TNF_N_CHAR
, sizeof (tnf_char_t
) },
354 { TNF_N_INT8
, sizeof (tnf_int8_t
) },
355 { TNF_N_INT16
, sizeof (tnf_int16_t
) },
356 { TNF_N_INT32
, sizeof (tnf_int32_t
) },
357 { TNF_N_UINT8
, sizeof (tnf_uint8_t
) },
358 { TNF_N_UINT16
, sizeof (tnf_uint16_t
) },
359 { TNF_N_UINT32
, sizeof (tnf_uint32_t
) },
360 { TNF_N_INT64
, sizeof (tnf_int64_t
) },
361 { TNF_N_UINT64
, sizeof (tnf_uint64_t
) },
362 { TNF_N_FLOAT32
, sizeof (tnf_float32_t
) },
363 { TNF_N_FLOAT64
, sizeof (tnf_float64_t
) },
369 base_tag
= _tnf_get_base_tag(tnf
, tag
);
371 #ifndef INFINITE_RECURSION_SIZE
372 base_name
= _tnf_get_name(tnf
, base_tag
);
374 /* XXX Why are we in this mess? */
377 if (strcmp(p
->name
, base_name
) == 0)
383 sizep
= _tnf_get_slot_typed(tnf
, base_tag
, TNF_N_TYPE_SIZE
);
386 /* LINTED pointer cast may result in improper alignment */
387 return (_GET_UINT32(tnf
, (tnf_uint32_t
*)sizep
));
389 slot_types
= (tnf_ref32_t
*)
390 /* LINTED pointer cast may result in improper alignment */
391 _tnf_get_slot_typed(tnf
, base_tag
, TNF_N_SLOT_TYPES
);
393 _tnf_get_element_named(tnf
, slot_types
, TNF_N_SELF_SIZE
))
403 * Return the alignment restriction for any tag
407 _tnf_get_align(TNF
*tnf
, tnf_ref32_t
*tag
)
409 if (HAS_PROPERTY(tnf
, tag
, TNF_N_SCALAR
)) {
410 tnf_ref32_t
*base_tag
;
413 base_tag
= _tnf_get_base_tag(tnf
, tag
);
414 alignp
= _tnf_get_slot_typed(tnf
, base_tag
, TNF_N_ALIGN
);
416 /* LINTED pointer cast may result in improper alignment */
417 return (_GET_UINT32(tnf
, (tnf_uint32_t
*)alignp
));
419 /* default: word alignment */
424 * Only works for records
425 * Doesn't check for slot_names in tag
426 * Tag records, for example, never have named slots
430 _tnf_get_slot_typed(TNF
*tnf
, tnf_ref32_t
*record
, char *name
)
432 tnf_ref32_t
*tag
, *base_tag
;
433 tnf_ref32_t
*slot_types
, *types
;
437 tag
= _tnf_get_tag(tnf
, record
);
438 base_tag
= _tnf_get_base_tag(tnf
, tag
);
441 * The position of slot_types is ABI fixed
442 * XXX Assume it is present in tag
444 slot_types
= _tnf_get_slot_types(tnf
, base_tag
);
445 count
= _tnf_get_element_count(tnf
, slot_types
, sizeof (tnf_ref32_t
));
446 /* LINTED pointer cast may result in improper alignment */
447 types
= (tnf_ref32_t
*)_tnf_get_elements(tnf
, slot_types
);
451 for (i
= 0; i
< count
; i
++) {
452 tnf_ref32_t
*type_elt
;
453 size_t ref_size
, align
;
455 /* Find the type record for slot */
456 if ((type_elt
= _GET_REF32(tnf
, &types
[i
])) == TNF_NULL
) {
457 /* Can't have missing type records */
458 _tnf_error(tnf
, TNF_ERR_BADTNF
);
459 return ((caddr_t
)NULL
);
462 /* See similar hack in init_slots() */
464 /* Calculate reference size */
465 ref_size
= _tnf_get_ref_size(tnf
, type_elt
);
468 * Calculate alignment
469 * XXX Prevent infinite recursion by assuming that
470 * a reference size of 4 implies word alignment
472 align
= (ref_size
== 4)? 4: _tnf_get_align(tnf
, type_elt
);
474 /* Adjust offset to account for alignment, if needed */
475 offset
= ALIGN(offset
, align
);
477 /* Check whether name corresponds to type name */
478 if (strcmp(name
, _tnf_get_name(tnf
, type_elt
)) == 0)
480 return (fetch_slot(tnf
, (caddr_t
)record
+ offset
,
483 /* Bump offset by reference size */
487 return ((caddr_t
)NULL
);
491 * Only works for records
495 _tnf_get_slot_named(TNF
*tnf
, tnf_ref32_t
*record
, char *name
)
497 tnf_ref32_t
*tag
, *base_tag
;
498 tnf_ref32_t
*slot_types
, *slot_names
, *types
, *names
;
502 tag
= _tnf_get_tag(tnf
, record
);
503 base_tag
= _tnf_get_base_tag(tnf
, tag
);
506 * slot_names are optional
508 slot_names
= (tnf_ref32_t
*)
509 /* LINTED pointer cast may result in improper alignment */
510 _tnf_get_slot_typed(tnf
, base_tag
, TNF_N_SLOT_NAMES
);
512 /* no slot_names; use _tnf_get_slot_typed() */
513 if (slot_names
== TNF_NULL
)
514 return (_tnf_get_slot_typed(tnf
, record
, name
));
517 * The position of slot_types is ABI fixed
518 * XXX Assume it is present in tag
520 slot_types
= _tnf_get_slot_types(tnf
, base_tag
);
521 count
= _tnf_get_element_count(tnf
, slot_types
, sizeof (tnf_ref32_t
));
522 /* LINTED pointer cast may result in improper alignment */
523 types
= (tnf_ref32_t
*)_tnf_get_elements(tnf
, slot_types
);
524 /* LINTED pointer cast may result in improper alignment */
525 names
= (tnf_ref32_t
*)_tnf_get_elements(tnf
, slot_names
);
529 for (i
= 0; i
< count
; i
++) {
530 tnf_ref32_t
*type_elt
, *name_elt
;
531 size_t ref_size
, align
;
533 /* Find the type record for slot */
534 if ((type_elt
= _GET_REF32(tnf
, &types
[i
])) == TNF_NULL
) {
535 /* Can't have missing type records */
536 _tnf_error(tnf
, TNF_ERR_BADTNF
);
537 return ((caddr_t
)NULL
);
540 /* XXX Keep consistent with init_slots() */
542 /* Calculate reference size */
543 ref_size
= _tnf_get_ref_size(tnf
, type_elt
);
546 * Calculate alignment
547 * XXX Prevent infinite recursion by assuming that
548 * a reference size of 4 implies word alignment
550 align
= (ref_size
== 4)? 4: _tnf_get_align(tnf
, type_elt
);
552 /* Adjust offset to account for alignment, if needed */
553 offset
= ALIGN(offset
, align
);
555 /* First check slot name, then type name */
556 if ((((name_elt
= _GET_REF32(tnf
, &names
[i
])) != TNF_NULL
) &&
557 (strcmp(name
, _tnf_get_chars(tnf
, name_elt
)) == 0)) ||
558 (strcmp(name
, _tnf_get_name(tnf
, type_elt
)) == 0))
560 return (fetch_slot(tnf
, (caddr_t
)record
+ offset
,
563 /* Bump offset by reference size */
567 return ((caddr_t
)NULL
);
571 fetch_slot(TNF
*tnf
, caddr_t p
, tnf_ref32_t
*tag
)
573 if (HAS_PROPERTY(tnf
, tag
, TNF_N_INLINE
))
575 else /* XXX assume tagged */
576 /* LINTED pointer cast may result in improper alignment */
577 return ((caddr_t
)_GET_REF32(tnf
, (tnf_ref32_t
*)p
));