///|
/// Whether a context slot can change while generated code for one function runs.
pub(all) enum ContextSlotMutability {
Immutable
Mutable
} derive(Eq, Debug)
///|
/// Optional physical-register cache role for a context-derived pointer.
pub(all) enum ContextSlotCacheRole {
NoContextCache
ContextCache0Descriptor
ContextCache0Source
ContextCache1
} derive(Eq, Debug)
///|
/// Opaque embedding-context slot metadata.
///
/// The `id` is owned by the embedding adapter. Reusable infrastructure may use
/// `offset`, `mutability`, and `cache_role` facts without interpreting what the
/// slot represents.
pub(all) struct ContextSlot {
id : Int
offset : Int
mutability : ContextSlotMutability
cache_role : ContextSlotCacheRole
} derive(Eq, Debug)
///|
/// Machine-level offsets for an embedding-provided runtime context.
///
/// MachV treats these as opaque offsets from the context base register. The
/// embedding owns the concrete runtime structure and translates its layout into
/// this shape before invoking lowering or emission.
pub(all) struct EmbeddingContextLayout {
slots : Array[ContextSlot]
active_function_index_slot : Int?
allocation_cursor_slot : Int?
allocation_limit_slot : Int?
}
///|
pub fn EmbeddingContextLayout::slot(
self : EmbeddingContextLayout,
id : Int,
) -> ContextSlot? {
for slot in self.slots {
if slot.id == id {
return Some(slot)
}
}
None
}
///|
pub fn EmbeddingContextLayout::slot_offset(
self : EmbeddingContextLayout,
id : Int,
) -> Int? {
match self.slot(id) {
Some(slot) => Some(slot.offset)
None => None
}
}
///|
pub fn EmbeddingContextLayout::slot_offset_for_cache_role(
self : EmbeddingContextLayout,
role : ContextSlotCacheRole,
) -> Int? {
for slot in self.slots {
if slot.cache_role == role {
return Some(slot.offset)
}
}
None
}
///|
pub fn EmbeddingContextLayout::require_cache_role_offset(
self : EmbeddingContextLayout,
role : ContextSlotCacheRole,
) -> Int {
match self.slot_offset_for_cache_role(role) {
Some(offset) => offset
None => abort("missing embedding context cache role")
}
}
///|
pub fn EmbeddingContextLayout::require_slot_offset(
self : EmbeddingContextLayout,
id : Int,
) -> Int {
match self.slot_offset(id) {
Some(offset) => offset
None => abort("missing embedding context slot \{id}")
}
}
///|
pub fn EmbeddingContextLayout::require_active_function_index_offset(
self : EmbeddingContextLayout,
) -> Int {
match self.active_function_index_slot {
Some(id) => self.require_slot_offset(id)
None => abort("active function index context slot is required")
}
}
///|
pub fn EmbeddingContextLayout::require_allocation_cursor_offset(
self : EmbeddingContextLayout,
) -> Int {
match self.allocation_cursor_slot {
Some(id) => self.require_slot_offset(id)
None => abort("allocation cursor context slot is required")
}
}
///|
pub fn EmbeddingContextLayout::require_allocation_limit_offset(
self : EmbeddingContextLayout,
) -> Int {
match self.allocation_limit_slot {
Some(id) => self.require_slot_offset(id)
None => abort("allocation limit context slot is required")
}
}