From 7773cc6c145cc16a3b574e5bd5e8a2aaf1ce208a Mon Sep 17 00:00:00 2001 From: r4 Date: Wed, 29 Dec 2021 13:27:58 +0100 Subject: [PATCH] change IR stream to linked list --- ir.c | 140 +++++++++++++++++++++++++++++++++----------------------- ir.h | 30 +++++++----- main.c | 8 ++-- parse.c | 81 ++++++++++++++++---------------- parse.h | 2 +- vm.c | 15 +++--- vm.h | 2 +- 7 files changed, 159 insertions(+), 119 deletions(-) diff --git a/ir.c b/ir.c index 49c6646..c7a8b17 100644 --- a/ir.c +++ b/ir.c @@ -23,55 +23,81 @@ const char *irinstr_str[IRInstrEnumSize] = { [IRAddrOf] = "addrof", }; -#define IRTOKS_INIT_CAP_LONG 4096 -#define IRTOKS_INIT_CAP_SHORT 16 +#define IRLIST_INIT_CAP_LONG 4096 +#define IRLIST_INIT_CAP_SHORT 16 -static void irtoks_init_with_cap(IRToks *v, size_t cap); +static void irlist_init_with_cap(IRList *v, size_t cap); +static IRItem *irlist_new_item(IRList *v); -static void irtoks_init_with_cap(IRToks *v, size_t cap) { - v->toks = xmalloc(sizeof(IRTok) * cap); +static void irlist_init_with_cap(IRList *v, size_t cap) { + v->begin = NULL; + v->end = NULL; + v->p = pool_new(sizeof(IRItem) * cap); + v->index = NULL; v->len = 0; - v->cap = cap; } -void irtoks_init_long(IRToks *v) { - irtoks_init_with_cap(v, IRTOKS_INIT_CAP_LONG); - +static IRItem *irlist_new_item(IRList *v) { + IRItem *ret = pool_alloc(v->p, sizeof(IRItem)); + ret->next = NULL; + return ret; } -void irtoks_init_short(IRToks *v) { - irtoks_init_with_cap(v, IRTOKS_INIT_CAP_SHORT); +void irlist_init_long(IRList *v) { + irlist_init_with_cap(v, IRLIST_INIT_CAP_LONG); } -void irtoks_term(IRToks *v) { - for (size_t i = 0; i < v->len; i++) { - if (v->toks[i].instr == IRCallInternal && v->toks[i].CallI.args) - free(v->toks[i].CallI.args); +void irlist_init_short(IRList *v) { + irlist_init_with_cap(v, IRLIST_INIT_CAP_SHORT); +} + +void irlist_term(IRList *v) { + for (IRItem *i = v->begin; i; i = i->next) { + if (i->tok.instr == IRCallInternal && i->tok.CallI.args) + free(i->tok.CallI.args); } - free(v->toks); + pool_term(v->p); } -void irtoks_app(IRToks *v, IRTok t) { - if (v->len+1 > v->cap) - v->toks = xrealloc(v->toks, sizeof(IRTok) * (v->cap *= 2)); - v->toks[v->len++] = t; +void irlist_app(IRList *v, IRTok t) { + v->index = NULL; /* invalidate index */ + IRItem *itm = irlist_new_item(v); + itm->tok = t; + + if (!v->begin && !v->end) + v->begin = v->end = itm; + else { + v->end->next = itm; + v->end = itm; + } + + v->len++; } -void irtoks_eat_irtoks(IRToks *v, IRToks *other, size_t jmp_offset) { - if (v->len+other->len > v->cap) - v->toks = xrealloc(v->toks, sizeof(IRTok) * (other->len + (v->cap *= 2))); - for (size_t i = 0; i < other->len; i++) { +void irlist_eat_irlist(IRList *v, IRList *other) { + v->index = NULL; /* invalidate index */ + size_t jmp_offset = v->len-1; + for (IRItem *i = other->begin; i; i = i->next) { /* correct for changed jump addresses */ - if (other->toks[i].instr == IRJmp) - other->toks[i].Jmp.iaddr += jmp_offset; - else if (other->toks[i].instr == IRJnz) - other->toks[i].CJmp.iaddr += jmp_offset; + if (i->tok.instr == IRJmp) + i->tok.Jmp.iaddr += jmp_offset; + else if (i->tok.instr == IRJnz) + i->tok.CJmp.iaddr += jmp_offset; - v->toks[v->len++] = other->toks[i]; + irlist_app(v, i->tok); } - /* We're not calling irtoks_term() because we don't want associated items + /* We're not calling irlist_term() because we don't want associated items * (for example function arguments) to get deallocated as well. */ - free(other->toks); + pool_term(other->p); +} + +void irlist_update_index(IRList *v) { + if (v->index) + return; + v->index = pool_alloc(v->p, v->len); + size_t num_idx = 0; + for (IRItem *i = v->begin; i; i = i->next, num_idx++) + v->index[num_idx] = i; } static void print_irparam(const IRParam *p); @@ -84,17 +110,18 @@ static void print_irparam(const IRParam *p) { } } -void print_ir(IRToks *v, const BuiltinFunc *builtin_funcs) { - for (size_t i = 0; i < v->len; i++) { - printf("%04zx ", i); - printf("%s", irinstr_str[v->toks[i].instr]); - switch (v->toks[i].instr) { +void print_ir(IRList *v, const BuiltinFunc *builtin_funcs) { + size_t iaddr = 0; + for (IRItem *i = v->begin; i; i = i->next, iaddr++) { + printf("%04zx ", iaddr); + printf("%s", irinstr_str[i->tok.instr]); + switch (i->tok.instr) { case IRSet: case IRNeg: case IRNot: case IRAddrOf: - printf(" %%%zx ", v->toks[i].Unary.addr); - print_irparam(&v->toks[i].Unary.val); + printf(" %%%zx ", i->tok.Unary.addr); + print_irparam(&i->tok.Unary.val); break; case IRAdd: case IRSub: @@ -106,46 +133,47 @@ void print_ir(IRToks *v, const BuiltinFunc *builtin_funcs) { case IRLe: case IRAnd: case IROr: - printf(" %%%zx ", v->toks[i].Binary.addr); - print_irparam(&v->toks[i].Binary.lhs); + printf(" %%%zx ", i->tok.Binary.addr); + print_irparam(&i->tok.Binary.lhs); printf(" "); - print_irparam(&v->toks[i].Binary.rhs); + print_irparam(&i->tok.Binary.rhs); break; case IRJmp: - printf(" %zx", v->toks[i].Jmp.iaddr); + printf(" %zx", i->tok.Jmp.iaddr); break; case IRJnz: printf(" "); - print_irparam(&v->toks[i].CJmp.condition); - printf(" %zx", v->toks[i].CJmp.iaddr); + print_irparam(&i->tok.CJmp.condition); + printf(" %zx", i->tok.CJmp.iaddr); break; case IRCallInternal: { - const BuiltinFunc *f = &builtin_funcs[v->toks[i].CallI.fid]; + const BuiltinFunc *f = &builtin_funcs[i->tok.CallI.fid]; if (f->returns) - printf(" %%%zx", v->toks[i].CallI.ret_addr); + printf(" %%%zx", i->tok.CallI.ret_addr); printf(" %s", f->name); - for (size_t j = 0; j < v->toks[i].CallI.n_args; j++) { + for (size_t j = 0; j < i->tok.CallI.n_args; j++) { printf(" "); - print_irparam(&v->toks[i].CallI.args[j]); + print_irparam(&i->tok.CallI.args[j]); } break; } default: ASSERT_UNREACHED(); } - printf(" ; %zu:%zu", v->toks[i].ln, v->toks[i].col); + printf(" ; %zu:%zu", i->tok.ln, i->tok.col); printf("\n"); } } -void optimize_ir(IRToks *v) { - for (size_t i = 0; i < v->len; i++) { - switch (v->toks[i].instr) { +void optimize_ir(IRList *v) { + irlist_update_index(v); + for (IRItem *i = v->begin; i; i = i->next) { + switch (i->tok.instr) { case IRJmp: { /* resolve jump chains (esp. produced by if-else-if... statements) */ - size_t ja = i; - while (ja < v->len && v->toks[ja].instr == IRJmp) - ja = v->toks[ja].Jmp.iaddr; - v->toks[i].Jmp.iaddr = ja; + size_t ja = i->tok.Jmp.iaddr; + while (ja < v->len && v->index[ja]->tok.instr == IRJmp) + ja = v->index[ja]->tok.Jmp.iaddr; + i->tok.Jmp.iaddr = ja; } default: break; } diff --git a/ir.h b/ir.h index e1fe947..48339d4 100644 --- a/ir.h +++ b/ir.h @@ -109,19 +109,27 @@ typedef struct IRTok { }; } IRTok; -typedef struct IRToks { - size_t len, cap; - IRTok *toks; -} IRToks; +typedef struct IRItem { + struct IRItem *next; + IRTok tok; +} IRItem; -void irtoks_init_long(IRToks *v); -void irtoks_init_short(IRToks *v); -void irtoks_term(IRToks *v); -void irtoks_app(IRToks *v, IRTok t); -void irtoks_eat_irtoks(IRToks *v, IRToks *other, size_t jmp_offset); +typedef struct IRList { + IRItem *begin, *end; + Pool *p; + IRItem **index; /* index to pointer, irlist_update_index() must be called before use */ + size_t len; +} IRList; -void print_ir(IRToks *v, const BuiltinFunc *builtin_funcs); +void irlist_init_long(IRList *v); +void irlist_init_short(IRList *v); +void irlist_term(IRList *v); +void irlist_app(IRList *v, IRTok t); +void irlist_eat_irlist(IRList *v, IRList *other); +void irlist_update_index(IRList *v); /* should be used very conservatively */ -void optimize_ir(IRToks *v); +void print_ir(IRList *v, const BuiltinFunc *builtin_funcs); + +void optimize_ir(IRList *v); #endif /* IR_H */ diff --git a/main.c b/main.c index 2e8b0af..f55da11 100644 --- a/main.c +++ b/main.c @@ -244,9 +244,9 @@ int main(int argc, const char **argv) { { .name = "sleep", .kind = FuncFixedArgs, .returns = false, .side_effects = true, .FixedArgs = { .n_args = 1, .NoRet.func = fn_sleep, }}, { .name = "getln", .kind = FuncFixedArgs, .returns = true, .side_effects = true, .FixedArgs = { .n_args = 0, .WithRet.func = fn_getln, }}, }; - IRToks ir = parse(&tokens, funcs, sizeof(funcs) / sizeof(funcs[0])); + IRList ir = parse(&tokens, funcs, sizeof(funcs) / sizeof(funcs[0])); if (err) { - irtoks_term(&ir); + irlist_term(&ir); toklist_term(&tokens); pool_term(static_vars); fprintf(stderr, C_IRED "Parser error" C_RESET " in " C_CYAN "%s" C_RESET ":%zu:%zu: %s\n", filename, err_ln, err_col, errbuf); @@ -260,12 +260,12 @@ int main(int argc, const char **argv) { if (!opt_dry) { run(&ir, funcs); if (err) { - irtoks_term(&ir); + irlist_term(&ir); pool_term(static_vars); fprintf(stderr, C_IRED "Runtime error" C_RESET " in " C_CYAN "%s" C_RESET ":%zu:%zu: %s\n", filename, err_ln, err_col, errbuf); return 1; } } - irtoks_term(&ir); + irlist_term(&ir); pool_term(static_vars); } diff --git a/parse.c b/parse.c index 3dcf387..39331a3 100644 --- a/parse.c +++ b/parse.c @@ -32,12 +32,12 @@ static size_t get_ident_addr(const Scope *sc, const char *name, const Tok *errpo static IRParam tok_to_irparam(Scope *sc, Tok *t); static Scope make_scope(Scope *parent, bool with_idents); static void term_scope(Scope *sc); -static bool expr_flush_ir_and_maybe_return(IRToks *out_ir, TokList *toks, IRTok instr, TokListItem *expr_start, Scope *expr_scope, TokListItem *t, ExprRet *out_ret); -static ExprRet expr(IRToks *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t); -static void expr_into_addr(IRToks *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t, size_t addr); -static IRParam expr_into_irparam(IRToks *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t); +static bool expr_flush_ir_and_maybe_return(IRList *out_ir, TokList *toks, IRTok instr, TokListItem *expr_start, Scope *expr_scope, TokListItem *t, ExprRet *out_ret); +static ExprRet expr(IRList *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t); +static void expr_into_addr(IRList *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t, size_t addr); +static IRParam expr_into_irparam(IRList *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t); static void skip_newlns(TokList *toks, TokListItem *from); -static void stmt(IRToks *out_ir, TokList *toks, Map *funcs, Scope *sc, TokListItem *t); +static void stmt(IRList *out_ir, TokList *toks, Map *funcs, Scope *sc, TokListItem *t); static void mark_err(const Tok *t) { err_ln = t->ln; @@ -132,7 +132,7 @@ static void term_scope(Scope *sc) { * If ir_tok is not the expression's last instruction, ir_tok is written to * out_ir and t is replaced by a pointer to the result's memory address. * */ -static bool expr_flush_ir_and_maybe_return(IRToks *out_ir, TokList *toks, IRTok ir_tok, TokListItem *expr_start, Scope *expr_scope, TokListItem *t, ExprRet *out_ret) { +static bool expr_flush_ir_and_maybe_return(IRList *out_ir, TokList *toks, IRTok ir_tok, TokListItem *expr_start, Scope *expr_scope, TokListItem *t, ExprRet *out_ret) { if (t == expr_start && t->next->tok.kind == TokOp && op_prec[t->next->tok.Op] == PREC_DELIM) { /* ir_tok was the expression's last IR instruction. */ @@ -149,7 +149,7 @@ static bool expr_flush_ir_and_maybe_return(IRToks *out_ir, TokList *toks, IRTok size_t dest_addr = expr_scope->mem_addr++; set_irtok_dest_addr(&ir_tok, dest_addr); - irtoks_app(out_ir, ir_tok); + irlist_app(out_ir, ir_tok); t->tok = (Tok){ .kind = TokIdent, @@ -213,7 +213,7 @@ static bool expr_flush_ir_and_maybe_return(IRToks *out_ir, TokList *toks, IRTok * l_op r_op * both l_op and r_op are delimiters (their precedence is PREC_DELIM) => done */ -static ExprRet expr(IRToks *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t) { +static ExprRet expr(IRList *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t) { TokListItem *start = t; Scope sc = make_scope(parent_sc, false); @@ -253,7 +253,7 @@ static ExprRet expr(IRToks *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, if (r.kind == ExprRetLastInstr) { size_t res_addr = sc.mem_addr++; set_irtok_dest_addr(&r.LastInstr, res_addr); - irtoks_app(out_ir, r.LastInstr); + irlist_app(out_ir, r.LastInstr); t->tok = (Tok){ .ln = t->tok.ln, .col = t->tok.col, @@ -532,12 +532,12 @@ static ExprRet expr(IRToks *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, } } -static void expr_into_addr(IRToks *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t, size_t addr) { +static void expr_into_addr(IRList *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t, size_t addr) { ExprRet r; TRY(r = expr(out_ir, toks, funcs, parent_sc, t)); if (r.kind == ExprRetLastInstr) { set_irtok_dest_addr(&r.LastInstr, addr); - irtoks_app(out_ir, r.LastInstr); + irlist_app(out_ir, r.LastInstr); t->tok = (Tok){ .ln = t->tok.ln, .col = t->tok.col, @@ -550,7 +550,7 @@ static void expr_into_addr(IRToks *out_ir, TokList *toks, Map *funcs, Scope *par } else if (r.kind == ExprRetVal || r.kind == ExprRetIdent) { IRParam res; TRY(res = tok_to_irparam(parent_sc, &t->tok)); - irtoks_app(out_ir, (IRTok){ + irlist_app(out_ir, (IRTok){ .ln = t->tok.ln, .col = t->tok.col, .instr = IRSet, @@ -564,14 +564,14 @@ static void expr_into_addr(IRToks *out_ir, TokList *toks, Map *funcs, Scope *par ASSERT_UNREACHED(); } -static IRParam expr_into_irparam(IRToks *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t) { +static IRParam expr_into_irparam(IRList *out_ir, TokList *toks, Map *funcs, Scope *parent_sc, TokListItem *t) { ExprRet r; TRY_RET(r = expr(out_ir, toks, funcs, parent_sc, t), (IRParam){0}); if (r.kind == ExprRetLastInstr) { Scope sc = make_scope(parent_sc, false); size_t addr = sc.mem_addr++; set_irtok_dest_addr(&r.LastInstr, addr); - irtoks_app(out_ir, r.LastInstr); + irlist_app(out_ir, r.LastInstr); return (IRParam){ .kind = IRParamAddr, .Addr = addr, @@ -595,7 +595,7 @@ static void skip_newlns(TokList *toks, TokListItem *from) { toklist_del(toks, from, curr->prev); } -static void stmt(IRToks *out_ir, TokList *toks, Map *funcs, Scope *sc, TokListItem *t) { +static void stmt(IRList *out_ir, TokList *toks, Map *funcs, Scope *sc, TokListItem *t) { TokListItem *start = t; if (t->tok.kind == TokIdent && t->tok.Ident.kind == IdentName && (t->next->tok.kind == TokDeclare || t->next->tok.kind == TokAssign)) { char *name = t->tok.Ident.Name; @@ -643,8 +643,7 @@ static void stmt(IRToks *out_ir, TokList *toks, Map *funcs, Scope *sc, TokListIt * */ /* add initial jmp instruction */ - size_t jmp_instr_iaddr = out_ir->len; - irtoks_app(out_ir, (IRTok){ + irlist_app(out_ir, (IRTok){ .ln = t->tok.ln, .col = t->tok.col, .instr = IRJmp, @@ -652,30 +651,32 @@ static void stmt(IRToks *out_ir, TokList *toks, Map *funcs, Scope *sc, TokListIt .iaddr = 0, /* unknown for now */ }, }); + IRItem *jmp_instr = out_ir->end; + size_t body_iaddr = out_ir->len; /* parse condition */ - IRToks cond_ir; - irtoks_init_short(&cond_ir); + IRList cond_ir; + irlist_init_short(&cond_ir); IRParam cond; - TRY_ELSE(cond = expr_into_irparam(&cond_ir, toks, funcs, sc, t->next), irtoks_term(&cond_ir)); + TRY_ELSE(cond = expr_into_irparam(&cond_ir, toks, funcs, sc, t->next), irlist_term(&cond_ir)); /* parse loop body */ skip_newlns(toks, t->next); - TRY_ELSE(stmt(out_ir, toks, funcs, sc, t->next), irtoks_term(&cond_ir)); + TRY_ELSE(stmt(out_ir, toks, funcs, sc, t->next), irlist_term(&cond_ir)); /* finally we know where the jmp from the beginning has to jump to */ - out_ir->toks[jmp_instr_iaddr].Jmp.iaddr = out_ir->len; + jmp_instr->tok.Jmp.iaddr = out_ir->len; /* append condition IR to program IR, then terminate condition IR stream */ - irtoks_eat_irtoks(out_ir, &cond_ir, out_ir->len-1); + irlist_eat_irlist(out_ir, &cond_ir); /* add conditional jump */ - irtoks_app(out_ir, (IRTok){ + irlist_app(out_ir, (IRTok){ .ln = t->next->tok.ln, .col = t->next->tok.col, .instr = IRJnz, .CJmp = { - .iaddr = jmp_instr_iaddr + 1, + .iaddr = body_iaddr, .condition = cond, }, }); @@ -695,8 +696,7 @@ static void stmt(IRToks *out_ir, TokList *toks, Map *funcs, Scope *sc, TokListIt TRY(cond = expr_into_irparam(out_ir, toks, funcs, sc, t->next)); /* add conditional jmp instruction */ - size_t if_cjmp_instr_iaddr = out_ir->len; - irtoks_app(out_ir, (IRTok){ + irlist_app(out_ir, (IRTok){ .ln = t->tok.ln, .col = t->tok.col, .instr = IRJnz, @@ -705,12 +705,13 @@ static void stmt(IRToks *out_ir, TokList *toks, Map *funcs, Scope *sc, TokListIt .condition = cond, }, }); + IRItem *if_cjmp_instr = out_ir->end; /* parse if body */ skip_newlns(toks, t->next); - IRToks if_body; - irtoks_init_short(&if_body); - TRY_ELSE(stmt(&if_body, toks, funcs, sc, t->next), irtoks_term(&if_body)); + IRList if_body; + irlist_init_short(&if_body); + TRY_ELSE(stmt(&if_body, toks, funcs, sc, t->next), irlist_term(&if_body)); skip_newlns(toks, t->next); if (t->next->tok.kind == TokElse) { @@ -718,12 +719,11 @@ static void stmt(IRToks *out_ir, TokList *toks, Map *funcs, Scope *sc, TokListIt /* parse and add else body */ skip_newlns(toks, t->next); - TRY_ELSE(stmt(out_ir, toks, funcs, sc, t->next), irtoks_term(&if_body)); + TRY_ELSE(stmt(out_ir, toks, funcs, sc, t->next), irlist_term(&if_body)); } /* add jmp instruction to jump back to common code */ - size_t else_jmp_instr_iaddr = out_ir->len; - irtoks_app(out_ir, (IRTok){ + irlist_app(out_ir, (IRTok){ .ln = t->tok.ln, .col = t->tok.col, .instr = IRJmp, @@ -731,15 +731,16 @@ static void stmt(IRToks *out_ir, TokList *toks, Map *funcs, Scope *sc, TokListIt .iaddr = 0, /* unknown for now */ }, }); + IRItem *else_jmp_instr = out_ir->end; /* set if condition jmp target */ - out_ir->toks[if_cjmp_instr_iaddr].CJmp.iaddr = out_ir->len; + if_cjmp_instr->tok.CJmp.iaddr = out_ir->len; /* add if body */ - irtoks_eat_irtoks(out_ir, &if_body, out_ir->len-1); + irlist_eat_irlist(out_ir, &if_body); /* set else jmp target */ - out_ir->toks[else_jmp_instr_iaddr].CJmp.iaddr = out_ir->len; + else_jmp_instr->tok.CJmp.iaddr = out_ir->len; } else { /* assume expression */ TRY(expr_into_irparam(out_ir, toks, funcs, sc, t)); @@ -748,7 +749,7 @@ static void stmt(IRToks *out_ir, TokList *toks, Map *funcs, Scope *sc, TokListIt toklist_del(toks, start, t); } -IRToks parse(TokList *toks, BuiltinFunc *builtin_funcs, size_t n_builtin_funcs) { +IRList parse(TokList *toks, BuiltinFunc *builtin_funcs, size_t n_builtin_funcs) { bf = builtin_funcs; Map funcs; @@ -760,12 +761,12 @@ IRToks parse(TokList *toks, BuiltinFunc *builtin_funcs, size_t n_builtin_funcs) err_ln = 0; err_col = 0; set_err("Builtin function %s() declared more than once", builtin_funcs[i].name); map_term(&funcs); - return (IRToks){0}; + return (IRList){0}; } } - IRToks ir; - irtoks_init_long(&ir); + IRList ir; + irlist_init_long(&ir); Scope global_scope = make_scope(NULL, true); for (;;) { skip_newlns(toks, toks->begin); diff --git a/parse.h b/parse.h index 89d6704..f4e44ad 100644 --- a/parse.h +++ b/parse.h @@ -5,6 +5,6 @@ #include "tok.h" #include "util.h" -IRToks parse(TokList *toks, BuiltinFunc *builtin_funcs, size_t n_builtin_funcs); +IRList parse(TokList *toks, BuiltinFunc *builtin_funcs, size_t n_builtin_funcs); #endif /* PARSE_H */ diff --git a/vm.c b/vm.c index fc728d5..a9383a3 100644 --- a/vm.c +++ b/vm.c @@ -42,14 +42,17 @@ static Value *irparam_to_val(Stack *s, IRParam *v) { ASSERT_UNREACHED(); } -void run(const IRToks *ir, const BuiltinFunc *builtin_funcs) { +void run(IRList *ir, const BuiltinFunc *builtin_funcs) { /* so we don't have to call malloc on every function call */ size_t fn_args_cap = 16; Value *fn_args = xmalloc(sizeof(Value) * fn_args_cap); + /* so we can use index-based addressing */ + irlist_update_index(ir); + Stack s = stack_make(); - for (size_t i = 0; i < ir->len;) { - IRTok *instr = &ir->toks[i]; + for (IRItem *i = ir->begin; i;) { + IRTok *instr = &i->tok; err_ln = instr->ln; err_col = instr->col; switch (instr->instr) { @@ -91,11 +94,11 @@ void run(const IRToks *ir, const BuiltinFunc *builtin_funcs) { {free(fn_args); stack_term(&s);}); break; case IRJmp: - i = instr->Jmp.iaddr; + i = ir->index[instr->Jmp.iaddr]; continue; case IRJnz: if (is_nonzero(irparam_to_val(&s, &instr->CJmp.condition))) { - i = instr->Jmp.iaddr; + i = ir->index[instr->Jmp.iaddr]; continue; } break; @@ -137,7 +140,7 @@ void run(const IRToks *ir, const BuiltinFunc *builtin_funcs) { ASSERT_UNREACHED(); } - i++; + i = i->next; } stack_term(&s); free(fn_args); diff --git a/vm.h b/vm.h index 8378da1..fddeb0f 100644 --- a/vm.h +++ b/vm.h @@ -3,6 +3,6 @@ #include "ir.h" -void run(const IRToks *ir, const BuiltinFunc *builtin_funcs); +void run(IRList *ir, const BuiltinFunc *builtin_funcs); #endif /* VM_H */