Affix

 view release on metacpan or  search on metacpan

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

        goto cleanup;
    }

    handle->is_direct_trampoline = true;  // Mark this as a direct marshalling trampoline.

    size_t required_metadata_size = _estimate_metadata_size(temp_arena, return_type, arg_types, num_args);
    handle->arena = infix_arena_create(required_metadata_size + INFIX_TRAMPOLINE_HEADROOM);
    handle->is_external_arena = false;
    if (handle->arena == nullptr) {
        status = INFIX_ERROR_ALLOCATION_FAILED;
        goto cleanup;
    }

    handle->return_type = _copy_type_graph_to_arena(handle->arena, return_type);
    if (num_args > 0) {
        handle->arg_types = infix_arena_alloc(handle->arena, sizeof(infix_type *) * num_args, _Alignof(infix_type *));
        if (!handle->arg_types) {
            status = INFIX_ERROR_ALLOCATION_FAILED;
            goto cleanup;
        }
        for (size_t i = 0; i < num_args; ++i) {
            handle->arg_types[i] = _copy_type_graph_to_arena(handle->arena, arg_types[i]);
            if (arg_types[i] && !handle->arg_types[i] && !handle->arena->error) {
                status = INFIX_ERROR_ALLOCATION_FAILED;
                goto cleanup;
            }
        }
    }
    handle->num_args = num_args;
    handle->num_fixed_args = num_args;  // Direct trampolines are always fixed-arity.
    handle->target_fn = target_fn;
    handle->ref_count = 1;

    // 4. Allocate and Finalize Executable Memory
    handle->exec = infix_executable_alloc(buf.size);
    if (handle->exec.rw_ptr == nullptr) {
        status = INFIX_ERROR_ALLOCATION_FAILED;
        goto cleanup;
    }
    infix_memcpy(handle->exec.rw_ptr, buf.code, buf.size);
    if (!infix_executable_make_executable(
            &handle->exec, INFIX_EXECUTABLE_DIRECT, layout->prologue_size, layout->epilogue_offset)) {
        status = INFIX_ERROR_PROTECTION_FAILED;
        goto cleanup;
    }

    infix_dump_hex(handle->exec.rx_ptr, handle->exec.size, "Direct-Marshalling Forward Trampoline Machine Code");
    *out_trampoline = handle;

cleanup:
    if (status != INFIX_SUCCESS && handle != nullptr)
        infix_forward_destroy(handle);
    infix_arena_destroy(temp_arena);
    return status;
}
/**
 * @brief Creates a bound forward trampoline from `infix_type` objects (Manual API).
 *
 * @details This is the lower-level, programmatic way to create a bound forward trampoline.
 * It bypasses the signature string parser, making it suitable for performance-critical
 * applications or language bindings that construct type information dynamically.
 *
 * All `infix_type` objects passed to this function must be fully resolved and have
 * a valid layout. They should be allocated from a user-managed `infix_arena_t`.
 *
 * @param[out] out_trampoline Receives the created trampoline handle.
 * @param[in] return_type The `infix_type` for the function's return value.
 * @param[in] arg_types An array of `infix_type*` for the function's arguments.
 * @param[in] num_args The number of arguments.
 * @param[in] num_fixed_args The number of non-variadic arguments.
 * @param[in] target_function The address of the C function to call.
 * @return `INFIX_SUCCESS` on success.
 */
INFIX_API c23_nodiscard infix_status infix_forward_create_manual(infix_forward_t ** out_trampoline,
                                                                 infix_type * return_type,
                                                                 infix_type ** arg_types,
                                                                 size_t num_args,
                                                                 size_t num_fixed_args,
                                                                 void * target_function) {
    // This is part of the "Manual API". It calls the internal implementation directly
    // without involving the signature parser. `source_arena` is null because the
    // types are assumed to be managed by the user.
    _infix_clear_error();
    return _infix_forward_create_impl(
        out_trampoline, nullptr, return_type, arg_types, num_args, num_fixed_args, target_function, false);
}
/**
 * @brief Creates an unbound forward trampoline from `infix_type` objects (Manual API).
 *
 * @details This is the lower-level, programmatic way to create an unbound forward trampoline.
 * It bypasses the signature string parser.
 *
 * @param[out] out_trampoline Receives the created trampoline handle.
 * @param[in] return_type The `infix_type` for the function's return value.
 * @param[in] arg_types An array of `infix_type*` for the function's arguments.
 * @param[in] num_args The number of arguments.
 * @param[in] num_fixed_args The number of non-variadic arguments.
 * @return `INFIX_SUCCESS` on success.
 */
INFIX_API c23_nodiscard infix_status infix_forward_create_unbound_manual(infix_forward_t ** out_trampoline,
                                                                         infix_type * return_type,
                                                                         infix_type ** arg_types,
                                                                         size_t num_args,
                                                                         size_t num_fixed_args) {
    _infix_clear_error();
    return _infix_forward_create_impl(
        out_trampoline, nullptr, return_type, arg_types, num_args, num_fixed_args, nullptr, false);
}
/**
 * @internal
 * @brief Internal implementation of forward trampoline destruction.
 */
void _infix_forward_destroy_internal(infix_forward_t * trampoline) {
    if (trampoline == nullptr)
        return;
    // Destroying the private arena frees all deep-copied type metadata and the signature string.
    if (trampoline->arena && !trampoline->is_external_arena)
        infix_arena_destroy(trampoline->arena);
    // Free the JIT-compiled executable code.
    infix_executable_free(trampoline->exec);
    // Free the handle struct itself.



( run in 0.612 second using v1.01-cache-2.11-cpan-2398b32b56e )