Affix
view release on metacpan or search on metacpan
infix/src/common/infix_internals.h view on Meta::CPAN
* "bumping" a pointer. All memory allocated from an arena is freed at once by
* destroying the arena itself, eliminating the need to track individual allocations.
*/
struct infix_arena_t {
char * buffer; /**< The backing memory buffer for the arena. */
size_t capacity; /**< The total size of the buffer. */
size_t current_offset; /**< The current high-water mark of allocation. */
bool error; /**< A flag set if any allocation fails, preventing subsequent allocations. */
struct infix_arena_t * next_block; /**< A pointer to the next block in the chain, if this one is full. */
size_t block_size; /**< The size of this specific block's buffer, for chained arenas. */
};
// Mutex Abstraction for Internal Synchronization
#if defined(INFIX_OS_WINDOWS)
#include <windows.h>
typedef SRWLOCK infix_mutex_t;
#define INFIX_MUTEX_INITIALIZER SRWLOCK_INIT
#define INFIX_MUTEX_LOCK(m) AcquireSRWLockExclusive(m)
#define INFIX_MUTEX_UNLOCK(m) ReleaseSRWLockExclusive(m)
#define INFIX_MUTEX_DESTROY(m) ((void)0)
#else
#include <pthread.h>
typedef pthread_mutex_t infix_mutex_t;
#define INFIX_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
#define INFIX_MUTEX_LOCK(m) pthread_mutex_lock(m)
#define INFIX_MUTEX_UNLOCK(m) pthread_mutex_unlock(m)
#define INFIX_MUTEX_DESTROY(m) pthread_mutex_destroy(m)
#endif
/**
* @struct _infix_registry_entry_t
* @brief A single entry in the registry's hash table.
* @details This is a node in a singly-linked list used for chaining in the
* event of a hash collision.
*/
typedef struct _infix_registry_entry_t {
const char * name; /**< The registered name of the type. */
uint64_t hash; /**< The pre-calculated djb2 hash of the name. */
infix_type * type; /**< A pointer to the canonical `infix_type` object. */
bool is_forward_declaration; /**< `true` if this is just a forward declaration (`@Name;`). */
struct _infix_registry_entry_t * next; /**< The next entry in the hash bucket chain. */
} _infix_registry_entry_t;
/**
* @struct infix_registry_t
* @brief Internal definition of a named type registry.
* @details Implemented as a hash table with separate chaining for collision resolution.
* The canonical `infix_type` objects and entry metadata are owned by a single arena,
* while the internal bucket array is heap-allocated to allow for efficient resizing.
*/
struct infix_registry_t {
infix_arena_t * arena; /**< The arena that owns all type metadata and entry structs. */
bool is_external_arena; /**< True if the arena is user-provided and should not be freed. */
size_t num_buckets; /**< The number of buckets in the hash table. */
size_t num_items; /**< The total number of items in the registry. */
_infix_registry_entry_t ** buckets; /**< The array of hash table buckets (heap-allocated). */
};
/**
* @struct parser_state
* @brief Holds the complete state of the recursive descent parser during a single parse operation.
*/
typedef struct {
const char * p; /**< The current read position (cursor) in the signature string. */
const char * start; /**< The beginning of the signature string, used for calculating error positions. */
infix_arena_t * arena; /**< The temporary arena for allocating the raw, unresolved type graph. */
int depth; /**< The current recursion depth, to prevent stack overflows. */
} parser_state;
/**
* @struct code_buffer
* @brief A dynamic buffer for staged machine code generation.
*/
typedef struct {
uint8_t * code; /**< A pointer to the code buffer, allocated from the arena. */
size_t capacity; /**< The current capacity of the buffer. */
size_t size; /**< The number of bytes currently written to the buffer. */
bool error; /**< A flag set on allocation failure. */
infix_arena_t * arena; /**< The temporary arena used for code generation. */
} code_buffer;
/**
* @struct infix_library_t
* @brief Internal definition of a dynamic library handle.
* @details This is a simple wrapper around the platform's native library handle to provide a consistent API.
*
* On Windows, GetModuleHandle(NULL) returns a special handle to the main executable that must NOT be freed with
* FreeLibrary. This flag tracks that state to ensure infix_library_close behaves correctly.
*/
struct infix_library_t {
void * handle; /**< The platform-native library handle (`HMODULE` on Windows, `void*` on POSIX). */
#if defined(INFIX_OS_WINDOWS)
bool is_pseudo_handle; /**< True if the handle is a "pseudo-handle" from GetModuleHandle. */
#endif
};
// ABI Abstraction Layer
/**
* @def INFIX_MAX_STACK_ALLOC
* @brief A safety limit (4MB) for the total stack space a trampoline can allocate.
* This prevents stack exhaustion from malformed or malicious type layouts.
*/
#define INFIX_MAX_STACK_ALLOC (1024 * 1024 * 4)
/**
* @def INFIX_MAX_ARG_SIZE
* @brief A safety limit (64KB) for the size of a single argument.
*/
#define INFIX_MAX_ARG_SIZE (1024 * 64)
/**
* @enum infix_arg_location_type
* @brief Describes the physical location where a function argument is passed according to the ABI.
*
* This enumeration abstracts away the differences in how various ABIs use
* registers and the stack to pass data. It is the primary output of the ABI
* classification process.
*/
typedef enum {
/** @brief Argument is passed in a general-purpose integer register (e.g., `RCX`, `RDI`, `X0`). */
ARG_LOCATION_GPR,
#if defined(INFIX_ABI_AAPCS64)
/** @brief (AArch64) Argument is passed in a vector/floating-point register (e.g., `V0`). */
ARG_LOCATION_VPR,
/** @brief (AArch64) A struct <= 16 bytes passed in a pair of GPRs (e.g., `X0`, `X1`). */
ARG_LOCATION_GPR_PAIR,
/** @brief (AArch64) A large struct (> 16 bytes) passed by reference; the pointer is in a GPR. */
ARG_LOCATION_GPR_REFERENCE,
( run in 1.290 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )