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
120 .category = INFIX_TYPE_PRIMITIVE,
121 .size = 2,
122 .alignment = 2,
123 .is_arena_allocated = false,
124 .arena = nullptr,
125 .source_offset = 0,
126 .meta.primitive_id = INFIX_PRIMITIVE_FLOAT16};
131#if defined(INFIX_COMPILER_MSVC) || (defined(INFIX_OS_WINDOWS) && defined(INFIX_COMPILER_CLANG))
132// On these platforms, long double is just an alias for double, so no separate singleton is needed.
133#else
136#endif
137// Public API: Type Creation Functions
145 switch (id) {
147 return &_infix_type_bool;
149 return &_infix_type_uint8;
151 return &_infix_type_sint8;
153 return &_infix_type_uint16;
155 return &_infix_type_sint16;
157 return &_infix_type_uint32;
159 return &_infix_type_sint32;
161 return &_infix_type_uint64;
163 return &_infix_type_sint64;
164#if !defined(INFIX_COMPILER_MSVC)
166 return &_infix_type_uint128;
168 return &_infix_type_sint128;
169#endif
171 return &_infix_type_float16;
173 return &_infix_type_float;
175 return &_infix_type_double;
177#if defined(INFIX_COMPILER_MSVC) || (defined(INFIX_OS_WINDOWS) && defined(INFIX_COMPILER_CLANG))
178 // On MSVC and macOS/Clang (sometimes), long double is an alias for double.
179 // We map to the double singleton to maintain type identity.
180 return &_infix_type_double;
181#else
182 // On MinGW and Linux, long double is distinct (16 bytes).
183 // We MUST use the distinct type to handle layout and passing correctly.
185#endif
186 default:
187 // Return null for any invalid primitive ID.
188 return nullptr;
189 }
190}
208INFIX_API infix_struct_member infix_type_create_member(const char * name, infix_type * type, size_t offset) {
209 return (infix_struct_member){name, type, offset, 0, 0, false};
210}
220 infix_type * type,
221 size_t offset,
222 uint8_t bit_width) {
223 return (infix_struct_member){name, type, offset, bit_width, 0, true};
224}
225
231static bool _layout_struct(infix_type * type) {
232 size_t current_byte_offset = 0;
233 size_t current_unit_offset = 0;
234 size_t current_unit_size = 0;
235 uint32_t current_unit_bits_used = 0;
236 size_t max_alignment = 1;
237 bool in_bitfield = false;
238
239 for (size_t i = 0; i < type->meta.aggregate_info.num_members; ++i) {
240 infix_struct_member * member = &type->meta.aggregate_info.members[i];
241 infix_type * mtype = member->type;
242
243 if (member->is_bitfield) {
244 size_t align = mtype->alignment;
245 if (align == 0)
246 align = 1;
247 if (type->meta.aggregate_info.is_packed)
248 align = 1;
249 if (align > max_alignment && !type->meta.aggregate_info.is_packed)
250 max_alignment = align;
251
252 // Zero-width bitfield or type mismatch or doesn't fit -> start new unit
253 if (member->bit_width == 0 || !in_bitfield || mtype->size != current_unit_size ||
254 current_unit_bits_used + member->bit_width > mtype->size * 8) {
255
256 // Align to start of new unit
257 size_t start = _infix_align_up(current_byte_offset, align);
258 if (start < current_byte_offset) {
260 return false;
261 }
262
263 current_unit_offset = start;
264 current_unit_size = mtype->size;
265 current_unit_bits_used = 0;
266 in_bitfield = true;
267
268 current_byte_offset = current_unit_offset;
269 }
270
271 member->offset = current_unit_offset + (current_unit_bits_used / 8);
272 member->bit_offset = (uint8_t)(current_unit_bits_used % 8);
273 current_unit_bits_used += member->bit_width;
274
275 size_t bytes_used = (current_unit_bits_used + 7) / 8;
276 if (current_unit_offset + bytes_used > current_byte_offset)
277 current_byte_offset = current_unit_offset + bytes_used;
278 }
279 else {
280 // Handle Flexible Array Members (FAM)
281 if (mtype->category == INFIX_TYPE_ARRAY && mtype->meta.array_info.is_flexible) {
282 in_bitfield = false;
283 size_t align = mtype->alignment;
284 if (align == 0)
285 align = 1;
286 if (type->meta.aggregate_info.is_packed)
287 align = 1;
288
289 if (align > max_alignment && !type->meta.aggregate_info.is_packed)
290 max_alignment = align;
291
292 size_t aligned = _infix_align_up(current_byte_offset, align);
293 if (aligned < current_byte_offset) {
295 return false;
296 }
297 current_byte_offset = aligned;
298 member->offset = current_byte_offset;
299 member->bit_offset = 0;
300 continue;
301 }
302
303 // Standard Member
304 in_bitfield = false;
305 size_t align = mtype->alignment;
306 if (align == 0)
307 align = 1;
308 if (type->meta.aggregate_info.is_packed)
309 align = 1;
310
311 if (align > max_alignment && !type->meta.aggregate_info.is_packed)
312 max_alignment = align;
313
314 size_t aligned = _infix_align_up(current_byte_offset, align);
315 if (aligned < current_byte_offset) {
317 return false;
318 }
319 current_byte_offset = aligned;
320 member->offset = current_byte_offset;
321 member->bit_offset = 0;
322
323 if (current_byte_offset > SIZE_MAX - mtype->size) {
325 return false;
326 }
327 current_byte_offset += mtype->size;
328 }
329 }
330
331 // If it is packed, the alignment is explicitly determined by the user.
332 if (type->meta.aggregate_info.is_packed)
333 max_alignment = type->alignment;
334
335 type->alignment = max_alignment;
336 type->size = _infix_align_up(current_byte_offset, max_alignment);
337 return true;
338}
357 infix_type ** out_type,
358 infix_struct_member ** out_arena_members,
360 size_t num_members) {
361 if (out_type == nullptr)
363 // Pre-flight check: ensure all provided member types are valid.
364 for (size_t i = 0; i < num_members; ++i) {
365 if (members[i].type == nullptr) {
366 *out_type = nullptr;
369 }
370 }
371 infix_type * type = infix_arena_calloc(arena, 1, sizeof(infix_type), _Alignof(infix_type));
372 if (type == nullptr) {
373 *out_type = nullptr;
376 }
377 infix_struct_member * arena_members = nullptr;
378 if (num_members > 0) {
379 arena_members =
380 infix_arena_alloc(arena, sizeof(infix_struct_member) * num_members, _Alignof(infix_struct_member));
381 if (arena_members == nullptr) {
382 *out_type = nullptr;
385 }
386 infix_memcpy(arena_members, members, sizeof(infix_struct_member) * num_members);
387 }
388 *out_type = type;
389 *out_arena_members = arena_members;
390 return INFIX_SUCCESS;
391}
400 infix_type ** out_type,
401 infix_type * pointee_type) {
403 if (!out_type || !pointee_type) {
406 }
407 infix_type * type = infix_arena_calloc(arena, 1, sizeof(infix_type), _Alignof(infix_type));
408 if (type == nullptr) {
409 *out_type = nullptr;
412 }
413 // Start by copying the layout of a generic pointer.
414 *type = *infix_type_create_pointer();
415 // Mark it as arena-allocated so it can be deep-copied and freed correctly.
416 type->is_arena_allocated = true;
417 // Set the specific pointee type.
418 type->meta.pointer_info.pointee_type = pointee_type;
419 *out_type = type;
420 return INFIX_SUCCESS;
421}
431 infix_type ** out_type,
432 infix_type * element_type,
433 size_t num_elements) {
435 if (out_type == nullptr || element_type == nullptr) {
438 }
439 if (element_type->size > 0 && num_elements > SIZE_MAX / element_type->size) {
440 *out_type = nullptr;
443 }
444 infix_type * type = infix_arena_calloc(arena, 1, sizeof(infix_type), _Alignof(infix_type));
445 if (type == nullptr) {
446 *out_type = nullptr;
449 }
450 type->is_arena_allocated = true;
452 type->meta.array_info.element_type = element_type;
453 type->meta.array_info.num_elements = num_elements;
454 type->meta.array_info.is_flexible = false;
455 // An array's alignment is the same as its element's alignment.
456 type->alignment = element_type->alignment;
457 type->size = element_type->size * num_elements;
458 *out_type = type;
459 return INFIX_SUCCESS;
460}
461
470 infix_type ** out_type,
471 infix_type * element_type) {
473 if (out_type == nullptr || element_type == nullptr) {
476 }
477 // Flexible arrays of incomplete types (size 0) are generally not allowed.
478 if (element_type->category == INFIX_TYPE_VOID || element_type->size == 0) {
479 *out_type = nullptr;
482 }
483
484 infix_type * type = infix_arena_calloc(arena, 1, sizeof(infix_type), _Alignof(infix_type));
485 if (type == nullptr) {
486 *out_type = nullptr;
489 }
490 type->is_arena_allocated = true;
492 type->meta.array_info.element_type = element_type;
493 type->meta.array_info.num_elements = 0;
494 type->meta.array_info.is_flexible = true; // Mark as flexible
495
496 // A flexible array member itself has size 0 within the struct (it hangs off the end).
497 // However, its alignment requirement affects the struct.
498 type->alignment = element_type->alignment;
499 type->size = 0;
500
501 *out_type = type;
502 return INFIX_SUCCESS;
503}
504
514 infix_type ** out_type,
515 infix_type * underlying_type) {
517 if (out_type == nullptr || underlying_type == nullptr) {
520 }
521 if (underlying_type->category != INFIX_TYPE_PRIMITIVE ||
522 underlying_type->meta.primitive_id > INFIX_PRIMITIVE_SINT128) {
525 }
526 infix_type * type = infix_arena_calloc(arena, 1, sizeof(infix_type), _Alignof(infix_type));
527 if (type == nullptr) {
528 *out_type = nullptr;
531 }
532 type->is_arena_allocated = true;
534 // An enum has the same memory layout as its underlying integer type.
535 type->size = underlying_type->size;
536 type->alignment = underlying_type->alignment;
537 type->meta.enum_info.underlying_type = underlying_type;
538 *out_type = type;
539 return INFIX_SUCCESS;
540}
549 infix_type ** out_type,
550 infix_type * base_type) {
552 if (out_type == nullptr || base_type == nullptr || (!is_float(base_type) && !is_double(base_type))) {
555 }
556 infix_type * type = infix_arena_calloc(arena, 1, sizeof(infix_type), _Alignof(infix_type));
557 if (type == nullptr) {
558 *out_type = nullptr;
561 }
562 type->is_arena_allocated = true;
564 // A complex number is simply two floating-point numbers back-to-back.
565 type->size = base_type->size * 2;
566 type->alignment = base_type->alignment;
567 type->meta.complex_info.base_type = base_type;
568 *out_type = type;
569 return INFIX_SUCCESS;
570}
580 infix_type ** out_type,
581 infix_type * element_type,
582 size_t num_elements) {
584 if (out_type == nullptr || element_type == nullptr || element_type->category != INFIX_TYPE_PRIMITIVE) {
587 }
588 if (element_type->size > 0 && num_elements > SIZE_MAX / element_type->size) {
589 *out_type = nullptr;
592 }
593 infix_type * type = infix_arena_calloc(arena, 1, sizeof(infix_type), _Alignof(infix_type));
594 if (type == nullptr) {
595 *out_type = nullptr;
598 }
599 type->is_arena_allocated = true;
601 type->meta.vector_info.element_type = element_type;
602 type->meta.vector_info.num_elements = num_elements;
603 type->size = element_type->size * num_elements;
604 // Vector alignment is its total size.
605 // This ensures __m128 is 16-byte aligned, __m256 is 32-byte, and __m512 is 64-byte.
606 type->alignment = type->size;
607 *out_type = type;
608 return INFIX_SUCCESS;
609}
619 infix_type ** out_type,
621 size_t num_members) {
623 infix_type * type = nullptr;
624 infix_struct_member * arena_members = nullptr;
625 infix_status status = _create_aggregate_setup(arena, &type, &arena_members, members, num_members);
626 if (status != INFIX_SUCCESS) {
627 *out_type = nullptr;
628 return status;
629 }
630 type->is_arena_allocated = true;
632 type->meta.aggregate_info.members = arena_members;
633 type->meta.aggregate_info.num_members = num_members;
634 type->meta.aggregate_info.is_packed = false; // Unions don't use this flag currently
635 // A union's size is the size of its largest member, and its alignment is the
636 // alignment of its most-aligned member.
637 size_t max_size = 0;
638 size_t max_alignment = 1;
639 for (size_t i = 0; i < num_members; ++i) {
640 arena_members[i].offset = 0; // All union members have an offset of 0.
641 if (arena_members[i].type->size > max_size)
642 max_size = arena_members[i].type->size;
643 if (arena_members[i].type->alignment > max_alignment)
644 max_alignment = arena_members[i].type->alignment;
645 }
646 type->alignment = max_alignment;
647 // The total size is the size of the largest member, padded up to the required alignment.
648 type->size = _infix_align_up(max_size, max_alignment);
649 // Overflow check
650 if (type->size < max_size) {
651 *out_type = nullptr;
654 }
655 *out_type = type;
656 return INFIX_SUCCESS;
657}
667 infix_type ** out_type,
669 size_t num_members) {
671 infix_type * type = nullptr;
672 infix_struct_member * arena_members = nullptr;
673 infix_status status = _create_aggregate_setup(arena, &type, &arena_members, members, num_members);
674 if (status != INFIX_SUCCESS) {
675 *out_type = nullptr;
676 return status;
677 }
678 type->is_arena_allocated = true;
680 type->meta.aggregate_info.members = arena_members;
681 type->meta.aggregate_info.num_members = num_members;
682 type->meta.aggregate_info.is_packed = false;
683
684 // This performs a preliminary layout calculation.
685 // Note: This layout may be incomplete if it contains unresolved named references or flexible arrays.
686 // The final, correct layout will be computed by `_infix_type_recalculate_layout`.
687 // However, we must set a preliminary size/alignment here.
688
689 // We use the recalculate logic to do the heavy lifting, assuming a temporary arena can be made.
690 // But we can't create an arena here easily if we are in a strict context.
691 // So we do a simplified pass just like the old logic, ignoring complex bitfield rules for now.
692 // The proper bitfield layout happens in `_infix_type_recalculate_layout`.
693
694 for (size_t i = 0; i < num_members; ++i) {
695 infix_struct_member * member = &arena_members[i];
696 if (member->type->alignment == 0 && member->type->category != INFIX_TYPE_NAMED_REFERENCE &&
697 !(member->type->category == INFIX_TYPE_ARRAY && member->type->meta.array_info.is_flexible)) {
698 if (member->type->category != INFIX_TYPE_ARRAY) {
699 *out_type = nullptr;
702 }
703 }
704 }
705
706 // Calculate Layout (including bitfields and FAMs)
707 if (!_layout_struct(type)) {
708 *out_type = nullptr;
710 }
711
712 *out_type = type;
713 return INFIX_SUCCESS;
714}
726 infix_type ** out_type,
727 size_t total_size,
728 size_t alignment,
730 size_t num_members) {
732 if (out_type == nullptr || (num_members > 0 && members == nullptr)) {
735 }
736 // Validate alignment is power-of-two AND within sane limits.
737 if (alignment == 0 || (alignment & (alignment - 1)) != 0) {
740 }
741 if (alignment > INFIX_MAX_ALIGNMENT) {
744 }
745 infix_type * type = infix_arena_calloc(arena, 1, sizeof(infix_type), _Alignof(infix_type));
746 if (type == nullptr) {
747 *out_type = nullptr;
750 }
751 infix_struct_member * arena_members = nullptr;
752 if (num_members > 0) {
753 arena_members =
754 infix_arena_alloc(arena, sizeof(infix_struct_member) * num_members, _Alignof(infix_struct_member));
755 if (arena_members == nullptr) {
756 *out_type = nullptr;
759 }
760 infix_memcpy(arena_members, members, sizeof(infix_struct_member) * num_members);
761 }
762 type->is_arena_allocated = true;
763 type->size = total_size;
764 type->alignment = alignment;
765 type->category = INFIX_TYPE_STRUCT; // Packed structs are still fundamentally structs.
766 type->meta.aggregate_info.members = arena_members;
767 type->meta.aggregate_info.num_members = num_members;
768 type->meta.aggregate_info.is_packed = true; // Marked as packed
769 // Calculate member offsets (with alignment=1 for all members).
770 if (!_layout_struct(type)) {
771 *out_type = nullptr;
773 }
774 *out_type = type;
775 return INFIX_SUCCESS;
776}
789 infix_type ** out_type,
790 const char * name,
793 if (out_type == nullptr || name == nullptr) {
796 }
797 infix_type * type = infix_arena_calloc(arena, 1, sizeof(infix_type), _Alignof(infix_type));
798 if (type == nullptr) {
799 *out_type = nullptr;
802 }
803 // The name must be copied into the arena to ensure its lifetime matches the type's.
804 size_t name_len = strlen(name) + 1;
805 char * arena_name = infix_arena_alloc(arena, name_len, 1);
806 if (arena_name == nullptr) {
807 *out_type = nullptr;
810 }
811 infix_memcpy(arena_name, name, name_len);
812 type->is_arena_allocated = true;
814 type->size = 0; // Size and alignment are unknown until resolution.
815 type->alignment = 1; // Default to 1 to be safe in preliminary layout calculations.
816 type->meta.named_reference.name = arena_name;
818 *out_type = type;
819 return INFIX_SUCCESS;
820}
821// Internal Type Graph Management
862 recalc_visited_node_t ** visited_head) {
863 if (!type || !type->is_arena_allocated)
864 return; // Base case: Don't modify static singleton types.
865 // Cycle detection: If we have already visited this node in the current recursion
866 // path, we are in a cycle. Return immediately to break the loop. The layout of
867 // this node will be calculated when the recursion unwinds to its first visit.
868 for (recalc_visited_node_t * v = *visited_head; v != nullptr; v = v->next)
869 if (v->type == type)
870 return;
871 // Allocate the memoization node from a stable temporary arena.
872 recalc_visited_node_t * visited_node =
873 infix_arena_alloc(temp_arena, sizeof(recalc_visited_node_t), _Alignof(recalc_visited_node_t));
874 if (!visited_node)
875 return; // Cannot proceed without memory.
876 visited_node->type = type;
877 visited_node->next = *visited_head;
878 *visited_head = visited_node;
879 // Recurse into child types first (post-order traversal).
880 switch (type->category) {
883 break;
884 case INFIX_TYPE_ARRAY:
886 break;
888 case INFIX_TYPE_UNION:
889 for (size_t i = 0; i < type->meta.aggregate_info.num_members; ++i) {
891 temp_arena, type->meta.aggregate_info.members[i].type, visited_head);
892 }
893 break;
894 default:
895 break; // Other types have no child types to recurse into.
896 }
897 // After children are updated, recalculate this type's layout.
900 else if (type->category == INFIX_TYPE_UNION) {
901 size_t max_size = 0;
902 size_t max_alignment = 1;
903 for (size_t i = 0; i < type->meta.aggregate_info.num_members; ++i) {
904 infix_type * member_type = type->meta.aggregate_info.members[i].type;
905 if (member_type->size > max_size)
906 max_size = member_type->size;
907 if (member_type->alignment > max_alignment)
908 max_alignment = member_type->alignment;
909 }
910 type->alignment = max_alignment;
911 type->size = _infix_align_up(max_size, max_alignment);
912 }
913 else if (type->category == INFIX_TYPE_ARRAY) {
914 // Flexible arrays have size 0 but inherit alignment.
915 // Fixed arrays calculate size normally.
918 type->size = 0;
919 }
920 else {
923 }
924 }
925}
936 // Create a temporary arena solely for the visited list's lifetime.
937 infix_arena_t * temp_arena = infix_arena_create(1024);
938 if (!temp_arena)
939 return;
940 recalc_visited_node_t * visited_head = nullptr;
941 _infix_type_recalculate_layout_recursive(temp_arena, type, &visited_head);
942 infix_arena_destroy(temp_arena);
943}
972 const infix_type * src_type,
973 memo_node_t ** memo_head) {
974 if (src_type == nullptr)
975 return nullptr;
976 // If the source type lives in the same arena as our destination, we can safely share the pointer instead of
977 // performing a deep copy.
978 if (src_type->arena == dest_arena)
979 return (infix_type *)src_type;
980 // Base case: Static types don't need to be copied; return the singleton pointer.
981 if (!src_type->is_arena_allocated)
982 return (infix_type *)src_type;
983 // Check memoization table: if we've already copied this node, return the existing copy.
984 // This correctly handles cycles and shared sub-graphs.
985 for (memo_node_t * node = *memo_head; node != NULL; node = node->next)
986 if (node->src == src_type)
987 return node->dest;
988 // Allocate the new type object in the destination arena.
989 infix_type * dest_type = infix_arena_calloc(dest_arena, 1, sizeof(infix_type), _Alignof(infix_type));
990 if (dest_type == nullptr)
991 return nullptr;
992 // Add this new pair to the memoization table BEFORE recursing. This is crucial
993 // for handling cycles: the recursive call will find this entry and return `dest_type`.
994 memo_node_t * new_memo_node = infix_arena_alloc(dest_arena, sizeof(memo_node_t), _Alignof(memo_node_t));
995 if (!new_memo_node)
996 return nullptr;
997 new_memo_node->src = src_type;
998 new_memo_node->dest = dest_type;
999 new_memo_node->next = *memo_head;
1000 *memo_head = new_memo_node;
1001 // Perform a shallow copy of the main struct, then recurse to deep copy child pointers.
1002 *dest_type = *src_type;
1003 dest_type->is_arena_allocated = true;
1004 dest_type->is_incomplete = src_type->is_incomplete;
1005 dest_type->arena = dest_arena; // The new type now belongs to the destination arena.
1006 // Deep copy the semantic name string, if it exists.
1007 if (src_type->name) {
1008 size_t name_len = strlen(src_type->name) + 1;
1009 char * dest_name = infix_arena_alloc(dest_arena, name_len, 1);
1010 if (!dest_name)
1011 return nullptr; // Allocation failed
1012 infix_memcpy((void *)dest_name, src_type->name, name_len);
1013 dest_type->name = dest_name;
1014 }
1015 switch (src_type->category) {
1016 case INFIX_TYPE_POINTER:
1017 dest_type->meta.pointer_info.pointee_type =
1018 _copy_type_graph_to_arena_recursive(dest_arena, src_type->meta.pointer_info.pointee_type, memo_head);
1019 break;
1020 case INFIX_TYPE_ARRAY:
1021 dest_type->meta.array_info.element_type =
1022 _copy_type_graph_to_arena_recursive(dest_arena, src_type->meta.array_info.element_type, memo_head);
1023 // Explicitly copy the flexible flag to ensure it persists.
1024 dest_type->meta.array_info.is_flexible = src_type->meta.array_info.is_flexible;
1025 break;
1026 case INFIX_TYPE_STRUCT:
1027 case INFIX_TYPE_UNION:
1028 if (src_type->meta.aggregate_info.num_members > 0) {
1029 // Copy the members array itself.
1030 size_t members_size = sizeof(infix_struct_member) * src_type->meta.aggregate_info.num_members;
1031 dest_type->meta.aggregate_info.members =
1032 infix_arena_alloc(dest_arena, members_size, _Alignof(infix_struct_member));
1033 if (dest_type->meta.aggregate_info.members == nullptr)
1034 return nullptr;
1035 dest_type->meta.aggregate_info.is_packed = src_type->meta.aggregate_info.is_packed; // Copy packed flag
1036 // Now, recurse for each member's type and copy its name.
1037 for (size_t i = 0; i < src_type->meta.aggregate_info.num_members; ++i) {
1038 dest_type->meta.aggregate_info.members[i] = src_type->meta.aggregate_info.members[i];
1040 dest_arena, src_type->meta.aggregate_info.members[i].type, memo_head);
1041 const char * src_name = src_type->meta.aggregate_info.members[i].name;
1042 if (src_name) {
1043 size_t name_len = strlen(src_name) + 1;
1044 char * dest_name = infix_arena_alloc(dest_arena, name_len, 1);
1045 if (!dest_name)
1046 return nullptr;
1047 infix_memcpy((void *)dest_name, src_name, name_len);
1048 dest_type->meta.aggregate_info.members[i].name = dest_name;
1049 }
1050 // Copy bitfield properties
1051 dest_type->meta.aggregate_info.members[i].bit_width =
1052 src_type->meta.aggregate_info.members[i].bit_width;
1053 dest_type->meta.aggregate_info.members[i].bit_offset =
1055 dest_type->meta.aggregate_info.members[i].is_bitfield =
1057 }
1058 }
1059 break;
1061 {
1062 const char * src_name = src_type->meta.named_reference.name;
1063 if (src_name) {
1064 size_t name_len = strlen(src_name) + 1;
1065 char * dest_name = infix_arena_alloc(dest_arena, name_len, 1);
1066 if (!dest_name)
1067 return nullptr;
1068 infix_memcpy((void *)dest_name, src_name, name_len);
1069 dest_type->meta.named_reference.name = dest_name;
1070 }
1071 break;
1072 }
1074 dest_type->meta.func_ptr_info.return_type =
1075 _copy_type_graph_to_arena_recursive(dest_arena, src_type->meta.func_ptr_info.return_type, memo_head);
1076 if (src_type->meta.func_ptr_info.num_args > 0) {
1077 size_t args_size = sizeof(infix_function_argument) * src_type->meta.func_ptr_info.num_args;
1078 dest_type->meta.func_ptr_info.args =
1079 infix_arena_alloc(dest_arena, args_size, _Alignof(infix_function_argument));
1080 if (dest_type->meta.func_ptr_info.args == nullptr)
1081 return nullptr;
1082 for (size_t i = 0; i < src_type->meta.func_ptr_info.num_args; ++i) {
1083 dest_type->meta.func_ptr_info.args[i] = src_type->meta.func_ptr_info.args[i];
1085 dest_arena, src_type->meta.func_ptr_info.args[i].type, memo_head);
1086 const char * src_name = src_type->meta.func_ptr_info.args[i].name;
1087 if (src_name) {
1088 size_t name_len = strlen(src_name) + 1;
1089 char * dest_name = infix_arena_alloc(dest_arena, name_len, 1);
1090 if (!dest_name)
1091 return nullptr;
1092 infix_memcpy((void *)dest_name, src_name, name_len);
1093 dest_type->meta.func_ptr_info.args[i].name = dest_name;
1094 }
1095 }
1096 }
1097 break;
1098 case INFIX_TYPE_ENUM:
1099 dest_type->meta.enum_info.underlying_type =
1100 _copy_type_graph_to_arena_recursive(dest_arena, src_type->meta.enum_info.underlying_type, memo_head);
1101 break;
1102 case INFIX_TYPE_COMPLEX:
1103 dest_type->meta.complex_info.base_type =
1104 _copy_type_graph_to_arena_recursive(dest_arena, src_type->meta.complex_info.base_type, memo_head);
1105 break;
1106 case INFIX_TYPE_VECTOR:
1107 dest_type->meta.vector_info.element_type =
1108 _copy_type_graph_to_arena_recursive(dest_arena, src_type->meta.vector_info.element_type, memo_head);
1109 break;
1110 default:
1111 // Other types like primitives have no child pointers to copy.
1112 break;
1113 }
1114 return dest_type;
1115}
1124 memo_node_t * memo_head = nullptr;
1125 return _copy_type_graph_to_arena_recursive(dest_arena, src_type, &memo_head);
1126}
1149 const infix_type * type,
1150 estimate_visited_node_t ** visited_head) {
1151 if (!type || !type->is_arena_allocated)
1152 return 0;
1153 // Cycle detection: if we've seen this node, it's already accounted for.
1154 for (estimate_visited_node_t * v = *visited_head; v != NULL; v = v->next)
1155 if (v->type == type)
1156 return 0;
1157 // Add this node to the visited list before recursing.
1158 estimate_visited_node_t * visited_node =
1160 if (!visited_node) {
1161 // On allocation failure, we can't proceed with estimation. Return a large
1162 // number to ensure the caller allocates a fallback-sized arena.
1163 return 65536;
1164 }
1165 visited_node->type = type;
1166 visited_node->next = *visited_head;
1167 *visited_head = visited_node;
1168 // The size includes the type object itself, a memoization node, and the name string if it exists.
1169 size_t total_size = sizeof(infix_type) + sizeof(memo_node_t);
1170 if (type->name)
1171 total_size += strlen(type->name) + 1;
1172 switch (type->category) {
1173 case INFIX_TYPE_POINTER:
1174 total_size += _estimate_graph_size_recursive(temp_arena, type->meta.pointer_info.pointee_type, visited_head);
1175 break;
1176 case INFIX_TYPE_ARRAY:
1177 total_size += _estimate_graph_size_recursive(temp_arena, type->meta.array_info.element_type, visited_head);
1178 break;
1179 case INFIX_TYPE_STRUCT:
1180 case INFIX_TYPE_UNION:
1182 total_size += sizeof(infix_struct_member) * type->meta.aggregate_info.num_members;
1183 for (size_t i = 0; i < type->meta.aggregate_info.num_members; ++i) {
1184 const infix_struct_member * member = &type->meta.aggregate_info.members[i];
1185 if (member->name)
1186 total_size += strlen(member->name) + 1;
1187 total_size += _estimate_graph_size_recursive(temp_arena, member->type, visited_head);
1188 }
1189 }
1190 break;
1193 total_size += strlen(type->meta.named_reference.name) + 1;
1194 break;
1196 total_size += _estimate_graph_size_recursive(temp_arena, type->meta.func_ptr_info.return_type, visited_head);
1197 if (type->meta.func_ptr_info.num_args > 0) {
1198 total_size += sizeof(infix_function_argument) * type->meta.func_ptr_info.num_args;
1199 for (size_t i = 0; i < type->meta.func_ptr_info.num_args; ++i) {
1201 if (arg->name)
1202 total_size += strlen(arg->name) + 1;
1203 total_size += _estimate_graph_size_recursive(temp_arena, arg->type, visited_head);
1204 }
1205 }
1206 break;
1207 case INFIX_TYPE_ENUM:
1208 total_size += _estimate_graph_size_recursive(temp_arena, type->meta.enum_info.underlying_type, visited_head);
1209 break;
1210 case INFIX_TYPE_COMPLEX:
1211 total_size += _estimate_graph_size_recursive(temp_arena, type->meta.complex_info.base_type, visited_head);
1212 break;
1213 case INFIX_TYPE_VECTOR:
1214 total_size += _estimate_graph_size_recursive(temp_arena, type->meta.vector_info.element_type, visited_head);
1215 break;
1216 default:
1217 break;
1218 }
1219 return total_size;
1220}
1229 if (!temp_arena || !type)
1230 return 0;
1231 estimate_visited_node_t * visited_head = nullptr;
1232 return _estimate_graph_size_recursive(temp_arena, type, &visited_head);
1233}
1234// Public API: Introspection Functions
1242 if (type == nullptr)
1243 return nullptr;
1244 if (type->name)
1245 return type->name;
1246 // Add this check so Affix can inspect unresolved types!
1248 return type->meta.named_reference.name;
1249 return nullptr;
1250}
1291 return nullptr;
1292 return &type->meta.aggregate_info.members[index];
1293}
1301INFIX_API c23_nodiscard const char * infix_type_get_arg_name(const infix_type * func_type, size_t index) {
1302 if (!func_type || func_type->category != INFIX_TYPE_REVERSE_TRAMPOLINE ||
1303 index >= func_type->meta.func_ptr_info.num_args)
1304 return nullptr;
1305 return func_type->meta.func_ptr_info.args[index].name;
1306}
1313INFIX_API c23_nodiscard const infix_type * infix_type_get_arg_type(const infix_type * func_type, size_t index) {
1314 if (!func_type || func_type->category != INFIX_TYPE_REVERSE_TRAMPOLINE ||
1315 index >= func_type->meta.func_ptr_info.num_args)
1316 return nullptr;
1317 return func_type->meta.func_ptr_info.args[index].type;
1318}
1325 return trampoline ? trampoline->num_args : 0;
1326}
1333 return trampoline ? trampoline->num_fixed_args : 0;
1334}
1341 return trampoline ? trampoline->return_type : nullptr;
1342}
1350 size_t index) {
1351 if (!trampoline || index >= trampoline->num_args)
1352 return nullptr;
1353 return trampoline->arg_types[index];
1354}
1361 return trampoline ? trampoline->num_args : 0;
1362}
1369 return trampoline ? trampoline->num_fixed_args : 0;
1370}
1377 return trampoline ? trampoline->return_type : nullptr;
1378}
1386 size_t index) {
1387 if (!trampoline || index >= trampoline->num_args)
1388 return nullptr;
1389 return trampoline->arg_types[index];
1390}
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
clock_t start
Definition 901_call_overhead.c:48
#define c23_nodiscard
Internal alias for the public INFIX_NODISCARD macro.
Definition compat_c23.h:92
@ INFIX_CODE_INVALID_MEMBER_TYPE
Definition infix.h:1389
@ INFIX_CODE_INVALID_ALIGNMENT
Definition infix.h:1373
@ INFIX_CODE_INTEGER_OVERFLOW
Definition infix.h:1380
@ INFIX_CODE_TYPE_TOO_LARGE
Definition infix.h:1387
@ INFIX_CODE_NULL_POINTER
Definition infix.h:1365
@ INFIX_CODE_OUT_OF_MEMORY
Definition infix.h:1370
@ INFIX_CATEGORY_ABI
Definition infix.h:1356
@ INFIX_CATEGORY_ALLOCATION
Definition infix.h:1354
@ INFIX_CATEGORY_GENERAL
Definition infix.h:1353
@ INFIX_CATEGORY_PARSER
Definition infix.h:1355
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:296
struct infix_type_t::@0::@7 vector_info
Metadata for INFIX_TYPE_VECTOR.
bool is_incomplete
Definition infix.h:281
infix_type * type
Definition infix.h:349
struct infix_type_t::@0::@4 func_ptr_info
Metadata for INFIX_TYPE_REVERSE_TRAMPOLINE.
size_t num_elements
Definition infix.h:301
infix_arena_t * arena
Definition infix.h:282
size_t size
Definition infix.h:278
size_t alignment
Definition infix.h:279
uint8_t bit_offset
Definition infix.h:340
infix_struct_member * members
Definition infix.h:294
bool is_bitfield
Definition infix.h:341
struct infix_type_t::@0::@6 complex_info
Metadata for INFIX_TYPE_COMPLEX.
const char * name
Definition infix.h:276
infix_function_argument * args
Definition infix.h:307
infix_aggregate_category_t aggregate_category
Definition infix.h:327
infix_status
Enumerates the possible status codes returned by infix API functions.
Definition infix.h:435
const char * name
Definition infix.h:348
const char * name
Definition infix.h:336
infix_type_category category
Definition infix.h:277
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:290
infix_type * type
Definition infix.h:337
struct infix_type_t * element_type
Definition infix.h:300
bool is_flexible
Definition infix.h:302
struct infix_type_t * return_type
Definition infix.h:306
size_t offset
Definition infix.h:338
struct infix_type_t::@0::@5 enum_info
Metadata for INFIX_TYPE_ENUM.
struct infix_type_t * base_type
Definition infix.h:317
uint8_t bit_width
Definition infix.h:339
size_t num_members
Definition infix.h:295
struct infix_type_t * underlying_type
Definition infix.h:313
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:287
size_t num_args
Definition infix.h:308
bool is_arena_allocated
Definition infix.h:280
@ INFIX_ERROR_ALLOCATION_FAILED
Definition infix.h:437
@ INFIX_SUCCESS
Definition infix.h:436
@ INFIX_ERROR_INVALID_ARGUMENT
Definition infix.h:438
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:1324
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:388
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:208
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:399
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:208
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:725
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:548
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:1349
infix_primitive_type_id
Enumerates the supported primitive C types.
Definition infix.h:244
INFIX_API c23_nodiscard infix_type * infix_type_create_void(void)
Creates a static descriptor for the void type.
Definition types.c:200
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:1288
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:618
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:1301
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:210
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:219
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:1264
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:1340
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:788
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:1376
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:1313
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:1277
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:212
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:1256
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:144
INFIX_API c23_nodiscard infix_type * infix_type_create_pointer(void)
Creates a static descriptor for a generic pointer (void*).
Definition types.c:195
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:1368
infix_type_category
Enumerates the fundamental categories of types that infix can represent.
Definition infix.h:228
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:579
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:1385
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:1241
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:666
infix_aggregate_category_t
Specifies whether a named type reference refers to a struct or a union.
Definition infix.h:265
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:1332
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:513
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:1360
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:469
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:430
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:1270
@ INFIX_PRIMITIVE_UINT16
Definition infix.h:248
@ INFIX_PRIMITIVE_UINT32
Definition infix.h:250
@ INFIX_PRIMITIVE_LONG_DOUBLE
Definition infix.h:259
@ INFIX_PRIMITIVE_FLOAT
Definition infix.h:257
@ INFIX_PRIMITIVE_DOUBLE
Definition infix.h:258
@ INFIX_PRIMITIVE_SINT16
Definition infix.h:249
@ INFIX_PRIMITIVE_SINT64
Definition infix.h:253
@ INFIX_PRIMITIVE_SINT32
Definition infix.h:251
@ INFIX_PRIMITIVE_UINT8
Definition infix.h:246
@ INFIX_PRIMITIVE_UINT128
Definition infix.h:254
@ INFIX_PRIMITIVE_BOOL
Definition infix.h:245
@ INFIX_PRIMITIVE_UINT64
Definition infix.h:252
@ INFIX_PRIMITIVE_FLOAT16
Definition infix.h:256
@ INFIX_PRIMITIVE_SINT128
Definition infix.h:255
@ INFIX_PRIMITIVE_SINT8
Definition infix.h:247
@ INFIX_TYPE_UNION
Definition infix.h:232
@ INFIX_TYPE_PRIMITIVE
Definition infix.h:229
@ INFIX_TYPE_COMPLEX
Definition infix.h:236
@ INFIX_TYPE_ARRAY
Definition infix.h:233
@ INFIX_TYPE_VECTOR
Definition infix.h:237
@ INFIX_TYPE_VOID
Definition infix.h:239
@ INFIX_TYPE_POINTER
Definition infix.h:230
@ INFIX_TYPE_NAMED_REFERENCE
Definition infix.h:238
@ INFIX_TYPE_REVERSE_TRAMPOLINE
Definition infix.h:234
@ INFIX_TYPE_ENUM
Definition infix.h:235
@ INFIX_TYPE_STRUCT
Definition infix.h:231
#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:769
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:793
INFIX_INTERNAL void _infix_clear_error(void)
Clears the thread-local error state.
Definition error.c:268
static bool is_float(const infix_type *type)
A fast inline check to determine if an infix_type is a float (32-bit).
Definition infix_internals.h:785
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:175
Definition types.c:1132
struct estimate_visited_node_t * next
Definition types.c:1134
const infix_type * type
Definition types.c:1133
Internal definition of a memory arena.
Definition infix_internals.h:143
Internal definition of a forward trampoline handle.
Definition infix_internals.h:90
size_t num_args
Definition infix_internals.h:97
size_t num_fixed_args
Definition infix_internals.h:98
infix_type ** arg_types
Definition infix_internals.h:96
infix_type * return_type
Definition infix_internals.h:95
Describes a single argument to a C function.
Definition infix.h:347
Internal definition of a reverse trampoline (callback/closure) handle.
Definition infix_internals.h:119
infix_type * return_type
Definition infix_internals.h:123
size_t num_args
Definition infix_internals.h:125
size_t num_fixed_args
Definition infix_internals.h:126
infix_type ** arg_types
Definition infix_internals.h:124
Describes a single member of a C struct or union.
Definition infix.h:335
A semi-opaque structure that describes a C type.
Definition infix.h:275
Definition types.c:952
infix_type * dest
Definition types.c:954
struct memo_node_t * next
Definition types.c:955
const infix_type * src
Definition types.c:953
Definition types.c:834
struct recalc_visited_node_t * next
Definition types.c:836
infix_type * type
Definition types.c:835
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:1148
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:935
static infix_type _infix_type_double
Definition types.c:130
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:128
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:1123
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:1228
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:135
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:971
static infix_type _infix_type_uint64
Definition types.c:109
static infix_type _infix_type_float16
Definition types.c:119
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:356
static void _infix_type_recalculate_layout_recursive(infix_arena_t *temp_arena, infix_type *type, recalc_visited_node_t **visited_head)
Definition types.c:860
static bool _layout_struct(infix_type *type)
Definition types.c:231
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.