diff options
author | David Young <dyoung@hdfgroup.org> | 2022-04-22 13:52:01 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-04-22 13:52:01 (GMT) |
commit | a6876a974556bf70a9d736f1ab4c21b2da8e1a88 (patch) | |
tree | 2d75eef87714381de3253c1bb545323ee98b05d4 /src/H5Tnative.c | |
parent | ac9c21dd6fcccfd281c04ee14caf2e5c871191d7 (diff) | |
download | hdf5-a6876a974556bf70a9d736f1ab4c21b2da8e1a88.zip hdf5-a6876a974556bf70a9d736f1ab4c21b2da8e1a88.tar.gz hdf5-a6876a974556bf70a9d736f1ab4c21b2da8e1a88.tar.bz2 |
Replace H5detect's build-time detection of C99 integer properties with a (#1400)
* Replace H5detect's build-time detection of C99 integer properties with a
table-driven routine, `H5T__init_native_int()`, that is run at library
initialization time.
Diffstat (limited to 'src/H5Tnative.c')
-rw-r--r-- | src/H5Tnative.c | 351 |
1 files changed, 336 insertions, 15 deletions
diff --git a/src/H5Tnative.c b/src/H5Tnative.c index e75d1df..114e0a3 100644 --- a/src/H5Tnative.c +++ b/src/H5Tnative.c @@ -177,13 +177,13 @@ H5T__get_native_type(H5T_t *dtype, H5T_direction_t direction, size_t *struct_ali if (H5T_IS_VL_STRING(dtype->shared)) { /* Update size, offset and compound alignment for parent. */ - if (H5T__cmp_offset(comp_size, offset, sizeof(char *), (size_t)1, H5T_POINTER_COMP_ALIGN_g, + if (H5T__cmp_offset(comp_size, offset, sizeof(char *), (size_t)1, H5T_POINTER_ALIGN_g, struct_align) < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot compute compound offset") } /* end if */ else { /* Update size, offset and compound alignment for parent. */ - if (H5T__cmp_offset(comp_size, offset, sizeof(char), size, H5T_NATIVE_SCHAR_COMP_ALIGN_g, + if (H5T__cmp_offset(comp_size, offset, sizeof(char), size, H5T_NATIVE_SCHAR_ALIGN_g, struct_align) < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot compute compound offset") } /* end else */ @@ -208,7 +208,7 @@ H5T__get_native_type(H5T_t *dtype, H5T_direction_t direction, size_t *struct_ali HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot retrieve float type") /* Update size, offset and compound alignment for parent. */ - if (H5T__cmp_offset(comp_size, offset, sizeof(char), size, H5T_NATIVE_SCHAR_COMP_ALIGN_g, + if (H5T__cmp_offset(comp_size, offset, sizeof(char), size, H5T_NATIVE_SCHAR_ALIGN_g, struct_align) < 0) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "cannot compute compound offset") break; @@ -227,7 +227,7 @@ H5T__get_native_type(H5T_t *dtype, H5T_direction_t direction, size_t *struct_ali /* Update size, offset and compound alignment for parent. */ if (0 == H5T_cmp(ret_value, dt, FALSE)) { - align = H5T_HOBJREF_COMP_ALIGN_g; + align = H5T_HOBJREF_ALIGN_g; ref_size = sizeof(hobj_ref_t); } /* end if */ else { @@ -236,12 +236,12 @@ H5T__get_native_type(H5T_t *dtype, H5T_direction_t direction, size_t *struct_ali HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a data type") if (0 == H5T_cmp(ret_value, dt, FALSE)) { - align = H5T_HDSETREGREF_COMP_ALIGN_g; + align = H5T_HDSETREGREF_ALIGN_g; ref_size = sizeof(hdset_reg_ref_t); } /* end if */ else { /* Only pointers to underlying opaque reference types */ - align = H5T_REF_COMP_ALIGN_g; + align = H5T_REF_ALIGN_g; ref_size = sizeof(H5R_ref_t); } /* end else */ } /* end else */ @@ -479,7 +479,7 @@ H5T__get_native_type(H5T_t *dtype, H5T_direction_t direction, size_t *struct_ali HGOTO_ERROR(H5E_ARGS, H5E_CLOSEERROR, NULL, "cannot close datatype") /* Update size, offset and compound alignment for parent compound type directly. */ - vl_align = H5T_HVL_COMP_ALIGN_g; + vl_align = H5T_HVL_ALIGN_g; vl_size = sizeof(hvl_t); if (H5T__cmp_offset(comp_size, offset, vl_size, (size_t)1, vl_align, struct_align) < 0) @@ -625,7 +625,7 @@ H5T__get_native_integer(size_t prec, H5T_sign_t sign, H5T_direction_t direction, else tid = H5T_NATIVE_UCHAR; - align = H5T_NATIVE_SCHAR_COMP_ALIGN_g; + align = H5T_NATIVE_SCHAR_ALIGN_g; break; case H5T_NATIVE_INT_MATCH_SHORT: @@ -633,7 +633,7 @@ H5T__get_native_integer(size_t prec, H5T_sign_t sign, H5T_direction_t direction, tid = H5T_NATIVE_SHORT; else tid = H5T_NATIVE_USHORT; - align = H5T_NATIVE_SHORT_COMP_ALIGN_g; + align = H5T_NATIVE_SHORT_ALIGN_g; break; case H5T_NATIVE_INT_MATCH_INT: @@ -642,7 +642,7 @@ H5T__get_native_integer(size_t prec, H5T_sign_t sign, H5T_direction_t direction, else tid = H5T_NATIVE_UINT; - align = H5T_NATIVE_INT_COMP_ALIGN_g; + align = H5T_NATIVE_INT_ALIGN_g; break; case H5T_NATIVE_INT_MATCH_LONG: @@ -651,7 +651,7 @@ H5T__get_native_integer(size_t prec, H5T_sign_t sign, H5T_direction_t direction, else tid = H5T_NATIVE_ULONG; - align = H5T_NATIVE_LONG_COMP_ALIGN_g; + align = H5T_NATIVE_LONG_ALIGN_g; break; case H5T_NATIVE_INT_MATCH_LLONG: @@ -660,7 +660,7 @@ H5T__get_native_integer(size_t prec, H5T_sign_t sign, H5T_direction_t direction, else tid = H5T_NATIVE_ULLONG; - align = H5T_NATIVE_LLONG_COMP_ALIGN_g; + align = H5T_NATIVE_LLONG_ALIGN_g; break; case H5T_NATIVE_INT_MATCH_UNKNOWN: @@ -764,17 +764,17 @@ H5T__get_native_float(size_t size, H5T_direction_t direction, size_t *struct_ali switch (match) { case H5T_NATIVE_FLOAT_MATCH_FLOAT: tid = H5T_NATIVE_FLOAT; - align = H5T_NATIVE_FLOAT_COMP_ALIGN_g; + align = H5T_NATIVE_FLOAT_ALIGN_g; break; case H5T_NATIVE_FLOAT_MATCH_DOUBLE: tid = H5T_NATIVE_DOUBLE; - align = H5T_NATIVE_DOUBLE_COMP_ALIGN_g; + align = H5T_NATIVE_DOUBLE_ALIGN_g; break; case H5T_NATIVE_FLOAT_MATCH_LDOUBLE: tid = H5T_NATIVE_LDOUBLE; - align = H5T_NATIVE_LDOUBLE_COMP_ALIGN_g; + align = H5T_NATIVE_LDOUBLE_ALIGN_g; break; case H5T_NATIVE_FLOAT_MATCH_UNKNOWN: @@ -940,3 +940,324 @@ H5T__cmp_offset(size_t *comp_size, size_t *offset, size_t elem_size, size_t nele FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5T__cmp_offset() */ + +#define TAG_ALIGNMENT(tag) (offsetof(alignments_t, tag.x) - offsetof(alignments_t, tag)) + +/* clang-format off */ +#define NATIVE_ENTRY_INITIALIZER(tag, type, precision, has_sign) { \ + .alignmentp = &H5T_NATIVE_##tag##_ALIGN_g \ +, .alignment = TAG_ALIGNMENT(tag) \ +, .hidp = &H5T_NATIVE_##tag##_g \ +, .size = sizeof(type) \ +, .atomic = { \ + .offset = 0 \ + , .prec = (precision != 0) ? precision : (sizeof(type) * 8) \ + , .lsb_pad = H5T_PAD_ZERO \ + , .msb_pad = H5T_PAD_ZERO \ + , .u.i.sign = has_sign ? H5T_SGN_2 : H5T_SGN_NONE \ + } \ +} +/* clang-format on */ + +static H5T_order_t +get_host_byte_order(void) +{ + static const union { + uint64_t u64; + char byte[8]; + } endian_exemplar = {.byte = {1}}; + + return (endian_exemplar.u64 == 1) ? H5T_ORDER_LE : H5T_ORDER_BE; +} + +/* Establish `H5T_t`s for C99 integer types including fixed- and + * minimum-width types (uint16_t, uint_least16_t, uint_fast16_t, ...). + * + * Also establish alignment for some miscellaneous types: pointers, + * HDF5 references, and so on. + */ +herr_t +H5T__init_native_internal(void) +{ + /* Here we construct a type that lets us find alignment constraints + * without using the alignof operator, which is not available in C99. + * + * Between each sub-struct's `char` member `c` and member `x`, the + * compiler must insert padding to ensure proper alignment of `x`. + * We can find the alignment constraint of each `x` by looking at + * its offset from the beginning of its sub-struct. + */ + typedef struct { + struct { + char c; + signed char x; + } SCHAR; + struct { + char c; + unsigned char x; + } UCHAR; + struct { + char c; + short x; + } SHORT; + struct { + char c; + unsigned short x; + } USHORT; + struct { + char c; + int x; + } INT; + struct { + char c; + unsigned int x; + } UINT; + struct { + char c; + long x; + } LONG; + struct { + char c; + unsigned long x; + } ULONG; + struct { + char c; + long long x; + } LLONG; + struct { + char c; + unsigned long long x; + } ULLONG; + struct { + char c; + int8_t x; + } INT8; + struct { + char c; + uint8_t x; + } UINT8; + struct { + char c; + int_least8_t x; + } INT_LEAST8; + struct { + char c; + uint_least8_t x; + } UINT_LEAST8; + struct { + char c; + int_fast8_t x; + } INT_FAST8; + struct { + char c; + uint_fast8_t x; + } UINT_FAST8; + struct { + char c; + int16_t x; + } INT16; + struct { + char c; + uint16_t x; + } UINT16; + struct { + char c; + int_least16_t x; + } INT_LEAST16; + struct { + char c; + uint_least16_t x; + } UINT_LEAST16; + struct { + char c; + int_fast16_t x; + } INT_FAST16; + struct { + char c; + uint_fast16_t x; + } UINT_FAST16; + struct { + char c; + int32_t x; + } INT32; + struct { + char c; + uint32_t x; + } UINT32; + struct { + char c; + int_least32_t x; + } INT_LEAST32; + struct { + char c; + uint_least32_t x; + } UINT_LEAST32; + struct { + char c; + int_fast32_t x; + } INT_FAST32; + struct { + char c; + uint_fast32_t x; + } UINT_FAST32; + struct { + char c; + int64_t x; + } INT64; + struct { + char c; + uint64_t x; + } UINT64; + struct { + char c; + int_least64_t x; + } INT_LEAST64; + struct { + char c; + uint_least64_t x; + } UINT_LEAST64; + struct { + char c; + int_fast64_t x; + } INT_FAST64; + struct { + char c; + uint_fast64_t x; + } UINT_FAST64; + struct { + char c; + void *x; + } pointer; + struct { + char c; + hvl_t x; + } hvl; + struct { + char c; + hobj_ref_t x; + } hobjref; + struct { + char c; + hdset_reg_ref_t x; + } hdsetregref; + struct { + char c; + H5R_ref_t x; + } ref; + } alignments_t; + + /* Describe a C99 type, `type`, and tell where to write its + * H5T_t identifier and alignment. Tables of these descriptions + * drive the initialization of `H5T_t`s. + */ + typedef struct { + /* Pointer to the global variable that receives the + * alignment of `type`: + */ + size_t *alignmentp; + size_t alignment; // natural alignment of `type` + /* Pointer to the global variable that receives the + * identifier for `type`'s H5T_t: + */ + hid_t * hidp; + size_t size; // sizeof(`type`) + H5T_atomic_t atomic; // `type` facts such as signedness + } native_int_t; + + typedef struct { + const native_int_t *table; + size_t nelmts; + } native_int_table_t; + + /* clang-format off */ + + /* The library compiles with a limit on `static` object size, so + * I broke this table into three. + */ + static const native_int_t table1[] = { + NATIVE_ENTRY_INITIALIZER(SCHAR, signed char, 0, true) + , NATIVE_ENTRY_INITIALIZER(UCHAR, unsigned char, 0, false) + , NATIVE_ENTRY_INITIALIZER(SHORT, short, 0, true) + , NATIVE_ENTRY_INITIALIZER(USHORT, unsigned short, 0, false) + , NATIVE_ENTRY_INITIALIZER(INT, int, 0, true) + , NATIVE_ENTRY_INITIALIZER(UINT, unsigned int, 0, false) + , NATIVE_ENTRY_INITIALIZER(INT, int, 0, true) + , NATIVE_ENTRY_INITIALIZER(UINT, unsigned int, 0, false) + , NATIVE_ENTRY_INITIALIZER(LONG, long, 0, true) + , NATIVE_ENTRY_INITIALIZER(ULONG, unsigned long, 0, false) + , NATIVE_ENTRY_INITIALIZER(LLONG, long long, 0, true) + , NATIVE_ENTRY_INITIALIZER(ULLONG, unsigned long long, 0, false) + }; + static const native_int_t table2[] = { + NATIVE_ENTRY_INITIALIZER(INT8, int8_t, 0, true) + , NATIVE_ENTRY_INITIALIZER(UINT8, uint8_t, 0, false) + , NATIVE_ENTRY_INITIALIZER(INT_LEAST8, int_least8_t, 0, true) + , NATIVE_ENTRY_INITIALIZER(UINT_LEAST8, uint_least8_t, 0, false) + , NATIVE_ENTRY_INITIALIZER(INT_FAST8, int_fast8_t, 0, true) + , NATIVE_ENTRY_INITIALIZER(UINT_FAST8, uint_fast8_t, 0, false) + , NATIVE_ENTRY_INITIALIZER(INT16, int16_t, 0, true) + , NATIVE_ENTRY_INITIALIZER(UINT16, uint16_t, 0, false) + , NATIVE_ENTRY_INITIALIZER(INT_LEAST16, int_least16_t, 0, true) + , NATIVE_ENTRY_INITIALIZER(UINT_LEAST16, uint_least16_t, 0, false) + , NATIVE_ENTRY_INITIALIZER(INT_FAST16, int_fast16_t, 0, true) + , NATIVE_ENTRY_INITIALIZER(UINT_FAST16, uint_fast16_t, 0, false) + }; + static const native_int_t table3[] = { + NATIVE_ENTRY_INITIALIZER(INT32, int32_t, 0, true) + , NATIVE_ENTRY_INITIALIZER(UINT32, uint32_t, 0, false) + , NATIVE_ENTRY_INITIALIZER(INT_LEAST32, int_least32_t, 0, true) + , NATIVE_ENTRY_INITIALIZER(UINT_LEAST32, uint_least32_t, 0, false) + , NATIVE_ENTRY_INITIALIZER(INT_FAST32, int_fast32_t, 0, true) + , NATIVE_ENTRY_INITIALIZER(UINT_FAST32, uint_fast32_t, 0, false) + , NATIVE_ENTRY_INITIALIZER(INT64, int64_t, 0, true) + , NATIVE_ENTRY_INITIALIZER(UINT64, uint64_t, 0, false) + , NATIVE_ENTRY_INITIALIZER(INT_LEAST64, int_least64_t, 0, true) + , NATIVE_ENTRY_INITIALIZER(UINT_LEAST64, uint_least64_t, 0, false) + , NATIVE_ENTRY_INITIALIZER(INT_FAST64, int_fast64_t, 0, true) + , NATIVE_ENTRY_INITIALIZER(UINT_FAST64, uint_fast64_t, 0, false) + }; + static const native_int_table_t table_table[] = { + {table1, NELMTS(table1)} + , {table2, NELMTS(table2)} + , {table3, NELMTS(table3)} + }; + /* clang-format on */ + + size_t i, j; + H5T_order_t byte_order = get_host_byte_order(); + + for (i = 0; i < NELMTS(table_table); i++) { + const native_int_t *table = table_table[i].table; + size_t nelmts = table_table[i].nelmts; + + /* For each C99 type in `table`, create its H5T_t, + * register a hid_t for the H5T_t, and record the type's + * alignment and hid_t in the variables named by the + * table. + */ + for (j = 0; j < nelmts; j++) { + H5T_t *dt; + + if (NULL == (dt = H5T__alloc())) + return FAIL; + + dt->shared->state = H5T_STATE_IMMUTABLE; + dt->shared->type = H5T_INTEGER; + dt->shared->size = table[j].size; + dt->shared->u.atomic = table[j].atomic; + dt->shared->u.atomic.order = byte_order; + *table[j].alignmentp = table[j].alignment; + + if ((*table[j].hidp = H5I_register(H5I_DATATYPE, dt, FALSE)) < 0) + return FAIL; + } + } + + H5T_POINTER_ALIGN_g = TAG_ALIGNMENT(pointer); + H5T_HVL_ALIGN_g = TAG_ALIGNMENT(hvl); + H5T_HOBJREF_ALIGN_g = TAG_ALIGNMENT(hobjref); + H5T_HDSETREGREF_ALIGN_g = TAG_ALIGNMENT(hdsetregref); + H5T_REF_ALIGN_g = TAG_ALIGNMENT(ref); + + return SUCCEED; +} |