From df640dc7f55fef962b598562e10d8dd4d60fedc0 Mon Sep 17 00:00:00 2001
From: dec05eba <dec05eba@protonmail.com>
Date: Wed, 21 Aug 2019 07:02:02 +0200
Subject: Code cleanup in ssa/bytecode. Remove ugly memcpy

---
 src/bytecode/bytecode.c | 237 +++++-------------------------------------------
 src/ssa/ssa.c           | 117 ++++++++++++------------
 src/std/buffer.c        |   7 +-
 src/std/hash_map.c      |   1 +
 4 files changed, 86 insertions(+), 276 deletions(-)

(limited to 'src')

diff --git a/src/bytecode/bytecode.c b/src/bytecode/bytecode.c
index 8daa4ce..80cc95b 100644
--- a/src/bytecode/bytecode.c
+++ b/src/bytecode/bytecode.c
@@ -23,49 +23,9 @@ int bytecode_init(Bytecode *self, ArenaAllocator *allocator) {
     return buffer_init(&self->data, allocator);
 }
 
-static CHECK_RESULT usize ssa_extract_form1(u8 *instruction_data, SsaInsForm1 *result) {
-    am_memcpy(&result->lhs, instruction_data, sizeof(result->lhs));
-    am_memcpy(&result->rhs, instruction_data + sizeof(result->lhs), sizeof(result->rhs));
-    return sizeof(result->lhs) + sizeof(result->rhs);
-}
-
-static CHECK_RESULT usize ssa_extract_form2(u8 *instruction_data, SsaInsForm2 *result) {
-    am_memcpy(&result->result, instruction_data, sizeof(result->result));
-    am_memcpy(&result->lhs, instruction_data + sizeof(result->result), sizeof(result->lhs));
-    am_memcpy(&result->rhs, instruction_data + sizeof(result->result) + sizeof(result->lhs), sizeof(result->rhs));
-    return sizeof(result->result) + sizeof(result->lhs) + sizeof(result->rhs);
-}
-
-static CHECK_RESULT usize ssa_extract_func_start(u8 *instruction_data, SsaInsFuncStart *result) {
-    am_memcpy(&result->func_index, instruction_data, sizeof(result->func_index));
-    am_memcpy(&result->num_params_regs, instruction_data + sizeof(result->func_index), sizeof(result->num_params_regs));
-    am_memcpy(&result->num_local_vars_regs, instruction_data + sizeof(result->func_index) + sizeof(result->num_params_regs), sizeof(result->num_local_vars_regs));
-    return sizeof(result->func_index) + sizeof(result->num_params_regs) + sizeof(result->num_local_vars_regs);
-}
-
-static CHECK_RESULT usize ssa_extract_func_call(u8 *instruction_data, SsaInsFuncCall *result) {
-    result->num_args = instruction_data[0];
-    am_memcpy(&result->result, instruction_data + 1, sizeof(result->result));
-    am_memcpy(&result->func_decl, instruction_data + 1 + sizeof(result->result), sizeof(result->func_decl));
-    return sizeof(u8) + sizeof(result->result) + sizeof(result->func_decl);
-}
-
-static CHECK_RESULT usize ssa_extract_func_call_extern(u8 *instruction_data, SsaInsFuncCallExtern *result) {
-    result->num_args = instruction_data[0];
-    am_memcpy(&result->result, instruction_data + 1, sizeof(result->result));
-    am_memcpy(&result->extern_func_index, instruction_data + 1 + sizeof(result->result), sizeof(result->extern_func_index));
-    return sizeof(u8) + sizeof(result->result) + sizeof(result->extern_func_index);
-}
-
-static CHECK_RESULT usize ssa_extract_jump_zero(u8 *instruction_data, SsaInsJumpZero *result) {
-    am_memcpy(&result->condition_reg, instruction_data, sizeof(result->condition_reg));
-    am_memcpy(&result->jump_offset, instruction_data + sizeof(result->condition_reg), sizeof(result->jump_offset));
-    return sizeof(result->condition_reg) + sizeof(result->jump_offset);
-}
-
-static CHECK_RESULT usize ssa_extract_jump(u8 *instruction_data, SsaInsJump *result) {
-    am_memcpy(&result->jump_offset, instruction_data, sizeof(result->jump_offset));
-    return sizeof(result->jump_offset);
+static CHECK_RESULT usize ssa_extract_data(u8 *instruction_data, void *result, usize size) {
+    am_memcpy(result, instruction_data, size);
+    return size;
 }
 
 static void add_intermediates(BytecodeCompilerContext *self) {
@@ -328,10 +288,6 @@ static void add_instructions(BytecodeCompilerContext *self) {
         |Instruction|Instructions data|The instructions data. Each instructions begins with an opcode, see #Opcode|
     */
 
-    Ssa *ssa;
-    u8 *instruction;
-    u8 *instructions_end;
-
     SsaInsForm1 ssa_ins_form1;
     SsaInsForm2 ssa_ins_form2;
     SsaInsFuncStart ssa_ins_func_start;
@@ -340,210 +296,69 @@ static void add_instructions(BytecodeCompilerContext *self) {
     SsaInsJumpZero ssa_ins_jump_zero;
     SsaInsJump ssa_ins_jump;
 
-    FILE *file;
-    char *filename;
+    Ssa *ssa = self->parser->ssa;
+    u8 *instruction = buffer_begin(&ssa->instructions);
+    u8 *instructions_end = buffer_end(&ssa->instructions);
 
-    u32 num_instructions_index;
-    num_instructions_index = self->bytecode.data.size;
+    u32 num_instructions_index = self->bytecode.data.size;
     throw_if_error(buffer_append_empty(&self->bytecode.data, sizeof(num_instructions_index)));
-    #ifdef COMPILE_TO_C
-    LhsExpr *reg_types[NUM_MAX_REGS]; /* TODO: Remove this. Encode this data in the register itself */
-    SsaRegister func_arg_stack[NUM_MAX_FUNC_ARGS]; /* TODO: Remove this? */
-    int func_arg_index;
-    #endif
-
-    ssa = self->parser->ssa;
-    instruction = buffer_begin(&ssa->instructions);
-    instructions_end = buffer_end(&ssa->instructions);
-    /*#warning "dont forget to remove this" */
-    filename = malloc(self->parser->tokenizer.code_name.size + 3);
-    filename[0] = '\0';
-    strcat(filename, self->parser->tokenizer.code_name.data);
-    strcat(filename, ".z");
-    file = fopen(filename, "wb");
-    free(filename);
-    #ifdef COMPILE_TO_C
-    #ifdef DEBUG
-    am_memset(reg_types, 0, sizeof(reg_types));
-    #endif
-    func_arg_index = 0;
-
-    fputs("typedef i64 signed long long;\n", file);
-    fputs("typedef f64 double;\n", file);
-
-    #define ARITH_OP(op) do {\
-        const char *rhs_type_name; \
-        instruction += ssa_extract_form2(instruction, &ssa_ins_form2); \
-        assert(ssa_ins_form2.result < NUM_MAX_REGS); \
-        assert(ssa_ins_form2.lhs < NUM_MAX_REGS); \
-        rhs_type_name = lhs_expr_get_c_name(self, reg_types[ssa_ins_form2.lhs]); \
-        fprintf(file, "%s r%d = r%d %s r%d;\n", rhs_type_name, ssa_ins_form2.result, ssa_ins_form2.lhs, (op), ssa_ins_form2.rhs); \
-        reg_types[ssa_ins_form2.result] = reg_types[ssa_ins_form2.lhs]; \
-    } while(0)
-
-    while(instruction != instructions_end) {
-        switch((SsaInstruction)*instruction++) {
-            case SSA_ASSIGN_INTER: {
-                SsaNumber number;
-                instruction += ssa_extract_form1(instruction, &ssa_ins_form1);
-                number = ssa_get_intermediate(ssa, ssa_ins_form1.rhs);
-                assert(ssa_ins_form1.lhs < NUM_MAX_REGS);
-                if(number.type == SSA_NUMBER_TYPE_INTEGER) {
-                    fprintf(file, "i64 r%d = %zu;\n", ssa_ins_form1.lhs, number.value.integer);
-                    reg_types[ssa_ins_form1.lhs] = self->parser->compiler->default_types.i64;
-                } else if(number.type == SSA_NUMBER_TYPE_FLOAT) {
-                    fprintf(file, "f64 r%d = %f;\n", ssa_ins_form1.lhs, number.value.floating);
-                    reg_types[ssa_ins_form1.lhs] = self->parser->compiler->default_types.f64;
-                } else {
-                    assert(bool_false && "TODO: Implement");
-                }
-                break;
-            }
-            case SSA_ASSIGN_STRING: {
-                BufferView str;
-                instruction += ssa_extract_form1(instruction, &ssa_ins_form1);
-                str = ssa_get_string(ssa, ssa_ins_form1.rhs);
-                fprintf(file, "const char* r%d = \"%.*s\";\n", ssa_ins_form1.lhs, (int)str.size, str.data);
-                assert(ssa_ins_form1.lhs < NUM_MAX_REGS);
-                reg_types[ssa_ins_form1.lhs] = self->parser->compiler->default_types.str;
-                break;
-            }
-            case SSA_ASSIGN_REG: {
-                const char *rhs_type_name;
-                instruction += ssa_extract_form1(instruction, &ssa_ins_form1);
-                assert(ssa_ins_form1.rhs < NUM_MAX_REGS);
-                rhs_type_name = lhs_expr_get_c_name(self, reg_types[ssa_ins_form1.rhs]);
-                fprintf(file, "%s r%d = r%d;\n", rhs_type_name, ssa_ins_form1.lhs, ssa_ins_form1.rhs);
-                reg_types[ssa_ins_form1.lhs] = reg_types[ssa_ins_form1.rhs];
-                break;
-            }
-            case SSA_ADD: {
-                ARITH_OP("+");
-                break;
-            }
-            case SSA_SUB: {
-                ARITH_OP("-");
-                break;
-            }
-            case SSA_MUL: {
-                ARITH_OP("*");
-                break;
-            }
-            case SSA_DIV: {
-                ARITH_OP("/");
-                break;
-            }
-            case SSA_EQUALS: {
-                ARITH_OP("==");
-                break;
-            }
-            case SSA_FUNC_START: {
-                int i;
-                instruction += ssa_extract_func_start(instruction, &ssa_ins_func_start);
-                fprintf(file, "void f%zu(", ssa_ins_func_start.func_index);
-                fputs(") {\n", file);
-                for(i = 0; i < ssa_ins_func_start.num_args; ++i) {
-                    if(i > 0)
-                        fputs(", ", file);
-                    fprintf(file, "p%d", i);
-                }
-                break;
-            }
-            case SSA_FUNC_END:
-                fputs("}\n", file);
-                break;
-            case SSA_PUSH: {
-                SsaRegister reg;
-                am_memcpy(&reg, instruction, sizeof(SsaRegister));
-                instruction += sizeof(SsaRegister);
-                assert(func_arg_index < NUM_MAX_FUNC_ARGS);
-                func_arg_stack[func_arg_index++] = reg;
-                break;
-            }
-            case SSA_CALL: {
-                int i;
-                instruction += ssa_extract_func_call(instruction, &ssa_ins_func_call);
-                fprintf(file, "r%d = f%p(", ssa_ins_func_call.result, ssa_ins_func_call.func_decl);
-                for(i = 0; i < func_arg_index; ++i) {
-                    if(i > 0)
-                        fputs(", ", file);
-                    fprintf(file, "r%d", func_arg_stack[i]);
-                }
-                func_arg_index = 0;
-                fputs(");\n", file);
-                break;
-            }
-            case SSA_JUMP_ZERO: {
-                assert(bool_false && "Not implemented!");
-                instruction += ssa_extract_jump_zero(instruction, &ssa_ins_jump_zero);
-                break;
-            }
-            case SSA_JUMP: {
-                assert(bool_false && "Not implemented!");
-                instruction += ssa_extract_jump(instruction, &ssa_ins_jump);
-                break;
-            }
-        }
-    }
-    #else
 
     /* TODO: Keep all registers under 256 */
-
     while(instruction != instructions_end) {
         SsaInstruction ins = (SsaInstruction)*instruction++;
         switch(ins) {
             case SSA_ASSIGN_INTER: {
-                instruction += ssa_extract_form1(instruction, &ssa_ins_form1);
+                instruction += ssa_extract_data(instruction, &ssa_ins_form1, sizeof(ssa_ins_form1));
                 add_ins6(self, AMAL_OP_MOVI, ssa_ins_form1.lhs, ssa_ins_form1.rhs, "movi r%d, i%d");
                 break;
             }
             case SSA_ASSIGN_STRING: {
-                instruction += ssa_extract_form1(instruction, &ssa_ins_form1);
+                instruction += ssa_extract_data(instruction, &ssa_ins_form1, sizeof(ssa_ins_form1));
                 add_ins6(self, AMAL_OP_MOVD, ssa_ins_form1.lhs, ssa_ins_form1.rhs, "movd r%d, s%d");
                 break;
             }
             case SSA_ASSIGN_REG: {
-                instruction += ssa_extract_form1(instruction, &ssa_ins_form1);
+                instruction += ssa_extract_data(instruction, &ssa_ins_form1, sizeof(ssa_ins_form1));
                 add_ins3(self, AMAL_OP_MOV, ssa_ins_form1.lhs, ssa_ins_form1.rhs, "mov r%d, r%d");
                 break;
             }
             case SSA_ADD: {
-                instruction += ssa_extract_form2(instruction, &ssa_ins_form2);
+                instruction += ssa_extract_data(instruction, &ssa_ins_form2, sizeof(ssa_ins_form2));
                 add_ins5(self, AMAL_OP_ADD, ssa_ins_form2.result, ssa_ins_form2.lhs, ssa_ins_form2.rhs, "add r%d, r%d, r%d");
                 break;
             }
             case SSA_SUB: {
-                instruction += ssa_extract_form2(instruction, &ssa_ins_form2);
+                instruction += ssa_extract_data(instruction, &ssa_ins_form2, sizeof(ssa_ins_form2));
                 add_ins5(self, AMAL_OP_SUB, ssa_ins_form2.result, ssa_ins_form2.lhs, ssa_ins_form2.rhs, "sub r%d, r%d, r%d");
                 break;
             }
             case SSA_IMUL: {
-                instruction += ssa_extract_form2(instruction, &ssa_ins_form2);
+                instruction += ssa_extract_data(instruction, &ssa_ins_form2, sizeof(ssa_ins_form2));
                 add_ins5(self, AMAL_OP_IMUL, ssa_ins_form2.result, ssa_ins_form2.lhs, ssa_ins_form2.rhs, "imul r%d, r%d, r%d");
                 break;
             }
             case SSA_MUL: {
-                instruction += ssa_extract_form2(instruction, &ssa_ins_form2);
+                instruction += ssa_extract_data(instruction, &ssa_ins_form2, sizeof(ssa_ins_form2));
                 add_ins5(self, AMAL_OP_MUL, ssa_ins_form2.result, ssa_ins_form2.lhs, ssa_ins_form2.rhs, "mul r%d, r%d, r%d");
                 break;
             }
             case SSA_IDIV: {
-                instruction += ssa_extract_form2(instruction, &ssa_ins_form2);
+                instruction += ssa_extract_data(instruction, &ssa_ins_form2, sizeof(ssa_ins_form2));
                 add_ins5(self, AMAL_OP_IDIV, ssa_ins_form2.result, ssa_ins_form2.lhs, ssa_ins_form2.rhs, "idiv r%d, r%d, r%d");
                 break;
             }
             case SSA_DIV: {
-                instruction += ssa_extract_form2(instruction, &ssa_ins_form2);
+                instruction += ssa_extract_data(instruction, &ssa_ins_form2, sizeof(ssa_ins_form2));
                 add_ins5(self, AMAL_OP_DIV, ssa_ins_form2.result, ssa_ins_form2.lhs, ssa_ins_form2.rhs, "div r%d, r%d, r%d");
                 break;
             }
             case SSA_EQUALS: {
-                instruction += ssa_extract_form2(instruction, &ssa_ins_form2);
+                instruction += ssa_extract_data(instruction, &ssa_ins_form2, sizeof(ssa_ins_form2));
                 add_ins5(self, AMAL_OP_CMP, ssa_ins_form2.result, ssa_ins_form2.lhs, ssa_ins_form2.rhs, "cmp r%d, r%d, r%d");
                 break;
             }
             case SSA_FUNC_START: {
-                instruction += ssa_extract_func_start(instruction, &ssa_ins_func_start);
+                instruction += ssa_extract_data(instruction, &ssa_ins_func_start, sizeof(ssa_ins_func_start));
                 add_ins6(self, AMAL_OP_FUNC_START, ssa_ins_func_start.num_params_regs, ssa_ins_func_start.num_local_vars_regs, "func_start %d, %u");
                 break;
             }
@@ -567,22 +382,22 @@ static void add_instructions(BytecodeCompilerContext *self) {
                     the function indices can be increased by their block index (ssa_func_index + block index), where block index
                     is defined as the size of all previous files' number of functions.
                 */
-                instruction += ssa_extract_func_call(instruction, &ssa_ins_func_call);
+                instruction += ssa_extract_data(instruction, &ssa_ins_func_call, sizeof(ssa_ins_func_call));
                 add_ins7(self, AMAL_OP_CALL, ssa_ins_func_call.func_decl->ssa_func_index, ssa_ins_func_call.num_args, ssa_ins_func_call.result, "call f%d, %d, r%d");
                 break;
             }
             case SSA_CALL_EXTERN: {
-                instruction += ssa_extract_func_call_extern(instruction, &ssa_ins_func_call_extern);
+                instruction += ssa_extract_data(instruction, &ssa_ins_func_call_extern, sizeof(ssa_ins_func_call_extern));
                 add_ins7(self, AMAL_OP_CALLE, ssa_ins_func_call_extern.extern_func_index, ssa_ins_func_call_extern.num_args, ssa_ins_func_call_extern.result, "calle ef%d, %d, r%d");
                 break;
             }
             case SSA_JUMP_ZERO: {
-                instruction += ssa_extract_jump_zero(instruction, &ssa_ins_jump_zero);
+                instruction += ssa_extract_data(instruction, &ssa_ins_jump_zero, sizeof(ssa_ins_jump_zero));
                 add_ins6(self, AMAL_OP_JZ, ssa_ins_jump_zero.condition_reg, ssa_ins_jump_zero.jump_offset, "jz r%d, %d");
                 break;
             }
             case SSA_JUMP: {
-                instruction += ssa_extract_jump(instruction, &ssa_ins_jump);
+                instruction += ssa_extract_data(instruction, &ssa_ins_jump, sizeof(ssa_ins_jump));
                 add_ins4(self, AMAL_OP_JMP, ssa_ins_jump.jump_offset, "jmp %d");
                 break;
             }
@@ -598,14 +413,10 @@ static void add_instructions(BytecodeCompilerContext *self) {
 
     /* Prepend instructions with its size */
     {
-        u32 instructions_size;
         /* -sizeof to Remove the count itself from the size of the instructions size */
-        instructions_size = self->bytecode.data.size - num_instructions_index - sizeof(instructions_size);
-        am_memcpy(&self->bytecode.data.data[num_instructions_index], &instructions_size, sizeof(instructions_size));
+        const u32 instructions_size = self->bytecode.data.size - num_instructions_index - sizeof(instructions_size);
+        am_memcpy(self->bytecode.data.data + num_instructions_index, &instructions_size, sizeof(instructions_size));
     }
-
-    #endif /* COMPILE_TO_C */
-    fclose(file);
 }
 
 void generate_bytecode_from_ssa(BytecodeCompilerContext *self) {
diff --git a/src/ssa/ssa.c b/src/ssa/ssa.c
index 01c4f0f..39b5a80 100644
--- a/src/ssa/ssa.c
+++ b/src/ssa/ssa.c
@@ -193,12 +193,11 @@ static CHECK_RESULT int ssa_try_add_extern_func(Ssa *self, FunctionSignature *fu
 }
 
 static CHECK_RESULT int ssa_add_ins_form1(Ssa *self, SsaInstruction ins_type, SsaRegister lhs, u16 rhs) {
-    const usize index = self->instructions.size;
-    return_if_error(buffer_append_empty(&self->instructions, sizeof(u8) + sizeof(SsaRegister) + sizeof(u16)));
-    self->instructions.data[index + 0] = ins_type;
-    am_memcpy(self->instructions.data + index + 1, &lhs, sizeof(lhs));
-    am_memcpy(self->instructions.data + index + 3, &rhs, sizeof(rhs));
-    return 0;
+    SsaInsForm1 ins_form_1;
+    ins_form_1.lhs = lhs;
+    ins_form_1.rhs = rhs;
+    return_if_error(buffer_append(&self->instructions, &ins_type, 1));
+    return buffer_append(&self->instructions, &ins_form_1, sizeof(ins_form_1));
 }
 
 static const char* binop_type_to_string(SsaInstruction binop_type) {
@@ -214,15 +213,14 @@ static const char* binop_type_to_string(SsaInstruction binop_type) {
 }
 
 static CHECK_RESULT int ssa_add_ins_form2(Ssa *self, SsaInstruction ins_type, SsaRegister lhs, SsaRegister rhs, SsaRegister *result) {
-    const usize index = self->instructions.size;
+    SsaInsForm2 ins_form_2;
     return_if_error(ssa_get_unique_reg(self, result));
-    return_if_error(buffer_append_empty(&self->instructions, sizeof(u8) + sizeof(SsaRegister) + sizeof(SsaRegister) + sizeof(SsaRegister)));
-    self->instructions.data[index + 0] = ins_type;
-    am_memcpy(self->instructions.data + index + 1, result, sizeof(SsaRegister));
-    am_memcpy(self->instructions.data + index + 3, &lhs, sizeof(lhs));
-    am_memcpy(self->instructions.data + index + 5, &rhs, sizeof(rhs));
+    ins_form_2.result = *result;
+    ins_form_2.lhs = lhs;
+    ins_form_2.rhs = rhs;
     amal_log_debug("r%d = r%d %s r%d", *result, lhs, binop_type_to_string(ins_type), rhs);
-    return 0;
+    return_if_error(buffer_append(&self->instructions, &ins_type, 1));
+    return buffer_append(&self->instructions, &ins_form_2, sizeof(ins_form_2));
 }
 
 static CHECK_RESULT int ssa_ins_assign_inter(Ssa *self, SsaRegister dest, SsaNumber number) {
@@ -250,7 +248,8 @@ static CHECK_RESULT int ssa_ins_binop(Ssa *self, SsaInstruction binop_type, SsaR
 }
 
 static CHECK_RESULT int ssa_ins_func_start(Ssa *self, SsaRegister num_reg_params, SsaFuncIndex *result, usize *func_metadata_index) {
-    const usize index = self->instructions.size;
+    const u8 ins_type = SSA_FUNC_START;
+    SsaInsFuncStart ins_func_start;
 
     /* Overflow */
     if(self->func_counter + 1 <= self->func_counter) {
@@ -258,86 +257,82 @@ static CHECK_RESULT int ssa_ins_func_start(Ssa *self, SsaRegister num_reg_params
         return -1;
     }
 
-    return_if_error(buffer_append_empty(&self->instructions, sizeof(u8) + sizeof(SsaFuncIndex) + sizeof(SsaRegister) + sizeof(u16)));
     *result = self->func_counter++;
-    self->instructions.data[index + 0] = SSA_FUNC_START;
-    am_memcpy(self->instructions.data + index + 1, result, sizeof(SsaFuncIndex));
-    am_memcpy(self->instructions.data + index + 1 + sizeof(SsaFuncIndex), &num_reg_params, sizeof(SsaRegister));
-    *func_metadata_index = index + 1 + sizeof(SsaFuncIndex) + sizeof(num_reg_params);
-    /* No need to add data to instructions.data here, it can contain undefined data until we set it (@ the caller) */
+    ins_func_start.func_index = *result;
+    ins_func_start.num_params_regs = num_reg_params;
+    /* Dont set number of local registers yet. That will be set by @func_metadata_index later when it's known */
+    /*ins_func_start.num_local_vars_regs = ---*/
+    return_if_error(buffer_append(&self->instructions, &ins_type, 1));
+    return_if_error(buffer_append(&self->instructions, &ins_func_start, sizeof(ins_func_start)));
+    *func_metadata_index = self->instructions.size - sizeof(ins_func_start.num_local_vars_regs);
     amal_log_debug("FUNC_START f%u, %d", *result, num_reg_params);
     return 0;
 }
 
 static CHECK_RESULT int ssa_ins_func_end(Ssa *self) {
-    const u8 ins = SSA_FUNC_END;
+    const u8 ins_type = SSA_FUNC_END;
     amal_log_debug("FUNC_END");
-    return buffer_append(&self->instructions, &ins, 1);
+    return buffer_append(&self->instructions, &ins_type, 1);
 }
 
 static CHECK_RESULT int ssa_ins_push(Ssa *self, SsaRegister reg) {
-    const usize index = self->instructions.size;
-    return_if_error(buffer_append_empty(&self->instructions, sizeof(u8) + sizeof(SsaRegister)));
-    self->instructions.data[index + 0] = SSA_PUSH;
-    am_memcpy(self->instructions.data + index + 1, &reg, sizeof(SsaRegister));
+    const u8 ins_type = SSA_PUSH;
     amal_log_debug("PUSH r%d", reg);
-    return 0;
+    return_if_error(buffer_append(&self->instructions, &ins_type, 1));
+    return buffer_append(&self->instructions, &reg, sizeof(reg));
 }
 
 static CHECK_RESULT int ssa_ins_call(Ssa *self, FunctionDecl *func_decl, u8 num_args, SsaRegister *result) {
-    const usize index = self->instructions.size;
+    const u8 ins_type = SSA_CALL;
+    SsaInsFuncCall ins_func_call;
     return_if_error(ssa_get_unique_reg(self, result));
-    return_if_error(buffer_append_empty(&self->instructions, sizeof(u8) + sizeof(u8) + sizeof(SsaRegister) + sizeof(func_decl)));
-    self->instructions.data[index + 0] = SSA_CALL;
-    self->instructions.data[index + 1] = num_args;
-    am_memcpy(self->instructions.data + index + 2, result, sizeof(SsaRegister));
-    am_memcpy(self->instructions.data + index + 2 + sizeof(SsaRegister), &func_decl, sizeof(func_decl));
+    ins_func_call.num_args = num_args;
+    ins_func_call.result = *result;
+    ins_func_call.func_decl = func_decl;
     amal_log_debug("r%d = CALL %d, %p", *result, num_args, func_decl);
-    return 0;
+    return_if_error(buffer_append(&self->instructions, &ins_type, 1));
+    return buffer_append(&self->instructions, &ins_func_call, sizeof(ins_func_call));
 }
 
 static CHECK_RESULT int ssa_ins_call_extern(Ssa *self, SsaExternFuncIndex extern_func_index, u8 num_args, SsaRegister *result) {
-    const usize index = self->instructions.size;
-    assert(extern_func_index < self->extern_func_counter);
+    const u8 ins_type = SSA_CALL_EXTERN;
+    SsaInsFuncCallExtern ins_func_call_extern;
     return_if_error(ssa_get_unique_reg(self, result));
-    return_if_error(buffer_append_empty(&self->instructions, sizeof(u8) + sizeof(u8) + sizeof(SsaRegister) + sizeof(extern_func_index)));
-    self->instructions.data[index + 0] = SSA_CALL_EXTERN;
-    self->instructions.data[index + 1] = num_args;
-    am_memcpy(self->instructions.data + index + 2, result, sizeof(SsaRegister));
-    am_memcpy(self->instructions.data + index + 2 + sizeof(SsaRegister), &extern_func_index, sizeof(extern_func_index));
+    assert(extern_func_index < self->extern_func_counter);
+    ins_func_call_extern.num_args = num_args;
+    ins_func_call_extern.result = *result;
+    ins_func_call_extern.extern_func_index = extern_func_index;
     amal_log_debug("r%d = CALL_EXTERN %d, %d", *result, num_args, extern_func_index);
-    return 0;
+    return_if_error(buffer_append(&self->instructions, &ins_type, 1));
+    return buffer_append(&self->instructions, &ins_func_call_extern, sizeof(ins_func_call_extern));
 }
 
 static CHECK_RESULT int ssa_ins_jumpzero(Ssa *self, SsaRegister condition_reg, JumpOffset jump_offset) {
-    const usize index = self->instructions.size;
-
-    return_if_error(buffer_append_empty(&self->instructions, sizeof(u8) + sizeof(SsaRegister) + sizeof(JumpOffset)));
-    self->instructions.data[index + 0] = SSA_JUMP_ZERO;
-    am_memcpy(self->instructions.data + index + 1, &condition_reg, sizeof(SsaRegister));
-    am_memcpy(self->instructions.data + index + 1 + sizeof(SsaRegister), &jump_offset, sizeof(JumpOffset));
+    const u8 ins_type = SSA_JUMP_ZERO;
+    SsaInsJumpZero ins_jump_zero;
+    ins_jump_zero.condition_reg = condition_reg;
+    ins_jump_zero.jump_offset = jump_offset;
     if(jump_offset == 0)
         amal_log_debug("JUMP_ZERO r%d, DUMMY", condition_reg);
     else
         amal_log_debug("JUMP_ZERO r%d, %d", condition_reg, jump_offset);
-    return 0;
+    return_if_error(buffer_append(&self->instructions, &ins_type, 1));
+    return buffer_append(&self->instructions, &ins_jump_zero, sizeof(ins_jump_zero));
 }
 
 static CHECK_RESULT int ssa_ins_jump(Ssa *self, JumpOffset jump_offset) {
-    const usize index = self->instructions.size;
-    return_if_error(buffer_append_empty(&self->instructions, sizeof(u8) + sizeof(JumpOffset)));
-    self->instructions.data[index + 0] = SSA_JUMP;
-    am_memcpy(self->instructions.data + index + 1, &jump_offset, sizeof(JumpOffset));
+    const u8 ins_type = SSA_JUMP;
+    SsaInsJump ins_jump;
+    ins_jump.jump_offset = jump_offset;
     amal_log_debug("JUMP %d", jump_offset);
-    return 0;
+    return_if_error(buffer_append(&self->instructions, &ins_type, 1));
+    return buffer_append(&self->instructions, &ins_jump, sizeof(ins_jump));
 }
 
 static CHECK_RESULT int ssa_ins_return(Ssa *self, SsaRegister reg) {
-    const usize index = self->instructions.size;
-    return_if_error(buffer_append_empty(&self->instructions, sizeof(u8) + sizeof(SsaRegister)));
-    self->instructions.data[index + 0] = SSA_RET;
-    am_memcpy(self->instructions.data + index + 1, &reg, sizeof(SsaRegister));
-    return 0;
+    const u8 ins_type = SSA_RET;
+    return_if_error(buffer_append(&self->instructions, &ins_type, 1));
+    return buffer_append(&self->instructions, &reg, sizeof(reg));
 }
 
 static usize ssa_ins_get_index(Ssa *self) {
@@ -352,9 +347,9 @@ static CHECK_RESULT int ssa_ins_jump_set_target(Ssa *self, usize jump_ins_index)
             /* TODO: Should something be done about this? */
             if(jump_offset < -0x7FFF || jump_offset > 0x7FFF) {
                 amal_log_error("Unexpected error. Jump offset has to be less than +-32767, was %d", jump_offset);
-                return 1;
+                return -1;
             }
-            am_memcpy(self->instructions.data + jump_ins_index + 1 + sizeof(SsaRegister), &jump_offset, sizeof(JumpOffset));
+            am_memcpy(self->instructions.data + jump_ins_index + 1 + offsetof(SsaInsJumpZero, jump_offset), &jump_offset, sizeof(JumpOffset));
             break;
         }
         default:
diff --git a/src/std/buffer.c b/src/std/buffer.c
index 93e8558..a482bb9 100644
--- a/src/std/buffer.c
+++ b/src/std/buffer.c
@@ -37,9 +37,12 @@ static CHECK_RESULT int buffer_ensure_capacity(Buffer *self, usize new_capacity)
     if(capacity == 0) {
         capacity = new_capacity;
     } else {
-        while(capacity < new_capacity) {
-            capacity *= 1.5;
+        double cap = capacity;
+        const double new_cap = new_capacity;
+        while(cap < new_cap) {
+            cap *= 1.5;
         }
+        capacity = cap;
     }
 
     alloc_result = am_realloc(self->data, capacity, &new_mem);
diff --git a/src/std/hash_map.c b/src/std/hash_map.c
index 48e9e38..98ebf40 100644
--- a/src/std/hash_map.c
+++ b/src/std/hash_map.c
@@ -85,6 +85,7 @@ int hash_map_init(HashMap *self, ArenaAllocator *allocator, usize value_type_siz
     return_if_error(buffer_init(&self->buckets, self->allocator));
     assert(self->buckets.size == 0);
     return_if_error(buffer_append_empty(&self->buckets, sizeof(HashMapBucket) * HASH_MAP_INITIAL_SIZE));
+    assert(HASH_MAP_INITIAL_SIZE != 0);
     am_memset(self->buckets.data, 0, self->buckets.size);
     return 0;
 }
-- 
cgit v1.2.3-70-g09d2