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
|
#ifndef AMALGAM_BYTECODE_H
#define AMALGAM_BYTECODE_H
#include "../std/defs.h"
#include "../std/misc.h"
#include "../std/buffer.h"
#include "../defs.h"
#include <setjmp.h>
/*doc(Opcode)
Variable length opcodes. Sizes range from 1 to 4 bytes.
# Instruction formats
Instructions can be in 6 different formats:
1. 1 byte: Opcode
2. 2 bytes: Opcode + register
3. 3 bytes: Opcode + register + register
4. 3 bytes:\
4.1 Opcode + intermediate\
4.2 Opcode + data\
4.3 Opcode + index\
4.4 Opcode + offset
5. 4 bytes: Opcode + register + register + register
6. 4 bytes:\
6.1 Opcode + register + offset\
6.2 Opcode + register + intermediate\
6.3 Opcode + register + data
*/
typedef enum {
AMAL_OP_NOP, /* No operation. This can be used for patching */
AMAL_OP_SETZ, /* setz reg - Set register value to 0 */
AMAL_OP_MOV, /* mov dst, src - move src register to dst register */
AMAL_OP_MOVI, /* movi dst, src - move src intermediate to dst register */
AMAL_OP_MOVD, /* movd dst, src - move src data to dst register */
AMAL_OP_ADD, /* add dst, reg1, reg2 */
AMAL_OP_SUB, /* sub dst, reg1, reg2 */
AMAL_OP_MUL, /* mul dst, reg1, reg2 */
AMAL_OP_DIV, /* div dst, reg1, reg2 */
AMAL_OP_PUSH, /* push reg - Push register onto stack */
AMAL_OP_PUSHI, /* pushi int - Push intermediate onto stack */
AMAL_OP_PUSHD, /* pushd data - Push data onto stack */
AMAL_OP_CALL, /* call fi - Call a function using function index (fi). fi is u16 */
AMAL_OP_CALLR, /* callr reg - Call a function using a register. Used for function pointers */
AMAL_OP_CMP, /* cmp dst, reg1, reg2 - Set dst to 1 if reg1 equals reg2, otherwise set it to 0 */
AMAL_OP_JZ, /* jz reg, offset - jump to offset if reg is zero. offset is i16 */
AMAL_OP_JMP, /* jmp offset - unconditional jump to offset. offset is i16 */
AMAL_OP_RET, /* ret */
AMAL_OP_FUNC_START, /* func_start */
AMAL_OP_FUNC_END /* func_end */
} AmalOpcode;
typedef u8 AmalOpcodeType;
typedef struct {
Buffer/*<headers + instruction data>*/ data;
} Bytecode;
typedef struct {
jmp_buf env;
Bytecode bytecode;
Parser *parser; /* borrowed */
} BytecodeCompilerContext;
CHECK_RESULT int bytecode_init(Bytecode *self, ScopedAllocator *allocator);
/* longjump to self->env on failure */
void generate_bytecode_from_ssa(BytecodeCompilerContext *self);
#endif
|