Files
spl/stage1/spl_emit.h

156 lines
5.0 KiB
C

#ifndef __SPL_EMIT_H__
#define __SPL_EMIT_H__
#include "../stage0/spl_ir.h"
#include "spl_type.h"
#include <stdint.h>
/* ============================================================
* Frame allocator
* ============================================================ */
typedef struct {
int current_bytes;
int peak_bytes;
} spl_frame_alloc_t;
static inline void fa_init(spl_frame_alloc_t *fa) {
fa->current_bytes = 0;
fa->peak_bytes = 0;
}
static inline int fa_alloc(spl_frame_alloc_t *fa, usize byte_size) {
usize aligned = (byte_size + sizeof(spl_val_t) - 1) & ~(sizeof(spl_val_t) - 1);
if (aligned < sizeof(spl_val_t))
aligned = sizeof(spl_val_t);
int offset = fa->current_bytes;
fa->current_bytes += (int)aligned;
if (fa->current_bytes > fa->peak_bytes)
fa->peak_bytes = fa->current_bytes;
return offset;
}
int fa_alloc_type(spl_frame_alloc_t *fa, spl_type_ctx_t *tctx, int type_idx);
static inline void fa_reset_to(spl_frame_alloc_t *fa, int mark) { fa->current_bytes = mark; }
static inline int fa_alloc_slots(spl_frame_alloc_t *fa, usize nslots) {
return fa_alloc(fa, nslots * sizeof(spl_val_t));
}
static inline int fa_alloc_temp(spl_frame_alloc_t *fa, usize nslots) {
return fa_alloc_slots(fa, nslots);
}
static inline void fa_free(spl_frame_alloc_t *fa, int mark) { fa->current_bytes = mark; }
/* ============================================================
* Emit context
* ============================================================ */
typedef struct {
spl_val_t insn_idx;
int func_idx;
} spl_fixup_entry_t;
typedef struct {
spl_prog_t *prog;
spl_frame_alloc_t frame;
VEC(spl_fixup_entry_t) fixups;
} spl_emit_t;
void spl_emit_init(spl_emit_t *e, spl_prog_t *prog);
void spl_emit_drop(spl_emit_t *e);
/* ============================================================
* Layer 1 — single-instruction semantic wrappers
* ============================================================ */
/* Stack ops */
void emit_drop(spl_emit_t *e);
void emit_dup(spl_emit_t *e);
void emit_swap(spl_emit_t *e);
void emit_rot(spl_emit_t *e);
void emit_pick(spl_emit_t *e, int n);
/* Push */
void emit_push_i32(spl_emit_t *e, int v);
void emit_push_usize(spl_emit_t *e, usize v);
void emit_push_u64(spl_emit_t *e, uint64_t v);
void emit_push_f64(spl_emit_t *e, uint64_t v);
void emit_push_ptr(spl_emit_t *e, spl_val_t v);
void emit_push_type(spl_emit_t *e, uint16_t bt, spl_val_t v);
/* Load */
void emit_load_ptr(spl_emit_t *e);
void emit_load_usize(spl_emit_t *e);
void emit_load_type(spl_emit_t *e, uint16_t bt);
/* Store */
void emit_store_i32(spl_emit_t *e);
void emit_store_ptr(spl_emit_t *e);
void emit_store_usize(spl_emit_t *e);
void emit_store_type(spl_emit_t *e, uint16_t bt);
/* Arithmetic */
void emit_add_usize(spl_emit_t *e);
void emit_add_u64(spl_emit_t *e);
void emit_mul_u64(spl_emit_t *e);
void emit_sub_usize(spl_emit_t *e);
/* Compare */
void emit_ult_usize(spl_emit_t *e);
/* Branch */
void emit_jmp(spl_emit_t *e, spl_val_t offset);
spl_val_t emit_jmp_here(spl_emit_t *e);
spl_val_t emit_bz_here(spl_emit_t *e);
spl_val_t emit_bnz_here(spl_emit_t *e);
void emit_patch(spl_emit_t *e, spl_val_t addr, spl_val_t target);
void emit_patch_here(spl_emit_t *e, spl_val_t addr);
/* Address */
void emit_laddr(spl_emit_t *e, int offset);
void emit_gaddr(spl_emit_t *e, int idx);
/* Call */
void emit_call(spl_emit_t *e, int nargs);
void emit_ncall(spl_emit_t *e, int nargs);
/* Misc */
void emit_alloc(spl_emit_t *e, int slots);
void emit_binop(spl_emit_t *e, uint16_t op, uint16_t bt);
void emit_dbg_void(spl_emit_t *e);
void emit_dbg_usize(spl_emit_t *e);
/* Low-level emit (raw opcode + type + imm) */
spl_val_t emit_raw(spl_emit_t *e, uint16_t opcode, uint16_t type, spl_val_t imm);
/* ============================================================
* Layer 2 — semantic-level helpers
* ============================================================ */
void emit_frame_copy(spl_emit_t *e, int dest_offset, usize nslots);
void emit_copy_addr_to_addr(spl_emit_t *e, usize nslots, int depth);
void emit_load_to_var(spl_emit_t *e, spl_type_ctx_t *tctx, int ptr_slot_offset, usize byte_offset,
int data_type_idx, int var_offset);
void emit_store_to_laddr(spl_emit_t *e, int offset, uint16_t type);
void emit_ptr_add(spl_emit_t *e, usize byte_off);
spl_val_t emit_call_with_fixup(spl_emit_t *e, int nargs, int func_idx);
void emit_return(spl_emit_t *e, spl_type_ctx_t *tctx, int ret_type_idx);
/* Patch all fixups */
void emit_patch_call_fixups(spl_emit_t *e, spl_prog_t *prog);
/* ============================================================
* Layer 3 — compiler-level helpers (need spl_comp_t for tctx)
* ============================================================ */
struct spl_comp;
void spl_emit_ret(struct spl_comp *ctx, int ret_type_idx);
void spl_emit_store_init(struct spl_comp *ctx, int var_offset, int var_type_idx);
void spl_emit_defer(struct spl_comp *ctx);
void spl_emit_defer_epilogue(struct spl_comp *ctx, int depth);
#endif /* __SPL_EMIT_H__ */