aboutsummaryrefslogtreecommitdiff
path: root/src/bytecode/bytecode.c
blob: 7feb185fa98a0c8fb98bbabfdb63f4a6d4a4d7b4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include "../../include/bytecode/bytecode.h"
#include "../../include/std/mem.h"
#include "../../include/ssa/ssa.h"
#include "../../include/parser.h"
#include <assert.h>

#define throw(result) do { throw_debug_msg; longjmp(self->env, (result)); } while(0)
#define throw_if_error(result) \
    do { \
        int return_if_result; \
        return_if_result = (result); \
        if((return_if_result) != 0) \
            throw(return_if_result); \
    } while(0)

int bytecode_init(Bytecode *self, ScopedAllocator *allocator) {
    return buffer_init(&self->instructions, 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_args, instruction_data + sizeof(result->func_index), sizeof(result->num_args));
    return sizeof(result->func_index) + sizeof(result->num_args);
}

static CHECK_RESULT usize ssa_extract_func_call(u8 *instruction_data, SsaInsFuncCall *result) {
    am_memcpy(&result->result, instruction_data, sizeof(result->result));
    am_memcpy(&result->func_decl, instruction_data + sizeof(result->result), sizeof(result->func_decl));
    return sizeof(result->result) + sizeof(result->func_decl);
}

static void add_intermediates(BytecodeCompilerContext *self) {
    Ssa *ssa;
    Buffer *instructions;
    SsaNumber *intermediate;
    SsaNumber *intermediates_end;

    ssa = self->parser->ssa;
    instructions = &self->bytecode->instructions;
    intermediate = buffer_begin(&ssa->intermediates);
    intermediates_end = buffer_end(&ssa->intermediates);

    throw_if_error(buffer_expand(instructions,
                                 sizeof(u16) + (sizeof(u8) + sizeof(u64)) * ssa->intermediates.size));
    throw_if_error(buffer_append(instructions, &ssa->intermediates.size, sizeof(u16)));
    for(; intermediate != intermediates_end; ++intermediate) {
        throw_if_error(buffer_append(instructions, &intermediate->type, sizeof(u8)));
        throw_if_error(buffer_append(instructions, &intermediate->value.integer, sizeof(u64)));
    }
}

static void add_instructions(BytecodeCompilerContext *self) {
    Ssa *ssa;
    u8 *instruction;
    u8 *instructions_end;
    SsaInsForm1 ssa_ins_form1;
    SsaInsForm2 ssa_ins_form2;
    SsaInsFuncStart ssa_ins_func_start;
    SsaInsFuncCall ssa_ins_func_call;

    ssa = self->parser->ssa;
    instruction = buffer_begin(&ssa->instructions);
    instructions_end = buffer_end(&ssa->instructions);

    while(instruction != instructions_end) {
        switch(*instruction++) {
            case SSA_ASSIGN_INTER: {
                SsaNumber number;
                instruction += ssa_extract_form1(instruction, &ssa_ins_form1);
                number = ssa_get_intermediate(ssa, ssa_ins_form1.rhs);
                (void)number;
                break;
            }
            case SSA_ASSIGN_STRING:
                instruction += ssa_extract_form1(instruction, &ssa_ins_form1);
                break;
            case SSA_ASSIGN_REG:
                instruction += ssa_extract_form1(instruction, &ssa_ins_form1);
                break;
            case SSA_ADD:
                instruction += ssa_extract_form2(instruction, &ssa_ins_form2);
                break;
            case SSA_SUB:
                instruction += ssa_extract_form2(instruction, &ssa_ins_form2);
                break;
            case SSA_MUL:
                instruction += ssa_extract_form2(instruction, &ssa_ins_form2);
                break;
            case SSA_DIV:
                instruction += ssa_extract_form2(instruction, &ssa_ins_form2);
                break;
            case SSA_FUNC_START:
                instruction += ssa_extract_func_start(instruction, &ssa_ins_func_start);
                break;
            case SSA_FUNC_END:
                break;
            case SSA_PUSH: {
                SsaRegister reg;
                am_memcpy(&reg, instruction, sizeof(SsaRegister));
                instruction += sizeof(SsaRegister);
                break;
            }
            case SSA_CALL:
                instruction += ssa_extract_func_call(instruction, &ssa_ins_func_call);
                break;
        }
    }
}

void generate_bytecode_from_ssa(BytecodeCompilerContext *self) {
    add_intermediates(self);
    add_instructions(self);
}