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
56#define INFIX_TYPE_INIT(id, T) \
57 {.name = nullptr, \
58 .category = INFIX_TYPE_PRIMITIVE, \
59 .size = sizeof(T), \
60 .alignment = _Alignof(T), \
61 .is_arena_allocated = false, \
62 .arena = nullptr, \
63 .source_offset = 0, \
64 .meta.primitive_id = id}
70static infix_type _infix_type_void = {.name = nullptr,
71 .category = INFIX_TYPE_VOID,
72 .size = 0,
73 .alignment = 0,
74 .is_arena_allocated = false,
75 .arena = nullptr,
76 .source_offset = 0,
77 .meta = {0}};
83static infix_type _infix_type_pointer = {.name = nullptr,
84 .category = INFIX_TYPE_POINTER,
85 .size = sizeof(void *),
86 .alignment = _Alignof(void *),
87 .is_arena_allocated = false,
88 .arena = nullptr,
89 .source_offset = 0,
90 .meta.pointer_info = {.pointee_type = &_infix_type_void}};
109#if !defined(INFIX_COMPILER_MSVC)
114#endif
119#if defined(INFIX_COMPILER_MSVC) || (defined(INFIX_OS_WINDOWS) && defined(INFIX_COMPILER_CLANG)) || \
120 defined(INFIX_OS_MACOS)
121// On these platforms, long double is just an alias for double, so no separate singleton is needed.
122#else
125#endif
126// Public API: Type Creation Functions
134 switch (id) {
136 return &_infix_type_bool;
138 return &_infix_type_uint8;
140 return &_infix_type_sint8;
142 return &_infix_type_uint16;
144 return &_infix_type_sint16;
146 return &_infix_type_uint32;
148 return &_infix_type_sint32;
150 return &_infix_type_uint64;
152 return &_infix_type_sint64;
153#if !defined(INFIX_COMPILER_MSVC)
155 return &_infix_type_uint128;
157 return &_infix_type_sint128;
158#endif
160 return &_infix_type_float;
162 return &_infix_type_double;
164#if defined(INFIX_COMPILER_MSVC) || (defined(INFIX_OS_WINDOWS) && defined(INFIX_COMPILER_CLANG)) || \
165 defined(INFIX_OS_MACOS)
166 // On platforms where long double is just an alias for double, return the double singleton
167 // to maintain consistent type representation.
168 return &_infix_type_double;
169#else
171#endif
172 default:
173 // Return null for any invalid primitive ID.
174 return nullptr;
175 }
176}
194infix_struct_member infix_type_create_member(const char * name, infix_type * type, size_t offset) {
195 return (infix_struct_member){name, type, offset, 0, 0, false};
196}
206 infix_type * type,
207 size_t offset,
208 uint8_t bit_width) {
209 return (infix_struct_member){name, type, offset, bit_width, 0, true};
210}
211
217static bool _layout_struct(infix_type * type) {
218 size_t current_byte_offset = 0;
219 uint8_t current_bit_offset = 0; // 0-7 bits used in the current byte
220 size_t max_alignment = 1;
221
222 for (size_t i = 0; i < type->meta.aggregate_info.num_members; ++i) {
223 infix_struct_member * member = &type->meta.aggregate_info.members[i];
224
225 // 1. Handle Flexible Array Members (FAM)
226 if (member->type->category == INFIX_TYPE_ARRAY && member->type->meta.array_info.is_flexible) {
227 // Flush any pending bits to the next byte
228 if (current_bit_offset > 0) {
229 if (current_byte_offset == SIZE_MAX) {
231 return false;
232 }
233 current_byte_offset++;
234 current_bit_offset = 0;
235 }
236
237 // FAM aligns according to its element type.
238 size_t member_align = member->type->alignment;
239 if (member_align == 0)
240 member_align = 1;
241
242 size_t aligned = _infix_align_up(current_byte_offset, member_align);
243 if (aligned < current_byte_offset) {
245 return false;
246 }
247 current_byte_offset = aligned;
248 member->offset = current_byte_offset;
249
250 if (member_align > max_alignment)
251 max_alignment = member_align;
252 continue; // FAM logic done
253 }
254
255 // 2. Handle Bitfields
256 if (member->is_bitfield) {
257 // Zero-width bitfield: force alignment to the next boundary of the declared type.
258 if (member->bit_width == 0) {
259 if (current_bit_offset > 0) {
260 if (current_byte_offset == SIZE_MAX) {
262 return false;
263 }
264 current_byte_offset++;
265 current_bit_offset = 0;
266 }
267 size_t align = member->type->alignment;
268 if (align == 0)
269 align = 1;
270
271 size_t aligned = _infix_align_up(current_byte_offset, align);
272 if (aligned < current_byte_offset) {
274 return false;
275 }
276 current_byte_offset = aligned;
277 member->offset = current_byte_offset;
278 member->bit_offset = 0;
279
280 if (align > max_alignment)
281 max_alignment = align;
282 continue;
283 }
284
285 // Standard Bitfield
286 // Simplified System V packing: pack into current byte if it fits.
287 if (current_bit_offset + member->bit_width > 8) {
288 // Overflow: move to start of next byte
289 if (current_byte_offset == SIZE_MAX) {
291 return false;
292 }
293 current_byte_offset++;
294 current_bit_offset = 0;
295 }
296
297 member->offset = current_byte_offset;
298 member->bit_offset = current_bit_offset;
299 current_bit_offset += member->bit_width;
300
301 // If we filled the byte exactly, advance to next byte
302 if (current_bit_offset == 8) {
303 if (current_byte_offset == SIZE_MAX) {
305 return false;
306 }
307 current_byte_offset++;
308 current_bit_offset = 0;
309 }
310
311 // Update struct alignment. Bitfields typically impose the alignment of their base type.
312 size_t align = member->type->alignment;
313 if (align == 0)
314 align = 1;
315 if (align > max_alignment)
316 max_alignment = align;
317 }
318 else {
319 // 3. Standard Member
320
321 // Flush bits first
322 if (current_bit_offset > 0) {
323 if (current_byte_offset == SIZE_MAX) {
325 return false;
326 }
327 current_byte_offset++;
328 current_bit_offset = 0;
329 }
330
331 size_t member_align = member->type->alignment;
332 if (member_align == 0)
333 member_align = 1;
334
335 if (member_align > max_alignment)
336 max_alignment = member_align;
337
338 size_t aligned = _infix_align_up(current_byte_offset, member_align);
339 if (aligned < current_byte_offset) {
341 return false;
342 }
343 current_byte_offset = aligned;
344 member->offset = current_byte_offset;
345
346 if (current_byte_offset > SIZE_MAX - member->type->size) {
348 return false;
349 }
350 current_byte_offset += member->type->size;
351 }
352 }
353
354 // Final flush
355 if (current_bit_offset > 0)
356 current_byte_offset++;
357
358 // If it is packed, the alignment is explicitly determined by the user (defaulting to 1
359 // if not specified in the syntax). We must respect this value absolutely, ignoring
360 // the natural alignment of members.
361 if (type->meta.aggregate_info.is_packed)
362 max_alignment = type->alignment;
363
364 type->alignment = max_alignment;
365 type->size = _infix_align_up(current_byte_offset, max_alignment);
366 return true;
367}
386 infix_type ** out_type,
387 infix_struct_member ** out_arena_members,
389 size_t num_members) {
390 if (out_type == nullptr)
392 // Pre-flight check: ensure all provided member types are valid.
393 for (size_t i = 0; i < num_members; ++i) {
394 if (members[i].type == nullptr) {
395 *out_type = nullptr;
398 }
399 }
400 infix_type * type = infix_arena_calloc(arena, 1, sizeof(infix_type), _Alignof(infix_type));
401 if (type == nullptr) {
402 *out_type = nullptr;
405 }
406 infix_struct_member * arena_members = nullptr;
407 if (num_members > 0) {
408 arena_members =
409 infix_arena_alloc(arena, sizeof(infix_struct_member) * num_members, _Alignof(infix_struct_member));
410 if (arena_members == nullptr) {
411 *out_type = nullptr;
414 }
415 infix_memcpy(arena_members, members, sizeof(infix_struct_member) * num_members);
416 }
417 *out_type = type;
418 *out_arena_members = arena_members;
419 return INFIX_SUCCESS;
420}
429 infix_type ** out_type,
430 infix_type * pointee_type) {
431 if (!out_type || !pointee_type) {
434 }
435 infix_type * type = infix_arena_calloc(arena, 1, sizeof(infix_type), _Alignof(infix_type));
436 if (type == nullptr) {
437 *out_type = nullptr;
440 }
441 // Start by copying the layout of a generic pointer.
442 *type = *infix_type_create_pointer();
443 // Mark it as arena-allocated so it can be deep-copied and freed correctly.
444 type->is_arena_allocated = true;
445 // Set the specific pointee type.
446 type->meta.pointer_info.pointee_type = pointee_type;
447 *out_type = type;
448 return INFIX_SUCCESS;
449}
459 infix_type ** out_type,
460 infix_type * element_type,
461 size_t num_elements) {
462 if (out_type == nullptr || element_type == nullptr) {
465 }
466 if (element_type->size > 0 && num_elements > SIZE_MAX / element_type->size) {
467 *out_type = nullptr;
470 }
471 infix_type * type = infix_arena_calloc(arena, 1, sizeof(infix_type), _Alignof(infix_type));
472 if (type == nullptr) {
473 *out_type = nullptr;
476 }
477 type->is_arena_allocated = true;
479 type->meta.array_info.element_type = element_type;
480 type->meta.array_info.num_elements = num_elements;
481 type->meta.array_info.is_flexible = false;
482 // An array's alignment is the same as its element's alignment.
483 type->alignment = element_type->alignment;
484 type->size = element_type->size * num_elements;
485 *out_type = type;
486 return INFIX_SUCCESS;
487}
488
497 infix_type ** out_type,
498 infix_type * element_type) {
499 if (out_type == nullptr || element_type == nullptr) {
502 }
503 // Flexible arrays of incomplete types (size 0) are generally not allowed.
504 if (element_type->category == INFIX_TYPE_VOID || element_type->size == 0) {
505 *out_type = nullptr;
508 }
509
510 infix_type * type = infix_arena_calloc(arena, 1, sizeof(infix_type), _Alignof(infix_type));
511 if (type == nullptr) {
512 *out_type = nullptr;
515 }
516 type->is_arena_allocated = true;
518 type->meta.array_info.element_type = element_type;
519 type->meta.array_info.num_elements = 0;
520 type->meta.array_info.is_flexible = true; // Mark as flexible
521
522 // A flexible array member itself has size 0 within the struct (it hangs off the end).
523 // However, its alignment requirement affects the struct.
524 type->alignment = element_type->alignment;
525 type->size = 0;
526
527 *out_type = type;
528 return INFIX_SUCCESS;
529}
530
540 infix_type ** out_type,
541 infix_type * underlying_type) {
542 if (out_type == nullptr || underlying_type == nullptr) {
545 }
546 if (underlying_type->category != INFIX_TYPE_PRIMITIVE ||
547 underlying_type->meta.primitive_id > INFIX_PRIMITIVE_SINT128) {
550 }
551 infix_type * type = infix_arena_calloc(arena, 1, sizeof(infix_type), _Alignof(infix_type));
552 if (type == nullptr) {
553 *out_type = nullptr;
556 }
557 type->is_arena_allocated = true;
559 // An enum has the same memory layout as its underlying integer type.
560 type->size = underlying_type->size;
561 type->alignment = underlying_type->alignment;
562 type->meta.enum_info.underlying_type = underlying_type;
563 *out_type = type;
564 return INFIX_SUCCESS;
565}
574 infix_type ** out_type,
575 infix_type * base_type) {
576 if (out_type == nullptr || base_type == nullptr || (!is_float(base_type) && !is_double(base_type))) {
579 }
580 infix_type * type = infix_arena_calloc(arena, 1, sizeof(infix_type), _Alignof(infix_type));
581 if (type == nullptr) {
582 *out_type = nullptr;
585 }
586 type->is_arena_allocated = true;
588 // A complex number is simply two floating-point numbers back-to-back.
589 type->size = base_type->size * 2;
590 type->alignment = base_type->alignment;
591 type->meta.complex_info.base_type = base_type;
592 *out_type = type;
593 return INFIX_SUCCESS;
594}
604 infix_type ** out_type,
605 infix_type * element_type,
606 size_t num_elements) {
607 if (out_type == nullptr || element_type == nullptr || element_type->category != INFIX_TYPE_PRIMITIVE) {
610 }
611 if (element_type->size > 0 && num_elements > SIZE_MAX / element_type->size) {
612 *out_type = nullptr;
615 }
616 infix_type * type = infix_arena_calloc(arena, 1, sizeof(infix_type), _Alignof(infix_type));
617 if (type == nullptr) {
618 *out_type = nullptr;
621 }
622 type->is_arena_allocated = true;
624 type->meta.vector_info.element_type = element_type;
625 type->meta.vector_info.num_elements = num_elements;
626 type->size = element_type->size * num_elements;
627 // Vector alignment is typically its total size, up to a platform-specific maximum (e.g., 16 on x64).
628 // This is a simplification; the ABI-specific classifiers will handle the true alignment rules.
629 type->alignment = type->size > 8 ? 16 : type->size;
630 *out_type = type;
631 return INFIX_SUCCESS;
632}
642 infix_type ** out_type,
644 size_t num_members) {
645 infix_type * type = nullptr;
646 infix_struct_member * arena_members = nullptr;
647 infix_status status = _create_aggregate_setup(arena, &type, &arena_members, members, num_members);
648 if (status != INFIX_SUCCESS) {
649 *out_type = nullptr;
650 return status;
651 }
652 type->is_arena_allocated = true;
654 type->meta.aggregate_info.members = arena_members;
655 type->meta.aggregate_info.num_members = num_members;
656 type->meta.aggregate_info.is_packed = false; // Unions don't use this flag currently
657 // A union's size is the size of its largest member, and its alignment is the
658 // alignment of its most-aligned member.
659 size_t max_size = 0;
660 size_t max_alignment = 1;
661 for (size_t i = 0; i < num_members; ++i) {
662 arena_members[i].offset = 0; // All union members have an offset of 0.
663 if (arena_members[i].type->size > max_size)
664 max_size = arena_members[i].type->size;
665 if (arena_members[i].type->alignment > max_alignment)
666 max_alignment = arena_members[i].type->alignment;
667 }
668 type->alignment = max_alignment;
669 // The total size is the size of the largest member, padded up to the required alignment.
670 type->size = _infix_align_up(max_size, max_alignment);
671 // Overflow check
672 if (type->size < max_size) {
673 *out_type = nullptr;
676 }
677 *out_type = type;
678 return INFIX_SUCCESS;
679}
689 infix_type ** out_type,
691 size_t num_members) {
693 infix_type * type = nullptr;
694 infix_struct_member * arena_members = nullptr;
695 infix_status status = _create_aggregate_setup(arena, &type, &arena_members, members, num_members);
696 if (status != INFIX_SUCCESS) {
697 *out_type = nullptr;
698 return status;
699 }
700 type->is_arena_allocated = true;
702 type->meta.aggregate_info.members = arena_members;
703 type->meta.aggregate_info.num_members = num_members;
704 type->meta.aggregate_info.is_packed = false;
705
706 // This performs a preliminary layout calculation.
707 // Note: This layout may be incomplete if it contains unresolved named references or flexible arrays.
708 // The final, correct layout will be computed by `_infix_type_recalculate_layout`.
709 // However, we must set a preliminary size/alignment here.
710
711 // We use the recalculate logic to do the heavy lifting, assuming a temporary arena can be made.
712 // But we can't create an arena here easily if we are in a strict context.
713 // So we do a simplified pass just like the old logic, ignoring complex bitfield rules for now.
714 // The proper bitfield layout happens in `_infix_type_recalculate_layout`.
715
716 for (size_t i = 0; i < num_members; ++i) {
717 infix_struct_member * member = &arena_members[i];
718 if (member->type->alignment == 0 && member->type->category != INFIX_TYPE_NAMED_REFERENCE &&
719 !(member->type->category == INFIX_TYPE_ARRAY && member->type->meta.array_info.is_flexible)) {
720 if (member->type->category != INFIX_TYPE_ARRAY) {
721 *out_type = nullptr;
724 }
725 }
726 }
727
728 // Calculate Layout (including bitfields and FAMs)
729 if (!_layout_struct(type)) {
730 *out_type = nullptr;
732 }
733
734 *out_type = type;
735 return INFIX_SUCCESS;
736}
748 infix_type ** out_type,
749 size_t total_size,
750 size_t alignment,
752 size_t num_members) {
753 if (out_type == nullptr || (num_members > 0 && members == nullptr)) {
756 }
757 if (alignment == 0) {
760 }
761 infix_type * type = infix_arena_calloc(arena, 1, sizeof(infix_type), _Alignof(infix_type));
762 if (type == nullptr) {
763 *out_type = nullptr;
766 }
767 infix_struct_member * arena_members = nullptr;
768 if (num_members > 0) {
769 arena_members =
770 infix_arena_alloc(arena, sizeof(infix_struct_member) * num_members, _Alignof(infix_struct_member));
771 if (arena_members == nullptr) {
772 *out_type = nullptr;
775 }
776 infix_memcpy(arena_members, members, sizeof(infix_struct_member) * num_members);
777 }
778 type->is_arena_allocated = true;
779 type->size = total_size;
780 type->alignment = alignment;
781 type->category = INFIX_TYPE_STRUCT; // Packed structs are still fundamentally structs.
782 type->meta.aggregate_info.members = arena_members;
783 type->meta.aggregate_info.num_members = num_members;
784 type->meta.aggregate_info.is_packed = true; // Marked as packed
785 *out_type = type;
786 return INFIX_SUCCESS;
787}
800 infix_type ** out_type,
801 const char * name,
803 if (out_type == nullptr || name == nullptr) {
806 }
807 infix_type * type = infix_arena_calloc(arena, 1, sizeof(infix_type), _Alignof(infix_type));
808 if (type == nullptr) {
809 *out_type = nullptr;
812 }
813 // The name must be copied into the arena to ensure its lifetime matches the type's.
814 size_t name_len = strlen(name) + 1;
815 char * arena_name = infix_arena_alloc(arena, name_len, 1);
816 if (arena_name == nullptr) {
817 *out_type = nullptr;
820 }
821 infix_memcpy(arena_name, name, name_len);
822 type->is_arena_allocated = true;
824 type->size = 0; // Size and alignment are unknown until resolution.
825 type->alignment = 1; // Default to 1 to be safe in preliminary layout calculations.
826 type->meta.named_reference.name = arena_name;
828 *out_type = type;
829 return INFIX_SUCCESS;
830}
831// Internal Type Graph Management
872 recalc_visited_node_t ** visited_head) {
873 if (!type || !type->is_arena_allocated)
874 return; // Base case: Don't modify static singleton types.
875 // Cycle detection: If we have already visited this node in the current recursion
876 // path, we are in a cycle. Return immediately to break the loop. The layout of
877 // this node will be calculated when the recursion unwinds to its first visit.
878 for (recalc_visited_node_t * v = *visited_head; v != nullptr; v = v->next)
879 if (v->type == type)
880 return;
881 // Allocate the memoization node from a stable temporary arena.
882 recalc_visited_node_t * visited_node =
883 infix_arena_alloc(temp_arena, sizeof(recalc_visited_node_t), _Alignof(recalc_visited_node_t));
884 if (!visited_node)
885 return; // Cannot proceed without memory.
886 visited_node->type = type;
887 visited_node->next = *visited_head;
888 *visited_head = visited_node;
889 // Recurse into child types first (post-order traversal).
890 switch (type->category) {
893 break;
894 case INFIX_TYPE_ARRAY:
896 break;
898 case INFIX_TYPE_UNION:
899 for (size_t i = 0; i < type->meta.aggregate_info.num_members; ++i) {
901 temp_arena, type->meta.aggregate_info.members[i].type, visited_head);
902 }
903 break;
904 default:
905 break; // Other types have no child types to recurse into.
906 }
907 // After children are updated, recalculate this type's layout.
910 else if (type->category == INFIX_TYPE_UNION) {
911 size_t max_size = 0;
912 size_t max_alignment = 1;
913 for (size_t i = 0; i < type->meta.aggregate_info.num_members; ++i) {
914 infix_type * member_type = type->meta.aggregate_info.members[i].type;
915 if (member_type->size > max_size)
916 max_size = member_type->size;
917 if (member_type->alignment > max_alignment)
918 max_alignment = member_type->alignment;
919 }
920 type->alignment = max_alignment;
921 type->size = _infix_align_up(max_size, max_alignment);
922 }
923 else if (type->category == INFIX_TYPE_ARRAY) {
924 // Flexible arrays have size 0 but inherit alignment.
925 // Fixed arrays calculate size normally.
928 type->size = 0;
929 }
930 else {
933 }
934 }
935}
946 // Create a temporary arena solely for the visited list's lifetime.
947 infix_arena_t * temp_arena = infix_arena_create(1024);
948 if (!temp_arena)
949 return;
950 recalc_visited_node_t * visited_head = nullptr;
951 _infix_type_recalculate_layout_recursive(temp_arena, type, &visited_head);
952 infix_arena_destroy(temp_arena);
953}
982 const infix_type * src_type,
983 memo_node_t ** memo_head) {
984 if (src_type == nullptr)
985 return nullptr;
986 // If the source type lives in the same arena as our destination, we can safely share the pointer instead of
987 // performing a deep copy.
988 if (src_type->arena == dest_arena)
989 return (infix_type *)src_type;
990 // Base case: Static types don't need to be copied; return the singleton pointer.
991 if (!src_type->is_arena_allocated)
992 return (infix_type *)src_type;
993 // Check memoization table: if we've already copied this node, return the existing copy.
994 // This correctly handles cycles and shared sub-graphs.
995 for (memo_node_t * node = *memo_head; node != NULL; node = node->next)
996 if (node->src == src_type)
997 return node->dest;
998 // Allocate the new type object in the destination arena.
999 infix_type * dest_type = infix_arena_calloc(dest_arena, 1, sizeof(infix_type), _Alignof(infix_type));
1000 if (dest_type == nullptr)
1001 return nullptr;
1002 // Add this new pair to the memoization table BEFORE recursing. This is crucial
1003 // for handling cycles: the recursive call will find this entry and return `dest_type`.
1004 memo_node_t * new_memo_node = infix_arena_alloc(dest_arena, sizeof(memo_node_t), _Alignof(memo_node_t));
1005 if (!new_memo_node)
1006 return nullptr;
1007 new_memo_node->src = src_type;
1008 new_memo_node->dest = dest_type;
1009 new_memo_node->next = *memo_head;
1010 *memo_head = new_memo_node;
1011 // Perform a shallow copy of the main struct, then recurse to deep copy child pointers.
1012 *dest_type = *src_type;
1013 dest_type->is_arena_allocated = true;
1014 dest_type->is_incomplete = src_type->is_incomplete;
1015 dest_type->arena = dest_arena; // The new type now belongs to the destination arena.
1016 // Deep copy the semantic name string, if it exists.
1017 if (src_type->name) {
1018 size_t name_len = strlen(src_type->name) + 1;
1019 char * dest_name = infix_arena_alloc(dest_arena, name_len, 1);
1020 if (!dest_name)
1021 return nullptr; // Allocation failed
1022 infix_memcpy((void *)dest_name, src_type->name, name_len);
1023 dest_type->name = dest_name;
1024 }
1025 switch (src_type->category) {
1026 case INFIX_TYPE_POINTER:
1027 dest_type->meta.pointer_info.pointee_type =
1028 _copy_type_graph_to_arena_recursive(dest_arena, src_type->meta.pointer_info.pointee_type, memo_head);
1029 break;
1030 case INFIX_TYPE_ARRAY:
1031 dest_type->meta.array_info.element_type =
1032 _copy_type_graph_to_arena_recursive(dest_arena, src_type->meta.array_info.element_type, memo_head);
1033 // Explicitly copy the flexible flag to ensure it persists.
1034 dest_type->meta.array_info.is_flexible = src_type->meta.array_info.is_flexible;
1035 break;
1036 case INFIX_TYPE_STRUCT:
1037 case INFIX_TYPE_UNION:
1038 if (src_type->meta.aggregate_info.num_members > 0) {
1039 // Copy the members array itself.
1040 size_t members_size = sizeof(infix_struct_member) * src_type->meta.aggregate_info.num_members;
1041 dest_type->meta.aggregate_info.members =
1042 infix_arena_alloc(dest_arena, members_size, _Alignof(infix_struct_member));
1043 if (dest_type->meta.aggregate_info.members == nullptr)
1044 return nullptr;
1045 dest_type->meta.aggregate_info.is_packed = src_type->meta.aggregate_info.is_packed; // Copy packed flag
1046 // Now, recurse for each member's type and copy its name.
1047 for (size_t i = 0; i < src_type->meta.aggregate_info.num_members; ++i) {
1048 dest_type->meta.aggregate_info.members[i] = src_type->meta.aggregate_info.members[i];
1050 dest_arena, src_type->meta.aggregate_info.members[i].type, memo_head);
1051 const char * src_name = src_type->meta.aggregate_info.members[i].name;
1052 if (src_name) {
1053 size_t name_len = strlen(src_name) + 1;
1054 char * dest_name = infix_arena_alloc(dest_arena, name_len, 1);
1055 if (!dest_name)
1056 return nullptr;
1057 infix_memcpy((void *)dest_name, src_name, name_len);
1058 dest_type->meta.aggregate_info.members[i].name = dest_name;
1059 }
1060 // Copy bitfield properties
1061 dest_type->meta.aggregate_info.members[i].bit_width =
1062 src_type->meta.aggregate_info.members[i].bit_width;
1063 dest_type->meta.aggregate_info.members[i].bit_offset =
1065 dest_type->meta.aggregate_info.members[i].is_bitfield =
1067 }
1068 }
1069 break;
1071 {
1072 const char * src_name = src_type->meta.named_reference.name;
1073 if (src_name) {
1074 size_t name_len = strlen(src_name) + 1;
1075 char * dest_name = infix_arena_alloc(dest_arena, name_len, 1);
1076 if (!dest_name)
1077 return nullptr;
1078 infix_memcpy((void *)dest_name, src_name, name_len);
1079 dest_type->meta.named_reference.name = dest_name;
1080 }
1081 break;
1082 }
1084 dest_type->meta.func_ptr_info.return_type =
1085 _copy_type_graph_to_arena_recursive(dest_arena, src_type->meta.func_ptr_info.return_type, memo_head);
1086 if (src_type->meta.func_ptr_info.num_args > 0) {
1087 size_t args_size = sizeof(infix_function_argument) * src_type->meta.func_ptr_info.num_args;
1088 dest_type->meta.func_ptr_info.args =
1089 infix_arena_alloc(dest_arena, args_size, _Alignof(infix_function_argument));
1090 if (dest_type->meta.func_ptr_info.args == nullptr)
1091 return nullptr;
1092 for (size_t i = 0; i < src_type->meta.func_ptr_info.num_args; ++i) {
1093 dest_type->meta.func_ptr_info.args[i] = src_type->meta.func_ptr_info.args[i];
1095 dest_arena, src_type->meta.func_ptr_info.args[i].type, memo_head);
1096 const char * src_name = src_type->meta.func_ptr_info.args[i].name;
1097 if (src_name) {
1098 size_t name_len = strlen(src_name) + 1;
1099 char * dest_name = infix_arena_alloc(dest_arena, name_len, 1);
1100 if (!dest_name)
1101 return nullptr;
1102 infix_memcpy((void *)dest_name, src_name, name_len);
1103 dest_type->meta.func_ptr_info.args[i].name = dest_name;
1104 }
1105 }
1106 }
1107 break;
1108 case INFIX_TYPE_ENUM:
1109 dest_type->meta.enum_info.underlying_type =
1110 _copy_type_graph_to_arena_recursive(dest_arena, src_type->meta.enum_info.underlying_type, memo_head);
1111 break;
1112 case INFIX_TYPE_COMPLEX:
1113 dest_type->meta.complex_info.base_type =
1114 _copy_type_graph_to_arena_recursive(dest_arena, src_type->meta.complex_info.base_type, memo_head);
1115 break;
1116 case INFIX_TYPE_VECTOR:
1117 dest_type->meta.vector_info.element_type =
1118 _copy_type_graph_to_arena_recursive(dest_arena, src_type->meta.vector_info.element_type, memo_head);
1119 break;
1120 default:
1121 // Other types like primitives have no child pointers to copy.
1122 break;
1123 }
1124 return dest_type;
1125}
1134 memo_node_t * memo_head = nullptr;
1135 return _copy_type_graph_to_arena_recursive(dest_arena, src_type, &memo_head);
1136}
1159 const infix_type * type,
1160 estimate_visited_node_t ** visited_head) {
1161 if (!type || !type->is_arena_allocated)
1162 return 0;
1163 // Cycle detection: if we've seen this node, it's already accounted for.
1164 for (estimate_visited_node_t * v = *visited_head; v != NULL; v = v->next)
1165 if (v->type == type)
1166 return 0;
1167 // Add this node to the visited list before recursing.
1168 estimate_visited_node_t * visited_node =
1170 if (!visited_node) {
1171 // On allocation failure, we can't proceed with estimation. Return a large
1172 // number to ensure the caller allocates a fallback-sized arena.
1173 return 65536;
1174 }
1175 visited_node->type = type;
1176 visited_node->next = *visited_head;
1177 *visited_head = visited_node;
1178 // The size includes the type object itself, a memoization node, and the name string if it exists.
1179 size_t total_size = sizeof(infix_type) + sizeof(memo_node_t);
1180 if (type->name)
1181 total_size += strlen(type->name) + 1;
1182 switch (type->category) {
1183 case INFIX_TYPE_POINTER:
1184 total_size += _estimate_graph_size_recursive(temp_arena, type->meta.pointer_info.pointee_type, visited_head);
1185 break;
1186 case INFIX_TYPE_ARRAY:
1187 total_size += _estimate_graph_size_recursive(temp_arena, type->meta.array_info.element_type, visited_head);
1188 break;
1189 case INFIX_TYPE_STRUCT:
1190 case INFIX_TYPE_UNION:
1192 total_size += sizeof(infix_struct_member) * type->meta.aggregate_info.num_members;
1193 for (size_t i = 0; i < type->meta.aggregate_info.num_members; ++i) {
1194 const infix_struct_member * member = &type->meta.aggregate_info.members[i];
1195 if (member->name)
1196 total_size += strlen(member->name) + 1;
1197 total_size += _estimate_graph_size_recursive(temp_arena, member->type, visited_head);
1198 }
1199 }
1200 break;
1203 total_size += strlen(type->meta.named_reference.name) + 1;
1204 break;
1206 total_size += _estimate_graph_size_recursive(temp_arena, type->meta.func_ptr_info.return_type, visited_head);
1207 if (type->meta.func_ptr_info.num_args > 0) {
1208 total_size += sizeof(infix_function_argument) * type->meta.func_ptr_info.num_args;
1209 for (size_t i = 0; i < type->meta.func_ptr_info.num_args; ++i) {
1211 if (arg->name)
1212 total_size += strlen(arg->name) + 1;
1213 total_size += _estimate_graph_size_recursive(temp_arena, arg->type, visited_head);
1214 }
1215 }
1216 break;
1217 case INFIX_TYPE_ENUM:
1218 total_size += _estimate_graph_size_recursive(temp_arena, type->meta.enum_info.underlying_type, visited_head);
1219 break;
1220 case INFIX_TYPE_COMPLEX:
1221 total_size += _estimate_graph_size_recursive(temp_arena, type->meta.complex_info.base_type, visited_head);
1222 break;
1223 case INFIX_TYPE_VECTOR:
1224 total_size += _estimate_graph_size_recursive(temp_arena, type->meta.vector_info.element_type, visited_head);
1225 break;
1226 default:
1227 break;
1228 }
1229 return total_size;
1230}
1239 if (!temp_arena || !type)
1240 return 0;
1241 estimate_visited_node_t * visited_head = nullptr;
1242 return _estimate_graph_size_recursive(temp_arena, type, &visited_head);
1243}
1244// Public API: Introspection Functions
1252 if (type == nullptr)
1253 return nullptr;
1254 return type->name;
1255}
1296 return nullptr;
1297 return &type->meta.aggregate_info.members[index];
1298}
1306c23_nodiscard const char * infix_type_get_arg_name(const infix_type * func_type, size_t index) {
1307 if (!func_type || func_type->category != INFIX_TYPE_REVERSE_TRAMPOLINE ||
1308 index >= func_type->meta.func_ptr_info.num_args)
1309 return nullptr;
1310 return func_type->meta.func_ptr_info.args[index].name;
1311}
1318c23_nodiscard const infix_type * infix_type_get_arg_type(const infix_type * func_type, size_t index) {
1319 if (!func_type || func_type->category != INFIX_TYPE_REVERSE_TRAMPOLINE ||
1320 index >= func_type->meta.func_ptr_info.num_args)
1321 return nullptr;
1322 return func_type->meta.func_ptr_info.args[index].type;
1323}
1330 return trampoline ? trampoline->num_args : 0;
1331}
1338 return trampoline ? trampoline->num_fixed_args : 0;
1339}
1346 return trampoline ? trampoline->return_type : nullptr;
1347}
1354c23_nodiscard const infix_type * infix_forward_get_arg_type(const infix_forward_t * trampoline, size_t index) {
1355 if (!trampoline || index >= trampoline->num_args)
1356 return nullptr;
1357 return trampoline->arg_types[index];
1358}
1365 return trampoline ? trampoline->num_args : 0;
1366}
1373 return trampoline ? trampoline->num_fixed_args : 0;
1374}
1381 return trampoline ? trampoline->return_type : nullptr;
1382}
1389c23_nodiscard const infix_type * infix_reverse_get_arg_type(const infix_reverse_t * trampoline, size_t index) {
1390 if (!trampoline || index >= trampoline->num_args)
1391 return nullptr;
1392 return trampoline->arg_types[index];
1393}
infix_arena_t * arena
Definition 005_layouts.c:60
infix_status status
Definition 103_unions.c:59
infix_struct_member * members
Definition 103_unions.c:53
#define c23_nodiscard
A compatibility macro for the C23 [[nodiscard]] attribute.
Definition compat_c23.h:106
@ INFIX_CODE_INVALID_MEMBER_TYPE
Definition infix.h:1252
@ INFIX_CODE_INVALID_ALIGNMENT
Definition infix.h:1236
@ INFIX_CODE_INTEGER_OVERFLOW
Definition infix.h:1243
@ INFIX_CODE_NULL_POINTER
Definition infix.h:1229
@ INFIX_CODE_OUT_OF_MEMORY
Definition infix.h:1233
@ INFIX_CATEGORY_ALLOCATION
Definition infix.h:1218
@ INFIX_CATEGORY_GENERAL
Definition infix.h:1217
@ INFIX_CATEGORY_PARSER
Definition infix.h:1219
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:215
struct infix_type_t::@0::@7 vector_info
Metadata for INFIX_TYPE_VECTOR.
bool is_incomplete
Definition infix.h:200
infix_type * type
Definition infix.h:268
struct infix_type_t::@0::@4 func_ptr_info
Metadata for INFIX_TYPE_REVERSE_TRAMPOLINE.
size_t num_elements
Definition infix.h:220
infix_arena_t * arena
Definition infix.h:201
size_t size
Definition infix.h:197
size_t alignment
Definition infix.h:198
uint8_t bit_offset
Definition infix.h:259
infix_struct_member * members
Definition infix.h:213
bool is_bitfield
Definition infix.h:260
struct infix_type_t::@0::@6 complex_info
Metadata for INFIX_TYPE_COMPLEX.
const char * name
Definition infix.h:195
infix_function_argument * args
Definition infix.h:226
infix_aggregate_category_t aggregate_category
Definition infix.h:246
infix_status
Enumerates the possible status codes returned by infix API functions.
Definition infix.h:354
const char * name
Definition infix.h:267
const char * name
Definition infix.h:255
infix_type_category category
Definition infix.h:196
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:209
infix_type * type
Definition infix.h:256
struct infix_type_t * element_type
Definition infix.h:219
bool is_flexible
Definition infix.h:221
struct infix_type_t * return_type
Definition infix.h:225
size_t offset
Definition infix.h:257
struct infix_type_t::@0::@5 enum_info
Metadata for INFIX_TYPE_ENUM.
struct infix_type_t * base_type
Definition infix.h:236
uint8_t bit_width
Definition infix.h:258
size_t num_members
Definition infix.h:214
struct infix_type_t * underlying_type
Definition infix.h:232
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:206
size_t num_args
Definition infix.h:227
bool is_arena_allocated
Definition infix.h:199
@ INFIX_ERROR_ALLOCATION_FAILED
Definition infix.h:356
@ INFIX_SUCCESS
Definition infix.h:355
@ INFIX_ERROR_INVALID_ARGUMENT
Definition infix.h:357
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:1329
void infix_arena_destroy(infix_arena_t *)
Destroys an arena and frees all memory allocated from it.
Definition arena.c:83
#define infix_memcpy
A macro that can be defined to override the default memcpy function.
Definition infix.h:307
c23_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:179
c23_nodiscard void * infix_arena_alloc(infix_arena_t *, size_t, size_t)
Allocates a block of memory from an arena.
Definition arena.c:117
c23_nodiscard infix_arena_t * infix_arena_create(size_t)
Creates a new memory arena.
Definition arena.c:52
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:747
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:128
c23_nodiscard size_t infix_type_get_size(const infix_type *type)
Gets the size of a type in bytes.
Definition types.c:1269
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:496
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:1318
c23_nodiscard infix_type * infix_type_create_void(void)
Creates a static descriptor for the void type.
Definition types.c:186
c23_nodiscard size_t infix_type_get_alignment(const infix_type *type)
Gets the alignment requirement of a type in bytes.
Definition types.c:1275
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:1337
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:1251
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:1345
infix_primitive_type_id
Enumerates the supported primitive C types.
Definition infix.h:164
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:1354
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:641
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:539
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:603
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:1380
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:130
c23_nodiscard infix_type * infix_type_create_pointer(void)
Creates a static descriptor for a generic pointer (void*).
Definition types.c:181
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:573
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:1364
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:1282
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:132
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:1306
infix_type_category
Enumerates the fundamental categories of types that infix can represent.
Definition infix.h:148
c23_nodiscard infix_type_category infix_type_get_category(const infix_type *type)
Gets the fundamental category of a type.
Definition types.c:1261
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:458
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:428
infix_aggregate_category_t
Specifies whether a named type reference refers to a struct or a union.
Definition infix.h:184
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:205
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:688
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:799
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:1389
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:1372
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:133
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:194
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:1293
@ INFIX_PRIMITIVE_UINT16
Definition infix.h:168
@ INFIX_PRIMITIVE_UINT32
Definition infix.h:170
@ INFIX_PRIMITIVE_LONG_DOUBLE
Definition infix.h:178
@ INFIX_PRIMITIVE_FLOAT
Definition infix.h:176
@ INFIX_PRIMITIVE_DOUBLE
Definition infix.h:177
@ INFIX_PRIMITIVE_SINT16
Definition infix.h:169
@ INFIX_PRIMITIVE_SINT64
Definition infix.h:173
@ INFIX_PRIMITIVE_SINT32
Definition infix.h:171
@ INFIX_PRIMITIVE_UINT8
Definition infix.h:166
@ INFIX_PRIMITIVE_UINT128
Definition infix.h:174
@ INFIX_PRIMITIVE_BOOL
Definition infix.h:165
@ INFIX_PRIMITIVE_UINT64
Definition infix.h:172
@ INFIX_PRIMITIVE_SINT128
Definition infix.h:175
@ INFIX_PRIMITIVE_SINT8
Definition infix.h:167
@ INFIX_TYPE_UNION
Definition infix.h:152
@ INFIX_TYPE_PRIMITIVE
Definition infix.h:149
@ INFIX_TYPE_COMPLEX
Definition infix.h:156
@ INFIX_TYPE_ARRAY
Definition infix.h:153
@ INFIX_TYPE_VECTOR
Definition infix.h:157
@ INFIX_TYPE_VOID
Definition infix.h:159
@ INFIX_TYPE_POINTER
Definition infix.h:150
@ INFIX_TYPE_NAMED_REFERENCE
Definition infix.h:158
@ INFIX_TYPE_REVERSE_TRAMPOLINE
Definition infix.h:154
@ INFIX_TYPE_ENUM
Definition infix.h:155
@ INFIX_TYPE_STRUCT
Definition infix.h:151
Internal data structures, function prototypes, and constants.
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
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:727
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:743
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:735
Definition types.c:1142
struct estimate_visited_node_t * next
Definition types.c:1144
const infix_type * type
Definition types.c:1143
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:266
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:254
A semi-opaque structure that describes a C type.
Definition infix.h:194
Definition types.c:962
infix_type * dest
Definition types.c:964
struct memo_node_t * next
Definition types.c:965
const infix_type * src
Definition types.c:963
Definition types.c:844
struct recalc_visited_node_t * next
Definition types.c:846
infix_type * type
Definition types.c:845
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:1158
static infix_type _infix_type_sint128
Definition types.c:113
void _infix_type_recalculate_layout(infix_type *type)
Recalculates the layout of a fully resolved type graph.
Definition types.c:945
static infix_type _infix_type_double
Definition types.c:118
static infix_type _infix_type_uint32
Definition types.c:102
static infix_type _infix_type_bool
Definition types.c:92
static infix_type _infix_type_float
Definition types.c:116
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:1133
static infix_type _infix_type_sint64
Definition types.c:108
#define INFIX_TYPE_INIT(id, T)
Definition types.c:56
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:1238
static infix_type _infix_type_sint16
Definition types.c:100
static infix_type _infix_type_uint16
Definition types.c:98
static infix_type _infix_type_long_double
Definition types.c:124
static infix_type _infix_type_pointer
Definition types.c:83
static infix_type _infix_type_uint128
Definition types.c:111
static infix_type _infix_type_void
Definition types.c:70
static infix_type _infix_type_sint32
Definition types.c:104
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:981
static infix_type _infix_type_uint64
Definition types.c:106
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:385
static void _infix_type_recalculate_layout_recursive(infix_arena_t *temp_arena, infix_type *type, recalc_visited_node_t **visited_head)
Definition types.c:870
static bool _layout_struct(infix_type *type)
Definition types.c:217
static infix_type _infix_type_uint8
Definition types.c:94
static infix_type _infix_type_sint8
Definition types.c:96
A header for conditionally compiled debugging utilities.