Skip to content

CandleVM Executable Format ​

A CandleVM executable contains a header, plugin requirements, module and function metadata, embedded resources, and the bytecode instructions. The loader reads these sections in order. The bytecode starts immediately after the resource table and continues to the end of the file.

Integer encoding ​

Multi-byte integers are stored little-endian. A u8 occupies one byte; a u16 occupies two bytes; a u32 occupies four bytes. Signed i32 operands use the same byte order. Serialized Value values use their documented type discriminator and payload layout.

File layout ​

SectionEncodingDescription
Magic4 bytesThe ASCII bytes CAND.
Candle versionu16Version of the Candle ecosystem; the supported version is 1.
Plugin requirement countu16Number of required plugins that follow.
Plugin requirementsRepeated stringsEach entry contains the plugin name followed by its required version. The matching plugins must be available when the executable is loaded.
Module countu16Number of modules defined in the executable.
Module tableRepeated module recordsEach record contains a module name string, a function count (u16), and that many function records.
Resource countu16Number of embedded resources that follow.
Resource tableRepeated resource recordsEach record contains a resource ID string, a data length (u32), and that many data bytes.
BytecodeRemaining bytesThe instruction stream. Its length is determined by the end of the file.

Module names must be unique. Functions are numbered by their order within each module; function names must be unique within the module. Each function record contains:

FieldEncodingDescription
NameStringFunction name.
Entry addressu32Byte offset into the bytecode instruction stream where the function begins.
Parameter countu8Number of regular parameters, up to 8.
Capture countu8Number of captured values, up to 8.

Resource IDs must be unique. Each resource can contain up to 64 MiB of data. The executable can define up to 32,768 modules, with up to 65,535 functions per module.

Strings ​

Every string in the file uses the same encoding:

  1. A u32 byte length in little-endian order.
  2. Exactly that many UTF-8 bytes.

The length counts bytes, not Unicode characters. Strings are not null-terminated. Invalid UTF-8 or a string whose bytes run past the end of the file makes the executable invalid. Strings are used for plugin names and versions, module and function names, and resource IDs.

Bytecode instructions ​

The bytecode section is a sequence of instructions. Each instruction begins with one opcode byte, followed by that opcode's operands in the order listed in the opcode reference. Registers and u8 operands occupy one byte. Multi-byte numeric operands use the little-endian encoding described above. String operands use the string encoding in this section. A tagged value operand uses the encoding described in the Value reference.

For example, a string operand containing the UTF-8 text cat is encoded as a four-byte little-endian length (03 00 00 00), followed by the three bytes 63 61 74.

Built for the Candle ecosystem · Powered by VitePress.