bytecode

package
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 14, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package bytecode defines the instruction set of the Kukel stack machine and the compiled program image.

An instruction is a one-byte opcode followed by fixed-width little-endian operands: u16 for indices (constants, slots, globals, argument counts) and u32 for jump targets (absolute offsets in the function's code).

Index

Constants

View Source
const (
	CmpLt = iota
	CmpLe
	CmpGt
	CmpGe
	CmpEq
	CmpNe
	CmpJumpIfTrue = 0x100
)

The comparison operand of CMP_JUMP: one of these, plus CmpJumpIfTrue to jump when the comparison holds (else when it does not).

View Source
const (
	MaxCodeSize   = 1 << 24
	MaxStackDepth = 1 << 20
)

MaxCodeSize and MaxStackDepth are the largest code size (bytes) and MaxStack of one function a .kkc file can hold; the compiler refuses bigger functions.

View Source
const FormatVersion = 4 // 2: milestone 12 superinstructions; 3: native modules (GlobalNative); 4: THROW takes only Error objects (Kukel v0.4)

FormatVersion is the version of the .kkc format written by Encode.

Variables

This section is empty.

Functions

func Disassemble

func Disassemble(w io.Writer, p *Program) error

Disassemble writes a readable listing of the program.

func Encode

func Encode(p *Program) ([]byte, error)

Encode serializes a program.

func EncodeModule added in v0.7.0

func EncodeModule(m *Module) ([]byte, error)

EncodeModule serializes a module.

func LocalName added in v0.2.0

func LocalName(name string) string

LocalName returns the last part of a qualified name: "Stack" for "util::Stack". A class's constructor is the member function with the local name of the class.

func ReadU16

func ReadU16(code []byte, at int) int

ReadU16 and ReadU32 decode operands.

func ReadU32

func ReadU32(code []byte, at int) int

func Relocate added in v0.7.0

func Relocate(f *Function, global, class, fn func(int) (int, error)) error

Relocate rewrites the global, class and function index operands of f's code with global, class and fn. A mapping can refuse an index with an error.

func StackUse

func StackUse(op Op, operands []int) (pops, pushes int)

StackUse returns how many values an instruction pops and pushes. For ITER_NEXT it is the path that continues the loop (the end of the loop pushes nothing); TRY_PUSH's handler starts with one more value than the instruction had.

func Verify

func Verify(p *Program) error

Verify checks that a program cannot make the VM crash: every index in an instruction refers to something that exists, jumps land on instructions, no function can run past its last instruction, and on every path the operand stack depth is the same at each instruction, never negative and never above the function's MaxStack. Decode calls it for every file; the compiler's output always passes. Try handlers are counted the same way: the same number at each instruction on every path, TRY_POP only with one registered, and none left when the function returns.

Types

type Class

type Class struct {
	Name    string
	Base    int      // index in Program.Classes, or -1
	Fields  []string // own instance data members (the base's come first in an object)
	Statics []string // own static data members
	Methods []Method // own member functions
}

Class describes a class. A base class always comes before the classes derived from it in Program.Classes.

type Function

type Function struct {
	FuncName    string
	File        string // source file
	Line        int    // line of the definition
	NumParams   int    // required parameters
	NumOptional int    // optional parameters (with a default), after the required ones
	HasRest     bool   // a rest parameter follows the optional ones
	NumSlots    int    // parameters + locals + hidden slots (iterators, saved values)
	MaxStack    int    // operand stack depth needed above the slots
	Code        []byte
	Consts      []value.Value
	Lines       []LineInfo // sorted by PC
	SlotNames   []string   // for the disassembler
	Upvalues    []Upvalue  // a function literal's captured variables
	NumCaches   int        // inline cache slots of member instructions (the VM keeps the caches)

	// Index is the function's position in Program.Funcs (-1 for Init). It is
	// not stored in files: the compiler and Decode set it.
	Index int
}

Function is a compiled function: its code and constants.

func (*Function) LineAt

func (f *Function) LineAt(pc int) int

LineAt returns the source line of the instruction at pc.

func (*Function) Name

func (f *Function) Name() string

Name implements value.Named.

func (*Function) ParamSlots

func (f *Function) ParamSlots() int

ParamSlots is the number of slots that hold parameters.

func (*Function) Pos

func (f *Function) Pos() token.Pos

Pos returns the position of the function's definition.

type Global

type Global struct {
	Name  string
	Kind  GlobalKind
	Func  int // for GlobalFunc
	Class int // for GlobalClass
}

Global describes one global slot.

type GlobalKind

type GlobalKind uint8

GlobalKind says what a global slot holds when the program starts.

const (
	GlobalVar     GlobalKind = iota // a global variable (nil until initialized)
	GlobalFunc                      // a function: Funcs[Func]
	GlobalBuiltin                   // a built-in, looked up by name
	GlobalClass                     // a class: Classes[Class]
	GlobalNative                    // a function or class of a native module, looked up by its qualified name
)

type Layout added in v0.7.0

type Layout struct {
	Fields  []string // with the inherited ones first
	Statics []string
}

Layout is the data members of a class, which the code of member functions and of static data member accesses refers to by index: a program that links a module must have the same.

type LineInfo

type LineInfo struct {
	PC   int
	Line int
}

LineInfo maps code from PC onwards to a source line.

type Method

type Method struct {
	Name   string
	Static bool
	Func   int // index in Program.Funcs, or -1 when declared but not defined
}

Method is a member function of a class.

type Module added in v0.7.0

type Module struct {
	Name    string
	Header  string      // its declarations, with empty function bodies and no initializers (Kukel source)
	Globals []Global    // what global indexes in Code stand for: Name and Kind
	Classes []string    // what class indexes stand for: class names
	Layouts []Layout    // the classes' data members when the module was compiled
	Funcs   []string    // the functions of others, after Code in the index space
	Code    []*Function // the module's own functions
	Init    int         // the function in Code that initializes its global variables
}

Module is a module compiled on its own (kukel build -module), for linking into programs that use it. Its code refers to globals, classes and other modules' functions by index into the name tables here; the compiler that links it finds them by name and relocates the code.

The module file (Encode's format with flags 1):

"KUKL", uv format version, uv flags (1)
str name, str header
uv n, globals          str name, byte kind
uv n, classes          str name, uv n + str data members (with the
                       inherited ones), uv n + str static data members
uv n, functions        str name: functions of other modules (and of
                       the prelude) the code calls, as Code index len(Code)+i
uv init                index in Code
uv n, code             functions
u32 CRC-32 (IEEE) of everything before it

func DecodeModule added in v0.7.0

func DecodeModule(data []byte) (*Module, error)

DecodeModule reads a module written by EncodeModule. Its code is checked when it is linked (Relocate, and Verify of the program).

type Op

type Op uint8

Op is an opcode.

const (
	OpNop Op = iota

	// Stack.
	OpConst // k u16: push Consts[k]
	OpNil
	OpTrue
	OpFalse
	OpPop
	OpDup
	OpDup2 // a b -> a b a b

	// Variables. Stores pop the value.
	OpLoadLocal   // slot u16
	OpStoreLocal  // slot u16
	OpLoadGlobal  // global u16
	OpStoreGlobal // global u16

	// Arithmetic and logic: pop operands, push the result.
	OpAdd
	OpSub
	OpMul
	OpDiv
	OpMod
	OpBitAnd
	OpBitOr
	OpBitXor
	OpShl
	OpShr
	OpNeg
	OpNot // push !truthy(x)
	OpBitNot
	OpEq
	OpNe
	OpLt
	OpLe
	OpGt
	OpGe
	OpInc // x + 1 (for ++)
	OpDec // x - 1 (for --)

	// Control.
	OpJump        // target u32
	OpJumpIfFalse // target u32: pop, jump if not truthy
	OpJumpIfTrue  // target u32: pop, jump if truthy
	OpJumpIfArg   // n u16, target u32: jump if argument n was passed (n < argc)

	// Calls. The callee is below its arguments on the stack.
	OpCall      // argc u16
	OpCallV     // call with the arguments in a vector on top of the callee
	OpReturn    // return the top of the stack
	OpReturnNil // return nil

	// Vectors: vector literals and the argument lists of spread calls.
	OpMakeVector // n u16: pop n values, push a vector of them
	OpAppend     // pop x, append it to the vector below
	OpExtend     // pop vector x, append its elements to the vector below

	// Collections.
	OpMakeMap  // n u16: pop n key/value pairs, push a map of them
	OpIndexGet // x i -> x[i]
	OpIndexSet // x i v -> v, after x[i] = v
	OpIterInit // x -> an iterator over x
	OpIterNext // slot u16, n u16, end u32: advance the iterator in slot; push n values, or jump to end

	// Classes and objects. Member names are string constants (u16 index).
	OpLoadThis    // push this
	OpLoadMember  // field u16: push this.fields[field]
	OpStoreMember // field u16: pop into this.fields[field]
	OpGetMember   // name u16, cache u16: obj -> obj->name (data member or bound method)
	OpSetMember   // name u16, cache u16: obj v -> v, after obj->name = v
	OpCallMethod  // name u16, argc u16, cache u16: obj args -> result of obj->name(args)
	OpCallMethodV // name u16, cache u16: obj argvector -> result
	OpCallDirect  // func u16, argc u16: obj args -> result of Funcs[func] with this = obj (Base::m(...))
	OpLoadFunc    // func u16: push Funcs[func] (a static member function)
	OpLoadStatic  // class u16, slot u16: push a static data member
	OpStoreStatic // class u16, slot u16: pop into a static data member
	OpNew         // argc u16: class args -> new object (the constructor runs)
	OpNewV        // class argvector -> new object

	// Exceptions.
	OpTryPush // kind u16, handler u32: register a handler (kind 0: catch, 1: finally)
	OpTryPop  // remove the innermost handler
	OpThrow   // pop an Error object and throw it (anything else: throw a TypeError)
	OpRethrow // pop a pending exception (from a finally handler) and throw it again

	// Closures. A captured local lives in a cell held by its slot.
	OpNewCell      // slot u16: pop a value into a new cell in the slot
	OpLoadCell     // slot u16: push the value in the slot's cell
	OpStoreCell    // slot u16: pop into the slot's cell
	OpLoadUpvalue  // index u16: push the value of the closure's captured cell
	OpStoreUpvalue // index u16: pop into the closure's captured cell
	OpClosure      // func u16: push a closure of Funcs[func] (see Function.Upvalues)

	// Superinstructions (milestone 12): common pairs fused into one.
	OpCmpJump  // cmp u16, target u32: pop b, a; jump if (a cmp b) == want (see CmpJump*)
	OpIncLocal // slot u16: slot++ (a statement: no value is pushed)
	OpDecLocal // slot u16: slot--

)

func (Op) Size

func (op Op) Size() int

Size returns the size in bytes of an instruction with opcode op.

func (Op) String

func (op Op) String() string

type OpInfo

type OpInfo struct {
	Name     string
	Operands []int // byte width of each operand
}

OpInfo describes an opcode for the disassembler and the loader.

func Info

func Info(op Op) (OpInfo, bool)

Info returns the description of op; ok is false for an unknown opcode.

type Program

type Program struct {
	Globals []Global
	Classes []*Class
	Funcs   []*Function
	Init    *Function
	Main    int // global index of main
}

Program is a compiled program: global slots, functions, an init function that runs the global initializers, and the entry point.

func Decode

func Decode(data []byte) (*Program, error)

Decode reads a program written by Encode and verifies it (see Verify), so that running it cannot crash the VM.

type Upvalue

type Upvalue struct {
	Name      string // for the disassembler
	FromLocal bool
	Index     int // slot or upvalue index
}

Upvalue says where a closure gets a captured cell when it is made: from a slot of the function making it, or from that function's own upvalues.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL