gen/
data.c
10.9 KiB
data.h
2.5 KiB
emit.c
37.2 KiB
emit.h
4.6 KiB
.clang-format
570 B
.gitignore
30 B
.gitsigners
112 B
LICENSE
1.1 KiB
Makefile
911 B
README
1.8 KiB
ast.c
5.0 KiB
ast.h
15.1 KiB
desugar.c
23.1 KiB
desugar.h
286 B
gen.c
108.5 KiB
gen.h
4.9 KiB
io.c
1.1 KiB
io.h
444 B
limits.h
1.3 KiB
module.c
10.0 KiB
module.h
2.2 KiB
options.c
1.4 KiB
options.h
472 B
parser.c
68.3 KiB
parser.h
942 B
radiance.c
3.7 KiB
ralloc.c
2.0 KiB
ralloc.h
1.1 KiB
resolver.c
109.7 KiB
resolver.h
5.6 KiB
riscv.c
12.0 KiB
riscv.h
12.0 KiB
scanner.c
10.2 KiB
scanner.h
3.2 KiB
strings.c
2.6 KiB
strings.h
407 B
symtab.c
5.7 KiB
symtab.h
4.6 KiB
types.h
1.0 KiB
util.h
1.5 KiB
gen/emit.h
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 |