x64_target

    x64 direct MilkIR target pipeline to native code

    x64
    x86-64
    compiler
    codegen
    Download zip
    Author
    Version
    0.19.0
    License
    Apache-2.0
    Last updated
    3 days ago
    Downloads
    1K

    #x64_target

    x64 backend for direct MilkIR instruction selection.

    This module owns x64 instruction selection, validation and lowering of an embedding-provided internal ABI contract, register allocation policy, frame layout, machine-code emission, relocations, and final linking. A DirectLoweringSession consumes the streaming native-lowering protocol and constructs verified x64 Target VCode without an intermediate function graph.

    #Package

    • Milky2018/x64_target: x64 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.

    #Example: define the internal ABI

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

    #Integration

    Finish a DirectLoweringSession, then use compile_selected for the aggregate path, or call allocate, plan_frame, and emit when inspecting checkpoints. The returned UnlinkedCodeObject contains bytes, relocations, and safepoints; the embedding application supplies symbol addresses and executable memory.

    compile accepts an optional on_event callback that reports generic stage boundaries and a read-only allocation summary. This lets an embedding collect metrics without coupling the target to a product metrics system. The callback must not mutate compiler inputs.

    Parallel moves use R15 and XMM13 as dedicated transfer scratches and share the target-neutral emergency-aware move planner with AArch64. R10 and XMM14 remain the allocator's spill/edit scratches; R11 is a declared fixed-operand-only instruction temporary, and XMM15 remains reserved for emitter-local expansion. The frame reserves a raw 16-byte emergency area only for move groups that require it.

    Frame planning includes writes made by late parallel transfers to the reserved R15 temporary. The same call transfer planner is used for emission and this register footprint; a function saves R15 only when its emitted transfers need it.

    GprWidth

    using @Milky2018/vcode { type RegisterWidth as GprWidth }

    InternalAbi

    Register assignment shared by the native backends' internal calls.

    InternalAbiError

    InternalCallPlan

    LoweringContext

    TargetVCodeVerifyError

    X64Address

    using @Milky2018/vcode { type SymbolicAddress as X64Address }

    X64Condition

    using @Milky2018/vcode { type IntegerCondition as X64Condition }

    X64FloatBinary

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

    X64FloatCondition

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

    X64FloatTernary

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

    X64FloatTrapCondition

    using @Milky2018/vcode { type FloatTrapCondition as X64FloatTrapCondition }

    X64FloatUnary

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

    X64IntUnary

    using @Milky2018/vcode { type ScalarIntUnary as X64IntUnary }

    X64StackObject

    using @Milky2018/vcode { type SizedStackObject as X64StackObject }

    A function-local stack object before target frame placement.

    X64VectorConversion

    using @Milky2018/vcode { type VectorConversion as X64VectorConversion }

    X64VectorIntBinary

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

    X64VectorIntUnary

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

    X64VectorPredicate

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

    X64AllocationError

    X64AllocationError::output

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

    X64AllocationError::to_string

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

    X64CompileError

    pub suberror X64CompileError {
    TargetValidationFailed(cause~ :
    TargetVCodeVerifyError
    )
    AllocationFailed(cause~ : X64AllocationError)
    FramePlanningFailed(cause~ : X64FrameError)
    EmissionFailed(cause~ : X64EmitError)
    } derive(
    Debug
    )

    X64CompileError::output

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

    X64CompileError::to_string

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

    X64EmitError

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

    X64EmitError::output

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

    X64EmitError::to_string

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

    X64FrameError

    pub suberror X64FrameError {
    InvalidAllocation(cause~ : X64AllocationError)
    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
    )
    CallPlanningFailed(cause~ :
    CallTransferError
    )
    InvalidEmergencyMoveArea(offset~ : Int?)
    StaleAllocation(expected_edits~ : Int, actual_edits~ : Int)
    SavedRegisterSetMismatch
    } derive(
    Debug
    )

    X64FrameError::output

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

    X64FrameError::to_string

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

    X64LinkError

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

    X64LinkError::equal

    X64LinkError::not_equal

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

    X64LinkError::output

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

    X64LinkError::to_string

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

    X64LowerError

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

    X64LowerError::output

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

    X64LowerError::to_string

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

    CompilationDiagnostics

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

    }

    CompilationSession

    pub struct CompilationSession {
    // private fields
    }

    Compiles selected x64 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 X64CompileError

    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

    DirectLoweringSession

    pub struct DirectLoweringSession {
    // private fields
    }

    DirectLoweringSession::finish_selected

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

    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 x64 selection and VCode validation completed.

    X64Frame

    pub struct X64Frame {
    // private fields
    }

    X64Frame::alignment

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

    X64Frame::emergency_move_offset

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

    X64Frame::frame_size

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

    X64Frame::incoming_args_size

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

    X64Frame::outgoing_args_size

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

    X64Frame::saved_registers

    X64Frame::slot_offset

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

    X64Frame::stack_object_offset

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

    X64Frame::summary

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

    X64Frame::tail_args_size

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

    X64Inst

    pub(all) enum X64Inst {
    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
    , X64IntBinary)
    PopulationCount(
    RegisterWidth
    )
    IntHighMultiply(
    RegisterWidth
    ,
    Signedness
    )
    IntWithOverflow(
    RegisterWidth
    ,
    IntOverflowOp
    )
    IntRemainder(
    RegisterWidth
    ,
    Signedness
    )
    TrapIfZero(
    RegisterWidth
    )
    TrapIfSignedDivOverflow(
    RegisterWidth
    )
    CompareSet(
    RegisterWidth
    ,
    IntegerCondition
    )
    ReferenceCompareSet(
    ValueType
    ,
    IntegerCondition
    )
    FloatUnary(
    ValueType
    ,
    FloatUnaryOp
    )
    FloatBinary(
    ValueType
    ,
    FloatBinaryOp
    )
    FloatTernary(
    ValueType
    ,
    FloatTernaryOp
    )
    FloatCompareSet(
    ValueType
    ,
    FloatComparison
    )
    TrapIfFloat(
    ValueType
    ,
    FloatTrapCondition
    )
    Convert(X64Conversion)
    AddAddress
    ScalarLoad(
    AccessWidth
    ,
    LoadExtension
    ,
    ValueType
    , UInt64)
    ScalarStore(
    AccessWidth
    ,
    ValueType
    , UInt64)
    StoreRepeated64(UInt64, UInt, UInt64)
    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
    BranchNonZero32
    BranchCompare(
    RegisterWidth
    ,
    IntegerCondition
    )
    Switch(
    RegisterWidth
    , Array[UInt64])
    Trap(
    TrapReason
    )
    Return
    } derive(Eq,
    Debug
    )

    X64Inst::equal

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

    X64Inst::not_equal

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

    X64Inst::to_repr

    X64IntBinary

    pub(all) enum X64IntBinary {
    Add
    Sub
    Mul
    And
    Orr
    Eor
    Lsl
    Asr
    Lsr
    Ror
    Sdiv
    Udiv
    } derive(Eq,
    Debug
    )

    X64IntBinary::equal

    X64IntBinary::not_equal

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

    X64LinkPlan

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

    X64LinkPlan::code

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

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

    X64LinkPlan::veneer_offsets

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

    compile

    Compile externally supplied x64 VCode through the safe validated entry.

    compile_selected

    fn compile_selected(selected : SelectedFunction, on_event? : (
    TargetCompileEvent
    ) -> Unit, verify_allocation? : Bool) -> (
    UnlinkedCodeObject
    , Int) raise X64CompileError

    Compile VCode produced by select without repeating target validation.

    diagnose_selected

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

    verify_allocation

    fn verify_allocation(function :
    Function
    [X64Inst], allocation :
    Allocation
    ) -> Unit raise X64AllocationError

    verify_frame

    fn verify_frame(function :
    Function
    [X64Inst], allocation :
    Allocation
    , frame : X64Frame) -> Unit raise X64FrameError