x64_target

x64 direct MilkIR target pipeline to native code

x64
x86-64
compiler
codegen
Download zip
Author
Version
0.14.0
License
Apache-2.0
Last updated
16 hours ago
Downloads
126

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