diff --git a/src/compiler/Binary.c b/src/compiler/Binary.c new file mode 100644 index 0000000..4044060 --- /dev/null +++ b/src/compiler/Binary.c @@ -0,0 +1,36 @@ +#include "Binary.h" + +List_define(ConstDataProps); +List_define(NamedRef); +List_define(CompiledSection); +HashMap_define(CompiledSectionPtr, HashMap_DESTROY_VALUE_FUNC_NULL); + + +void CompiledSection_construct(CompiledSection* ptr, str name){ + ptr->name = name; + ptr->next = NULL; + ptr->offset = 0; + ptr->const_data_offsets = List_ConstDataProps_construct(NULL, 0, 0); + ptr->named_refs = List_NamedRef_construct(NULL, 0, 0); + ptr->bytes = List_u8_alloc(64); +} + +void CompiledSection_free(CompiledSection* ptr){ + free(ptr->const_data_offsets.data); + free(ptr->named_refs.data); + free(ptr->bytes.data); +} + + +void BinaryObject_construct(BinaryObject* ptr){ + ptr->section_list = List_CompiledSection_alloc(64); + HashMap_CompiledSectionPtr_alloc(&ptr->section_map); +} + +void BinaryObject_free(BinaryObject* ptr){ + for(u32 i = 0; i < ptr->section_list.len; i++){ + CompiledSection_free(&ptr->section_list.data[i]); + } + free(ptr->section_list.data); + HashMap_CompiledSectionPtr_free(&ptr->section_map); +} diff --git a/src/compiler/Binary.h b/src/compiler/Binary.h new file mode 100644 index 0000000..66d12a8 --- /dev/null +++ b/src/compiler/Binary.h @@ -0,0 +1,63 @@ +#pragma once +#include "../std.h" +#include "../string/str.h" +#include "../instructions/instructions.h" +#include "../instructions/registers.h" +#include "../collections/List.h" +#include "../collections/HashMap.h" +#include "AST.h" + +typedef struct CompiledSection CompiledSection; +typedef struct ConstDataProps { + str name; + u32 size; // size in bytes + u32 offset; // offset in bytes from section start +} ConstDataProps; + +#define ConstDataProps_construct(NAME, SIZE, OFFSET) ((ConstDataProps){ .name = NAME, .size = SIZE, .offset = OFFSET}) + +List_declare(ConstDataProps); + + +typedef enum NamedRefType { + NamedRefType_Unset, + NamedRefType_Ptr, + NamedRefType_Size, +} NamedRefType; + +typedef struct NamedRef { + str name; + NamedRefType type; + u32 offset; // offset in bytes from section start +} NamedRef; + +#define NamedRef_construct(NAME, TYPE, OFFSET) ((NamedRef){ .name = NAME, .type = TYPE, .offset = OFFSET}) + +List_declare(NamedRef); + +typedef struct CompiledSection { + str name; + CompiledSection* next; + u32 offset; + List_ConstDataProps const_data_offsets; + List_NamedRef named_refs; + List_u8 bytes; +} CompiledSection; + +void CompiledSection_construct(CompiledSection* ptr, str name); +void CompiledSection_free(CompiledSection* ptr); + + + +List_declare(CompiledSection); +typedef CompiledSection* CompiledSectionPtr; +HashMap_declare(CompiledSectionPtr); + +typedef struct BinaryObject { + List_CompiledSection section_list; + HashMap_CompiledSectionPtr section_map; + u32 total_size; +} BinaryObject; + +void BinaryObject_construct(BinaryObject* ptr); +void BinaryObject_free(BinaryObject* ptr); diff --git a/src/compiler/Compiler.c b/src/compiler/Compiler.c index d94f0ac..50e657f 100644 --- a/src/compiler/Compiler.c +++ b/src/compiler/Compiler.c @@ -1,11 +1,14 @@ #include "Compiler_internal.h" +HashMap_define(SectionPtr, HashMap_DESTROY_VALUE_FUNC_NULL); + void Compiler_init(Compiler* cmp){ memset(cmp, 0, sizeof(Compiler)); cmp->state = CompilerState_Initial; cmp->tokens = List_Token_alloc(4096); cmp->line_lengths = List_u32_alloc(1024); AST_init(&cmp->ast); + BinaryObject_construct(&cmp->binary); } void Compiler_free(Compiler* cmp){ @@ -13,6 +16,7 @@ void Compiler_free(Compiler* cmp){ free(cmp->tokens.data); free(cmp->line_lengths.data); AST_free(&cmp->ast); + BinaryObject_free(&cmp->binary); } CodePos Compiler_getLineAndColumn(Compiler* cmp, u32 pos){ @@ -60,14 +64,116 @@ str Compiler_constructTokenStr(Compiler* cmp, Token t){ return s; } +static bool compileSection(Compiler* cmp, Section* sec){ + CompiledSection* cs = List_CompiledSection_expand(&cmp->binary.section_list, 1); + CompiledSection_construct(cs, sec->name); + if(!HashMap_CompiledSectionPtr_tryPush(&cmp->binary.section_map, cs->name, cs)){ + returnError("duplicate section '%s'", str_copy(sec->name)); + } + + // compile code + u8 zeroes[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + for(u32 i = 0; i < sec->code.len; i++){ + Operation* op = &sec->code.data[i]; + List_u8_pushMany(&cs->bytes, (void*)&op->opcode, sizeof(op->opcode)); + for(u32 j = 0; j < op->args.len; j++){ + Argument* arg = &op->args.data[i]; + switch(arg->type){ + case ArgumentType_VarDataName: + returnError("argument type 'VarDataName' is not supported yet"); + case ArgumentType_Unset: + returnError("ArgumentType is not set"); + default: + returnError("invalid ArgumentType %i", arg->type); + + case ArgumentType_Register: + List_u8_push(&cs->bytes, arg->value.register_code); + break; + case ArgumentType_ConstValue: + //TODO: add const value size parsing + List_u8_pushMany(&cs->bytes, (void*)&arg->value.i, 4); + break; + case ArgumentType_ConstDataPointer: + List_NamedRef_push(&cs->named_refs, NamedRef_construct( + arg->value.data_name, + NamedRefType_Ptr, + cs->bytes.len)); + List_u8_pushMany(&cs->bytes, zeroes, 4); + break; + case ArgumentType_ConstDataSize: + List_NamedRef_push(&cs->named_refs, NamedRef_construct( + arg->value.data_name, + NamedRefType_Size, + cs->bytes.len)); + List_u8_pushMany(&cs->bytes, zeroes, 4); + break; + } + } + } + + // compile data + for(u32 i = 0; i < sec->data.len; i++){ + DataDefinition* ddf = &sec->data.data[i]; + List_ConstDataProps_push(&cs->const_data_offsets, ConstDataProps_construct(ddf->name, ddf->data.len, cs->bytes.len)); + List_u8_pushMany(&cs->bytes, ddf->data.data, ddf->data.len); + } + + // TODO: push padding + + return true; +} + +static bool compileBinary(Compiler* cmp){ + for(u32 i = 0; i < cmp->ast.sections.len; i++){ + SectionPtr sec = &cmp->ast.sections.data[i]; + if(!compileSection(cmp, sec)){ + return false; + } + } + + // find main section + str main_sec_name = STR("main"); + CompiledSection** main_sec_ptrptr = HashMap_CompiledSectionPtr_tryGetPtr(&cmp->binary.section_map, main_sec_name); + if(main_sec_ptrptr == NULL){ + returnError("no 'main' section was defined"); + } + + // create linked list of CompiledSection where main is the first + CompiledSection* prev_sec = *main_sec_ptrptr; + u32 total_size = 0; + for(u32 i = 0; i < cmp->binary.section_list.len; i++){ + CompiledSection* sec = &cmp->binary.section_list.data[i]; + total_size += sec->bytes.len; + if(str_equals(sec->name, main_sec_name)) + continue; + prev_sec->next = sec; + sec->offset = prev_sec->offset + prev_sec->bytes.len; + } + + cmp->binary.total_size = total_size; + return true; +} + static bool writeBinaryFile(Compiler* cmp, FILE* f){ returnErrorIf_auto(cmp->state != CompilerState_Parsing); cmp->state = CompilerState_Compiling; - for(u32 i = 0; i < cmp->ast.sections.len; i++){ - Section* sec = &cmp->ast.sections.data[i]; - + if(!compileBinary(cmp)){ + return false; + } + + + CompiledSection** main_sec_ptrptr = HashMap_CompiledSectionPtr_tryGetPtr(&cmp->binary.section_map, STR("main")); + if(main_sec_ptrptr == NULL){ + returnError("no 'main' section was defined"); } + CompiledSection* sec = *main_sec_ptrptr; + while(sec){ + fwrite(sec->bytes.data, 1, sec->bytes.len, f); + sec = sec->next; + } + + //TODO: print warnings for unused sections return true; } diff --git a/src/compiler/Compiler.h b/src/compiler/Compiler.h index 26cb6ea..87af093 100644 --- a/src/compiler/Compiler.h +++ b/src/compiler/Compiler.h @@ -2,8 +2,9 @@ #include "../std.h" #include "../string/str.h" #include "../collections/List.h" +#include "../collections/HashMap.h" #include "Token.h" -#include "AST.h" +#include "Binary.h" typedef enum CompilerState { CompilerState_Initial, @@ -14,16 +15,24 @@ typedef enum CompilerState { CompilerState_Success } CompilerState; +typedef Section* SectionPtr; +HashMap_declare(SectionPtr); + typedef struct Compiler { + /* general fields */ str code; u32 column; // > 0 if code parsing started u32 pos; CompilerState state; NULLABLE(char* error_message); + /* lexer fields */ List_Token tokens; List_u32 line_lengths; + /* parser fields */ AST ast; u32 tok_i; + /* compiler fields */ + BinaryObject binary; } Compiler; void Compiler_init(Compiler* cmp);