stage1 完成15测试

This commit is contained in:
zzy
2026-07-06 21:26:27 +08:00
parent 0892c084ee
commit 69cea030dc
6 changed files with 91 additions and 45 deletions

View File

@@ -207,19 +207,67 @@ int spl_add_global_data(spl_comp_t *ctx, void *data, usize size) {
/* ---- Defer ---- */
void spl_emit_defer(spl_comp_t *ctx) {
/* Record current ip for later patching */
if (ctx->defer_count < DEFER_MAX) {
ctx->defer_addrs[ctx->defer_count++] = vec_size(ctx->prog.insns);
}
if (ctx->defer_count >= DEFER_MAX)
return;
/* Emit JMP placeholder (will skip defer body during normal execution).
* This JMP is at the current position. The defer body starts right after. */
spl_val_t jmp_skip = spl_emit_jmp(ctx);
spl_defer_entry_t *e = &ctx->defer_stack[ctx->defer_count];
e->body_start = jmp_skip + 1; /* instruction right after the JMP = body start */
e->jmp_exit = 0; /* set after body is parsed */
e->depth = ctx->scope_depth;
e->count_at_decl = ctx->defer_count;
ctx->defer_count++;
}
void spl_emit_defer_epilogue(spl_comp_t *ctx) {
/* Emit deferコード in reverse order */
for (int i = ctx->defer_count - 1; i >= 0; i--) {
/* The code after defer_addrs[i] is the defer body */
/* We need to JMP over it, but the body is inline */
/* This is a simplified approach — just mark the range */
void spl_emit_defer_epilogue(spl_comp_t *ctx, int depth) {
/* === Pass 1: patch skip JMPs to jump past their defer body ===
* During normal execution, the skip JMP at body_start-1 must jump
* over the defer body (to jmp_exit + 1 = the code after the defer). */
for (int i = 0; i < ctx->defer_count; i++) {
if (ctx->defer_stack[i].depth != depth)
continue;
spl_defer_entry_t *e = &ctx->defer_stack[i];
spl_val_t skip_addr = e->body_start - 1; /* the JMP L_skip instruction */
spl_val_t skip_target = e->jmp_exit + 1; /* instruction right after defer body */
spl_val_t skip_offset = skip_target - skip_addr - 1;
spl_patch(ctx, skip_addr, skip_offset);
}
/* === Pass 2: at scope exit, emit backwards JMPs to each defer body ===
* Process in reverse order so the LAST declared defer runs FIRST at scope exit.
* Each defer body's trailing JMP_exit gets patched to jump to right after
* the scope-exit JMP we just emitted, so control chains through correctly. */
for (int i = ctx->defer_count - 1; i >= 0; i--) {
if (ctx->defer_stack[i].depth != depth)
continue;
spl_defer_entry_t *e = &ctx->defer_stack[i];
/* Emit JMP backwards to the defer body */
spl_val_t here = vec_size(ctx->prog.insns);
spl_val_t jmp_offset = (spl_val_t)((isize)e->body_start - (isize)here - 1);
spl_emit(ctx, SPL_JMP, SPL_VOID, jmp_offset);
/* Patch the body's trailing JMP_exit to jump to here+1 (right after the
* backwards JMP we just emitted). This chains to the next defer or exits. */
if (e->jmp_exit > 0) {
spl_val_t exit_target = here + 1;
spl_val_t offset = exit_target - e->jmp_exit - 1;
spl_patch(ctx, e->jmp_exit, offset);
}
}
/* Remove processed defers from stack */
int new_count = 0;
for (int i = 0; i < ctx->defer_count; i++) {
if (ctx->defer_stack[i].depth != depth) {
ctx->defer_stack[new_count++] = ctx->defer_stack[i];
}
}
ctx->defer_count = new_count;
}
/* ---- Register runtime natives ---- */