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;
}