Affix

 view release on metacpan or  search on metacpan

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

 * @details This module is the central orchestrator of the `infix` library. It brings
 * together the type system, memory management, and ABI-specific logic to generate
 * executable machine code at runtime.
 *
 * It implements both the high-level Signature API (e.g., `infix_forward_create`)
 * and the low-level Manual API (e.g., `infix_forward_create_manual`). The high-level
 * functions are convenient wrappers that use the signature parser to create the
 * necessary `infix_type` objects before calling the core internal implementation.
 *
 * The core logic is encapsulated in `_infix_forward_create_internal` and
 * `_infix_reverse_create_internal`. These functions follow a clear pipeline:
 * 1.  **Prepare:** Analyze the function signature with the appropriate ABI-specific
 *     `prepare_*_call_frame` function to create a layout blueprint.
 * 2.  **Generate:** Use the layout blueprint to call a sequence of ABI-specific
 *     `generate_*` functions, which emit machine code into a temporary `code_buffer`.
 * 3.  **Finalize:** Allocate executable memory, copy the generated code into it,
 *     create the final self-contained trampoline handle (deep-copying all type
 *     metadata), and make the code executable.
 */
#include "common/infix_internals.h"
#include "common/utility.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(INFIX_OS_MACOS)
#include <pthread.h>
#endif
#if defined(INFIX_OS_WINDOWS)
#include <windows.h>
#else
#include <sys/mman.h>
#include <unistd.h>
#endif
// Forward Declaration for Internal Creation Function
static infix_status _infix_reverse_create_internal(infix_reverse_t ** out_context,
                                                   infix_type * return_type,
                                                   infix_type ** arg_types,
                                                   size_t num_args,
                                                   size_t num_fixed_args,
                                                   void * user_callback_fn,
                                                   void * user_data,
                                                   bool is_callback);
// ABI Specification V-Table Declarations (extern to link to the specific implementations)
#if defined(INFIX_ABI_WINDOWS_X64)
extern const infix_forward_abi_spec g_win_x64_forward_spec;
extern const infix_reverse_abi_spec g_win_x64_reverse_spec;
extern const infix_direct_forward_abi_spec g_win_x64_direct_forward_spec;
#elif defined(INFIX_ABI_SYSV_X64)
extern const infix_forward_abi_spec g_sysv_x64_forward_spec;
extern const infix_reverse_abi_spec g_sysv_x64_reverse_spec;
extern const infix_direct_forward_abi_spec g_sysv_x64_direct_forward_spec;
#elif defined(INFIX_ABI_AAPCS64)
extern const infix_forward_abi_spec g_arm64_forward_spec;
extern const infix_reverse_abi_spec g_arm64_reverse_spec;
extern const infix_direct_forward_abi_spec g_arm64_direct_forward_spec;
#endif
/**
 * @internal
 * @brief Retrieves a pointer to the ABI specification v-table for forward calls.
 * @details This function is the entry point to the ABI abstraction layer. It uses
 * compile-time preprocessor macros (defined in `infix_config.h`) to select and
 * return the correct v-table for the target platform.
 * @return A pointer to the active `infix_forward_abi_spec`, or `nullptr` if the
 *         platform is unsupported.
 */
const infix_forward_abi_spec * get_current_forward_abi_spec() {
#if defined(INFIX_ABI_WINDOWS_X64)
    return &g_win_x64_forward_spec;
#elif defined(INFIX_ABI_SYSV_X64)
    return &g_sysv_x64_forward_spec;
#elif defined(INFIX_ABI_AAPCS64)
    return &g_arm64_forward_spec;
#else
    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;

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

        (num_args > 0) ? infix_arena_alloc(arena, sizeof(infix_type *) * num_args, _Alignof(infix_type *)) : nullptr;
    if (num_args > 0 && !arg_types) {
        infix_arena_destroy(arena);
        _infix_set_error(INFIX_CATEGORY_ALLOCATION, INFIX_CODE_OUT_OF_MEMORY, 0);
        return INFIX_ERROR_ALLOCATION_FAILED;
    }
    for (size_t i = 0; i < num_args; ++i)
        arg_types[i] = args[i].type;
    // Call the manual API with the parsed types.
    status =
        infix_reverse_create_callback_manual(out_context, ret_type, arg_types, num_args, num_fixed, user_callback_fn);
    infix_arena_destroy(arena);
    return status;
}
c23_nodiscard infix_status infix_reverse_create_closure(infix_reverse_t ** out_context,
                                                        const char * signature,
                                                        infix_closure_handler_fn user_callback_fn,
                                                        void * user_data,
                                                        infix_registry_t * registry) {
    infix_arena_t * arena = nullptr;
    infix_type * ret_type = nullptr;
    infix_function_argument * args = nullptr;
    size_t num_args = 0, num_fixed = 0;
    infix_status status = infix_signature_parse(signature, &arena, &ret_type, &args, &num_args, &num_fixed, registry);
    if (status != INFIX_SUCCESS) {
        infix_arena_destroy(arena);
        return status;
    }
    infix_type ** arg_types =
        (num_args > 0) ? infix_arena_alloc(arena, sizeof(infix_type *) * num_args, _Alignof(infix_type *)) : nullptr;
    if (num_args > 0 && !arg_types) {
        infix_arena_destroy(arena);
        _infix_set_error(INFIX_CATEGORY_ALLOCATION, INFIX_CODE_OUT_OF_MEMORY, 0);
        return INFIX_ERROR_ALLOCATION_FAILED;
    }
    for (size_t i = 0; i < num_args; ++i)
        arg_types[i] = args[i].type;
    status = infix_reverse_create_closure_manual(
        out_context, ret_type, arg_types, num_args, num_fixed, user_callback_fn, user_data);
    infix_arena_destroy(arena);
    return status;
}
// ============================================================================
//                       UNITY BUILD INCLUDES
// This section includes the actual ABI implementations at the end of the file.
// Because `trampoline.c` is the central translation unit, including the
// correct ABI-specific .c file here makes its functions (`g_win_x64_spec`, etc.)
// available without needing to add platform-specific logic to the build system.
// The `infix_config.h` header ensures only one of these #if blocks is active.
// ============================================================================
#if defined(INFIX_ABI_WINDOWS_X64)
#include "../arch/x64/abi_win_x64.c"
#include "../arch/x64/abi_x64_emitters.c"
#elif defined(INFIX_ABI_SYSV_X64)
#include "../arch/x64/abi_sysv_x64.c"
#include "../arch/x64/abi_x64_emitters.c"
#elif defined(INFIX_ABI_AAPCS64)
#include "../arch/aarch64/abi_arm64.c"
#include "../arch/aarch64/abi_arm64_emitters.c"
#else
#error "No supported ABI was selected for the unity build in trampoline.c."
#endif



( run in 0.506 second using v1.01-cache-2.11-cpan-39bf76dae61 )