stage1 完成15测试
This commit is contained in:
@@ -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 ---- */
|
||||
|
||||
Reference in New Issue
Block a user