gen/emit.h 4.6 KiB raw
1
#ifndef EMIT_H
2
#define EMIT_H
3
4
#include <stdlib.h>
5
#include <string.h>
6
7
#include "../ast.h"
8
#include "../gen.h"
9
#include "../io.h"
10
#include "../scanner.h"
11
#include "../types.h"
12
13
/* Code emission. */
14
#define emit(g, ins) __emit(g, ins)
15
16
/* Slice field offsets */
17
enum {
18
    SLICE_FIELD_PTR_OFFSET = 0,
19
    SLICE_FIELD_LEN_OFFSET = WORD_SIZE,
20
};
21
22
/* Helper describing the possibly-adjusted base register for stack accesses. */
23
typedef struct {
24
    reg_t base; /* Register that should be used for the access. */
25
    bool  temp; /* Whether `base` was synthesized and must be freed. */
26
} addr_adj_t;
27
28
/* Emit the given instruction. */
29
static inline usize __emit(gen_t *g, instr_t ins) {
30
    if (g->ninstrs >= MAX_INSTRS) {
31
        abort();
32
    }
33
    g->instrs[g->ninstrs] = ins;
34
    g->ninstrs++;
35
36
    return g->ninstrs - 1;
37
}
38
39
/* Split a 32-bit immediate into upper 20 bits and lower 12 bits for RISC-V. */
40
void split_imm(i32 imm, i32 *hi, i32 *lo);
41
/* Emit a load immediate (LI) instruction sequence. */
42
void emit_li(gen_t *g, reg_t rd, i32 imm);
43
/* Helper function to copy register values if needed. */
44
void emit_mv(gen_t *g, reg_t dst, reg_t src);
45
/* Emit relative jump to offset. */
46
usize emit_jump(gen_t *g, usize offset);
47
/* Emit a function call. */
48
usize emit_call(gen_t *g, usize addr);
49
/* Load a PC-relative address into a register. */
50
void emit_pc_rel_addr(gen_t *g, reg_t rd, usize addr);
51
/* Emit code to index into an array */
52
value_t emit_array_index(gen_t *g, value_t array_val, value_t index, bool);
53
/* Load a value into a specific register. */
54
reg_t emit_load_into(gen_t *g, reg_t dst, value_t src);
55
/* Load a value from a value. */
56
reg_t emit_load(gen_t *g, value_t v);
57
/* Load a word from a value. */
58
reg_t emit_load_dword(gen_t *g, value_t v);
59
/* Load a value with an offset. */
60
reg_t emit_load_offset(gen_t *g, value_t v, i32 offset);
61
/* Store a value on the stack. Returns a new value located on the stack. */
62
value_t emit_store(gen_t *g, value_t v, reg_t base, int offset);
63
/* Push a value to the stack. */
64
value_t emit_push(gen_t *g, value_t v);
65
/* Replace a value, eg. for assigning */
66
void emit_replace(gen_t *g, value_t old, value_t new);
67
/* Compute dst = base + offset while respecting SIMM12 limits. */
68
void emit_addr_offset(gen_t *g, reg_t dst, reg_t base, i32 offset);
69
/* Load a value at a stack offset into a register. */
70
usize emit_regload(gen_t *g, reg_t dst, reg_t base, i32 offset, type_t *ty);
71
/* Push a register to the stack. */
72
int emit_regpush(gen_t *g, reg_t src, type_t *ty);
73
/* Store a register value on the stack. */
74
usize emit_regstore(gen_t *g, reg_t src, reg_t base, i32 offset, type_t *ty);
75
/* Store a tvalue tag. */
76
void emit_store_tag(gen_t *g, tval_t tv, reg_t tag_reg);
77
/* Reserve stack space with explicit alignment. */
78
i32 reserve_aligned(gen_t *g, type_t *ty, i32 align);
79
80
/* Copy memory between two locations */
81
void emit_memcopy(gen_t *g, offset_t src, offset_t dst, type_t *ty);
82
/* Zero out a memory region */
83
void emit_memzero(gen_t *g, offset_t dst, i32 size);
84
/* Compare two registers based on their type:
85
 *
86
 * - If references, compares the addresses (pointers)
87
 * - If values, compares the content
88
 * - For records and arrays, compares each element
89
 * - For slices, compares the pointer addresses
90
 *
91
 * Puts the result (0 or 1) in the result register.
92
 */
93
void emit_memequal(gen_t *g, reg_t left, reg_t right, type_t *ty, reg_t result);
94
/* Compare raw bytes between two memory locations */
95
void emit_bytes_equal(
96
    gen_t *g, reg_t left, reg_t right, usize size, reg_t result
97
);
98
/* Copy a record from one memory offset to another. */
99
void emit_record_copy(gen_t *g, offset_t src, offset_t dst, type_t *ty);
100
/* Store a value directly to a record field. */
101
void emit_record_field_set(
102
    gen_t *g, value_t val, reg_t base, i32 record_offset, symbol_t *field
103
);
104
/* Calculate record field value from a record value and field symbol.
105
 * Creates a stack-based value pointing to the field at the correct offset. */
106
value_t emit_record_field_get(value_t sval, symbol_t *field);
107
/* Copy an array from one memory location to another. */
108
void emit_array_copy(gen_t *g, offset_t src, offset_t dst, type_t *ty);
109
/* Copy a word between two locations. Copies addresses of
110
 * pass-by-reference types. */
111
void emit_copy_by_ref(gen_t *g, value_t src, value_t dst);
112
/* Emit a slice literal */
113
value_t emit_slice_lit(gen_t *g, i32 offset, usize ptr, usize len, type_t *typ);
114
/* Store a successful result value by clearing the tag and
115
 * writing the payload. */
116
void emit_result_store_success(gen_t *g, value_t dest, value_t value);
117
/* Store an error result by writing the raw error tag and
118
 * zeroing the payload. */
119
void emit_result_store_error(gen_t *g, value_t dest, value_t err);
120
121
#endif