aarch64_target

    AArch64 direct MilkIR target pipeline to native code

    aarch64
    compiler
    codegen
    jit
    Download zip
    Author
    Version
    0.19.0
    License
    Apache-2.0
    Last updated
    3 days ago
    Downloads
    1K

    #aarch64_target

    AArch64 backend for direct MilkIR instruction selection.

    This module owns AArch64 instruction selection, validation and lowering of an embedding-provided internal ABI contract, register allocation policy, frame layout, machine-code emission, relocations, veneers, and final linking.

    #Package

    • Milky2018/aarch64_target: AArch64 Target VCode, lowering, allocation, frame layout, emission, and linking.

    #When to use it

    Use this module as the target sink for Milky2018/milkir/native, then install its generated code object through the embedding runtime.

    Environment fields are materialized at each lowered occurrence. MilkIR owns whether stable fields remain separate rematerializable values; the target does not merge them with distance or register-pressure heuristics. No physical register is reserved for embedding context data.

    #Example: define the internal ABI

    ///|
    test "validate the AArch64 internal ABI" {
    @aarch64_target.InternalAbi::new(
    0,
    8,
    [1, 2, 3, 4, 5, 6, 7],
    [0, 1, 2, 3, 4, 5, 6, 7],
    [0, 1, 2, 3, 4, 5, 6, 7],
    [0, 1, 2, 3, 4, 5, 6, 7],
    )
    |> ignore
    }

    #Integration

    Finish a DirectLoweringSession, then use compile_selected for the complete AArch64 target pipeline. It produces a verified Milky2018/vcode/code_object value. Runtime symbol resolution, relocation application, and executable-memory ownership remain responsibilities of the embedding application.

    compile performs allocation, frame planning, and emission without repeating checkpoint validation. Its optional on_event callback reports generic stage boundaries and a read-only allocation summary so an embedding can collect metrics without coupling this module to a product metrics system. The callback must not mutate compiler inputs.

    Internal functions use the tail-call convention: an ordinary internal caller places stack arguments in its reserved outgoing area, the callee pops that incoming area on return, and the call pseudo immediately restores the caller's frame-base SP. A function containing true tail calls enlarges its incoming area in the prologue to the maximum tail-callee requirement, then reuses that area when transferring control. Platform calls continue to use ordinary AAPCS64 caller-owned stack arguments.

    Parallel moves reserve X15 and V18 as one transfer scratch per register bank. X16 remains stack-address-only, while X17 and V16/V17 serve instruction and regalloc spill needs. A stack cycle that temporarily needs the live transfer scratch receives one verified 16-byte emergency frame area; ordinary frames do not pay for it.

    AArch64Address

    using @Milky2018/vcode { type SymbolicAddress as AArch64Address }

    AArch64Condition

    using @Milky2018/vcode { type IntegerCondition as AArch64Condition }

    AArch64FloatBinary

    using @Milky2018/vcode/native_lowering { type FloatBinaryOp as AArch64FloatBinary }

    AArch64FloatCondition

    using @Milky2018/vcode/native_lowering { type FloatComparison as AArch64FloatCondition }

    AArch64FloatTernary

    using @Milky2018/vcode/native_lowering { type FloatTernaryOp as AArch64FloatTernary }

    AArch64FloatTrapCondition

    using @Milky2018/vcode { type FloatTrapCondition as AArch64FloatTrapCondition }

    AArch64FloatUnary

    using @Milky2018/vcode/native_lowering { type FloatUnaryOp as AArch64FloatUnary }

    AArch64IntUnary

    using @Milky2018/vcode { type ScalarIntUnary as AArch64IntUnary }

    AArch64StackObject

    using @Milky2018/vcode { type SizedStackObject as AArch64StackObject }

    A function-local stack object before target frame placement.

    AArch64VectorConversion

    using @Milky2018/vcode { type VectorConversion as AArch64VectorConversion }

    AArch64VectorIntBinary

    using @Milky2018/vcode/native_lowering { type VectorIntBinaryOp as AArch64VectorIntBinary }

    AArch64VectorIntUnary

    using @Milky2018/vcode/native_lowering { type VectorIntUnaryOp as AArch64VectorIntUnary }

    AArch64VectorPredicate

    using @Milky2018/vcode/native_lowering { type VectorPredicateOp as AArch64VectorPredicate }

    GprWidth

    using @Milky2018/vcode { type RegisterWidth as GprWidth }

    InternalAbi

    Register assignment shared by the native backends' internal calls.

    InternalAbiError

    InternalCallPlan

    LoweringContext

    TargetVCodeVerifyError

    AArch64AllocationError

    AArch64AllocationError::output

    fn AArch64AllocationError::output(self : AArch64AllocationError, logger : &Logger) -> Unit

    AArch64AllocationError::to_string

    fn AArch64AllocationError::to_string(self : AArch64AllocationError) -> String

    AArch64CompileError

    pub suberror AArch64CompileError {
    TargetValidationFailed(cause~ :
    TargetVCodeVerifyError
    )
    AllocationFailed(cause~ : AArch64AllocationError)
    FramePlanningFailed(cause~ : AArch64FrameError)
    EmissionFailed(cause~ : AArch64EmitError)
    } derive(
    Debug
    )

    AArch64CompileError::output

    fn AArch64CompileError::output(self : AArch64CompileError, logger : &Logger) -> Unit

    AArch64CompileError::to_string

    fn AArch64CompileError::to_string(self : AArch64CompileError) -> String

    AArch64EmitError

    pub suberror AArch64EmitError {
    InvalidFrame(cause~ : AArch64FrameError)
    InvalidCodeObject(cause~ :
    CodeObjectVerifyError
    )
    InvalidParallelMove(cause~ :
    MoveResolveError
    )
    InvalidCallTransfer(cause~ :
    CallTransferError
    )
    UnresolvedStackMove
    MissingStackObjectArea
    MissingResultArea
    MissingEmergencyMoveArea
    UnexpectedStackOperand(instruction~ :
    Instruction
    , operand~ : Int)
    FrameOffsetOutOfRange(offset~ : Int)
    InvalidScalarMemoryAccess
    InvalidFloatInstruction
    InvalidVectorInstruction
    InvalidConversionInstruction
    BranchTargetMissing(block~ :
    Block
    )
    BranchLabelUnbound(label~ : Int)
    BranchSpanNotFixed(offset~ : Int)
    BranchOutOfRange(offset~ : Int, bits~ : Int)
    } derive(
    Debug
    )

    AArch64EmitError::output

    fn AArch64EmitError::output(self : AArch64EmitError, logger : &Logger) -> Unit

    AArch64EmitError::to_string

    fn AArch64EmitError::to_string(self : AArch64EmitError) -> String

    AArch64FrameError

    pub suberror AArch64FrameError {
    InvalidAllocation(cause~ : AArch64AllocationError)
    InvalidGenericFrame(cause~ :
    FrameVerifyError
    )
    InvalidSavedRegister(reg~ :
    PhysicalReg
    , offset~ : Int)
    InvalidStackSlot(slot~ :
    StackSlot
    )
    OutgoingAreaMismatch(expected~ : Int, actual~ : Int)
    ResultAreaMismatch(expected~ : Int, actual~ : Int)
    TailAreaMismatch(expected_incoming~ : Int, actual_incoming~ : Int, expected_tail~ : Int, actual_tail~ : Int)
    InvalidStackObjectArea(message~ : String)
    MovePlanningFailed(cause~ :
    MoveResolveError
    )
    InvalidEmergencyMoveArea(offset~ : Int?)
    StaleAllocation(expected_edits~ : Int, actual_edits~ : Int)
    SavedRegisterSetMismatch
    } derive(
    Debug
    )

    AArch64FrameError::output

    fn AArch64FrameError::output(self : AArch64FrameError, logger : &Logger) -> Unit

    AArch64FrameError::to_string

    fn AArch64FrameError::to_string(self : AArch64FrameError) -> String

    AArch64LinkError

    pub suberror AArch64LinkError {
    InvalidCodeObject(message~ : String)
    InvalidCodeBase(address~ : Int64)
    UnresolvedRelocation(index~ : Int)
    RelocationOutOfRange(index~ : Int)
    UnsupportedRelocation(index~ : Int)
    } derive(Eq,
    Debug
    )

    AArch64LinkError::equal

    AArch64LinkError::not_equal

    fn AArch64LinkError::not_equal(x : AArch64LinkError, y : AArch64LinkError) -> Bool

    AArch64LinkError::output

    fn AArch64LinkError::output(self : AArch64LinkError, logger : &Logger) -> Unit

    AArch64LinkError::to_string

    fn AArch64LinkError::to_string(self : AArch64LinkError) -> String

    AArch64LowerError

    pub suberror AArch64LowerError {
    UnsupportedOperation(block_index~ : Int, instruction_index~ : Int, operation~ :
    Operation
    )
    UnsupportedAbi(message~ : String)
    BuildFailure(cause~ :
    VCodeBuildError
    )
    InvalidTarget(cause~ :
    TargetVCodeVerifyError
    )
    } derive(
    Debug
    )

    AArch64LowerError::output

    fn AArch64LowerError::output(self : AArch64LowerError, logger : &Logger) -> Unit

    AArch64LowerError::to_string

    fn AArch64LowerError::to_string(self : AArch64LowerError) -> String

    AArch64Frame

    pub struct AArch64Frame {
    // private fields
    }

    AArch64Frame::alignment

    fn AArch64Frame::alignment(self : AArch64Frame) -> Int

    AArch64Frame::emergency_move_offset

    fn AArch64Frame::emergency_move_offset(self : AArch64Frame) -> Int?

    AArch64Frame::frame_size

    fn AArch64Frame::frame_size(self : AArch64Frame) -> Int

    AArch64Frame::incoming_args_size

    fn AArch64Frame::incoming_args_size(self : AArch64Frame) -> Int

    AArch64Frame::outgoing_args_size

    fn AArch64Frame::outgoing_args_size(self : AArch64Frame) -> Int

    AArch64Frame::saved_registers

    AArch64Frame::slot_offset

    fn AArch64Frame::slot_offset(self : AArch64Frame, slot :
    StackSlot
    ) -> Int?

    AArch64Frame::stack_object_offset

    fn AArch64Frame::stack_object_offset(self : AArch64Frame, object :
    SizedStackObject
    ) -> Int?

    AArch64Frame::summary

    fn AArch64Frame::summary(self : AArch64Frame) -> String

    AArch64Frame::tail_args_size

    fn AArch64Frame::tail_args_size(self : AArch64Frame) -> Int

    AArch64Inst

    pub(all) enum AArch64Inst {
    IncomingReg(
    ValueType
    ,
    PhysicalReg
    )
    IncomingStack(
    ValueType
    , Int)
    IncomingResultArea(
    PhysicalReg
    )
    IncomingCallResult(
    ValueType
    ,
    PhysicalReg
    )
    IncomingCallAreaResult(
    ValueType
    , Int)
    OutgoingReg(
    ValueType
    ,
    PhysicalReg
    )
    OutgoingAreaResult(
    ValueType
    , Int)
    KeepAlive(
    ValueType
    )
    LoadConstant(
    RegisterWidth
    , UInt64)
    LoadVectorConstant(UInt64, UInt64)
    LoadNull(
    ValueType
    )
    LoadAddress(
    SymbolicAddress
    )
    StackAddress(
    SizedStackObject
    )
    LoadFloatConstant(
    ValueType
    , UInt64)
    Move(
    ValueType
    )
    CarrierMove(
    ValueType
    ,
    ValueType
    )
    Select(
    ValueType
    )
    SpectreGuard
    VectorSelect
    VectorSplat(
    VectorLane
    )
    VectorExtractLane(
    VectorLane
    , Int,
    Signedness
    ?)
    VectorReplaceLane(
    VectorLane
    , Int)
    VectorShuffle(FixedArray[Int])
    VectorSwizzle
    VectorBitwise(
    VectorBitwiseOp
    )
    VectorIntUnary(
    VectorLane
    ,
    VectorIntUnaryOp
    )
    VectorIntBinary(
    VectorLane
    ,
    VectorIntBinaryOp
    )
    VectorIntShift(
    VectorLane
    ,
    VectorIntShiftOp
    )
    VectorIntCompare(
    VectorLane
    ,
    VectorIntComparison
    )
    VectorConvert(
    VectorConversion
    )
    VectorPredicate(
    VectorPredicateOp
    )
    VectorFloatUnary(
    VectorLane
    ,
    VectorFloatUnaryOp
    )
    VectorFloatBinary(
    VectorLane
    ,
    VectorFloatBinaryOp
    )
    VectorFloatTernary(
    VectorLane
    ,
    FloatTernaryOp
    )
    VectorFloatCompare(
    VectorLane
    ,
    VectorFloatComparison
    )
    VectorPairwiseAddI16x8
    VectorRelaxedDot8To16
    IntUnary(
    RegisterWidth
    ,
    ScalarIntUnary
    )
    IntBinary(
    RegisterWidth
    , AArch64IntBinary)
    IntBinaryImmediate(
    RegisterWidth
    , AArch64IntBinary, UInt64)
    IntMultiplyAdd(
    RegisterWidth
    )
    IntMultiplySubtract(
    RegisterWidth
    )
    IntShiftRegister(
    RegisterWidth
    , AArch64Shift)
    IntShiftImmediate(
    RegisterWidth
    , AArch64Shift, Int)
    IntAddShiftedLeft(
    RegisterWidth
    , Int)
    IntAddShiftedRight(
    RegisterWidth
    , Int)
    IntLowBitsShiftLeft(
    RegisterWidth
    , Int, Int)
    IntExtractBits(
    RegisterWidth
    , Int, Int)
    PopulationCount(
    RegisterWidth
    )
    IntHighMultiply(
    RegisterWidth
    ,
    Signedness
    )
    IntWithOverflow(
    RegisterWidth
    ,
    IntOverflowOp
    )
    IntRemainder(
    RegisterWidth
    ,
    Signedness
    )
    TrapIfZero(
    RegisterWidth
    )
    TrapIfSignedDivOverflow(
    RegisterWidth
    )
    CompareSet(
    RegisterWidth
    ,
    IntegerCondition
    )
    CompareSetImmediate(
    RegisterWidth
    ,
    IntegerCondition
    , UInt64)
    ReferenceCompareSet(
    ValueType
    ,
    IntegerCondition
    )
    FloatUnary(
    ValueType
    ,
    FloatUnaryOp
    )
    FloatBinary(
    ValueType
    ,
    FloatBinaryOp
    )
    FloatTernary(
    ValueType
    ,
    FloatTernaryOp
    )
    FloatCompareSet(
    ValueType
    ,
    FloatComparison
    )
    TrapIfFloat(
    ValueType
    ,
    FloatTrapCondition
    )
    Convert(AArch64Conversion)
    AddAddress
    AddAddressImmediate(UInt64)
    AddAddressUxtw(Int)
    ScalarLoad(
    AccessWidth
    ,
    LoadExtension
    ,
    ValueType
    , UInt64)
    ScalarLoadUxtw(
    AccessWidth
    ,
    LoadExtension
    ,
    ValueType
    , Int)
    ScalarStore(
    AccessWidth
    ,
    ValueType
    , UInt64)
    StoreRepeated64(UInt64, UInt, UInt64)
    ScalarStoreUxtw(
    AccessWidth
    ,
    ValueType
    , Int)
    VectorLoad128(UInt64)
    VectorStore128(UInt64)
    VectorLoadSplat(
    VectorLane
    , UInt64)
    VectorLoadExtend(
    VectorLane
    ,
    Signedness
    , UInt64)
    VectorLoadZero(
    AccessWidth
    , UInt64)
    VectorLoadLane(
    VectorLane
    , Int, UInt64)
    VectorStoreLane(
    VectorLane
    , Int, UInt64)
    AtomicLoad(
    AccessWidth
    ,
    ValueType
    )
    AtomicStore(
    AccessWidth
    ,
    ValueType
    )
    AtomicRmw(
    AccessWidth
    ,
    ValueType
    ,
    AtomicRmwOp
    )
    AtomicCompareExchange(
    AccessWidth
    ,
    ValueType
    )
    AtomicFence
    SafepointMarker
    PlatformCall(
    ExternalSymbol
    ,
    Signature
    )
    ReturnsTwicePlatformCall(
    ExternalSymbol
    ,
    Signature
    )
    InternalCall(
    CodeSymbol
    ,
    Signature
    ,
    InternalCallPlan
    )
    InternalCallIndirect(
    Signature
    ,
    InternalCallPlan
    )
    TailCallDirect(
    CodeSymbol
    ,
    Signature
    ,
    InternalCallPlan
    )
    TailCallIndirect(
    Signature
    ,
    InternalCallPlan
    )
    Jump
    BranchNonZero(
    RegisterWidth
    )
    BranchCompare(
    RegisterWidth
    ,
    IntegerCondition
    )
    BranchCompareImmediate(
    RegisterWidth
    ,
    IntegerCondition
    , UInt64)
    Switch(
    RegisterWidth
    , Array[UInt64])
    Trap(
    TrapReason
    )
    Return
    } derive(Eq,
    Debug
    )

    AArch64Inst::equal

    fn AArch64Inst::equal(AArch64Inst, AArch64Inst) -> Bool

    AArch64Inst::not_equal

    fn AArch64Inst::not_equal(x : AArch64Inst, y : AArch64Inst) -> Bool

    AArch64IntBinary

    pub(all) enum AArch64IntBinary {
    Add
    Sub
    Mul
    And
    Orr
    Eor
    Sdiv
    Udiv
    } derive(Eq,
    Debug
    )

    AArch64IntBinary::equal

    AArch64IntBinary::not_equal

    fn AArch64IntBinary::not_equal(x : AArch64IntBinary, y : AArch64IntBinary) -> Bool

    AArch64LinkPlan

    pub struct AArch64LinkPlan {
    // private fields
    } derive(
    Debug
    )

    AArch64LinkPlan::code

    fn AArch64LinkPlan::code(self : AArch64LinkPlan) -> Array[Byte]

    fn AArch64LinkPlan::link(self : AArch64LinkPlan, code_address : Int64, resolve : (
    RelocationTarget
    ) -> Int64?) -> Array[Byte] raise AArch64LinkError

    AArch64LinkPlan::veneer_offsets

    fn AArch64LinkPlan::veneer_offsets(self : AArch64LinkPlan) -> Array[Int]

    AArch64Shift

    pub(all) enum AArch64Shift {
    Lsl
    Asr
    Lsr
    Ror
    } derive(Eq,
    Debug
    )

    AArch64Shift::equal

    AArch64Shift::not_equal

    fn AArch64Shift::not_equal(x : AArch64Shift, y : AArch64Shift) -> Bool

    CompilationDiagnostics

    pub(all) struct CompilationDiagnostics {
    target_vcode : String
    allocated_vcode : String
    object :
    UnlinkedCodeObject

    }

    CompilationSession

    pub struct CompilationSession {
    // private fields
    }

    Compiles selected AArch64 VCode through allocation, frame planning, and emission. Each stage validates the invariant it introduces without revalidating invariants already established by this pipeline.

    on_event is an observation-only seam. It must not mutate function or any compiler object reachable while the callback runs.

    CompilationSession::compile_selected

    fn CompilationSession::compile_selected(self : CompilationSession, selected : SelectedFunction, on_event? : (
    TargetCompileEvent
    ) -> Unit, verify_allocation? : Bool, on_diagnostics? : (String, String) -> Unit?) -> (
    UnlinkedCodeObject
    , Int) raise AArch64CompileError

    Compile selected VCode while retaining allocator scratch capacity for the next serial call on this session. Diagnostic strings are rendered only when on_diagnostics is supplied; the callback observes this same compilation.

    CompilationSession::new

    fn CompilationSession::new(lse_atomic_add? : Bool) -> CompilationSession

    Callers enabling LSE must restrict generated code to CPUs supporting it.

    DirectLoweringSession

    pub struct DirectLoweringSession {
    // private fields
    }

    DirectLoweringSession::finish_selected

    fn DirectLoweringSession::finish_selected(self : DirectLoweringSession, verify_selected? : Bool) -> SelectedFunction raise AArch64LowerError

    Finish direct selection and return the VCode consumed by target compilation.

    verify_selected=false is reserved for compiler-owned construction paths covered by strict validation in CI. Public callers should keep the default.

    SelectedFunction

    pub struct SelectedFunction {
    // private fields
    }

    Opaque evidence that direct AArch64 selection and VCode validation completed.

    compile

    Compile externally supplied AArch64 VCode through the safe validated entry.

    compile_selected

    Compile VCode produced by select without repeating target validation.

    diagnose_selected

    fn diagnose_selected(selected : SelectedFunction) -> CompilationDiagnostics raise AArch64CompileError

    verify_allocation

    verify_frame