#ifndef AMALGAM_SSA_H #define AMALGAM_SSA_H #include "../std/buffer.h" #include "../std/hash_map.h" #include "../std/defs.h" #include "../defs.h" #include typedef enum { SSA_ASSIGN_INTER, SSA_ASSIGN_STRING, SSA_ASSIGN_REG, SSA_ADD, SSA_SUB, SSA_MUL, SSA_DIV, SSA_FUNC_START, SSA_FUNC_END, SSA_PUSH, SSA_CALL } SsaInstructionType; typedef enum { SSA_NUMBER_TYPE_INTEGER, SSA_NUMBER_TYPE_FLOAT } SsaNumberType; typedef struct { union { i64 integer; f64 floating; } value; SsaNumberType type; } SsaNumber; typedef u16 SsaRegister; typedef u16 SsaIntermediateIndex; typedef u16 SsaStringIndex; typedef usize SsaFuncIndex; typedef struct { Buffer/*instruction data*/ instructions; HashMap/**/ intermediates; HashMap/**/ strings; SsaIntermediateIndex intermediate_counter; SsaStringIndex string_counter; SsaRegister reg_counter; SsaFuncIndex func_counter; } Ssa; /* None of these functions are thread-safe */ SsaNumber create_ssa_integer(i64 value); SsaNumber create_ssa_float(f64 value); CHECK_RESULT int ssa_init(Ssa *self, ScopedAllocator *allocator); CHECK_RESULT int ssa_get_unique_reg(Ssa *self, SsaRegister *result); CHECK_RESULT int ssa_ins_assign_inter(Ssa *self, SsaRegister dest, SsaNumber number); CHECK_RESULT int ssa_ins_assign_string(Ssa *self, SsaRegister dest, BufferView str); CHECK_RESULT int ssa_ins_assign_reg(Ssa *self, SsaRegister dest, SsaRegister src); CHECK_RESULT int ssa_ins_binop(Ssa *self, SsaInstructionType binop_type, SsaRegister lhs, SsaRegister rhs, SsaRegister *result); CHECK_RESULT int ssa_ins_func_start(Ssa *self, u8 num_args, SsaFuncIndex *result); CHECK_RESULT int ssa_ins_func_end(Ssa *self); CHECK_RESULT int ssa_ins_push(Ssa *self, SsaRegister reg); CHECK_RESULT int ssa_ins_call(Ssa *self, void *func, SsaRegister *result); typedef struct { jmp_buf env; Ssa ssa; } SsaCompilerContext; /* longjump to compiler env on failure */ void scope_generate_ssa(Scope *self, SsaCompilerContext *context); #endif