Reworking ir stuff
This commit is contained in:
@@ -1,194 +0,0 @@
|
||||
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: {};
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user