Garter – bytecode

gyb objects

This bytecode is the backbone of the Garter backend. Garter bytecode is similar to p-code, containing a small subset of instructions common to most modern machines so that it is trivial to translate to real machine code. Most instructions in Garter bytecode one-to-one relate to real machine code instructions, meaning that the Garter assembly you write neatly corresponds to what users' hardware will be doing under-the-hood without having to worry about platform specific languages and naming conventions.

Because of how simple Garter bytecode is, it can be easily interpreted, translated to a C subset or various assembly languages, or turned into native executables.

Linking & Execution

To have the compiler toolchain link and build an executable from bytecode, pass it as the input without any other source files like

garter -o binary input.gyb

If you need to include external dependencies from a library that's been compiled to a shared object or bytecode file, use the preprocessor #link directive

Instructions use indexes within the symbol table instead of hard-coded literals so that they can be easily linked with other bytecode objects. Any symbols that have NULL references are assumed to be defined externally. The linker knows both how to read *.gyb bytecode objects and a subset of ELF Shared Objects.

file format

*.gyb files have a small header which contains a symbol table, a sections table, and if applicable an entry point for execution. If the entry pointer is NULL then the file needs to be linked with another file containing any external symbols it did not define.

Header

typedef struct {
    char magic[4];          // always  "gyb\n"
    char version[4];        // example "\0\0\0\n"
    void* entry;            // position within file
    void* symbol_table;
    void* section_table;
} gyb_header_t;

Symbol Table

typedef struct {
    uint32_t count;
    char** names;
    void** reference;       // position relative to first section
} gyb_symtable_t;

External symbols in the symbol table will have reference set to NULL and the linker will know to find the symbol externally before code emission.

Section Table

typedef struct {
    uint32_t count;
    uint32_t permissions;   // permissions = readable | writable | executable
    uint32_t size;
} gyb_section_t;

see also