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