2025-08-12 11:33:48 +00:00
|
|
|
/*!
|
|
|
|
|
* MIR Instruction Set - 20 Core Instructions per ChatGPT5 Design
|
2025-09-17 07:43:07 +09:00
|
|
|
*
|
2025-08-12 11:33:48 +00:00
|
|
|
* SSA-form instructions with effect tracking for optimization
|
|
|
|
|
*/
|
|
|
|
|
|
2025-11-13 16:40:58 +09:00
|
|
|
use super::{EffectMask, ValueId};
|
2025-09-24 01:05:44 +09:00
|
|
|
use crate::mir::definitions::Callee; // Import Callee from unified definitions
|
2025-09-22 21:52:39 +09:00
|
|
|
use crate::mir::types::{
|
|
|
|
|
BarrierOp, BinaryOp, CompareOp, ConstValue, MirType, TypeOpKind, UnaryOp, WeakRefOp,
|
|
|
|
|
};
|
2025-09-24 01:05:44 +09:00
|
|
|
|
2025-11-13 16:40:58 +09:00
|
|
|
// (unused imports removed)
|
2025-09-17 10:58:12 +09:00
|
|
|
|
2025-08-12 11:33:48 +00:00
|
|
|
/// MIR instruction types - limited to 20 core instructions
|
|
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
|
|
|
|
pub enum MirInstruction {
|
|
|
|
|
// === Constants and Values ===
|
|
|
|
|
/// Load a constant value
|
|
|
|
|
/// `%dst = const value`
|
2025-09-17 07:43:07 +09:00
|
|
|
Const { dst: ValueId, value: ConstValue },
|
|
|
|
|
|
2025-08-12 11:33:48 +00:00
|
|
|
// === Arithmetic Operations ===
|
|
|
|
|
/// Binary arithmetic operation
|
|
|
|
|
/// `%dst = %lhs op %rhs`
|
|
|
|
|
BinOp {
|
|
|
|
|
dst: ValueId,
|
|
|
|
|
op: BinaryOp,
|
|
|
|
|
lhs: ValueId,
|
|
|
|
|
rhs: ValueId,
|
|
|
|
|
},
|
2025-09-17 07:43:07 +09:00
|
|
|
|
2025-08-12 11:33:48 +00:00
|
|
|
/// Unary operation
|
|
|
|
|
/// `%dst = op %operand`
|
|
|
|
|
UnaryOp {
|
|
|
|
|
dst: ValueId,
|
|
|
|
|
op: UnaryOp,
|
|
|
|
|
operand: ValueId,
|
|
|
|
|
},
|
2025-09-17 07:43:07 +09:00
|
|
|
|
2025-08-12 11:33:48 +00:00
|
|
|
// === Comparison Operations ===
|
|
|
|
|
/// Compare two values
|
|
|
|
|
/// `%dst = %lhs cmp %rhs`
|
|
|
|
|
Compare {
|
|
|
|
|
dst: ValueId,
|
|
|
|
|
op: CompareOp,
|
|
|
|
|
lhs: ValueId,
|
|
|
|
|
rhs: ValueId,
|
|
|
|
|
},
|
2025-09-17 07:43:07 +09:00
|
|
|
|
2025-08-12 11:33:48 +00:00
|
|
|
// === Memory Operations ===
|
|
|
|
|
/// Load from memory/variable
|
|
|
|
|
/// `%dst = load %ptr`
|
2025-09-17 07:43:07 +09:00
|
|
|
Load { dst: ValueId, ptr: ValueId },
|
|
|
|
|
|
2025-08-12 11:33:48 +00:00
|
|
|
/// Store to memory/variable
|
|
|
|
|
/// `store %value -> %ptr`
|
2025-09-17 07:43:07 +09:00
|
|
|
Store { value: ValueId, ptr: ValueId },
|
|
|
|
|
|
2025-08-12 11:33:48 +00:00
|
|
|
// === Function Calls ===
|
2025-09-24 01:05:44 +09:00
|
|
|
/// Call a function with type-safe target resolution
|
|
|
|
|
/// `%dst = call %func(%args...)` (legacy)
|
|
|
|
|
/// `%dst = call Global("print")(%args...)` (new)
|
|
|
|
|
///
|
|
|
|
|
/// Phase 1 Migration: Both func and callee fields present
|
|
|
|
|
/// - callee: Some(_) -> Use new type-safe resolution (preferred)
|
|
|
|
|
/// - callee: None -> Fall back to legacy string-based resolution
|
2025-08-12 11:33:48 +00:00
|
|
|
Call {
|
|
|
|
|
dst: Option<ValueId>,
|
2025-09-24 01:05:44 +09:00
|
|
|
func: ValueId, // Legacy: string-based resolution (deprecated)
|
|
|
|
|
callee: Option<Callee>, // New: type-safe resolution (preferred)
|
2025-08-12 11:33:48 +00:00
|
|
|
args: Vec<ValueId>,
|
|
|
|
|
effects: EffectMask,
|
|
|
|
|
},
|
2025-09-04 03:41:02 +09:00
|
|
|
|
|
|
|
|
/// Create a function value (FunctionBox) from params/body and optional captures
|
2025-09-24 01:05:44 +09:00
|
|
|
/// `%dst = new_closure [params] {body} [captures...]`
|
2025-09-04 03:41:02 +09:00
|
|
|
/// Minimal lowering support: captures may be empty; 'me' is optional.
|
2025-09-24 01:05:44 +09:00
|
|
|
NewClosure {
|
2025-09-04 03:41:02 +09:00
|
|
|
dst: ValueId,
|
|
|
|
|
params: Vec<String>,
|
|
|
|
|
body: Vec<crate::ast::ASTNode>,
|
|
|
|
|
/// Pairs of (name, value) to capture by value
|
|
|
|
|
captures: Vec<(String, ValueId)>,
|
|
|
|
|
/// Optional 'me' value to capture weakly if it is a BoxRef at runtime
|
|
|
|
|
me: Option<ValueId>,
|
|
|
|
|
},
|
2025-09-17 07:43:07 +09:00
|
|
|
|
2025-08-12 11:33:48 +00:00
|
|
|
/// Box method invocation
|
|
|
|
|
/// `%dst = invoke %box.method(%args...)`
|
2025-08-26 20:48:48 +09:00
|
|
|
/// method_id: Optional numeric slot id when resolved at build time
|
2025-08-12 11:33:48 +00:00
|
|
|
BoxCall {
|
|
|
|
|
dst: Option<ValueId>,
|
|
|
|
|
box_val: ValueId,
|
|
|
|
|
method: String,
|
2025-08-26 20:48:48 +09:00
|
|
|
/// Optional numeric method slot id (Unified Registry). None = late bind.
|
|
|
|
|
method_id: Option<u16>,
|
2025-08-12 11:33:48 +00:00
|
|
|
args: Vec<ValueId>,
|
|
|
|
|
effects: EffectMask,
|
|
|
|
|
},
|
2025-08-30 02:04:00 +09:00
|
|
|
|
|
|
|
|
/// Plugin invocation (forces plugin path; no builtin fallback)
|
|
|
|
|
/// `%dst = plugin_invoke %box.method(%args...)`
|
|
|
|
|
PluginInvoke {
|
|
|
|
|
dst: Option<ValueId>,
|
|
|
|
|
box_val: ValueId,
|
|
|
|
|
method: String,
|
|
|
|
|
args: Vec<ValueId>,
|
|
|
|
|
effects: EffectMask,
|
|
|
|
|
},
|
2025-09-17 07:43:07 +09:00
|
|
|
|
2025-08-12 11:33:48 +00:00
|
|
|
// === Control Flow ===
|
|
|
|
|
/// Conditional branch
|
|
|
|
|
/// `br %condition -> %then_bb, %else_bb`
|
|
|
|
|
Branch {
|
|
|
|
|
condition: ValueId,
|
|
|
|
|
then_bb: super::BasicBlockId,
|
|
|
|
|
else_bb: super::BasicBlockId,
|
|
|
|
|
},
|
2025-09-17 07:43:07 +09:00
|
|
|
|
2025-08-12 11:33:48 +00:00
|
|
|
/// Unconditional jump
|
|
|
|
|
/// `jmp %target_bb`
|
2025-09-17 07:43:07 +09:00
|
|
|
Jump { target: super::BasicBlockId },
|
|
|
|
|
|
2025-08-12 11:33:48 +00:00
|
|
|
/// Return from function
|
|
|
|
|
/// `ret %value` or `ret void`
|
2025-09-17 07:43:07 +09:00
|
|
|
Return { value: Option<ValueId> },
|
|
|
|
|
|
2025-08-12 11:33:48 +00:00
|
|
|
// === SSA Phi Function ===
|
|
|
|
|
/// SSA phi function for merging values from different paths
|
|
|
|
|
/// `%dst = phi [%val1 from %bb1, %val2 from %bb2, ...]`
|
|
|
|
|
Phi {
|
|
|
|
|
dst: ValueId,
|
|
|
|
|
inputs: Vec<(super::BasicBlockId, ValueId)>,
|
|
|
|
|
},
|
2025-09-17 07:43:07 +09:00
|
|
|
|
2025-08-12 11:33:48 +00:00
|
|
|
// === Box Operations ===
|
|
|
|
|
/// Create a new Box instance
|
|
|
|
|
/// `%dst = new_box "BoxType"(%args...)`
|
|
|
|
|
NewBox {
|
|
|
|
|
dst: ValueId,
|
|
|
|
|
box_type: String,
|
|
|
|
|
args: Vec<ValueId>,
|
|
|
|
|
},
|
2025-09-17 07:43:07 +09:00
|
|
|
|
2025-08-12 11:33:48 +00:00
|
|
|
/// Check Box type
|
|
|
|
|
/// `%dst = type_check %box "BoxType"`
|
|
|
|
|
TypeCheck {
|
|
|
|
|
dst: ValueId,
|
|
|
|
|
value: ValueId,
|
|
|
|
|
expected_type: String,
|
|
|
|
|
},
|
2025-09-17 07:43:07 +09:00
|
|
|
|
2025-08-12 11:33:48 +00:00
|
|
|
// === Type Conversion ===
|
|
|
|
|
/// Convert between types
|
|
|
|
|
/// `%dst = cast %value as Type`
|
|
|
|
|
Cast {
|
|
|
|
|
dst: ValueId,
|
|
|
|
|
value: ValueId,
|
|
|
|
|
target_type: MirType,
|
|
|
|
|
},
|
2025-08-23 19:27:02 +09:00
|
|
|
|
|
|
|
|
// === Type Operations (Unified PoC) ===
|
|
|
|
|
/// Unified type operation (PoC): Check or Cast
|
|
|
|
|
/// `%dst = typeop(check|cast, %value, Type)`
|
|
|
|
|
TypeOp {
|
|
|
|
|
dst: ValueId,
|
|
|
|
|
op: TypeOpKind,
|
|
|
|
|
value: ValueId,
|
|
|
|
|
ty: MirType,
|
|
|
|
|
},
|
2025-09-17 07:43:07 +09:00
|
|
|
|
2025-08-12 11:33:48 +00:00
|
|
|
// === Array Operations ===
|
|
|
|
|
/// Get array element
|
|
|
|
|
/// `%dst = %array[%index]`
|
|
|
|
|
ArrayGet {
|
|
|
|
|
dst: ValueId,
|
|
|
|
|
array: ValueId,
|
|
|
|
|
index: ValueId,
|
|
|
|
|
},
|
2025-09-17 07:43:07 +09:00
|
|
|
|
2025-08-12 11:33:48 +00:00
|
|
|
/// Set array element
|
|
|
|
|
/// `%array[%index] = %value`
|
|
|
|
|
ArraySet {
|
|
|
|
|
array: ValueId,
|
|
|
|
|
index: ValueId,
|
|
|
|
|
value: ValueId,
|
|
|
|
|
},
|
2025-09-17 07:43:07 +09:00
|
|
|
|
2025-08-12 11:33:48 +00:00
|
|
|
// === Special Operations ===
|
|
|
|
|
/// Copy a value (for optimization passes)
|
|
|
|
|
/// `%dst = copy %src`
|
2025-09-17 07:43:07 +09:00
|
|
|
Copy { dst: ValueId, src: ValueId },
|
|
|
|
|
|
2025-08-12 11:33:48 +00:00
|
|
|
/// Debug/introspection instruction
|
|
|
|
|
/// `debug %value "message"`
|
2025-09-17 07:43:07 +09:00
|
|
|
Debug { value: ValueId, message: String },
|
|
|
|
|
|
2025-11-19 23:12:01 +09:00
|
|
|
/// Dev-only debug logging (MIR-level)
|
|
|
|
|
/// `debug_log "message" %v1 %v2 ...`
|
|
|
|
|
/// Executes only when NYASH_MIR_DEBUG_LOG=1; otherwise behaves as no-op.
|
|
|
|
|
DebugLog {
|
|
|
|
|
message: String,
|
|
|
|
|
values: Vec<ValueId>,
|
|
|
|
|
},
|
|
|
|
|
|
2025-08-13 05:59:10 +00:00
|
|
|
/// Print instruction for console output
|
|
|
|
|
/// `print %value`
|
2025-09-17 07:43:07 +09:00
|
|
|
Print { value: ValueId, effects: EffectMask },
|
|
|
|
|
|
2025-08-12 11:33:48 +00:00
|
|
|
/// No-op instruction (for optimization placeholders)
|
|
|
|
|
Nop,
|
2025-09-17 07:43:07 +09:00
|
|
|
|
2025-08-13 06:23:28 +00:00
|
|
|
// === Control Flow & Exception Handling (Phase 5) ===
|
|
|
|
|
/// Throw an exception
|
|
|
|
|
/// `throw %exception_value`
|
|
|
|
|
Throw {
|
|
|
|
|
exception: ValueId,
|
|
|
|
|
effects: EffectMask,
|
|
|
|
|
},
|
2025-09-17 07:43:07 +09:00
|
|
|
|
2025-08-13 06:23:28 +00:00
|
|
|
/// Catch handler setup (landing pad for exceptions)
|
|
|
|
|
/// `catch %exception_type -> %handler_bb`
|
|
|
|
|
Catch {
|
|
|
|
|
exception_type: Option<String>, // None = catch-all
|
|
|
|
|
exception_value: ValueId, // Where to store caught exception
|
|
|
|
|
handler_bb: super::BasicBlockId,
|
|
|
|
|
},
|
2025-09-17 07:43:07 +09:00
|
|
|
|
2025-08-13 06:23:28 +00:00
|
|
|
/// Safepoint instruction (no-op for now, can be used for GC/debugging)
|
|
|
|
|
/// `safepoint`
|
|
|
|
|
Safepoint,
|
2025-09-17 07:43:07 +09:00
|
|
|
|
2025-08-13 09:45:22 +00:00
|
|
|
// === Phase 6: Box Reference Operations ===
|
|
|
|
|
/// Create a new reference to a Box
|
|
|
|
|
/// `%dst = ref_new %box`
|
2025-09-17 07:43:07 +09:00
|
|
|
RefNew { dst: ValueId, box_val: ValueId },
|
|
|
|
|
|
2025-08-13 09:45:22 +00:00
|
|
|
/// Get/dereference a Box field through reference
|
|
|
|
|
/// `%dst = ref_get %ref.field`
|
|
|
|
|
RefGet {
|
|
|
|
|
dst: ValueId,
|
|
|
|
|
reference: ValueId,
|
|
|
|
|
field: String,
|
|
|
|
|
},
|
2025-09-17 07:43:07 +09:00
|
|
|
|
2025-08-13 09:45:22 +00:00
|
|
|
/// Set/assign Box field through reference
|
|
|
|
|
/// `ref_set %ref.field = %value`
|
|
|
|
|
RefSet {
|
|
|
|
|
reference: ValueId,
|
|
|
|
|
field: String,
|
|
|
|
|
value: ValueId,
|
|
|
|
|
},
|
2025-09-17 07:43:07 +09:00
|
|
|
|
2025-08-13 09:45:22 +00:00
|
|
|
/// Create a weak reference to a Box
|
|
|
|
|
/// `%dst = weak_new %box`
|
2025-09-17 07:43:07 +09:00
|
|
|
WeakNew { dst: ValueId, box_val: ValueId },
|
|
|
|
|
|
2025-08-13 09:45:22 +00:00
|
|
|
/// Load from weak reference (if still alive)
|
|
|
|
|
/// `%dst = weak_load %weak_ref`
|
2025-09-17 07:43:07 +09:00
|
|
|
WeakLoad { dst: ValueId, weak_ref: ValueId },
|
|
|
|
|
|
2025-08-13 09:45:22 +00:00
|
|
|
/// Memory barrier read (no-op for now, proper effect annotation)
|
|
|
|
|
/// `barrier_read %ptr`
|
2025-09-17 07:43:07 +09:00
|
|
|
BarrierRead { ptr: ValueId },
|
|
|
|
|
|
2025-08-13 09:45:22 +00:00
|
|
|
/// Memory barrier write (no-op for now, proper effect annotation)
|
|
|
|
|
/// `barrier_write %ptr`
|
2025-09-17 07:43:07 +09:00
|
|
|
BarrierWrite { ptr: ValueId },
|
2025-08-23 19:27:02 +09:00
|
|
|
|
|
|
|
|
// === Unified PoC: WeakRef/Barrier (flags-only scaffolding) ===
|
|
|
|
|
/// Unified weak reference op (PoC)
|
|
|
|
|
/// `%dst = weakref new %box` or `%dst = weakref load %weak`
|
|
|
|
|
WeakRef {
|
|
|
|
|
dst: ValueId,
|
|
|
|
|
op: WeakRefOp,
|
|
|
|
|
value: ValueId,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/// Unified barrier op (PoC)
|
|
|
|
|
/// `barrier read %ptr` or `barrier write %ptr`
|
2025-09-17 07:43:07 +09:00
|
|
|
Barrier { op: BarrierOp, ptr: ValueId },
|
|
|
|
|
|
2025-08-13 11:46:01 +00:00
|
|
|
// === Phase 7: Async/Future Operations ===
|
|
|
|
|
/// Create a new Future with initial value
|
|
|
|
|
/// `%dst = future_new %value`
|
2025-09-17 07:43:07 +09:00
|
|
|
FutureNew { dst: ValueId, value: ValueId },
|
|
|
|
|
|
2025-08-13 11:46:01 +00:00
|
|
|
/// Set Future value and mark as ready
|
|
|
|
|
/// `future_set %future = %value`
|
2025-09-17 07:43:07 +09:00
|
|
|
FutureSet { future: ValueId, value: ValueId },
|
|
|
|
|
|
2025-08-13 11:46:01 +00:00
|
|
|
/// Wait for Future completion and get value
|
|
|
|
|
/// `%dst = await %future`
|
2025-09-17 07:43:07 +09:00
|
|
|
Await { dst: ValueId, future: ValueId },
|
|
|
|
|
|
2025-08-14 08:56:39 +00:00
|
|
|
// === Phase 9.7: External Function Calls (Box FFI/ABI) ===
|
|
|
|
|
/// External function call through Box FFI/ABI
|
|
|
|
|
/// `%dst = extern_call interface.method(%args...)`
|
|
|
|
|
ExternCall {
|
|
|
|
|
dst: Option<ValueId>,
|
2025-09-17 07:43:07 +09:00
|
|
|
iface_name: String, // e.g., "env.console"
|
|
|
|
|
method_name: String, // e.g., "log"
|
2025-08-14 08:56:39 +00:00
|
|
|
args: Vec<ValueId>,
|
|
|
|
|
effects: EffectMask,
|
|
|
|
|
},
|
2025-08-12 11:33:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-09-25 03:46:37 +09:00
|
|
|
// Method implementations have been moved to src/mir/instruction/methods.rs
|
|
|
|
|
#[path = "instruction/methods.rs"]
|
|
|
|
|
mod methods;
|
2025-08-12 11:33:48 +00:00
|
|
|
|
2025-09-25 03:46:37 +09:00
|
|
|
// Display implementation has been moved to src/mir/instruction/display.rs
|
|
|
|
|
#[path = "instruction/display.rs"]
|
|
|
|
|
mod display;
|
2025-09-21 08:53:00 +09:00
|
|
|
|
2025-09-25 03:46:37 +09:00
|
|
|
// Tests have been moved to src/mir/instruction/tests.rs for better organization
|
2025-08-12 11:33:48 +00:00
|
|
|
#[cfg(test)]
|
2025-09-25 03:46:37 +09:00
|
|
|
#[path = "instruction/tests.rs"]
|
|
|
|
|
mod tests;
|