aboutsummaryrefslogtreecommitdiff
path: root/src/bytecode
diff options
context:
space:
mode:
Diffstat (limited to 'src/bytecode')
-rw-r--r--src/bytecode/bytecode.c268
1 files changed, 203 insertions, 65 deletions
diff --git a/src/bytecode/bytecode.c b/src/bytecode/bytecode.c
index 47d492c..0ee066c 100644
--- a/src/bytecode/bytecode.c
+++ b/src/bytecode/bytecode.c
@@ -20,11 +20,17 @@
} while(0)
int bytecode_init(Bytecode *self, ArenaAllocator *allocator) {
+ self->import_index = 0;
+ self->funcs_index = 0;
+ self->extern_funcs_index = 0;
+ self->offset = 0;
return buffer_init(&self->data, allocator);
}
/*doc(Bytecode)
-The layout of the full bytecode is: Header (Intermediates Strings Functions External_Functions Exported_Functions Instructions)*
+The layout of the full bytecode is: Header (X Intermediates X Strings X Functions X External_Functions X Exported_Functions X Imports X Instructions)*\
+Where the X is a magic number to make it easier to find errors while decoding the bytecode.\
+The value of the magic number is @AMAL_BYTECODE_SECTION_MAGIC_NUMBER
*/
CHECK_RESULT int buffer_append_header(Buffer *program_data) {
@@ -61,10 +67,10 @@ static CHECK_RESULT usize ssa_extract_data(u8 *instruction_data, void *result, u
static void add_intermediates(BytecodeCompilerContext *self) {
/*doc(Bytecode intermediates)
# Intermediates layout
- |Type |Field |Description |
- |------------|------------------|-------------------------------------------------------------------------------|
- |u32 |Intermediates size|The size of the intermediates section, in bytes. |
- |Intermediate|Intermediate data |Multiple intermediates, where the total size is defined by @Intermediates size.|
+ |Type |Field |Description |
+ |--------------|------------------|-------------------------------------------------------------------------------|
+ |u32 |Intermediates size|The size of all intermediates, in bytes. |
+ |Intermediate[]|Intermediate data |Multiple intermediates, where the total size is defined by @Intermediates size.|
# Intermediate
|Type|Field|Description |
@@ -74,7 +80,7 @@ static void add_intermediates(BytecodeCompilerContext *self) {
*/
Ssa *ssa = self->parser->ssa;
- Buffer *instructions = &self->bytecode.data;
+ Buffer *instructions = &self->bytecode->data;
SsaNumber *intermediate = buffer_begin(&ssa->intermediates);
SsaNumber *intermediates_end = buffer_end(&ssa->intermediates);
int i = 0;
@@ -93,11 +99,11 @@ static void add_intermediates(BytecodeCompilerContext *self) {
static void add_strings(BytecodeCompilerContext *self) {
/*doc(Bytecode strings)
# Strings layout
- |Type |Field |Description |
- |------|-----------------|------------------------------------------------------------------|
- |u16 |Number of strings|The number of strings. |
- |u32 |Strings size |The size of the strings section, in bytes. |
- |String|Strings data |Multiple strings, where the total size is defined by @Strings size|
+ |Type |Field |Description |
+ |--------|-----------------|------------------------------------------------------------------|
+ |u16 |Number of strings|The number of strings. |
+ |u32 |Strings size |The size of all strings, in bytes. |
+ |String[]|Strings data |Multiple strings, where the total size is defined by @Strings size|
# String
|Type|Field|Description |
@@ -107,7 +113,7 @@ static void add_strings(BytecodeCompilerContext *self) {
*/
Ssa *ssa = self->parser->ssa;
- Buffer *instructions = &self->bytecode.data;
+ Buffer *instructions = &self->bytecode->data;
BufferView *string = buffer_begin(&ssa->strings);
BufferView *strings_end = buffer_end(&ssa->strings);
u32 strings_size = 0;
@@ -128,36 +134,105 @@ static void add_strings(BytecodeCompilerContext *self) {
}
}
+static TypeSize function_signature_get_params_size(FunctionSignature *self) {
+ FunctionParameter *param = buffer_begin(&self->parameters);
+ FunctionParameter *param_end = buffer_end(&self->parameters);
+ TypeSize params_total_size;
+ params_total_size.num_pointers = 0;
+ params_total_size.fixed_size = 0;
+ for(; param != param_end; ++param) {
+ TypeSize param_size = resolved_type_get_byte_size(&param->resolve_data.type);
+ params_total_size.num_pointers += param_size.num_pointers;
+ params_total_size.fixed_size += param_size.fixed_size;
+ }
+ return params_total_size;
+}
+
+static TypeSize function_signature_get_return_types_size(FunctionSignature *self) {
+ FunctionReturnType *return_type = buffer_begin(&self->return_types);
+ FunctionReturnType *return_type_end = buffer_end(&self->return_types);
+ TypeSize return_types_total_size;
+ return_types_total_size.num_pointers = 0;
+ return_types_total_size.fixed_size = 0;
+ for(; return_type != return_type_end; ++return_type) {
+ TypeSize param_size = resolved_type_get_byte_size(&return_type->resolved_type);
+ return_types_total_size.num_pointers += param_size.num_pointers;
+ return_types_total_size.fixed_size += param_size.fixed_size;
+ }
+ return return_types_total_size;
+}
+
static void add_functions(BytecodeCompilerContext *self) {
/*doc(Bytecode functions)
- # Internal functions layout
- |Type|Field |Description |
- |----|-------------------|---------------------------------|
- |u16 |Number of functions|The number of internal functions.|
+ # Functions layout
+ |Type |Field |Description |
+ |----------|----------|--------------------------------------------------------------------------------------|
+ |u16 |num_funcs |The number of non-extern functions. |
+ |u32 |funcs_size|The size of all functions, in bytes. |
+ |Function[]|Functions |Multiple non-extern functions, where the number of functions is defined by @num_funcs.|
+
+ # Function
+ |Type|Field |Description |
+ |----|-------------------------|------------------------------------------------------------------------------------------------------------------------|
+ |u32 |func_offset |The offset in the program code (machine code) where the function starts. Is always 0 until the program has been started.|
+ |u8 |num_params |The number of parameters. |
+ |u32 |params_num_pointers |The number of pointers in the parameters. |
+ |u32 |params_fixed_size |The size of all non-pointer type parameters, in bytes. |
+ |u8 |num_return_types |The number of return values. |
+ |u32 |return_types_num_pointers|The number of pointers in the return types. |
+ |u32 |return_types_fixed_size |The size of all non-pointer type return types, in bytes. |
*/
- assert(sizeof(SsaFuncIndex) == sizeof(u16) && "Program decoder needs to be updated since size of func index has changed");
- throw_if_error(buffer_append(&self->bytecode.data, &self->parser->ssa->func_counter, sizeof(u16)));
+ Ssa *ssa = self->parser->ssa;
+ Buffer *instructions = &self->bytecode->data;
+ SsaFunc *func = buffer_begin(&ssa->funcs);
+ SsaFunc *func_end = buffer_end(&ssa->funcs);
+ u32 funcs_size = ssa->func_counter * sizeof(BytecodeHeaderFunction);
+ assert(sizeof(BytecodeHeaderFunction) == 22);
+
+ self->bytecode->funcs_index = instructions->size;
+ amal_log_debug("func index: %d", self->bytecode->funcs_index);
+ throw_if_error(buffer_expand(instructions, sizeof(u16) + sizeof(u32) + funcs_size));
+ throw_if_error(buffer_append(instructions, &ssa->func_counter, sizeof(u16)));
+ throw_if_error(buffer_append(instructions, &funcs_size, sizeof(u32)));
+ for(; func != func_end; ++func) {
+ BytecodeHeaderFunction header_func;
+ TypeSize params_total_size = function_signature_get_params_size(func->func_sig);
+ TypeSize return_types_total_size = function_signature_get_return_types_size(func->func_sig);
+
+ header_func.func_offset = 0;
+
+ header_func.num_params = buffer_get_size(&func->func_sig->parameters, FunctionParameter);
+ header_func.params_num_pointers = params_total_size.num_pointers;
+ header_func.params_fixed_size = params_total_size.fixed_size;
+
+ header_func.num_return_types = buffer_get_size(&func->func_sig->return_types, FunctionReturnType);
+ header_func.return_types_num_pointers = return_types_total_size.num_pointers;
+ header_func.return_types_fixed_size = return_types_total_size.fixed_size;
+ throw_if_error(buffer_append(instructions, &header_func, sizeof(header_func)));
+ }
+
+ assert(sizeof(ssa->func_counter) == sizeof(u16) && "Program decoder needs to be updated since size of func index has changed");
}
static void add_extern_functions(BytecodeCompilerContext *self) {
/*doc(Bytecode external functions)
# External functions layout
- |Type |Field |Description |
- |-----------------|------------------|-----------------------------------------------------------------------------------------|
- |u16 |num_extern_func |The number of external functions. |
- |u32 |extern_funcs_size |The size of the external functions section, in bytes. |
- |External function|External functions|Multiple external functions, where the number of functions is defined by @num_extern_func|
+ |Type |Field |Description |
+ |-------------------|------------------|-----------------------------------------------------------------------------------------|
+ |u16 |num_extern_func |The number of external functions. |
+ |u32 |extern_funcs_size |The size of all external functions, in bytes. |
+ |External function[]|External functions|Multiple external functions, where the number of functions is defined by @num_extern_func|
# External function
- |Type|Field |Description |
- |----|--------|-----------------------------------------------------------------------------------------------------|
- |u8 |num_args|The number of arguments the functions has. |
- |u8 |name_len|The length of the external function name, in bytes. Excluding the null-terminate character. |
- |u8* |name |The name of the external function, where the size is defined by @name_len. Names are null-terminated.|
+ |Type|Field |Description |
+ |----|----------|-----------------------------------------------------------------------------------------------------|
+ |u8 |num_params|The number of parameters the functions has. |
+ |u8 |name_len |The length of the external function name, in bytes. Excluding the null-terminate character. |
+ |u8[]|name |The name of the external function, where the size is defined by @name_len. Names are null-terminated.|
*/
Ssa *ssa = self->parser->ssa;
- Buffer *instructions = &self->bytecode.data;
+ Buffer *instructions = &self->bytecode->data;
SsaExternFunc *extern_func = buffer_begin(&ssa->extern_funcs);
SsaExternFunc *extern_func_end = buffer_end(&ssa->extern_funcs);
u32 extern_funcs_size = 0;
@@ -167,14 +242,16 @@ static void add_extern_functions(BytecodeCompilerContext *self) {
}
extern_func = buffer_begin(&ssa->extern_funcs);
+ self->bytecode->extern_funcs_index = instructions->size;
throw_if_error(buffer_expand(instructions, sizeof(u16) + sizeof(u32) + extern_funcs_size));
throw_if_error(buffer_append(instructions, &ssa->extern_func_counter, sizeof(u16)));
throw_if_error(buffer_append(instructions, &extern_funcs_size, sizeof(u32)));
for(; extern_func != extern_func_end; ++extern_func) {
const char null_s = '\0';
- u8 num_args = buffer_get_size(&extern_func->func_sig->parameters, FunctionParameter);
- throw_if_error(buffer_append(instructions, &num_args, sizeof(num_args)));
+ u8 num_params = buffer_get_size(&extern_func->func_sig->parameters, FunctionParameter);
+ throw_if_error(buffer_append(instructions, &num_params, sizeof(num_params)));
/* TODO: Add namespace to the function name */
+ /* u8 is fine, because the max length of a variable is 255 */
throw_if_error(buffer_append(instructions, &extern_func->name.size, sizeof(u8)));
throw_if_error(buffer_append(instructions, extern_func->name.data, extern_func->name.size));
throw_if_error(buffer_append(instructions, &null_s, sizeof(char)));
@@ -186,11 +263,11 @@ static void add_extern_functions(BytecodeCompilerContext *self) {
static void add_export_functions(BytecodeCompilerContext *self) {
/*doc(Bytecode exported functions)
# Exported functions layout
- |Type |Field |Description |
- |-----------------|------------------|-----------------------------------------------------------------------------------------|
- |u16 |num_export_func |The number of exported functions. |
- |u32 |export_funcs_size |The size of the exported functions section, in bytes. |
- |Exported function|Exported functions|Multiple exported functions, where the number of functions is defined by @num_export_func|
+ |Type |Field |Description |
+ |-------------------|------------------|-----------------------------------------------------------------------------------------|
+ |u16 |num_export_func |The number of exported functions. |
+ |u32 |export_funcs_size |The size of all exported functions, in bytes. |
+ |Exported function[]|Exported functions|Multiple exported functions, where the number of functions is defined by @num_export_func|
# Exported function
|Type|Field |Description |
@@ -198,10 +275,10 @@ static void add_export_functions(BytecodeCompilerContext *self) {
|u32 |instruction_offset|The offset in the instruction data where the exported function is defined. Is always 0 until the program has been started.|
|u8 |num_args |The number of arguments the functions has. |
|u8 |name_len |The length of the exported function name, in bytes. Excluding the null-terminate character. |
- |u8* |name |The name of the exported function, where the size is defined by @name_len. Names are null-terminated. |
+ |u8[]|name |The name of the exported function, where the size is defined by @name_len. Names are null-terminated. |
*/
Ssa *ssa = self->parser->ssa;
- Buffer *instructions = &self->bytecode.data;
+ Buffer *instructions = &self->bytecode->data;
SsaExportFunc *export_func = buffer_begin(&ssa->export_funcs);
SsaExportFunc *export_func_end = buffer_end(&ssa->export_funcs);
u32 export_funcs_size = 0;
@@ -228,8 +305,51 @@ static void add_export_functions(BytecodeCompilerContext *self) {
assert(sizeof(SsaExportFuncIndex) == sizeof(u16) && "Program decoder needs to be updated since size of export func index has changed");
}
+static void add_imports(BytecodeCompilerContext *self) {
+ /*doc(Bytecode imports)
+ # Imports layout
+ |Type |Field |Description |
+ |--------|------------|-------------------------------------------------------------------------|
+ |u8 |num_imports |The number of imports. |
+ |u32 |imports_size|The size of all imports, in bytes. |
+ |Import[]|Import |Multiple imports, where the number of imports is defined by @num_imports.|
+
+ # Import
+ |Type|Field |Description |
+ |----|---------------------|----------------------------------------------------------------------------------------|
+ |u32 |function_index |The index in the bytecode where function header begins for the imported file. |
+ |u32 |extern_function_index|The index in the bytecode where the extern function header begins for the imported file.|
+ */
+ Parser *parser = self->parser;
+ Buffer *instructions = &self->bytecode->data;
+ ParserFileScopeReference **import = buffer_begin(&parser->imports);
+ ParserFileScopeReference **import_end = buffer_end(&parser->imports);
+ u8 num_imports = 1 + (import_end - import);
+ u32 imports_size = num_imports * sizeof(BytecodeHeaderImport);
+ assert(sizeof(BytecodeHeaderImport) == 8);
+
+ self->bytecode->import_index = instructions->size;
+ throw_if_error(buffer_expand(instructions, sizeof(u8) + sizeof(u32) + imports_size));
+ throw_if_error(buffer_append(instructions, &num_imports, sizeof(num_imports)));
+ throw_if_error(buffer_append(instructions, &imports_size, sizeof(imports_size)));
+
+ /* The first import is always a reference to itself */
+ throw_if_error(buffer_append(instructions, &self->bytecode->funcs_index, sizeof(self->bytecode->funcs_index)));
+ throw_if_error(buffer_append(instructions, &self->bytecode->extern_funcs_index, sizeof(self->bytecode->extern_funcs_index)));
+ for(; import != import_end; ++import) {
+ /*
+ We don't know the index to the functions yet, so first fill them with the parser index that owns them
+ and after bytecode has been generated for each parser (file), modify these function indices
+ to point to the parsers function index in the bytecode.
+ */
+ u32 parser_index = (*import)->file_scope_ref->parser->index;
+ throw_if_error(buffer_append(instructions, &parser_index, sizeof(parser_index)));
+ throw_if_error(buffer_append(instructions, &parser_index, sizeof(parser_index)));
+ }
+}
+
static void add_ins1(BytecodeCompilerContext *self, AmalOpcode opcode, const char *fmt) {
- throw_if_error(buffer_append(&self->bytecode.data, &opcode, sizeof(AmalOpcodeType)));
+ throw_if_error(buffer_append(&self->bytecode->data, &opcode, sizeof(AmalOpcodeType)));
if(fmt) {
fprintf(stderr, fmt);
fputc('\n', stderr);
@@ -237,7 +357,7 @@ static void add_ins1(BytecodeCompilerContext *self, AmalOpcode opcode, const cha
}
static void add_ins2(BytecodeCompilerContext *self, AmalOpcode opcode, i8 reg, const char *fmt) {
- Buffer *instructions = &self->bytecode.data;
+ Buffer *instructions = &self->bytecode->data;
size_t index = instructions->size;
throw_if_error(buffer_append_empty(instructions, sizeof(AmalOpcodeType) + sizeof(reg)));
@@ -248,7 +368,7 @@ static void add_ins2(BytecodeCompilerContext *self, AmalOpcode opcode, i8 reg, c
}
static void add_ins3(BytecodeCompilerContext *self, AmalOpcode opcode, i8 dst_reg, i8 src_reg, const char *fmt) {
- Buffer *instructions = &self->bytecode.data;
+ Buffer *instructions = &self->bytecode->data;
size_t index = instructions->size;
throw_if_error(buffer_append_empty(instructions, sizeof(AmalOpcodeType) + sizeof(dst_reg) + sizeof(src_reg)));
@@ -260,7 +380,7 @@ static void add_ins3(BytecodeCompilerContext *self, AmalOpcode opcode, i8 dst_re
}
static void add_ins4(BytecodeCompilerContext *self, AmalOpcode opcode, u16 data, const char *fmt) {
- Buffer *instructions = &self->bytecode.data;
+ Buffer *instructions = &self->bytecode->data;
size_t index = instructions->size;
throw_if_error(buffer_append_empty(instructions, sizeof(AmalOpcodeType) + sizeof(data)));
@@ -271,7 +391,7 @@ static void add_ins4(BytecodeCompilerContext *self, AmalOpcode opcode, u16 data,
}
static void add_ins5(BytecodeCompilerContext *self, AmalOpcode opcode, i8 dst_reg, i8 reg1, i8 reg2, const char *fmt) {
- Buffer *instructions = &self->bytecode.data;
+ Buffer *instructions = &self->bytecode->data;
size_t index = instructions->size;
throw_if_error(buffer_append_empty(instructions, sizeof(AmalOpcodeType) + sizeof(dst_reg) + sizeof(reg1) + sizeof(reg2)));
@@ -284,7 +404,7 @@ static void add_ins5(BytecodeCompilerContext *self, AmalOpcode opcode, i8 dst_re
}
static void add_ins6(BytecodeCompilerContext *self, AmalOpcode opcode, i8 dst_reg, u16 data, const char *fmt) {
- Buffer *instructions = &self->bytecode.data;
+ Buffer *instructions = &self->bytecode->data;
size_t index = instructions->size;
throw_if_error(buffer_append_empty(instructions, sizeof(AmalOpcodeType) + sizeof(dst_reg) + sizeof(data)));
@@ -295,16 +415,16 @@ static void add_ins6(BytecodeCompilerContext *self, AmalOpcode opcode, i8 dst_re
fputc('\n', stderr);
}
-static void add_ins7(BytecodeCompilerContext *self, AmalOpcode opcode, u16 idx, i8 num_args, i8 dst_reg, const char *fmt) {
- Buffer *instructions = &self->bytecode.data;
+static void add_ins7(BytecodeCompilerContext *self, AmalOpcode opcode, u8 import_index, u16 func_index, i8 num_args, const char *fmt) {
+ Buffer *instructions = &self->bytecode->data;
size_t index = instructions->size;
- throw_if_error(buffer_append_empty(instructions, sizeof(AmalOpcodeType) + sizeof(idx) + sizeof(num_args) + sizeof(dst_reg)));
+ throw_if_error(buffer_append_empty(instructions, sizeof(AmalOpcodeType) + sizeof(import_index) + sizeof(func_index) + sizeof(num_args)));
instructions->data[index] = opcode;
- memcpy(instructions->data + index + sizeof(AmalOpcodeType), &idx, sizeof(idx));
- instructions->data[index + sizeof(AmalOpcodeType) + sizeof(idx)] = num_args;
- instructions->data[index + sizeof(AmalOpcodeType) + sizeof(idx) + sizeof(num_args)] = dst_reg;
- fprintf(stderr, fmt, idx, num_args, dst_reg);
+ memcpy(instructions->data + index + sizeof(AmalOpcodeType), &import_index, sizeof(import_index));
+ memcpy(instructions->data + index + sizeof(AmalOpcodeType) + sizeof(import_index), &func_index, sizeof(func_index));
+ memcpy(instructions->data + index + sizeof(AmalOpcodeType) + sizeof(import_index) + sizeof(func_index), &num_args, sizeof(num_args));
+ fprintf(stderr, fmt, import_index, func_index, num_args);
fputc('\n', stderr);
}
@@ -330,8 +450,8 @@ static void add_instructions(BytecodeCompilerContext *self) {
u8 *instructions_end = buffer_end(&ssa->instructions);
u16 label_counter = 0;
- u32 num_instructions_index = self->bytecode.data.size;
- throw_if_error(buffer_append_empty(&self->bytecode.data, sizeof(num_instructions_index)));
+ u32 num_instructions_index = self->bytecode->data.size;
+ throw_if_error(buffer_append_empty(&self->bytecode->data, sizeof(num_instructions_index)));
/* TODO: Keep all registers under 256 */
while(instruction != instructions_end) {
@@ -404,22 +524,21 @@ static void add_instructions(BytecodeCompilerContext *self) {
add_ins2(self, AMAL_OP_PUSH, reg, "push r%d");
break;
}
+ case SSA_PUSH_RET: {
+ SsaRegister reg;
+ am_memcpy(&reg, instruction, sizeof(SsaRegister));
+ instruction += sizeof(SsaRegister);
+ add_ins2(self, AMAL_OP_PUSH_RET, reg, "push_ret r%d");
+ break;
+ }
case SSA_CALL: {
- /*
- TODO: Using ssa_func_index only works correctly if the function was defined in the same
- file as the function call. To make this work with calling functions in other files,
- ssa_func_index should also have an offset index or something like that.
- So each file has it's own function list with indices and when they need to be combined in the end,
- the function indices can be increased by their block index (ssa_func_index + block index), where block index
- is defined as the size of all previous files' number of functions.
- */
instruction += ssa_extract_data(instruction, &ssa_ins_func_call, sizeof(ssa_ins_func_call));
- add_ins7(self, AMAL_OP_CALL, ssa_ins_func_call.func_decl->ssa_func_index, ssa_ins_func_call.num_args, ssa_ins_func_call.result, "call f%d, %d, r%d");
+ add_ins7(self, AMAL_OP_CALL, ssa_ins_func_call.import_index, ssa_ins_func_call.func_decl->ssa_func_index, ssa_ins_func_call.num_args, "call f(%d,%d), %d");
break;
}
case SSA_CALL_EXTERN: {
instruction += ssa_extract_data(instruction, &ssa_ins_func_call_extern, sizeof(ssa_ins_func_call_extern));
- add_ins7(self, AMAL_OP_CALLE, ssa_ins_func_call_extern.extern_func_index, ssa_ins_func_call_extern.num_args, ssa_ins_func_call_extern.result, "calle ef%d, %d, r%d");
+ add_ins7(self, AMAL_OP_CALLE, ssa_ins_func_call_extern.import_index, ssa_ins_func_call_extern.func_decl_lhs->extern_index, ssa_ins_func_call_extern.num_args, "calle ef(%d,%d), %d");
break;
}
case SSA_JUMP_ZERO: {
@@ -450,16 +569,35 @@ static void add_instructions(BytecodeCompilerContext *self) {
/* Prepend instructions with its size */
{
/* -sizeof to Remove the count itself from the size of the instructions size */
- const u32 instructions_size = self->bytecode.data.size - num_instructions_index - sizeof(instructions_size);
- am_memcpy(self->bytecode.data.data + num_instructions_index, &instructions_size, sizeof(instructions_size));
+ const u32 instructions_size = self->bytecode->data.size - num_instructions_index - sizeof(instructions_size);
+ am_memcpy(self->bytecode->data.data + num_instructions_index, &instructions_size, sizeof(instructions_size));
}
}
+static void add_section_magic_number(BytecodeCompilerContext *self) {
+ const u32 section_magic_number = AMAL_BYTECODE_SECTION_MAGIC_NUMBER;
+ throw_if_error(buffer_append(&self->bytecode->data, &section_magic_number, sizeof(section_magic_number)));
+}
+
void generate_bytecode_from_ssa(BytecodeCompilerContext *self) {
+ add_section_magic_number(self);
add_intermediates(self);
+
+ add_section_magic_number(self);
add_strings(self);
+
+ add_section_magic_number(self);
add_functions(self);
+
+ add_section_magic_number(self);
add_extern_functions(self);
+
+ add_section_magic_number(self);
add_export_functions(self);
+
+ add_section_magic_number(self);
+ add_imports(self);
+
+ add_section_magic_number(self);
add_instructions(self);
}