#ifndef __SPL_EMIT_H__ #define __SPL_EMIT_H__ #include "../stage0/spl_ir.h" #include "spl_type.h" #include /* ============================================================ * 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_prog_t *prog; spl_frame_alloc_t frame; VEC(spl_val_t) call_fixups; VEC(int) call_fixup_funcs; } 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); /* ============================================================ * 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); #endif /* __SPL_EMIT_H__ */