44#define INFIX_MAX_ALIGNMENT (1024 * 1024)
59#define INFIX_TYPE_INIT(id, T) \
61 .category = INFIX_TYPE_PRIMITIVE, \
63 .alignment = _Alignof(T), \
64 .is_arena_allocated = false, \
67 .meta.primitive_id = id}
77 .is_arena_allocated =
false,
88 .size =
sizeof(
void *),
89 .alignment = _Alignof(
void *),
90 .is_arena_allocated =
false,
112#if !defined(INFIX_COMPILER_MSVC)
122#if defined(INFIX_COMPILER_MSVC) || (defined(INFIX_OS_WINDOWS) && defined(INFIX_COMPILER_CLANG))
155#if !defined(INFIX_COMPILER_MSVC)
166#if defined(INFIX_COMPILER_MSVC) || (defined(INFIX_OS_WINDOWS) && defined(INFIX_COMPILER_CLANG))
221 size_t current_byte_offset = 0;
222 uint8_t current_bit_offset = 0;
223 size_t max_alignment = 1;
231 if (current_bit_offset > 0) {
232 if (current_byte_offset == SIZE_MAX) {
236 current_byte_offset++;
237 current_bit_offset = 0;
242 if (member_align == 0)
246 if (aligned < current_byte_offset) {
250 current_byte_offset = aligned;
251 member->
offset = current_byte_offset;
253 if (member_align > max_alignment)
254 max_alignment = member_align;
262 if (current_bit_offset > 0) {
263 if (current_byte_offset == SIZE_MAX) {
267 current_byte_offset++;
268 current_bit_offset = 0;
275 if (aligned < current_byte_offset) {
279 current_byte_offset = aligned;
280 member->
offset = current_byte_offset;
283 if (align > max_alignment)
284 max_alignment = align;
290 if (current_bit_offset + member->
bit_width > 8) {
292 if (current_byte_offset == SIZE_MAX) {
296 current_byte_offset++;
297 current_bit_offset = 0;
300 member->
offset = current_byte_offset;
305 if (current_bit_offset == 8) {
306 if (current_byte_offset == SIZE_MAX) {
310 current_byte_offset++;
311 current_bit_offset = 0;
318 if (align > max_alignment)
319 max_alignment = align;
325 if (current_bit_offset > 0) {
326 if (current_byte_offset == SIZE_MAX) {
330 current_byte_offset++;
331 current_bit_offset = 0;
335 if (member_align == 0)
338 if (member_align > max_alignment)
339 max_alignment = member_align;
342 if (aligned < current_byte_offset) {
346 current_byte_offset = aligned;
347 member->
offset = current_byte_offset;
349 if (current_byte_offset > SIZE_MAX - member->
type->
size) {
353 current_byte_offset += member->
type->
size;
358 if (current_bit_offset > 0)
359 current_byte_offset++;
392 size_t num_members) {
393 if (out_type ==
nullptr)
396 for (
size_t i = 0; i < num_members; ++i) {
397 if (
members[i].type ==
nullptr) {
404 if (type ==
nullptr) {
410 if (num_members > 0) {
413 if (arena_members ==
nullptr) {
421 *out_arena_members = arena_members;
434 if (!out_type || !pointee_type) {
439 if (type ==
nullptr) {
464 size_t num_elements) {
465 if (out_type ==
nullptr || element_type ==
nullptr) {
469 if (element_type->
size > 0 && num_elements > SIZE_MAX / element_type->
size) {
475 if (type ==
nullptr) {
487 type->
size = element_type->
size * num_elements;
502 if (out_type ==
nullptr || element_type ==
nullptr) {
514 if (type ==
nullptr) {
545 if (out_type ==
nullptr || underlying_type ==
nullptr) {
555 if (type ==
nullptr) {
579 if (out_type ==
nullptr || base_type ==
nullptr || (!
is_float(base_type) && !
is_double(base_type))) {
584 if (type ==
nullptr) {
609 size_t num_elements) {
614 if (element_type->
size > 0 && num_elements > SIZE_MAX / element_type->
size) {
620 if (type ==
nullptr) {
629 type->
size = element_type->
size * num_elements;
647 size_t num_members) {
663 size_t max_alignment = 1;
664 for (
size_t i = 0; i < num_members; ++i) {
665 arena_members[i].
offset = 0;
666 if (arena_members[i].type->
size > max_size)
667 max_size = arena_members[i].
type->
size;
668 if (arena_members[i].type->
alignment > max_alignment)
675 if (type->
size < max_size) {
694 size_t num_members) {
719 for (
size_t i = 0; i < num_members; ++i) {
755 size_t num_members) {
756 if (out_type ==
nullptr || (num_members > 0 &&
members ==
nullptr)) {
761 if (alignment == 0 || (alignment & (alignment - 1)) != 0) {
770 if (type ==
nullptr) {
776 if (num_members > 0) {
779 if (arena_members ==
nullptr) {
787 type->
size = total_size;
811 if (out_type ==
nullptr || name ==
nullptr) {
816 if (type ==
nullptr) {
822 size_t name_len = strlen(name) + 1;
824 if (arena_name ==
nullptr) {
895 visited_node->
next = *visited_head;
896 *visited_head = visited_node;
920 size_t max_alignment = 1;
923 if (member_type->
size > max_size)
924 max_size = member_type->
size;
925 if (member_type->
alignment > max_alignment)
992 if (src_type ==
nullptr)
996 if (src_type->
arena == dest_arena)
1003 for (
memo_node_t * node = *memo_head; node != NULL; node = node->
next)
1004 if (node->src == src_type)
1008 if (dest_type ==
nullptr)
1015 new_memo_node->
src = src_type;
1016 new_memo_node->
dest = dest_type;
1017 new_memo_node->
next = *memo_head;
1018 *memo_head = new_memo_node;
1020 *dest_type = *src_type;
1023 dest_type->
arena = dest_arena;
1025 if (src_type->
name) {
1026 size_t name_len = strlen(src_type->
name) + 1;
1031 dest_type->
name = dest_name;
1061 size_t name_len = strlen(src_name) + 1;
1082 size_t name_len = strlen(src_name) + 1;
1106 size_t name_len = strlen(src_name) + 1;
1173 if (v->type ==
type)
1178 if (!visited_node) {
1184 visited_node->
next = *visited_head;
1185 *visited_head = visited_node;
1189 total_size += strlen(
type->
name) + 1;
1204 total_size += strlen(member->
name) + 1;
1220 total_size += strlen(arg->
name) + 1;
1247 if (!temp_arena || !
type)
1260 if (
type ==
nullptr)
1338 return trampoline ? trampoline->
num_args : 0;
1354 return trampoline ? trampoline->
return_type :
nullptr;
1364 if (!trampoline || index >= trampoline->
num_args)
1374 return trampoline ? trampoline->
num_args : 0;
1390 return trampoline ? trampoline->
return_type :
nullptr;
1400 if (!trampoline || index >= trampoline->
num_args)
infix_arena_t * arena
Definition 005_layouts.c:62
infix_status status
Definition 103_unions.c:61
infix_struct_member * members
Definition 103_unions.c:55
#define c23_nodiscard
Internal alias for the public INFIX_NODISCARD macro.
Definition compat_c23.h:91
@ INFIX_CODE_INVALID_MEMBER_TYPE
Definition infix.h:1369
@ INFIX_CODE_INVALID_ALIGNMENT
Definition infix.h:1353
@ INFIX_CODE_INTEGER_OVERFLOW
Definition infix.h:1360
@ INFIX_CODE_TYPE_TOO_LARGE
Definition infix.h:1367
@ INFIX_CODE_NULL_POINTER
Definition infix.h:1346
@ INFIX_CODE_OUT_OF_MEMORY
Definition infix.h:1350
@ INFIX_CATEGORY_ABI
Definition infix.h:1337
@ INFIX_CATEGORY_ALLOCATION
Definition infix.h:1335
@ INFIX_CATEGORY_GENERAL
Definition infix.h:1334
@ INFIX_CATEGORY_PARSER
Definition infix.h:1336
struct infix_type_t::@0::@1 pointer_info
Metadata for INFIX_TYPE_POINTER.
union infix_type_t::@0 meta
A union containing metadata specific to the type's category.
bool is_packed
Definition infix.h:294
struct infix_type_t::@0::@7 vector_info
Metadata for INFIX_TYPE_VECTOR.
bool is_incomplete
Definition infix.h:279
infix_type * type
Definition infix.h:347
struct infix_type_t::@0::@4 func_ptr_info
Metadata for INFIX_TYPE_REVERSE_TRAMPOLINE.
size_t num_elements
Definition infix.h:299
infix_arena_t * arena
Definition infix.h:280
size_t size
Definition infix.h:276
size_t alignment
Definition infix.h:277
uint8_t bit_offset
Definition infix.h:338
infix_struct_member * members
Definition infix.h:292
bool is_bitfield
Definition infix.h:339
struct infix_type_t::@0::@6 complex_info
Metadata for INFIX_TYPE_COMPLEX.
const char * name
Definition infix.h:274
infix_function_argument * args
Definition infix.h:305
infix_aggregate_category_t aggregate_category
Definition infix.h:325
infix_status
Enumerates the possible status codes returned by infix API functions.
Definition infix.h:433
const char * name
Definition infix.h:346
const char * name
Definition infix.h:334
infix_type_category category
Definition infix.h:275
struct infix_type_t::@0::@2 aggregate_info
Metadata for INFIX_TYPE_STRUCT and INFIX_TYPE_UNION.
struct infix_type_t::@0::@3 array_info
Metadata for INFIX_TYPE_ARRAY.
struct infix_type_t * pointee_type
Definition infix.h:288
infix_type * type
Definition infix.h:335
struct infix_type_t * element_type
Definition infix.h:298
bool is_flexible
Definition infix.h:300
struct infix_type_t * return_type
Definition infix.h:304
size_t offset
Definition infix.h:336
struct infix_type_t::@0::@5 enum_info
Metadata for INFIX_TYPE_ENUM.
struct infix_type_t * base_type
Definition infix.h:315
uint8_t bit_width
Definition infix.h:337
size_t num_members
Definition infix.h:293
struct infix_type_t * underlying_type
Definition infix.h:311
struct infix_type_t::@0::@8 named_reference
Metadata for INFIX_TYPE_NAMED_REFERENCE.
infix_primitive_type_id primitive_id
Metadata for INFIX_TYPE_PRIMITIVE.
Definition infix.h:285
size_t num_args
Definition infix.h:306
bool is_arena_allocated
Definition infix.h:278
@ INFIX_ERROR_ALLOCATION_FAILED
Definition infix.h:435
@ INFIX_SUCCESS
Definition infix.h:434
@ INFIX_ERROR_INVALID_ARGUMENT
Definition infix.h:436
INFIX_API c23_nodiscard size_t infix_forward_get_num_args(const infix_forward_t *trampoline)
Gets the total number of arguments for a forward trampoline.
Definition types.c:1337
INFIX_API INFIX_NODISCARD void * infix_arena_alloc(infix_arena_t *, size_t, size_t)
Allocates a block of memory from an arena.
Definition arena.c:117
#define infix_memcpy
A macro that can be defined to override the default memcpy function.
Definition infix.h:386
INFIX_API INFIX_NODISCARD infix_arena_t * infix_arena_create(size_t)
Creates a new memory arena.
Definition arena.c:52
INFIX_API INFIX_NODISCARD void * infix_arena_calloc(infix_arena_t *, size_t, size_t, size_t)
Allocates and zero-initializes a block of memory from an arena.
Definition arena.c:188
INFIX_API void infix_arena_destroy(infix_arena_t *)
Destroys an arena and frees all memory allocated from it.
Definition arena.c:83
struct infix_type_t infix_type
A semi-opaque object describing a C type's memory layout and calling convention. See infix_type_t for...
Definition infix.h:207
c23_nodiscard infix_status infix_type_create_pointer_to(infix_arena_t *arena, infix_type **out_type, infix_type *pointee_type)
Creates a new pointer type that points to a specific type.
Definition types.c:431
INFIX_API infix_struct_member infix_type_create_member(const char *name, infix_type *type, size_t offset)
A factory function to create an infix_struct_member.
Definition types.c:197
INFIX_API c23_nodiscard infix_status infix_type_create_packed_struct(infix_arena_t *arena, infix_type **out_type, size_t total_size, size_t alignment, infix_struct_member *members, size_t num_members)
Creates a new packed struct type with a user-specified layout.
Definition types.c:750
INFIX_API c23_nodiscard infix_status infix_type_create_complex(infix_arena_t *arena, infix_type **out_type, infix_type *base_type)
Creates a new _Complex number type.
Definition types.c:576
INFIX_API c23_nodiscard const infix_type * infix_forward_get_arg_type(const infix_forward_t *trampoline, size_t index)
Gets the type of a specific argument for a forward trampoline.
Definition types.c:1362
infix_primitive_type_id
Enumerates the supported primitive C types.
Definition infix.h:243
INFIX_API c23_nodiscard infix_type * infix_type_create_void(void)
Creates a static descriptor for the void type.
Definition types.c:189
INFIX_API c23_nodiscard const infix_struct_member * infix_type_get_member(const infix_type *type, size_t index)
Gets a specific member from a struct or union type.
Definition types.c:1301
INFIX_API c23_nodiscard infix_status infix_type_create_union(infix_arena_t *arena, infix_type **out_type, infix_struct_member *members, size_t num_members)
Creates a new union type from an array of members.
Definition types.c:644
INFIX_API c23_nodiscard const char * infix_type_get_arg_name(const infix_type *func_type, size_t index)
Gets the name of a specific argument from a function type.
Definition types.c:1314
struct infix_struct_member_t infix_struct_member
A semi-opaque object describing a member of a C struct or union. See infix_struct_member_t for detail...
Definition infix.h:209
INFIX_API infix_struct_member infix_type_create_bitfield_member(const char *name, infix_type *type, size_t offset, uint8_t bit_width)
A factory function to create a bitfield infix_struct_member.
Definition types.c:208
INFIX_API c23_nodiscard size_t infix_type_get_size(const infix_type *type)
Gets the size of a type in bytes.
Definition types.c:1277
INFIX_API c23_nodiscard const infix_type * infix_forward_get_return_type(const infix_forward_t *trampoline)
Gets the return type for a forward trampoline.
Definition types.c:1353
INFIX_API c23_nodiscard infix_status infix_type_create_named_reference(infix_arena_t *arena, infix_type **out_type, const char *name, infix_aggregate_category_t agg_cat)
Creates a placeholder for a named type that will be resolved later by a type registry.
Definition types.c:807
INFIX_API c23_nodiscard const infix_type * infix_reverse_get_return_type(const infix_reverse_t *trampoline)
Gets the return type for a reverse trampoline.
Definition types.c:1389
INFIX_API c23_nodiscard const infix_type * infix_type_get_arg_type(const infix_type *func_type, size_t index)
Gets the type of a specific argument from a function type.
Definition types.c:1326
INFIX_API c23_nodiscard size_t infix_type_get_member_count(const infix_type *type)
Gets the number of members in a struct or union type.
Definition types.c:1290
struct infix_function_argument_t infix_function_argument
A semi-opaque object describing an argument to a C function. See infix_function_argument_t for detail...
Definition infix.h:211
INFIX_API c23_nodiscard infix_type_category infix_type_get_category(const infix_type *type)
Gets the fundamental category of a type.
Definition types.c:1269
INFIX_API c23_nodiscard infix_type * infix_type_create_primitive(infix_primitive_type_id id)
Creates a static descriptor for a primitive C type.
Definition types.c:135
INFIX_API c23_nodiscard infix_type * infix_type_create_pointer(void)
Creates a static descriptor for a generic pointer (void*).
Definition types.c:184
INFIX_API c23_nodiscard size_t infix_reverse_get_num_fixed_args(const infix_reverse_t *trampoline)
Gets the number of fixed (non-variadic) arguments for a reverse trampoline.
Definition types.c:1381
infix_type_category
Enumerates the fundamental categories of types that infix can represent.
Definition infix.h:227
INFIX_API c23_nodiscard infix_status infix_type_create_vector(infix_arena_t *arena, infix_type **out_type, infix_type *element_type, size_t num_elements)
Creates a new SIMD vector type.
Definition types.c:606
INFIX_API c23_nodiscard const infix_type * infix_reverse_get_arg_type(const infix_reverse_t *trampoline, size_t index)
Gets the type of a specific argument for a reverse trampoline.
Definition types.c:1398
INFIX_API c23_nodiscard const char * infix_type_get_name(const infix_type *type)
Gets the semantic alias of a type, if one exists.
Definition types.c:1259
INFIX_API c23_nodiscard infix_status infix_type_create_struct(infix_arena_t *arena, infix_type **out_type, infix_struct_member *members, size_t num_members)
Creates a new struct type from an array of members, calculating layout automatically.
Definition types.c:691
infix_aggregate_category_t
Specifies whether a named type reference refers to a struct or a union.
Definition infix.h:263
INFIX_API c23_nodiscard size_t infix_forward_get_num_fixed_args(const infix_forward_t *trampoline)
Gets the number of fixed (non-variadic) arguments for a forward trampoline.
Definition types.c:1345
INFIX_API c23_nodiscard infix_status infix_type_create_enum(infix_arena_t *arena, infix_type **out_type, infix_type *underlying_type)
Creates a new enum type with a specified underlying integer type.
Definition types.c:542
INFIX_API c23_nodiscard size_t infix_reverse_get_num_args(const infix_reverse_t *trampoline)
Gets the total number of arguments for a reverse trampoline.
Definition types.c:1373
INFIX_API c23_nodiscard infix_status infix_type_create_flexible_array(infix_arena_t *arena, infix_type **out_type, infix_type *element_type)
Creates a new flexible array member type ([?:type]).
Definition types.c:499
INFIX_API c23_nodiscard infix_status infix_type_create_array(infix_arena_t *arena, infix_type **out_type, infix_type *element_type, size_t num_elements)
Creates a new fixed-size array type.
Definition types.c:461
INFIX_API c23_nodiscard size_t infix_type_get_alignment(const infix_type *type)
Gets the alignment requirement of a type in bytes.
Definition types.c:1283
@ INFIX_PRIMITIVE_UINT16
Definition infix.h:247
@ INFIX_PRIMITIVE_UINT32
Definition infix.h:249
@ INFIX_PRIMITIVE_LONG_DOUBLE
Definition infix.h:257
@ INFIX_PRIMITIVE_FLOAT
Definition infix.h:255
@ INFIX_PRIMITIVE_DOUBLE
Definition infix.h:256
@ INFIX_PRIMITIVE_SINT16
Definition infix.h:248
@ INFIX_PRIMITIVE_SINT64
Definition infix.h:252
@ INFIX_PRIMITIVE_SINT32
Definition infix.h:250
@ INFIX_PRIMITIVE_UINT8
Definition infix.h:245
@ INFIX_PRIMITIVE_UINT128
Definition infix.h:253
@ INFIX_PRIMITIVE_BOOL
Definition infix.h:244
@ INFIX_PRIMITIVE_UINT64
Definition infix.h:251
@ INFIX_PRIMITIVE_SINT128
Definition infix.h:254
@ INFIX_PRIMITIVE_SINT8
Definition infix.h:246
@ INFIX_TYPE_UNION
Definition infix.h:231
@ INFIX_TYPE_PRIMITIVE
Definition infix.h:228
@ INFIX_TYPE_COMPLEX
Definition infix.h:235
@ INFIX_TYPE_ARRAY
Definition infix.h:232
@ INFIX_TYPE_VECTOR
Definition infix.h:236
@ INFIX_TYPE_VOID
Definition infix.h:238
@ INFIX_TYPE_POINTER
Definition infix.h:229
@ INFIX_TYPE_NAMED_REFERENCE
Definition infix.h:237
@ INFIX_TYPE_REVERSE_TRAMPOLINE
Definition infix.h:233
@ INFIX_TYPE_ENUM
Definition infix.h:234
@ INFIX_TYPE_STRUCT
Definition infix.h:230
#define INFIX_API
Symbol visibility macro.
Definition infix.h:114
Internal data structures, function prototypes, and constants.
static size_t _infix_align_up(size_t value, size_t alignment)
Aligns a value up to the next multiple of a power-of-two alignment.
Definition infix_internals.h:712
static bool is_double(const infix_type *type)
A fast inline check to determine if an infix_type is a double.
Definition infix_internals.h:728
INFIX_INTERNAL void _infix_clear_error(void)
Clears the thread-local error state.
Definition error.c:266
static bool is_float(const infix_type *type)
A fast inline check to determine if an infix_type is a float.
Definition infix_internals.h:720
INFIX_INTERNAL void _infix_set_error(infix_error_category_t category, infix_error_code_t code, size_t position)
Sets the thread-local error state with detailed information.
Definition error.c:173
struct estimate_visited_node_t * next
Definition types.c:1152
const infix_type * type
Definition types.c:1151
Internal definition of a memory arena.
Definition infix_internals.h:138
Internal definition of a forward trampoline handle.
Definition infix_internals.h:88
size_t num_args
Definition infix_internals.h:95
size_t num_fixed_args
Definition infix_internals.h:96
infix_type ** arg_types
Definition infix_internals.h:94
infix_type * return_type
Definition infix_internals.h:93
Describes a single argument to a C function.
Definition infix.h:345
Internal definition of a reverse trampoline (callback/closure) handle.
Definition infix_internals.h:114
infix_type * return_type
Definition infix_internals.h:118
size_t num_args
Definition infix_internals.h:120
size_t num_fixed_args
Definition infix_internals.h:121
infix_type ** arg_types
Definition infix_internals.h:119
Describes a single member of a C struct or union.
Definition infix.h:333
A semi-opaque structure that describes a C type.
Definition infix.h:273
infix_type * dest
Definition types.c:972
struct memo_node_t * next
Definition types.c:973
const infix_type * src
Definition types.c:971
struct recalc_visited_node_t * next
Definition types.c:854
infix_type * type
Definition types.c:853
static size_t _estimate_graph_size_recursive(infix_arena_t *temp_arena, const infix_type *type, estimate_visited_node_t **visited_head)
Definition types.c:1166
static infix_type _infix_type_sint128
Definition types.c:116
void _infix_type_recalculate_layout(infix_type *type)
Recalculates the layout of a fully resolved type graph.
Definition types.c:953
static infix_type _infix_type_double
Definition types.c:121
static infix_type _infix_type_uint32
Definition types.c:105
static infix_type _infix_type_bool
Definition types.c:95
static infix_type _infix_type_float
Definition types.c:119
infix_type * _copy_type_graph_to_arena(infix_arena_t *dest_arena, const infix_type *src_type)
Performs a deep copy of a type graph into a destination arena.
Definition types.c:1141
static infix_type _infix_type_sint64
Definition types.c:111
#define INFIX_TYPE_INIT(id, T)
Definition types.c:59
size_t _infix_estimate_graph_size(infix_arena_t *temp_arena, const infix_type *type)
Estimates the total memory required to deep-copy a complete type graph.
Definition types.c:1246
static infix_type _infix_type_sint16
Definition types.c:103
#define INFIX_MAX_ALIGNMENT
Definition types.c:44
static infix_type _infix_type_uint16
Definition types.c:101
static infix_type _infix_type_long_double
Definition types.c:126
static infix_type _infix_type_pointer
Definition types.c:86
static infix_type _infix_type_uint128
Definition types.c:114
static infix_type _infix_type_void
Definition types.c:73
static infix_type _infix_type_sint32
Definition types.c:107
static infix_type * _copy_type_graph_to_arena_recursive(infix_arena_t *dest_arena, const infix_type *src_type, memo_node_t **memo_head)
Definition types.c:989
static infix_type _infix_type_uint64
Definition types.c:109
static infix_status _create_aggregate_setup(infix_arena_t *arena, infix_type **out_type, infix_struct_member **out_arena_members, infix_struct_member *members, size_t num_members)
Definition types.c:388
static void _infix_type_recalculate_layout_recursive(infix_arena_t *temp_arena, infix_type *type, recalc_visited_node_t **visited_head)
Definition types.c:878
static bool _layout_struct(infix_type *type)
Definition types.c:220
static infix_type _infix_type_uint8
Definition types.c:97
static infix_type _infix_type_sint8
Definition types.c:99
A header for conditionally compiled debugging utilities.