Affix

 view release on metacpan or  search on metacpan

CODE_OF_CONDUCT.md  view on Meta::CPAN

Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.

## Scope

This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
https://github.com/sanko/Affix.pm/discussions.
All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the

infix/src/arch/aarch64/abi_arm64.c  view on Meta::CPAN

            default:
                break;
            }
        }
    }
    // Deallocate stack space and restore registers.
    // X29 was set to SP after all pushes.
    // mov sp, x29
    emit_arm64_mov_reg(buf, true, SP_REG, X29_FP_REG);

    emit_arm64_ldp_post_index(buf, true, X21_REG, X22_REG, SP_REG, 16);        // ldp x21, x22, [sp], #16
    emit_arm64_ldp_post_index(buf, true, X19_REG, X20_REG, SP_REG, 16);        // ldp x19, x20, [sp], #16
    emit_arm64_ldp_post_index(buf, true, X29_FP_REG, X30_LR_REG, SP_REG, 16);  // ldp x29, x30, [sp], #16
    emit_arm64_ret(buf, X30_LR_REG);                                           // ret
    return INFIX_SUCCESS;
}
/**
 * @internal
 * @brief Stage 1 (Reverse): Calculates the stack layout for a reverse trampoline stub.
 * @details This function determines the total stack space the JIT-compiled stub will need
 *          for its local variables. This space includes:
 *          1. A buffer to store the return value before it's placed in registers.
 *          2. An array of `void*` pointers (`args_array`) to pass to the C dispatcher.

infix/src/arch/aarch64/abi_arm64.c  view on Meta::CPAN

            emit_arm64_ldr_imm(buf, true, X0_REG, SP_REG, layout->return_buffer_offset);
            if (context->return_type->size > 8)
                emit_arm64_ldr_imm(buf, true, X1_REG, SP_REG, layout->return_buffer_offset + 8);
        }
    }
    // Deallocate stack and restore frame.
    if (layout->total_stack_alloc > 0)
        // add sp, sp, #total_stack_alloc
        emit_arm64_add_imm(buf, true, false, SP_REG, SP_REG, (uint32_t)layout->total_stack_alloc);  // Cast size_t
    // Restore Frame Pointer and Link Register, then return.
    emit_arm64_ldp_post_index(
        buf, true, X29_FP_REG, X30_LR_REG, SP_REG, 16);  // ldp x29, x30, [sp], #16 (Load pair, post-indexed)
    emit_arm64_ret(buf, X30_LR_REG);                     // ret
    return INFIX_SUCCESS;
}

/**
 * @internal
 * @brief Stage 1 (Direct): Analyzes a signature and creates a call frame layout for AAPCS64.
 */
static infix_status prepare_direct_forward_call_frame_arm64(infix_arena_t * arena,
                                                            infix_direct_call_frame_layout ** out_layout,

infix/src/arch/aarch64/abi_arm64.c  view on Meta::CPAN

            emit_arm64_add_imm(buf, true, false, SP_REG, SP_REG, 32);
        }
    }

    // Standard Epilogue
    // Restore stack pointer to the saved registers area.
    // X29 was set to SP after all pushes.
    // mov sp, x29
    emit_arm64_mov_reg(buf, true, SP_REG, X29_FP_REG);

    emit_arm64_ldp_post_index(buf, true, X21_REG, X22_REG, SP_REG, 16);
    emit_arm64_ldp_post_index(buf, true, X19_REG, X20_REG, SP_REG, 16);
    emit_arm64_ldp_post_index(buf, true, X29_FP_REG, X30_LR_REG, SP_REG, 16);
    emit_arm64_ret(buf, X30_LR_REG);

    return INFIX_SUCCESS;
}

infix/src/arch/aarch64/abi_arm64_emitters.c  view on Meta::CPAN

    // For STP: opc=?, L=0
    uint32_t instr =
        (is64 ? A64_SF_64BIT : A64_SF_32BIT) | A64_OPC_STP | A64_OP_LOAD_STORE_PAIR_BASE | A64_ADDR_PRE_INDEX;
    instr |= ((uint32_t)(offset / scale) & 0x7F) << 15;
    instr |= (uint32_t)(src2 & 0x1F) << 10;
    instr |= (uint32_t)(base & 0x1F) << 5;
    instr |= (uint32_t)(src1 & 0x1F);
    emit_int32(buf, instr);
}
/*
 * Implementation for emit_arm64_ldp_post_index (Load Pair).
 * Encodes `LDP <Xt1>, <Xt2>, [Xn|SP], #imm`.
 * Opcode (64-bit): 1010100011...
 */
INFIX_INTERNAL void emit_arm64_ldp_post_index(
    code_buffer * buf, bool is64, arm64_gpr dest1, arm64_gpr dest2, arm64_gpr base, int32_t offset) {
    uint32_t instr = 0xA8C00000;  // Base for LDP post-indexed
    if (is64)
        instr |= (1u << 31);
    int scale = is64 ? 8 : 4;
    assert(offset % scale == 0 && (offset / scale) >= -64 && (offset / scale) <= 63);
    instr |= ((uint32_t)(offset / scale) & 0x7F) << 15;
    instr |= (uint32_t)(dest2 & 0x1F) << 10;
    instr |= (uint32_t)(base & 0x1F) << 5;
    instr |= (uint32_t)(dest1 & 0x1F);
    emit_int32(buf, instr);
}

infix/src/arch/aarch64/abi_arm64_emitters.h  view on Meta::CPAN

INFIX_INTERNAL void emit_arm64_ldrsh_imm(code_buffer * buf, arm64_gpr dest, arm64_gpr base, int32_t offset);
/** @internal @brief Emits `STR <Wt|Xt>, [<Xn|SP>, #imm]` to store a GPR to memory. */
INFIX_INTERNAL void emit_arm64_str_imm(code_buffer * buf, bool is64, arm64_gpr src, arm64_gpr base, int32_t offset);
/** @internal @brief Emits `STRB <Wt>, [<Xn|SP>, #imm]` to store a byte from a GPR to memory. */
INFIX_INTERNAL void emit_arm64_strb_imm(code_buffer * buf, arm64_gpr src, arm64_gpr base, int32_t offset);
/** @internal @brief Emits `STRH <Wt>, [<Xn|SP>, #imm]` to store a half-word (16-bit) from a GPR to memory. */
INFIX_INTERNAL void emit_arm64_strh_imm(code_buffer * buf, arm64_gpr src, arm64_gpr base, int32_t offset);
/** @internal @brief Emits `STP <Xt1>, <Xt2>, [Xn|SP, #imm]!` with pre-indexing to store a pair of GPRs. */
INFIX_INTERNAL void emit_arm64_stp_pre_index(
    code_buffer * buf, bool is64, arm64_gpr src1, arm64_gpr src2, arm64_gpr base, int32_t offset);
/** @internal @brief Emits `LDP <Xt1>, <Xt2>, [Xn|SP], #imm` with post-indexing to load a pair of GPRs. */
INFIX_INTERNAL void emit_arm64_ldp_post_index(
    code_buffer * buf, bool is64, arm64_gpr dest1, arm64_gpr dest2, arm64_gpr base, int32_t offset);
// Memory <-> VPR (SIMD/FP) Emitters
/** @internal @brief Emits `LDR <Ht|St|Dt>, [<Xn|SP>, #imm]` to load a 16/32/64-bit FP value from memory. */
INFIX_INTERNAL void emit_arm64_ldr_vpr(code_buffer * buf, size_t size, arm64_vpr dest, arm64_gpr base, int32_t offset);
/** @internal @brief Emits `STR <Ht|St|Dt>, [<Xn|SP>, #imm]` to store a 16/32/64-bit FP value to memory. */
INFIX_INTERNAL void emit_arm64_str_vpr(code_buffer * buf, size_t size, arm64_vpr src, arm64_gpr base, int32_t offset);
/** @internal @brief Emits `LDR <Qt>, [<Xn|SP>, #imm]` for a 128-bit load into a SIMD&FP register. */
INFIX_INTERNAL void emit_arm64_ldr_q_imm(code_buffer * buf, arm64_vpr dest, arm64_gpr base, int32_t offset);
/** @internal @brief Emits `STR <Qt>, [<Xn|SP>, #imm]` for a 128-bit store from a SIMD&FP register. */
INFIX_INTERNAL void emit_arm64_str_q_imm(code_buffer * buf, arm64_vpr src, arm64_gpr base, int32_t offset);

infix/src/core/types.c  view on Meta::CPAN

} recalc_visited_node_t;
/**
 * @internal
 * @brief Recursively recalculates the size, alignment, and member offsets for a type graph.
 *
 * @details This function is the implementation of the **"Layout"** stage of the
 * "Parse -> Copy -> Resolve -> Layout" data pipeline. It is designed to be called
 * *after* a type graph has been fully resolved, ensuring that all
 * `INFIX_TYPE_NAMED_REFERENCE` nodes have been replaced with concrete types.
 *
 * The function performs a **post-order traversal** of the type graph. This is critical,
 * as it ensures that the layout of nested types (like a struct member) is correctly
 * calculated *before* the layout of the parent container that depends on it.
 *
 * It correctly handles cyclic graphs by using a `visited_head` linked list to track
 * nodes currently in the recursion stack, preventing infinite loops.
 *
 * @param[in,out] type The `infix_type` object to recalculate. Its `size`, `alignment`, and
 *        (if applicable) member `offset` fields are modified in-place. The function
 *        does nothing if `type` is `nullptr` or a static primitive (`is_arena_allocated` is false).
 * @param[in,out] visited_head A pointer to the head of the visited list for cycle detection.

infix/src/core/types.c  view on Meta::CPAN

        if (v->type == type)
            return;
    // Allocate the memoization node from a stable temporary arena.
    recalc_visited_node_t * visited_node =
        infix_arena_alloc(temp_arena, sizeof(recalc_visited_node_t), _Alignof(recalc_visited_node_t));
    if (!visited_node)
        return;  // Cannot proceed without memory.
    visited_node->type = type;
    visited_node->next = *visited_head;
    *visited_head = visited_node;
    // Recurse into child types first (post-order traversal).
    switch (type->category) {
    case INFIX_TYPE_POINTER:
        _infix_type_recalculate_layout_recursive(temp_arena, type->meta.pointer_info.pointee_type, visited_head);
        break;
    case INFIX_TYPE_ARRAY:
        _infix_type_recalculate_layout_recursive(temp_arena, type->meta.array_info.element_type, visited_head);
        break;
    case INFIX_TYPE_STRUCT:
    case INFIX_TYPE_UNION:
        for (size_t i = 0; i < type->meta.aggregate_info.num_members; ++i) {

lib/Affix/Build.pm  view on Meta::CPAN

                # Link the object to shared
                # We use the generic linker logic for this single file
                my $linker = $Config{cc} // 'cc';
                $self->_run( $linker, '-shared', '-o', "$out", "$obj" );
                return $out;
            }
            return { file => $obj, libs => ['gnat'] };
        }

        #~ https://github.com/bennoleslie/haskell-shared-example
        #~ https://www.hobson.space/posts/haskell-foreign-library/
        method _build_haskell ( $src, $out, $mode ) {
            my $file = $src->{path};
            my $ghc  = $self->_can_run('ghc') // croak "GHC not found";
            if ( $mode eq 'dynamic' ) {
                my @cmd = ( $ghc, '-shared', '-dynamic', "$file", '-o', "$out" );
                push @cmd, '-fPIC' unless $os eq 'MSWin32';
                $self->_run(@cmd);
                return $out;
            }
            else {

lib/Affix/Wrap.pm  view on Meta::CPAN

            $t =~ s/^\s*\*\s?//mg;
            $t =~ s/^\s*\/\/\s?//mg;
            $t =~ s/^\s+|\s+$//g;
            return $t;
        }

        method _extract_trailing( $f, $off ) {
            return '' unless defined $off;
            my $content = $self->_get_content($f);
            return '' unless length($content);
            my $post   = substr( $content, $off );
            my ($line) = split /\R/, $post, 2;
            return '' unless defined $line;
            if ( $line =~ /\/\/(.*)$/ ) {
                my $c = $1;
                $c =~ s/^\s+|\s+$//g;
                return $c;
            }
            return '';
        }

        method _extract_raw( $f, $s, $e ) {



( run in 2.007 seconds using v1.01-cache-2.11-cpan-5735350b133 )