Skip to main content

Bytecode Virtual Machine Backend

The AdeshLang Bytecode Virtual Machine is a portable, compact, and high-performance stack-based virtual machine. It compiles AdeshLang source code to a platform-independent bytecode format (.adbc) that runs anywhere without requiring external C toolchains or LLVM installations.

┌──────────────────────────────────────────────────────────┐
│ Bytecode Compilation Flow │
├──────────────────────────────────────────────────────────┤
│ Source (.adesh) ──► Semantic IR ──► Bytecode (.adbc) │
│ │ │
│ ▼ │
│ Stack-based VM Loop │
│ [Fetch-Decode-Exec] │
└──────────────────────────────────────────────────────────┘

1. VM Architecture Overview

The Bytecode VM operates with:

  • Stack-based Execution: Operands are pushed onto and popped from an evaluation value stack.
  • Value Representation: Compact 64-bit tagged unions / NaN-boxing for zero-allocation scalar values (integers, floats, booleans, pointers).
  • Constant Pool: Stores deduplicated strings, large floating-point numbers, and symbol identifiers.
  • Call Frame Stack: Manages function return addresses, base pointer offsets, and local variable slots.
  • Zero-GC Integration: Interacts directly with adesh_alloc reference counts without a garbage collection stop-the-world loop.

2. Opcode Reference Table

AdeshLang Bytecode instructions use an 8-bit opcode followed by 0, 1, or 2 operands:

OpcodeMnemonicOperandsDescription
0x01NoopNoneNo operation.
0x02PushConstidx: u32Pushes constant at constant pool idx onto the stack.
0x03PushI64val: i64Pushes inline 64-bit integer onto the stack.
0x04PopNoneDiscards top item from the stack.
0x05DupNoneDuplicates top item on the stack.
0x06LoadLocalslot: u16Pushes value from local stack frame slot onto the stack.
0x07StoreLocalslot: u16Pops value from stack and writes to local slot.
0x08LoadGlobalidx: u32Loads value from global table.
0x09StoreGlobalidx: u32Stores value to global table.
0x0AAddNonePops $b, a$, pushes $a + b$.
0x0BSubNonePops $b, a$, pushes $a - b$.
0x0CMulNonePops $b, a$, pushes $a \times b$.
0x0DDivNonePops $b, a$, pushes $a / b$.
0x0EModNonePops $b, a$, pushes $a \pmod b$.
0x0FCallDecoratedfn: u32, pipe: u32Dispatches decorated function pipeline.
0x10Jumpoffset: i32Unconditional jump to relative bytecode offset.
0x11JumpIfFalseoffset: i32Pops boolean condition; jumps if false.
0x12Callargc: u8Calls function with argc arguments.
0x13ReturnNoneReturns from active call frame.
0x14AllocArcsize: u32Allocates zero-GC ARC managed heap object.
0x15DropArcNoneDecrements ARC count and frees memory if count reaches zero.

3. Bytecode Compilation & Execution

# Run source code using the Bytecode VM backend
adesh run --backend=vm program.adesh

# Pre-compile source into standalone portable bytecode archive (.adbc)
adesh compile --target=bytecode -o program.adbc program.adesh

# Execute compiled bytecode file directly
adesh run program.adbc

4. Disassembling Bytecode

Inspect generated bytecode and stack instructions with adesh disasm:

adesh disasm program.adesh

Sample Disassembly Output:

=== Bytecode Disassembly: fn calculate(a: i64, b: i64): i64 ===
Constants: [ 10 ]
Locals: [ a, b, temp ]

0000: LoadLocal 0 ; push 'a'
0002: LoadLocal 1 ; push 'b'
0004: Add ; a + b
0005: PushConst 0 ; push 10
0007: Mul ; (a + b) * 10
0008: StoreLocal 2 ; temp = (a + b) * 10
0010: LoadLocal 2 ; push temp
0012: Return ; return result

5. Portability & Sandboxing

Because the Bytecode VM is implemented in pure Rust without native platform dependencies:

  • Bytecode binaries (.adbc) are 100% portable across Linux, macOS, Windows, BSD, and WebAssembly.
  • The VM can be embedded inside other applications as a deterministic, memory-safe scripting runtime.