Affix

 view release on metacpan or  search on metacpan

infix/src/jit/trampoline.c  view on Meta::CPAN

    return nullptr;
#endif
}
/**
 * @internal
 * @brief Retrieves a pointer to the ABI specification v-table for reverse calls.
 * @return A pointer to the active `infix_reverse_abi_spec`, or `nullptr` if the
 *         platform is unsupported.
 */
const infix_reverse_abi_spec * get_current_reverse_abi_spec() {
#if defined(INFIX_ABI_WINDOWS_X64)
    return &g_win_x64_reverse_spec;
#elif defined(INFIX_ABI_SYSV_X64)
    return &g_sysv_x64_reverse_spec;
#elif defined(INFIX_ABI_AAPCS64)
    return &g_arm64_reverse_spec;
#else
    return nullptr;
#endif
}
/**
 * @internal
 * @brief Retrieves a pointer to the ABI v-table for direct marshalling forward calls.
 * @return A pointer to the active `infix_direct_forward_abi_spec`, or `nullptr`.
 */
const infix_direct_forward_abi_spec * get_current_direct_forward_abi_spec() {
#if defined(INFIX_ABI_WINDOWS_X64)
    return &g_win_x64_direct_forward_spec;
#elif defined(INFIX_ABI_SYSV_X64)
    return &g_sysv_x64_direct_forward_spec;
#elif defined(INFIX_ABI_AAPCS64)
    return &g_arm64_direct_forward_spec;
#else
    return nullptr;
#endif
}
// Code Buffer Implementation
/**
 * @internal
 * @brief Initializes a `code_buffer` for JIT code generation.
 * @param buf A pointer to the `code_buffer` to initialize.
 * @param arena The temporary arena to use for the buffer's memory.
 */
void code_buffer_init(code_buffer * buf, infix_arena_t * arena) {
    buf->capacity = 64;  // Start with a small initial capacity.
    buf->arena = arena;
    buf->code = infix_arena_alloc(arena, buf->capacity, 16);
    buf->size = 0;
    buf->error = (buf->code == nullptr);
}
/**
 * @internal
 * @brief Appends data to a `code_buffer`, reallocating from its arena if necessary.
 *
 * @details If the buffer runs out of space, it doubles its capacity until the new data
 * fits. All allocations happen within the temporary arena, so no manual `free` or
 * `realloc` calls are needed; cleanup is automatic when the arena is destroyed.
 *
 * @param buf The code buffer.
 * @param data A pointer to the data to append.
 * @param len The length of the data in bytes.
 */
void code_buffer_append(code_buffer * buf, const void * data, size_t len) {
    if (buf->error)
        return;
    if (len > SIZE_MAX - buf->size) {  // Overflow check
        buf->error = true;
        _infix_set_error(INFIX_CATEGORY_ALLOCATION, INFIX_CODE_INTEGER_OVERFLOW, 0);
        return;
    }
    if (buf->size + len > buf->capacity) {
        size_t new_capacity = buf->capacity;
        while (new_capacity < buf->size + len) {
            if (new_capacity > SIZE_MAX / 2) {  // Overflow check
                buf->error = true;
                _infix_set_error(INFIX_CATEGORY_ALLOCATION, INFIX_CODE_INTEGER_OVERFLOW, 0);
                return;
            }
            new_capacity *= 2;
        }
        void * new_code = infix_arena_alloc(buf->arena, new_capacity, 16);
        if (new_code == nullptr) {
            buf->error = true;
            // infix_arena_alloc already sets INFIX_CODE_OUT_OF_MEMORY, so we don't need to override it here
            return;
        }
        infix_memcpy(new_code, buf->code, buf->size);
        buf->code = new_code;
        buf->capacity = new_capacity;
    }
    infix_memcpy(buf->code + buf->size, data, len);
    buf->size += len;
}
/** @internal @brief Appends a single byte to the code buffer. */
void emit_byte(code_buffer * buf, uint8_t byte) { code_buffer_append(buf, &byte, 1); }
/** @internal @brief Appends a 32-bit integer (little-endian) to the code buffer. */
void emit_int32(code_buffer * buf, int32_t value) { code_buffer_append(buf, &value, 4); }
/** @internal @brief Appends a 64-bit integer (little-endian) to the code buffer. */
void emit_int64(code_buffer * buf, int64_t value) { code_buffer_append(buf, &value, 8); }
// Type Graph Validation
/** @internal A node for a visited list to detect cycles in `_is_type_graph_resolved_recursive`. */
typedef struct visited_node_t {
    const infix_type * type;
    struct visited_node_t * next;
} visited_node_t;
/**
 * @internal
 * @brief Recursively checks if a type graph is fully resolved (contains no named references).
 *
 * This is a critical pre-flight check before passing a type graph to the ABI
 * classification layer, which expects all types to have concrete size and
 * alignment information. An unresolved `@Name` node would cause it to fail.
 *
 * @param type The type to check.
 * @param visited_head A list to track visited nodes and prevent infinite recursion on cycles.
 * @return `true` if the graph is fully resolved, `false` otherwise.
 */
static bool _is_type_graph_resolved_recursive(const infix_type * type, visited_node_t * visited_head) {
    if (!type)
        return true;
    if (type->is_incomplete)



( run in 0.614 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )