Trying to do some ir stuff
This commit is contained in:
194
bytecode_codegen.cpp
Normal file
194
bytecode_codegen.cpp
Normal file
@@ -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<Ir_Instruction, 64> instructions;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Ir_Call;
|
||||||
|
struct Ir_Var{
|
||||||
|
Ast_Decl *decl;
|
||||||
|
Ir_Storage storage;
|
||||||
|
Ir_Call *call;
|
||||||
|
Simple_Bucket_Array<Ir_Block, 16> blocks;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Ir_Call{
|
||||||
|
Ast_Decl *decl;
|
||||||
|
|
||||||
|
Array<Register_Index> used_registers;
|
||||||
|
Array<Register_Index> free_registers;
|
||||||
|
Register_Index register_ids;
|
||||||
|
|
||||||
|
Ir_Storage return_value;
|
||||||
|
Simple_Bucket_Array<Ir_Var, 4> args;
|
||||||
|
Simple_Bucket_Array<Ir_Block, 8> blocks;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Ir_Builder{
|
||||||
|
#define IR_NEW(T) exp_alloc_type(ir->arena, T, AF_ZeroMemory)
|
||||||
|
Arena _arena;
|
||||||
|
Arena *arena;
|
||||||
|
|
||||||
|
Simple_Bucket_Array<Ir_Var, 32> global_variables;
|
||||||
|
Simple_Bucket_Array<Ir_Call, 64> 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<Register_Index>(ir->arena, 32);
|
||||||
|
call->used_registers = array_make<Register_Index>(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: {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
3
main.cpp
3
main.cpp
@@ -171,7 +171,7 @@ want to export all the symbols, we can namespace them optionally.
|
|||||||
#include "c_language_codegen.cpp"
|
#include "c_language_codegen.cpp"
|
||||||
#include "intermediate_representation.cpp"
|
#include "intermediate_representation.cpp"
|
||||||
// #include "bytecode_interpreter.cpp"
|
// #include "bytecode_interpreter.cpp"
|
||||||
// #include "bytecode_codegen.cpp"
|
#include "bytecode_codegen.cpp"
|
||||||
|
|
||||||
|
|
||||||
int main(int argument_count, char **arguments){
|
int main(int argument_count, char **arguments){
|
||||||
@@ -236,6 +236,7 @@ int main(int argument_count, char **arguments){
|
|||||||
|
|
||||||
|
|
||||||
arena_clear(&pctx->stage_arena);
|
arena_clear(&pctx->stage_arena);
|
||||||
|
build_bytecode();
|
||||||
// compile_to_bc();
|
// compile_to_bc();
|
||||||
// __debugbreak();
|
// __debugbreak();
|
||||||
String result = get_compilation_result();
|
String result = get_compilation_result();
|
||||||
|
|||||||
Reference in New Issue
Block a user