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
- func Disassemble(w io.Writer, p *Program) error
- func Encode(p *Program) ([]byte, error)
- func EncodeModule(m *Module) ([]byte, error)
- func LocalName(name string) string
- func ReadU16(code []byte, at int) int
- func ReadU32(code []byte, at int) int
- func Relocate(f *Function, global, class, fn func(int) (int, error)) error
- func StackUse(op Op, operands []int) (pops, pushes int)
- func Verify(p *Program) error
- type Class
- type Function
- type Global
- type GlobalKind
- type JumpTable
- type Layout
- type LineInfo
- type Method
- type Module
- type Op
- type OpInfo
- type Program
- type Upvalue
Constants ¶
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).
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.
const FormatVersion = 6 // 2: milestone 12 superinstructions; 3: native modules (GlobalNative); 4: THROW takes only Error objects (Kukel v0.4); 5: jump tables and ADD_LOCAL (Kukel v0.8); 6: native base classes, CALL_NATIVE (Kukel v0.9)
FormatVersion is the version of the .kkc format written by Encode.
Variables ¶
This section is empty.
Functions ¶
func Disassemble ¶
Disassemble writes a readable listing of the program.
func EncodeModule ¶ added in v0.7.0
EncodeModule serializes a module.
func LocalName ¶ added in v0.2.0
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 Relocate ¶ added in v0.7.0
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 ¶
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 ¶
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
Native string // a native base class (Base is -1): its qualified name ("strings::Builder")
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)
Tables []JumpTable // of SWITCH_TABLE instructions
// 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) ParamSlots ¶
ParamSlots is the number of slots that hold parameters.
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 JumpTable ¶ added in v0.8.0
JumpTable maps the ints Min, Min+1, ... to code offsets (-1: none, the instruction's miss target).
type Layout ¶ added in v0.7.0
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 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
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-- // Jump tables (Kukel v0.8): a switch whose case values are dense ints. OpSwitchTable // table u16, miss u32: pop x; jump to Tables[table]'s target for x, else to miss OpAddLocal // slot u16: pop x; slot = slot + x (statement "local += x") // Native base classes (Kukel v0.9). OpCallNative // class u16, name u16, argc u16: this args -> result of the member function name of the native class in global class, on this (Base::m(...)) )