112 lines
3.2 KiB
C
112 lines
3.2 KiB
C
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
|
|
#include "compile.h"
|
|
#include "binary.h"
|
|
#include "parse.h"
|
|
#include "hash.h"
|
|
#include "unit.h"
|
|
#include "node.h"
|
|
|
|
|
|
static void write_unit(FILE *fp, struct unit *u) {
|
|
struct bin_header hdr;
|
|
size_t offset = sizeof(struct bin_header);
|
|
|
|
// Step 1 generate offsets
|
|
hdr.magic = 0xCEBAB123;
|
|
hdr.version = 1;
|
|
|
|
hdr.global_pool_size = u->global.var_counter;
|
|
|
|
hdr.unit_table_offset = offset;
|
|
hdr.unit_table_size = u->ext_units.size;
|
|
for (size_t i = 0; i < u->ext_units.size; ++i) {
|
|
struct ext_unit *unit = vector_ref(&u->ext_units, i);
|
|
offset += sizeof(struct bin_unit_entry) + strlen(unit->name) + 1;
|
|
}
|
|
|
|
hdr.ref_table_offset = offset;
|
|
hdr.ref_table_size = u->ext_refs.size;
|
|
for (size_t i = 0; i < u->ext_refs.size; ++i) {
|
|
struct ext_ref *ref = vector_ref(&u->ext_refs, i);
|
|
offset += sizeof(struct bin_ref_entry) + strlen(ref->name) + 1;
|
|
}
|
|
|
|
hdr.export_table_offset = offset;
|
|
hdr.export_table_size = 0;
|
|
|
|
hdr.func_table_offset = offset;
|
|
hdr.func_table_size = u->functions.size;
|
|
for (size_t i = 0; i < u->functions.size; ++i) {
|
|
struct function *fn = vector_ref(&u->functions, i);
|
|
offset += sizeof(struct bin_func_entry) + fn->bytecode.size;
|
|
}
|
|
|
|
fwrite(&hdr, 1, sizeof(struct bin_header), fp);
|
|
for (size_t i = 0; i < u->ext_units.size; ++i) {
|
|
struct ext_unit *unit = vector_ref(&u->ext_units, i);
|
|
struct bin_unit_entry bin_unit;
|
|
bin_unit.name_len = strlen(unit->name);
|
|
fwrite(&bin_unit, 1, sizeof(struct bin_unit_entry), fp);
|
|
fwrite(unit->name, 1, bin_unit.name_len + 1, fp);
|
|
}
|
|
for (size_t i = 0; i < u->ext_refs.size; ++i) {
|
|
struct ext_ref *ref = vector_ref(&u->ext_refs, i);
|
|
struct bin_ref_entry bin_ref;
|
|
bin_ref.unit_index = ref->unit_index;
|
|
bin_ref.name_len = strlen(ref->name);
|
|
fwrite(&bin_ref, 1, sizeof(struct bin_ref_entry), fp);
|
|
fwrite(ref->name, 1, bin_ref.name_len + 1, fp);
|
|
}
|
|
for (size_t i = 0; i < u->functions.size; ++i) {
|
|
struct function *fn = vector_ref(&u->functions, i);
|
|
struct bin_func_entry bin_func;
|
|
size_t argc = 0;
|
|
for (struct node *arg = fn->args; arg; arg = cdr(arg)) {
|
|
++argc;
|
|
}
|
|
bin_func.argc = argc;
|
|
bin_func.local_count = fn->local_count;
|
|
bin_func.len = fn->bytecode.size * sizeof(uint32_t);
|
|
fwrite(&bin_func, 1, sizeof(struct bin_func_entry), fp);
|
|
fwrite(fn->bytecode.data, 1, fn->bytecode.size * sizeof(uint32_t), fp);
|
|
}
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
const char *input, *output;
|
|
assert(argc == 3);
|
|
input = argv[1];
|
|
output = argv[2];
|
|
|
|
struct unit unit;
|
|
struct node *program;
|
|
FILE *fp;
|
|
|
|
unit_init(&unit);
|
|
fp = fopen(input, "r");
|
|
assert(fp);
|
|
program = vm_load_file(fp);
|
|
fclose(fp);
|
|
|
|
struct function *main = unit_lambda(&unit);
|
|
main->args = NULL;
|
|
main->body = program;
|
|
unit.global.owner = main;
|
|
emit_function(&unit.global, main);
|
|
|
|
fp = fopen(output, "wb");
|
|
if (!fp) {
|
|
perror(output);
|
|
return -1;
|
|
}
|
|
write_unit(fp, &unit);
|
|
fclose(fp);
|
|
|
|
return 0;
|
|
}
|