/// Wasmoon-owned native JIT trap and value-slot primitives.

/// Wasmoon-owned native JIT runtime primitives and managed handles.

///|
/// Read an i64-sized slot from a JIT-owned native value area.
pub fn native_value_slot_read(base : Int64, slot : Int) -> Int64 {
  c_jit_read_i64(base + (slot * 8).to_int64())
}

///|
/// Write an i64-sized slot in a JIT-owned native value area.
pub fn native_value_slot_write(base : Int64, slot : Int, value : Int64) -> Unit {
  c_jit_write_i64(base + (slot * 8).to_int64(), value)
}

///|
/// Low-level trap detail captured by the JIT signal handlers (best-effort).
pub struct TrapDetails {
  signal : Int
  pc : Int64
  lr : Int64
  fp : Int64
  frame_lr : Int64
  fault_addr : Int64
  brk_imm : Int
  func_idx : Int
  x0 : Int64
  x1 : Int64
  x2 : Int64
  x3 : Int64
  x6 : Int64
  x7 : Int64
  x8 : Int64
  x9 : Int64
  x10 : Int64
  x11 : Int64
  x15 : Int64
}

///|
pub fn TrapDetails::TrapDetails() -> TrapDetails {
  {
    signal: 0,
    pc: 0L,
    lr: 0L,
    fp: 0L,
    frame_lr: 0L,
    fault_addr: 0L,
    brk_imm: 0,
    func_idx: -1,
    x0: 0L,
    x1: 0L,
    x2: 0L,
    x3: 0L,
    x6: 0L,
    x7: 0L,
    x8: 0L,
    x9: 0L,
    x10: 0L,
    x11: 0L,
    x15: 0L,
  }
}

///|
/// Get the last captured trap details (best-effort).
/// These fields are reset at the start of each JIT call.
pub fn get_last_trap_details() -> TrapDetails {
  {
    signal: c_jit_get_trap_signal(),
    pc: c_jit_get_trap_pc(),
    lr: c_jit_get_trap_lr(),
    fp: c_jit_get_trap_fp(),
    frame_lr: c_jit_get_trap_frame_lr(),
    fault_addr: c_jit_get_trap_fault_addr(),
    brk_imm: c_jit_get_trap_brk_imm(),
    func_idx: c_jit_get_trap_func_idx(),
    x0: c_jit_get_trap_xreg(0),
    x1: c_jit_get_trap_xreg(1),
    x2: c_jit_get_trap_xreg(2),
    x3: c_jit_get_trap_xreg(3),
    x6: c_jit_get_trap_xreg(6),
    x7: c_jit_get_trap_xreg(7),
    x8: c_jit_get_trap_xreg(8),
    x9: c_jit_get_trap_xreg(9),
    x10: c_jit_get_trap_xreg(10),
    x11: c_jit_get_trap_xreg(11),
    x15: c_jit_get_trap_xreg(15),
  }
}

///|
pub fn format_signal_name(sig : Int) -> String {
  match sig {
    5 => "SIGTRAP(5)"
    10 => "SIGBUS(10)"
    11 => "SIGSEGV(11)"
    7 => "SIGBUS(7)"
    _ => "SIG(\{sig})"
  }
}

///|
pub fn jit_trap_message(code : Int) -> String {
  match code {
    1 => "out of bounds memory access"
    2 => "call stack exhausted"
    3 => "unreachable"
    4 => "indirect call type mismatch"
    5 => "invalid conversion to integer"
    6 => "integer divide by zero"
    7 => "integer overflow"
    8 => "jit backend trap"
    9 => "out of memory"
    10 => "gc precise roots unavailable"
    11 => "invocation cancelled"
    _ => "unknown trap"
  }
}

///|
pub fn is_cancelled_trap_code(code : Int) -> Bool {
  code == 11
}

///|
/// Map Wasm trap reasons to the payload consumed by Wasmoon's native trap
/// handler. MachV only carries the integer payload; this module owns the
/// Wasmoon-specific reason-to-payload policy.
pub fn wasm_trap_payload(reason : String) -> Int {
  if reason == "unreachable" {
    0
  } else if reason.contains("out of bounds") {
    1
  } else if reason.contains("type mismatch") {
    2
  } else if reason.contains("invalid conversion") {
    3
  } else if reason.contains("divide by zero") {
    4
  } else if reason.contains("overflow") {
    5
  } else {
    6
  }
}

///|
pub fn take_pending_trap_message() -> String? {
  let code = c_jit_get_trap_code()
  if code == 0 {
    None
  } else {
    c_jit_clear_trap()
    Some(jit_trap_message(code))
  }
}

///|
pub fn is_wasi_exit_trap_code(code : Int) -> Bool {
  code == 100
}