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.
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.
*.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.
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;
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.
typedef struct {
uint32_t count;
uint32_t permissions; // permissions = readable | writable | executable
uint32_t size;
} gyb_section_t;