infix
A JIT-Powered FFI Library for C
Loading...
Searching...
No Matches
types.c
Go to the documentation of this file.
1
37#include "common/utility.h"
38#include <limits.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42// Static Descriptors for Primitive and Built-in Types
43
44#define INFIX_MAX_ALIGNMENT (1024 * 1024) // 1MB Safety Limit
45
59#define INFIX_TYPE_INIT(id, T) \
60 {.name = nullptr, \
61 .category = INFIX_TYPE_PRIMITIVE, \
62 .size = sizeof(T), \
63 .alignment = _Alignof(T), \
64 .is_arena_allocated = false, \
65 .arena = nullptr, \
66 .source_offset = 0, \
67 .meta.primitive_id = id}
73static infix_type _infix_type_void = {.name = nullptr,
74 .category = INFIX_TYPE_VOID,
75 .size = 0,
76 .alignment = 0,
77 .is_arena_allocated = false,
78 .arena = nullptr,
79 .source_offset = 0,
80 .meta = {0}};
86static infix_type _infix_type_pointer = {.name = nullptr,
87 .category = INFIX_TYPE_POINTER,
88 .size = sizeof(void *),
89 .alignment = _Alignof(void *),
90 .is_arena_allocated = false,
91 .arena = nullptr,
92 .source_offset = 0,
93 .meta.pointer_info = {.pointee_type = &_infix_type_void}};
112#if !defined(INFIX_COMPILER_MSVC)
117#endif
122#if defined(INFIX_COMPILER_MSVC) || (defined(INFIX_OS_WINDOWS) && defined(INFIX_COMPILER_CLANG))
123// On these platforms, long double is just an alias for double, so no separate singleton is needed.
124#else
127#endif
128// Public API: Type Creation Functions
136 switch (id) {
138 return &_infix_type_bool;
140 return &_infix_type_uint8;
142 return &_infix_type_sint8;
144 return &_infix_type_uint16;
146 return &_infix_type_sint16;
148 return &_infix_type_uint32;
150 return &_infix_type_sint32;
152 return &_infix_type_uint64;
154 return &_infix_type_sint64;
155#if !defined(INFIX_COMPILER_MSVC)
157 return &_infix_type_uint128;
159 return &_infix_type_sint128;
160#endif
162 return &_infix_type_float;
164 return &_infix_type_double;
166#if defined(INFIX_COMPILER_MSVC) || (defined(INFIX_OS_WINDOWS) && defined(INFIX_COMPILER_CLANG))
167 // On MSVC and macOS/Clang (sometimes), long double is an alias for double.
168 // We map to the double singleton to maintain type identity.
169 return &_infix_type_double;
170#else
171 // On MinGW and Linux, long double is distinct (16 bytes).
172 // We MUST use the distinct type to handle layout and passing correctly.
174#endif
175 default:
176 // Return null for any invalid primitive ID.
177 return nullptr;
178 }
179}
197INFIX_API infix_struct_member infix_type_create_member(const char * name, infix_type * type, size_t offset) {
198 return (infix_struct_member){name, type, offset, 0, 0, false};
199}
209 infix_type * type,
210 size_t offset,
211 uint8_t bit_width) {
212 return (infix_struct_member){name, type, offset, bit_width, 0, true};
213}
214
220static bool _layout_struct(infix_type * type) {
221 size_t current_byte_offset = 0;
222 uint8_t current_bit_offset = 0; // 0-7 bits used in the current byte
223 size_t max_alignment = 1;
224
225 for (size_t i = 0; i < type->meta.aggregate_info.num_members; ++i) {
226 infix_struct_member * member = &type->meta.aggregate_info.members[i];
227
228 // 1. Handle Flexible Array Members (FAM)
229 if (member->type->category == INFIX_TYPE_ARRAY && member->type->meta.array_info.is_flexible) {
230 // Flush any pending bits to the next byte
231 if (current_bit_offset > 0) {
232 if (current_byte_offset == SIZE_MAX) {
234 return false;
235 }
236 current_byte_offset++;
237 current_bit_offset = 0;
238 }
239
240 // FAM aligns according to its element type.
241 size_t member_align = member->type->alignment;
242 if (member_align == 0)
243 member_align = 1;
244
245 size_t aligned = _infix_align_up(current_byte_offset, member_align);
246 if (aligned < current_byte_offset) {
248 return false;
249 }
250 current_byte_offset = aligned;
251 member->offset = current_byte_offset;
252
253 if (member_align > max_alignment)
254 max_alignment = member_align;
255 continue; // FAM logic done
256 }
257
258 // 2. Handle Bitfields
259 if (member->is_bitfield) {
260 // Zero-width bitfield: force alignment to the next boundary of the declared type.
261 if (member->bit_width == 0) {
262 if (current_bit_offset > 0) {
263 if (current_byte_offset == SIZE_MAX) {
265 return false;
266 }
267 current_byte_offset++;
268 current_bit_offset = 0;
269 }
270 size_t align = member->type->alignment;
271 if (align == 0)
272 align = 1;
273
274 size_t aligned = _infix_align_up(current_byte_offset, align);
275 if (aligned < current_byte_offset) {
277 return false;
278 }
279 current_byte_offset = aligned;
280 member->offset = current_byte_offset;
281 member->bit_offset = 0;
282
283 if (align > max_alignment)
284 max_alignment = align;
285 continue;
286 }
287
288 // Standard Bitfield
289 // Simplified System V packing: pack into current byte if it fits.
290 if (current_bit_offset + member->bit_width > 8) {
291 // Overflow: move to start of next byte
292 if (current_byte_offset == SIZE_MAX) {
294 return false;
295 }
296 current_byte_offset++;
297 current_bit_offset = 0;
298 }
299
300 member->offset = current_byte_offset;
301 member->bit_offset = current_bit_offset;
302 current_bit_offset += member->bit_width;
303
304 // If we filled the byte exactly, advance to next byte
305 if (current_bit_offset == 8) {
306 if (current_byte_offset == SIZE_MAX) {
308 return false;
309 }
310 current_byte_offset++;
311 current_bit_offset = 0;
312 }
313
314 // Update struct alignment. Bitfields typically impose the alignment of their base type.
315 size_t align = member->type->alignment;
316 if (align == 0)
317 align = 1;
318 if (align > max_alignment)
319 max_alignment = align;
320 }
321 else {
322 // 3. Standard Member
323
324 // Flush bits first
325 if (current_bit_offset > 0) {
326 if (current_byte_offset == SIZE_MAX) {
328 return false;
329 }
330 current_byte_offset++;
331 current_bit_offset = 0;
332 }
333
334 size_t member_align = member->type->alignment;
335 if (member_align == 0)
336 member_align = 1;
337
338 if (member_align > max_alignment)
339 max_alignment = member_align;
340
341 size_t aligned = _infix_align_up(current_byte_offset, member_align);
342 if (aligned < current_byte_offset) {
344 return false;
345 }
346 current_byte_offset = aligned;
347 member->offset = current_byte_offset;
348
349 if (current_byte_offset > SIZE_MAX - member->type->size) {
351 return false;
352 }
353 current_byte_offset += member->type->size;
354 }
355 }
356
357 // Final flush
358 if (current_bit_offset > 0)
359 current_byte_offset++;
360
361 // If it is packed, the alignment is explicitly determined by the user (defaulting to 1
362 // if not specified in the syntax). We must respect this value absolutely, ignoring
363 // the natural alignment of members.
364 if (type->meta.aggregate_info.is_packed)
365 max_alignment = type->alignment;
366
367 type->alignment = max_alignment;
368 type->size = _infix_align_up(current_byte_offset, max_alignment);
369 return true;
370}
389 infix_type ** out_type,
390 infix_struct_member ** out_arena_members,
392 size_t num_members) {
393 if (out_type == nullptr)
395 // Pre-flight check: ensure all provided member types are valid.
396 for (size_t i = 0; i < num_members; ++i) {
397 if (members[i].type == nullptr) {
398 *out_type = nullptr;
401 }
402 }
403 infix_type * type = infix_arena_calloc(arena, 1, sizeof(infix_type), _Alignof(infix_type));
404 if (type == nullptr) {
405 *out_type = nullptr;
408 }
409 infix_struct_member * arena_members = nullptr;
410 if (num_members > 0) {
411 arena_members =
412 infix_arena_alloc(arena, sizeof(infix_struct_member) * num_members, _Alignof(infix_struct_member));
413 if (arena_members == nullptr) {
414 *out_type = nullptr;
417 }
418 infix_memcpy(arena_members, members, sizeof(infix_struct_member) * num_members);
419 }
420 *out_type = type;
421 *out_arena_members = arena_members;
422 return INFIX_SUCCESS;
423}
432 infix_type ** out_type,
433 infix_type * pointee_type) {
434 if (!out_type || !pointee_type) {
437 }
438 infix_type * type = infix_arena_calloc(arena, 1, sizeof(infix_type), _Alignof(infix_type));
439 if (type == nullptr) {
440 *out_type = nullptr;
443 }
444 // Start by copying the layout of a generic pointer.
445 *type = *infix_type_create_pointer();
446 // Mark it as arena-allocated so it can be deep-copied and freed correctly.
447 type->is_arena_allocated = true;
448 // Set the specific pointee type.
449 type->meta.pointer_info.pointee_type = pointee_type;
450 *out_type = type;
451 return INFIX_SUCCESS;
452}
462 infix_type ** out_type,
463 infix_type * element_type,
464 size_t num_elements) {
465 if (out_type == nullptr || element_type == nullptr) {
468 }
469 if (element_type->size > 0 && num_elements > SIZE_MAX / element_type->size) {
470 *out_type = nullptr;
473 }
474 infix_type * type = infix_arena_calloc(arena, 1, sizeof(infix_type), _Alignof(infix_type));
475 if (type == nullptr) {
476 *out_type = nullptr;
479 }
480 type->is_arena_allocated = true;
482 type->meta.array_info.element_type = element_type;
483 type->meta.array_info.num_elements = num_elements;
484 type->meta.array_info.is_flexible = false;
485 // An array's alignment is the same as its element's alignment.
486 type->alignment = element_type->alignment;
487 type->size = element_type->size * num_elements;
488 *out_type = type;
489 return INFIX_SUCCESS;
490}
491
500 infix_type ** out_type,
501 infix_type * element_type) {
502 if (out_type == nullptr || element_type == nullptr) {
505 }
506 // Flexible arrays of incomplete types (size 0) are generally not allowed.
507 if (element_type->category == INFIX_TYPE_VOID || element_type->size == 0) {
508 *out_type = nullptr;
511 }
512
513 infix_type * type = infix_arena_calloc(arena, 1, sizeof(infix_type), _Alignof(infix_type));
514 if (type == nullptr) {
515 *out_type = nullptr;
518 }
519 type->is_arena_allocated = true;
521 type->meta.array_info.element_type = element_type;
522 type->meta.array_info.num_elements = 0;
523 type->meta.array_info.is_flexible = true; // Mark as flexible
524
525 // A flexible array member itself has size 0 within the struct (it hangs off the end).
526 // However, its alignment requirement affects the struct.
527 type->alignment = element_type->alignment;
528 type->size = 0;
529
530 *out_type = type;
531 return INFIX_SUCCESS;
532}
533
543 infix_type ** out_type,
544 infix_type * underlying_type) {
545 if (out_type == nullptr || underlying_type == nullptr) {
548 }
549 if (underlying_type->category != INFIX_TYPE_PRIMITIVE ||
550 underlying_type->meta.primitive_id > INFIX_PRIMITIVE_SINT128) {
553 }
554 infix_type * type = infix_arena_calloc(arena, 1, sizeof(infix_type), _Alignof(infix_type));
555 if (type == nullptr) {
556 *out_type = nullptr;
559 }
560 type->is_arena_allocated = true;
562 // An enum has the same memory layout as its underlying integer type.
563 type->size = underlying_type->size;
564 type->alignment = underlying_type->alignment;
565 type->meta.enum_info.underlying_type = underlying_type;
566 *out_type = type;
567 return INFIX_SUCCESS;
568}
577 infix_type ** out_type,
578 infix_type * base_type) {
579 if (out_type == nullptr || base_type == nullptr || (!is_float(base_type) && !is_double(base_type))) {
582 }
583 infix_type * type = infix_arena_calloc(arena, 1, sizeof(infix_type), _Alignof(infix_type));
584 if (type == nullptr) {
585 *out_type = nullptr;
588 }
589 type->is_arena_allocated = true;
591 // A complex number is simply two floating-point numbers back-to-back.
592 type->size = base_type->size * 2;
593 type->alignment = base_type->alignment;
594 type->meta.complex_info.base_type = base_type;
595 *out_type = type;
596 return INFIX_SUCCESS;
597}
607 infix_type ** out_type,
608 infix_type * element_type,
609 size_t num_elements) {
610 if (out_type == nullptr || element_type == nullptr || element_type->category != INFIX_TYPE_PRIMITIVE) {
613 }
614 if (element_type->size > 0 && num_elements > SIZE_MAX / element_type->size) {
615 *out_type = nullptr;
618 }
619 infix_type * type = infix_arena_calloc(arena, 1, sizeof(infix_type), _Alignof(infix_type));
620 if (type == nullptr) {
621 *out_type = nullptr;
624 }
625 type->is_arena_allocated = true;
627 type->meta.vector_info.element_type = element_type;
628 type->meta.vector_info.num_elements = num_elements;
629 type->size = element_type->size * num_elements;
630 // Vector alignment is typically its total size, up to a platform-specific maximum (e.g., 16 on x64).
631 // This is a simplification; the ABI-specific classifiers will handle the true alignment rules.
632 type->alignment = type->size > 8 ? 16 : type->size;
633 *out_type = type;
634 return INFIX_SUCCESS;
635}
645 infix_type ** out_type,
647 size_t num_members) {
648 infix_type * type = nullptr;
649 infix_struct_member * arena_members = nullptr;
650 infix_status status = _create_aggregate_setup(arena, &type, &arena_members, members, num_members);
651 if (status != INFIX_SUCCESS) {
652 *out_type = nullptr;
653 return status;
654 }
655 type->is_arena_allocated = true;
657 type->meta.aggregate_info.members = arena_members;
658 type->meta.aggregate_info.num_members = num_members;
659 type->meta.aggregate_info.is_packed = false; // Unions don't use this flag currently
660 // A union's size is the size of its largest member, and its alignment is the
661 // alignment of its most-aligned member.
662 size_t max_size = 0;
663 size_t max_alignment = 1;
664 for (size_t i = 0; i < num_members; ++i) {
665 arena_members[i].offset = 0; // All union members have an offset of 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)
669 max_alignment = arena_members[i].type->alignment;
670 }
671 type->alignment = max_alignment;
672 // The total size is the size of the largest member, padded up to the required alignment.
673 type->size = _infix_align_up(max_size, max_alignment);
674 // Overflow check
675 if (type->size < max_size) {
676 *out_type = nullptr;
679 }
680 *out_type = type;
681 return INFIX_SUCCESS;
682}
692 infix_type ** out_type,
694 size_t num_members) {
696 infix_type * type = nullptr;
697 infix_struct_member * arena_members = nullptr;
698 infix_status status = _create_aggregate_setup(arena, &type, &arena_members, members, num_members);
699 if (status != INFIX_SUCCESS) {
700 *out_type = nullptr;
701 return status;
702 }
703 type->is_arena_allocated = true;
705 type->meta.aggregate_info.members = arena_members;
706 type->meta.aggregate_info.num_members = num_members;
707 type->meta.aggregate_info.is_packed = false;
708
709 // This performs a preliminary layout calculation.
710 // Note: This layout may be incomplete if it contains unresolved named references or flexible arrays.
711 // The final, correct layout will be computed by `_infix_type_recalculate_layout`.
712 // However, we must set a preliminary size/alignment here.
713
714 // We use the recalculate logic to do the heavy lifting, assuming a temporary arena can be made.
715 // But we can't create an arena here easily if we are in a strict context.
716 // So we do a simplified pass just like the old logic, ignoring complex bitfield rules for now.
717 // The proper bitfield layout happens in `_infix_type_recalculate_layout`.
718
719 for (size_t i = 0; i < num_members; ++i) {
720 infix_struct_member * member = &arena_members[i];
721 if (member->type->alignment == 0 && member->type->category != INFIX_TYPE_NAMED_REFERENCE &&
722 !(member->type->category == INFIX_TYPE_ARRAY && member->type->meta.array_info.is_flexible)) {
723 if (member->type->category != INFIX_TYPE_ARRAY) {
724 *out_type = nullptr;
727 }
728 }
729 }
730
731 // Calculate Layout (including bitfields and FAMs)
732 if (!_layout_struct(type)) {
733 *out_type = nullptr;
735 }
736
737 *out_type = type;
738 return INFIX_SUCCESS;
739}
751 infix_type ** out_type,
752 size_t total_size,
753 size_t alignment,
755 size_t num_members) {
756 if (out_type == nullptr || (num_members > 0 && members == nullptr)) {
759 }
760 // Validate alignment is power-of-two AND within sane limits.
761 if (alignment == 0 || (alignment & (alignment - 1)) != 0) {
764 }
765 if (alignment > INFIX_MAX_ALIGNMENT) {
768 }
769 infix_type * type = infix_arena_calloc(arena, 1, sizeof(infix_type), _Alignof(infix_type));
770 if (type == nullptr) {
771 *out_type = nullptr;
774 }
775 infix_struct_member * arena_members = nullptr;
776 if (num_members > 0) {
777 arena_members =
778 infix_arena_alloc(arena, sizeof(infix_struct_member) * num_members, _Alignof(infix_struct_member));
779 if (arena_members == nullptr) {
780 *out_type = nullptr;
783 }
784 infix_memcpy(arena_members, members, sizeof(infix_struct_member) * num_members);
785 }
786 type->is_arena_allocated = true;
787 type->size = total_size;
788 type->alignment = alignment;
789 type->category = INFIX_TYPE_STRUCT; // Packed structs are still fundamentally structs.
790 type->meta.aggregate_info.members = arena_members;
791 type->meta.aggregate_info.num_members = num_members;
792 type->meta.aggregate_info.is_packed = true; // Marked as packed
793 *out_type = type;
794 return INFIX_SUCCESS;
795}
808 infix_type ** out_type,
809 const char * name,
811 if (out_type == nullptr || name == nullptr) {
814 }
815 infix_type * type = infix_arena_calloc(arena, 1, sizeof(infix_type), _Alignof(infix_type));
816 if (type == nullptr) {
817 *out_type = nullptr;
820 }
821 // The name must be copied into the arena to ensure its lifetime matches the type's.
822 size_t name_len = strlen(name) + 1;
823 char * arena_name = infix_arena_alloc(arena, name_len, 1);
824 if (arena_name == nullptr) {
825 *out_type = nullptr;
828 }
829 infix_memcpy(arena_name, name, name_len);
830 type->is_arena_allocated = true;
832 type->size = 0; // Size and alignment are unknown until resolution.
833 type->alignment = 1; // Default to 1 to be safe in preliminary layout calculations.
834 type->meta.named_reference.name = arena_name;
836 *out_type = type;
837 return INFIX_SUCCESS;
838}
839// Internal Type Graph Management
880 recalc_visited_node_t ** visited_head) {
881 if (!type || !type->is_arena_allocated)
882 return; // Base case: Don't modify static singleton types.
883 // Cycle detection: If we have already visited this node in the current recursion
884 // path, we are in a cycle. Return immediately to break the loop. The layout of
885 // this node will be calculated when the recursion unwinds to its first visit.
886 for (recalc_visited_node_t * v = *visited_head; v != nullptr; v = v->next)
887 if (v->type == type)
888 return;
889 // Allocate the memoization node from a stable temporary arena.
890 recalc_visited_node_t * visited_node =
891 infix_arena_alloc(temp_arena, sizeof(recalc_visited_node_t), _Alignof(recalc_visited_node_t));
892 if (!visited_node)
893 return; // Cannot proceed without memory.
894 visited_node->type = type;
895 visited_node->next = *visited_head;
896 *visited_head = visited_node;
897 // Recurse into child types first (post-order traversal).
898 switch (type->category) {
901 break;
902 case INFIX_TYPE_ARRAY:
904 break;
906 case INFIX_TYPE_UNION:
907 for (size_t i = 0; i < type->meta.aggregate_info.num_members; ++i) {
909 temp_arena, type->meta.aggregate_info.members[i].type, visited_head);
910 }
911 break;
912 default:
913 break; // Other types have no child types to recurse into.
914 }
915 // After children are updated, recalculate this type's layout.
918 else if (type->category == INFIX_TYPE_UNION) {
919 size_t max_size = 0;
920 size_t max_alignment = 1;
921 for (size_t i = 0; i < type->meta.aggregate_info.num_members; ++i) {
922 infix_type * member_type = type->meta.aggregate_info.members[i].type;
923 if (member_type->size > max_size)
924 max_size = member_type->size;
925 if (member_type->alignment > max_alignment)
926 max_alignment = member_type->alignment;
927 }
928 type->alignment = max_alignment;
929 type->size = _infix_align_up(max_size, max_alignment);
930 }
931 else if (type->category == INFIX_TYPE_ARRAY) {
932 // Flexible arrays have size 0 but inherit alignment.
933 // Fixed arrays calculate size normally.
936 type->size = 0;
937 }
938 else {
941 }
942 }
943}
954 // Create a temporary arena solely for the visited list's lifetime.
955 infix_arena_t * temp_arena = infix_arena_create(1024);
956 if (!temp_arena)
957 return;
958 recalc_visited_node_t * visited_head = nullptr;
959 _infix_type_recalculate_layout_recursive(temp_arena, type, &visited_head);
960 infix_arena_destroy(temp_arena);
961}
990 const infix_type * src_type,
991 memo_node_t ** memo_head) {
992 if (src_type == nullptr)
993 return nullptr;
994 // If the source type lives in the same arena as our destination, we can safely share the pointer instead of
995 // performing a deep copy.
996 if (src_type->arena == dest_arena)
997 return (infix_type *)src_type;
998 // Base case: Static types don't need to be copied; return the singleton pointer.
999 if (!src_type->is_arena_allocated)
1000 return (infix_type *)src_type;
1001 // Check memoization table: if we've already copied this node, return the existing copy.
1002 // This correctly handles cycles and shared sub-graphs.
1003 for (memo_node_t * node = *memo_head; node != NULL; node = node->next)
1004 if (node->src == src_type)
1005 return node->dest;
1006 // Allocate the new type object in the destination arena.
1007 infix_type * dest_type = infix_arena_calloc(dest_arena, 1, sizeof(infix_type), _Alignof(infix_type));
1008 if (dest_type == nullptr)
1009 return nullptr;
1010 // Add this new pair to the memoization table BEFORE recursing. This is crucial
1011 // for handling cycles: the recursive call will find this entry and return `dest_type`.
1012 memo_node_t * new_memo_node = infix_arena_alloc(dest_arena, sizeof(memo_node_t), _Alignof(memo_node_t));
1013 if (!new_memo_node)
1014 return 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;
1019 // Perform a shallow copy of the main struct, then recurse to deep copy child pointers.
1020 *dest_type = *src_type;
1021 dest_type->is_arena_allocated = true;
1022 dest_type->is_incomplete = src_type->is_incomplete;
1023 dest_type->arena = dest_arena; // The new type now belongs to the destination arena.
1024 // Deep copy the semantic name string, if it exists.
1025 if (src_type->name) {
1026 size_t name_len = strlen(src_type->name) + 1;
1027 char * dest_name = infix_arena_alloc(dest_arena, name_len, 1);
1028 if (!dest_name)
1029 return nullptr; // Allocation failed
1030 infix_memcpy((void *)dest_name, src_type->name, name_len);
1031 dest_type->name = dest_name;
1032 }
1033 switch (src_type->category) {
1034 case INFIX_TYPE_POINTER:
1035 dest_type->meta.pointer_info.pointee_type =
1036 _copy_type_graph_to_arena_recursive(dest_arena, src_type->meta.pointer_info.pointee_type, memo_head);
1037 break;
1038 case INFIX_TYPE_ARRAY:
1039 dest_type->meta.array_info.element_type =
1040 _copy_type_graph_to_arena_recursive(dest_arena, src_type->meta.array_info.element_type, memo_head);
1041 // Explicitly copy the flexible flag to ensure it persists.
1042 dest_type->meta.array_info.is_flexible = src_type->meta.array_info.is_flexible;
1043 break;
1044 case INFIX_TYPE_STRUCT:
1045 case INFIX_TYPE_UNION:
1046 if (src_type->meta.aggregate_info.num_members > 0) {
1047 // Copy the members array itself.
1048 size_t members_size = sizeof(infix_struct_member) * src_type->meta.aggregate_info.num_members;
1049 dest_type->meta.aggregate_info.members =
1050 infix_arena_alloc(dest_arena, members_size, _Alignof(infix_struct_member));
1051 if (dest_type->meta.aggregate_info.members == nullptr)
1052 return nullptr;
1053 dest_type->meta.aggregate_info.is_packed = src_type->meta.aggregate_info.is_packed; // Copy packed flag
1054 // Now, recurse for each member's type and copy its name.
1055 for (size_t i = 0; i < src_type->meta.aggregate_info.num_members; ++i) {
1056 dest_type->meta.aggregate_info.members[i] = src_type->meta.aggregate_info.members[i];
1058 dest_arena, src_type->meta.aggregate_info.members[i].type, memo_head);
1059 const char * src_name = src_type->meta.aggregate_info.members[i].name;
1060 if (src_name) {
1061 size_t name_len = strlen(src_name) + 1;
1062 char * dest_name = infix_arena_alloc(dest_arena, name_len, 1);
1063 if (!dest_name)
1064 return nullptr;
1065 infix_memcpy((void *)dest_name, src_name, name_len);
1066 dest_type->meta.aggregate_info.members[i].name = dest_name;
1067 }
1068 // Copy bitfield properties
1069 dest_type->meta.aggregate_info.members[i].bit_width =
1070 src_type->meta.aggregate_info.members[i].bit_width;
1071 dest_type->meta.aggregate_info.members[i].bit_offset =
1073 dest_type->meta.aggregate_info.members[i].is_bitfield =
1075 }
1076 }
1077 break;
1079 {
1080 const char * src_name = src_type->meta.named_reference.name;
1081 if (src_name) {
1082 size_t name_len = strlen(src_name) + 1;
1083 char * dest_name = infix_arena_alloc(dest_arena, name_len, 1);
1084 if (!dest_name)
1085 return nullptr;
1086 infix_memcpy((void *)dest_name, src_name, name_len);
1087 dest_type->meta.named_reference.name = dest_name;
1088 }
1089 break;
1090 }
1092 dest_type->meta.func_ptr_info.return_type =
1093 _copy_type_graph_to_arena_recursive(dest_arena, src_type->meta.func_ptr_info.return_type, memo_head);
1094 if (src_type->meta.func_ptr_info.num_args > 0) {
1095 size_t args_size = sizeof(infix_function_argument) * src_type->meta.func_ptr_info.num_args;
1096 dest_type->meta.func_ptr_info.args =
1097 infix_arena_alloc(dest_arena, args_size, _Alignof(infix_function_argument));
1098 if (dest_type->meta.func_ptr_info.args == nullptr)
1099 return nullptr;
1100 for (size_t i = 0; i < src_type->meta.func_ptr_info.num_args; ++i) {
1101 dest_type->meta.func_ptr_info.args[i] = src_type->meta.func_ptr_info.args[i];
1103 dest_arena, src_type->meta.func_ptr_info.args[i].type, memo_head);
1104 const char * src_name = src_type->meta.func_ptr_info.args[i].name;
1105 if (src_name) {
1106 size_t name_len = strlen(src_name) + 1;
1107 char * dest_name = infix_arena_alloc(dest_arena, name_len, 1);
1108 if (!dest_name)
1109 return nullptr;
1110 infix_memcpy((void *)dest_name, src_name, name_len);
1111 dest_type->meta.func_ptr_info.args[i].name = dest_name;
1112 }
1113 }
1114 }
1115 break;
1116 case INFIX_TYPE_ENUM:
1117 dest_type->meta.enum_info.underlying_type =
1118 _copy_type_graph_to_arena_recursive(dest_arena, src_type->meta.enum_info.underlying_type, memo_head);
1119 break;
1120 case INFIX_TYPE_COMPLEX:
1121 dest_type->meta.complex_info.base_type =
1122 _copy_type_graph_to_arena_recursive(dest_arena, src_type->meta.complex_info.base_type, memo_head);
1123 break;
1124 case INFIX_TYPE_VECTOR:
1125 dest_type->meta.vector_info.element_type =
1126 _copy_type_graph_to_arena_recursive(dest_arena, src_type->meta.vector_info.element_type, memo_head);
1127 break;
1128 default:
1129 // Other types like primitives have no child pointers to copy.
1130 break;
1131 }
1132 return dest_type;
1133}
1142 memo_node_t * memo_head = nullptr;
1143 return _copy_type_graph_to_arena_recursive(dest_arena, src_type, &memo_head);
1144}
1167 const infix_type * type,
1168 estimate_visited_node_t ** visited_head) {
1169 if (!type || !type->is_arena_allocated)
1170 return 0;
1171 // Cycle detection: if we've seen this node, it's already accounted for.
1172 for (estimate_visited_node_t * v = *visited_head; v != NULL; v = v->next)
1173 if (v->type == type)
1174 return 0;
1175 // Add this node to the visited list before recursing.
1176 estimate_visited_node_t * visited_node =
1178 if (!visited_node) {
1179 // On allocation failure, we can't proceed with estimation. Return a large
1180 // number to ensure the caller allocates a fallback-sized arena.
1181 return 65536;
1182 }
1183 visited_node->type = type;
1184 visited_node->next = *visited_head;
1185 *visited_head = visited_node;
1186 // The size includes the type object itself, a memoization node, and the name string if it exists.
1187 size_t total_size = sizeof(infix_type) + sizeof(memo_node_t);
1188 if (type->name)
1189 total_size += strlen(type->name) + 1;
1190 switch (type->category) {
1191 case INFIX_TYPE_POINTER:
1192 total_size += _estimate_graph_size_recursive(temp_arena, type->meta.pointer_info.pointee_type, visited_head);
1193 break;
1194 case INFIX_TYPE_ARRAY:
1195 total_size += _estimate_graph_size_recursive(temp_arena, type->meta.array_info.element_type, visited_head);
1196 break;
1197 case INFIX_TYPE_STRUCT:
1198 case INFIX_TYPE_UNION:
1200 total_size += sizeof(infix_struct_member) * type->meta.aggregate_info.num_members;
1201 for (size_t i = 0; i < type->meta.aggregate_info.num_members; ++i) {
1202 const infix_struct_member * member = &type->meta.aggregate_info.members[i];
1203 if (member->name)
1204 total_size += strlen(member->name) + 1;
1205 total_size += _estimate_graph_size_recursive(temp_arena, member->type, visited_head);
1206 }
1207 }
1208 break;
1211 total_size += strlen(type->meta.named_reference.name) + 1;
1212 break;
1214 total_size += _estimate_graph_size_recursive(temp_arena, type->meta.func_ptr_info.return_type, visited_head);
1215 if (type->meta.func_ptr_info.num_args > 0) {
1216 total_size += sizeof(infix_function_argument) * type->meta.func_ptr_info.num_args;
1217 for (size_t i = 0; i < type->meta.func_ptr_info.num_args; ++i) {
1219 if (arg->name)
1220 total_size += strlen(arg->name) + 1;
1221 total_size += _estimate_graph_size_recursive(temp_arena, arg->type, visited_head);
1222 }
1223 }
1224 break;
1225 case INFIX_TYPE_ENUM:
1226 total_size += _estimate_graph_size_recursive(temp_arena, type->meta.enum_info.underlying_type, visited_head);
1227 break;
1228 case INFIX_TYPE_COMPLEX:
1229 total_size += _estimate_graph_size_recursive(temp_arena, type->meta.complex_info.base_type, visited_head);
1230 break;
1231 case INFIX_TYPE_VECTOR:
1232 total_size += _estimate_graph_size_recursive(temp_arena, type->meta.vector_info.element_type, visited_head);
1233 break;
1234 default:
1235 break;
1236 }
1237 return total_size;
1238}
1247 if (!temp_arena || !type)
1248 return 0;
1249 estimate_visited_node_t * visited_head = nullptr;
1250 return _estimate_graph_size_recursive(temp_arena, type, &visited_head);
1251}
1252// Public API: Introspection Functions
1260 if (type == nullptr)
1261 return nullptr;
1262 return type->name;
1263}
1304 return nullptr;
1305 return &type->meta.aggregate_info.members[index];
1306}
1314INFIX_API c23_nodiscard const char * infix_type_get_arg_name(const infix_type * func_type, size_t index) {
1315 if (!func_type || func_type->category != INFIX_TYPE_REVERSE_TRAMPOLINE ||
1316 index >= func_type->meta.func_ptr_info.num_args)
1317 return nullptr;
1318 return func_type->meta.func_ptr_info.args[index].name;
1319}
1326INFIX_API c23_nodiscard const infix_type * infix_type_get_arg_type(const infix_type * func_type, size_t index) {
1327 if (!func_type || func_type->category != INFIX_TYPE_REVERSE_TRAMPOLINE ||
1328 index >= func_type->meta.func_ptr_info.num_args)
1329 return nullptr;
1330 return func_type->meta.func_ptr_info.args[index].type;
1331}
1338 return trampoline ? trampoline->num_args : 0;
1339}
1346 return trampoline ? trampoline->num_fixed_args : 0;
1347}
1354 return trampoline ? trampoline->return_type : nullptr;
1355}
1363 size_t index) {
1364 if (!trampoline || index >= trampoline->num_args)
1365 return nullptr;
1366 return trampoline->arg_types[index];
1367}
1374 return trampoline ? trampoline->num_args : 0;
1375}
1382 return trampoline ? trampoline->num_fixed_args : 0;
1383}
1390 return trampoline ? trampoline->return_type : nullptr;
1391}
1399 size_t index) {
1400 if (!trampoline || index >= trampoline->num_args)
1401 return nullptr;
1402 return trampoline->arg_types[index];
1403}
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
Definition types.c:1150
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
Definition types.c:970
infix_type * dest
Definition types.c:972
struct memo_node_t * next
Definition types.c:973
const infix_type * src
Definition types.c:971
Definition types.c:852
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.