x64_target

    x64 direct MilkIR target pipeline to native code

    x64
    x86-64
    compiler
    codegen
    Download zip
    Author
    Version
    0.15.0
    License
    Apache-2.0
    Last updated
    17 days ago
    Downloads
    156

    #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" {
    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.

    InternalAbiError

    pub suberror InternalAbiError {
    InvalidRegister(role~ : String, index~ : Int)
    DuplicateRegister(role~ : String, index~ : Int)
    ContextRegisterReused(index~ : Int)
    ResultAreaRegisterReused(index~ : Int)
    InvalidSignature(message~ : String)
    } derive(Eq,
    Debug
    )

    InternalAbiError::equal

    InternalAbiError::not_equal

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

    InternalAbiError::output

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

    InternalAbiError::to_string

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

    TargetVCodeVerifyError

    pub suberror TargetVCodeVerifyError {
    CommonFailure(cause~ :
    VCodeVerifyError
    )
    InvalidInstruction(instruction~ :
    Instruction
    , message~ : String)
    } derive(Eq,
    Debug
    )

    TargetVCodeVerifyError::equal

    TargetVCodeVerifyError::not_equal

    TargetVCodeVerifyError::output

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

    TargetVCodeVerifyError::to_string

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

    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
    )
    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

    CallArgumentLocation

    type CallArgumentLocation derive(Eq,
    Debug
    )

    CallArgumentLocation::equal

    CallArgumentLocation::not_equal

    CallLayout

    type CallLayout derive(Eq,
    Debug
    )

    CallLayout::equal

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

    CallLayout::not_equal

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

    CallResultLocation

    type CallResultLocation derive(Eq,
    Debug
    )

    CallResultLocation::equal

    CallResultLocation::not_equal

    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

    Compile selected VCode while retaining allocator scratch capacity for the next serial call on this session.

    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.

    GprWidth

    pub(all) enum GprWidth {
    W32
    W64
    } derive(Eq,
    Debug
    )

    GprWidth::equal

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

    GprWidth::not_equal

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

    GprWidth::to_repr

    InternalAbi

    pub struct InternalAbi {
    // private fields
    }

    InternalAbi::new

    fn InternalAbi::new(context_argument : Int, result_area_argument : Int, integer_arguments : Array[Int], fp_arguments : Array[Int], integer_results : Array[Int], fp_results : Array[Int]) -> InternalAbi raise InternalAbiError

    InternalCallPlan

    pub struct InternalCallPlan {
    // private fields
    } derive(Eq,
    Debug
    )

    InternalCallPlan::equal

    InternalCallPlan::not_equal

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

    LoweringContext

    pub struct LoweringContext {
    // private fields
    }

    LoweringContext::new

    fn LoweringContext::new(internal_abi : InternalAbi) -> LoweringContext

    LoweringContext::with_environment_field

    LoweringContext::with_environment_field_resolver

    SelectedFunction

    pub struct SelectedFunction {
    // private fields
    }

    Opaque evidence that direct x64 selection and VCode validation completed.

    X64Condition

    pub(all) enum X64Condition {
    Eq
    Ne
    Lt
    Le
    Gt
    Ge
    Lo
    Ls
    Hi
    Hs
    } derive(Eq,
    Debug
    )

    X64Condition::equal

    X64Condition::not_equal

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

    X64FloatBinary

    pub(all) enum X64FloatBinary {
    Add
    Sub
    Mul
    Div
    Min
    Max
    CopySign
    } derive(Eq,
    Debug
    )

    X64FloatBinary::equal

    X64FloatBinary::not_equal

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

    X64FloatCondition

    pub(all) enum X64FloatCondition {
    Equal
    NotEqual
    LessThan
    LessOrEqual
    GreaterThan
    GreaterOrEqual
    Ordered
    Unordered
    } derive(Eq,
    Debug
    )

    X64FloatCondition::equal

    X64FloatCondition::not_equal

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

    X64FloatTernary

    pub(all) enum X64FloatTernary {
    Fmadd
    Fmsub
    Fnmadd
    Fnmsub
    } derive(Eq,
    Debug
    )

    X64FloatTernary::equal

    X64FloatTernary::not_equal

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

    X64FloatTrapCondition

    pub(all) enum X64FloatTrapCondition {
    Unordered
    LessThan
    LessOrEqual
    GreaterOrEqual
    } derive(Eq,
    Debug
    )

    X64FloatTrapCondition::equal

    X64FloatTrapCondition::not_equal

    X64FloatUnary

    pub(all) enum X64FloatUnary {
    Negate
    Absolute
    SquareRoot
    Ceil
    Floor
    Truncate
    Nearest
    } derive(Eq,
    Debug
    )

    X64FloatUnary::equal

    X64FloatUnary::not_equal

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

    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 : X64StackObject) -> 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(GprWidth, UInt64)
    LoadVectorConstant(UInt64, UInt64)
    LoadNull(
    ValueType
    )
    LoadAddress(X64Address)
    StackAddress(X64StackObject)
    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
    , X64VectorIntUnary)
    VectorIntBinary(
    VectorLane
    , X64VectorIntBinary)
    VectorIntShift(
    VectorLane
    ,
    VectorIntShiftOp
    )
    VectorIntCompare(
    VectorLane
    ,
    VectorIntComparison
    )
    VectorConvert(X64VectorConversion)
    VectorPredicate(X64VectorPredicate)
    VectorFloatUnary(
    VectorLane
    ,
    VectorFloatUnaryOp
    )
    VectorFloatBinary(
    VectorLane
    ,
    VectorFloatBinaryOp
    )
    VectorFloatTernary(
    VectorLane
    ,
    FloatTernaryOp
    )
    VectorFloatCompare(
    VectorLane
    ,
    VectorFloatComparison
    )
    VectorPairwiseAddI16x8
    VectorRelaxedDot8To16
    IntUnary(GprWidth, X64IntUnary)
    IntBinary(GprWidth, X64IntBinary)
    PopulationCount(GprWidth)
    IntHighMultiply(GprWidth,
    Signedness
    )
    IntWithOverflow(GprWidth,
    IntOverflowOp
    )
    IntRemainder(GprWidth,
    Signedness
    )
    TrapIfZero(GprWidth)
    TrapIfSignedDivOverflow(GprWidth)
    CompareSet(GprWidth, X64Condition)
    ReferenceCompareSet(
    ValueType
    , X64Condition)
    FloatUnary(
    ValueType
    , X64FloatUnary)
    FloatBinary(
    ValueType
    , X64FloatBinary)
    FloatTernary(
    ValueType
    , X64FloatTernary)
    FloatCompareSet(
    ValueType
    , X64FloatCondition)
    TrapIfFloat(
    ValueType
    , X64FloatTrapCondition)
    Convert(X64Conversion)
    AddAddress
    ScalarLoad(
    AccessWidth
    ,
    LoadExtension
    ,
    ValueType
    , UInt64)
    ScalarStore(
    AccessWidth
    ,
    ValueType
    , 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
    Switch(GprWidth, 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

    X64IntUnary

    pub(all) enum X64IntUnary {
    Mvn
    Clz
    Rbit
    Neg
    } derive(Eq,
    Debug
    )

    X64IntUnary::equal

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

    X64IntUnary::not_equal

    fn X64IntUnary::not_equal(x : X64IntUnary, y : X64IntUnary) -> 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]

    X64StackObject

    pub struct X64StackObject {
    id : Int
    size : Int
    alignment : Int
    } derive(Eq,
    Debug
    )

    X64StackObject::equal

    X64StackObject::new

    fn X64StackObject::new(id : Int, size : Int, alignment : Int) -> X64StackObject

    X64StackObject::not_equal

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

    X64VectorIntUnary

    pub(all) enum X64VectorIntUnary {
    Absolute
    Negate
    PopulationCount
    ExtendAddPairwise(
    Signedness
    )
    } derive(Eq,
    Debug
    )

    X64VectorIntUnary::equal

    X64VectorIntUnary::not_equal

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

    X64VectorPredicate

    X64VectorPredicate::equal

    X64VectorPredicate::not_equal

    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

    verify_vcode

    fn verify_vcode(function :
    Function
    [X64Inst]) -> Unit raise TargetVCodeVerifyError