aboutsummaryrefslogtreecommitdiffstats
path: root/src/ir.h
blob: d5b167efc161a910804280eb5f6608632910429b (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
#ifndef BDL_IR_H
#define BDL_IR_H

typedef enum Operator {
    // Arithmetic ops.
    OP_ADD,
    OP_SUB,
    OP_MUL,
    OP_DIV,
    OP_MOD,

    // Load/store/copy operations.
    OP_LD8,
    OP_LD16,
    OP_LD32,
    OP_LD64,
    OP_ST8,
    OP_ST16,
    OP_ST32,
    OP_ST64,
    OP_CP8,
    OP_CP16,
    OP_CP32,
    OP_CP64,

    // Bit fiddling operations.
    OP_NOT,
    OP_AND,
    OP_OR,
    OP_XOR,
    OP_LSHIFT,
    OP_RSHIFT,
    OP_LROT,
    OP_RROT,

    // (Un)conditional jump operations.
    OP_LABEL,
    OP_JMP,
    OP_JMP_EQ,
    OP_JMP_NEQ,
    OP_JMP_GT,
    OP_JMP_LT,
    OP_JMP_GE,
    OP_JMP_LE,
} Operator;

typedef enum OperandType {
    OP_TYPE_REG,
    OP_TYPE_CONST,
    OP_TYPE_LABEL,
} OperandType;

#define NEW_REG()  (Operand){ .type = OP_TYPE_REG, .id = reg_gen_id++ }
#define NEW_LAB()  (Operand){ .type = OP_TYPE_LABEL, .id = lab_gen_id++ }
#define NEW_S64(C) (Operand){ .type = OP_TYPE_CONST, .constant.sval = (C) }
#define EMIT_0(PROGRAM, LINE, OP, DST) do {   \
        Instruction inst = (Instruction){     \
            .op = (OP),                       \
            .dst = (DST),                     \
        };                                    \
        array_push((PROGRAM)->inst, inst);    \
        array_push((PROGRAM)->lines, (LINE)); \
    } while(false);
#define EMIT_1(PROGRAM, LINE, OP, DST, A) do { \
        Instruction inst = (Instruction){      \
            .op = (OP),                        \
            .dst = (DST),                      \
            .src_a = (A),                      \
        };                                     \
        array_push((PROGRAM)->inst, inst);     \
        array_push((PROGRAM)->lines, (LINE));  \
    } while(false);
#define EMIT_2(PROGRAM, LINE, OP, DST, A, B) do { \
        Instruction inst = (Instruction){         \
            .op = (OP),                           \
            .dst = (DST),                         \
            .src_a = (A),                         \
            .src_b = (B),                         \
        };                                        \
        array_push((PROGRAM)->inst, inst);        \
        array_push((PROGRAM)->lines, (LINE));     \
    } while(false);

typedef struct Operand {
    OperandType type;
    union {
        // REG/LABEL
        size_t id;

        // s64 constant;
        struct {
            union {
                u64 uval;
                s64 sval;
            };
        } constant;
    };
} Operand;

typedef struct Instruction {
    Operator op;
    Operand dst;
    Operand src_a;
    Operand src_b;
} Instruction;

typedef struct LineInfo {
    size_t line;
    size_t col;
} LineInfo;

typedef struct ProgramBASM {
    Instruction *inst;
    LineInfo *lines;
} ProgramBASM;

Operand emit_basm(ProgramBASM *program, Node *node);

#endif // BDL_IR_H