From 6dd904346e58a8a97fe670aae499c1e8ef9fd31b Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Fri, 24 Jun 2022 21:56:21 +0200 Subject: [PATCH] Trying to do some ir stuff --- bytecode_codegen.cpp | 194 +++++++++++++++++++++++++++++++++++++++++++ main.cpp | 3 +- 2 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 bytecode_codegen.cpp diff --git a/bytecode_codegen.cpp b/bytecode_codegen.cpp new file mode 100644 index 0000000..c490c2b --- /dev/null +++ b/bytecode_codegen.cpp @@ -0,0 +1,194 @@ +typedef S32 Register_Index; +union Register{ + F64 f64; + S64 s64; + + S64 *pointer_s64; + F64 *pointer_f64; + U8 *pointer; + U64 *pointer64; + + U64 *pointer_u64; + U32 *pointer_u32; + U16 *pointer_u16; + U8 *pointer_u8; + + U64 u64; + U32 u32; + U16 u16; + U8 u8; + +}; +static_assert(sizeof(Register) == 8, "not 8 bytes"); + +enum Ir_Storage_Kind{ + STORAGE_NULL, + STORAGE_GLOBAL, + STORAGE_CONSTANT, + STORAGE_REGISTER, + STORAGE_STACK, +}; + +struct Ir_Storage{ + Ast_Type *type; + Ir_Storage *next; + Ir_Storage_Kind kind; + union{ S64 register_index; S64 offset; Register constant; }; +}; + +enum Ir_Instruction_Kind{ + IR_NOOP, + + IR_STORE, + IR_LOAD, + + IR_ADD, + IR_SUB, + IR_MUL, + IR_DIV, +}; + +struct Ir_Instruction{ + Ir_Instruction_Kind kind; + Ir_Storage *a; + Ir_Storage *b; + Ir_Storage *c; +}; + +struct Ir_Block{ + Simple_Bucket_Array instructions; +}; + +struct Ir_Call; +struct Ir_Var{ + Ast_Decl *decl; + Ir_Storage storage; + Ir_Call *call; + Simple_Bucket_Array blocks; +}; + +struct Ir_Call{ + Ast_Decl *decl; + + Array used_registers; + Array free_registers; + Register_Index register_ids; + + Ir_Storage return_value; + Simple_Bucket_Array args; + Simple_Bucket_Array blocks; +}; + +struct Ir_Builder{ + #define IR_NEW(T) exp_alloc_type(ir->arena, T, AF_ZeroMemory) + Arena _arena; + Arena *arena; + + Simple_Bucket_Array global_variables; + Simple_Bucket_Array calls; +}; + +function Register_Index +allocate_register(Ir_Call *call){ + Register_Index result = -1; + if(call->free_registers.len > 0){ + result = call->free_registers.pop(); + } + else{ + result = call->register_ids++; + } + + assert(result != -1); + call->used_registers.add(result); + return result; +} + +function void +release_register(Ir_Call *call, Register_Index index){ + if(index == -1) return; + + B32 found = false; + For(call->used_registers){ + if(index == it){ + call->used_registers.unordered_remove(&it); + found = true; + break; + } + } + + assert_msg(found, "Internal compiler error: releasing register that is not marked as used"); + call->free_registers.add(index); +} + +function void +build_bytecode(){ + Ir_Builder ir_builder = {}; + arena_init(&ir_builder._arena, "Ir builder arena"_s); + ir_builder.arena = &ir_builder._arena; + + Ir_Builder *ir = &ir_builder; + For_Named(pctx->ordered_decls, ast){ + switch(ast->kind){ + CASE(LAMBDA, Decl){ + Ir_Call *call = ir->calls.allocate(ir->arena); + call->decl = node; + // @todo multiple return values + call->return_value.type = node->lambda->ret[0]->resolved_type; + call->free_registers = array_make(ir->arena, 32); + call->used_registers = array_make(ir->arena, 32); + + For_It(node->lambda->args){ + Ir_Var *arg = call->args.allocate(ir->arena); + arg->decl = *it.it; + arg->call = call; + arg->storage.kind = STORAGE_REGISTER; + arg->storage.register_index = allocate_register(call); + } + + // @todo: Allocate all variables in function + // + // + + For(node->lambda->scope->stmts){ + CASE(VAR, Decl){ + + + + BREAK(); + } + } + + BREAK(); + } + + CASE(VAR, Decl){ + if(is_flag_set(node->flags, AST_FOREIGN)){ + break; // @todo + } + if(!is_flag_set(node->flags, AST_VAR_IS_CONST)){ + compiler_error(node->pos, "Global variable has value assigned that is not constant and requires computation"); + } + + Ir_Var *v = ir->global_variables.allocate(ir->arena); + v->decl = node; + v->storage.kind = STORAGE_GLOBAL; + v->storage.type = node->type; + if(node->type->size <= 8){ + switch(node->type->kind){ + CASE_UINT: v->storage.constant.u64 = bigint_as_unsigned(&node->big_int_val); break; + CASE_SINT: v->storage.constant.s64 = bigint_as_signed(&node->big_int_val); break; + CASE_FLOAT: v->storage.constant.f64 = node->f64_val; break; + invalid_default_case; + } + } + else { + // Doesn't fit in register + invalid_codepath; + } + + BREAK(); + } + default: {}; + } + } +} \ No newline at end of file diff --git a/main.cpp b/main.cpp index 19d2a64..ab3eba1 100644 --- a/main.cpp +++ b/main.cpp @@ -171,7 +171,7 @@ want to export all the symbols, we can namespace them optionally. #include "c_language_codegen.cpp" #include "intermediate_representation.cpp" // #include "bytecode_interpreter.cpp" -// #include "bytecode_codegen.cpp" +#include "bytecode_codegen.cpp" int main(int argument_count, char **arguments){ @@ -236,6 +236,7 @@ int main(int argument_count, char **arguments){ arena_clear(&pctx->stage_arena); + build_bytecode(); // compile_to_bc(); // __debugbreak(); String result = get_compilation_result();