From bb55bbfdde50a12283e6eb37910752cae48348aa Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Thu, 28 May 2015 00:21:49 +0900 Subject: [PATCH] [bugfix] codegen causes segv when default irep size is short --- extlib/benz/codegen.c | 246 +++++++++++++++++++++--------------------- 1 file changed, 121 insertions(+), 125 deletions(-) diff --git a/extlib/benz/codegen.c b/extlib/benz/codegen.c index 062fc20c..f3f003ad 100644 --- a/extlib/benz/codegen.c +++ b/extlib/benz/codegen.c @@ -144,22 +144,17 @@ static bool push_scope(analyze_state *state, pic_value formals) { pic_state *pic = state->pic; - analyze_scope *scope; + analyze_scope *scope = pic_alloc(pic, sizeof(analyze_scope)); bool varg; - xvect args, locals, captures; - xv_init(args); - xv_init(locals); - xv_init(captures); + xv_init(scope->args); + xv_init(scope->locals); + xv_init(scope->captures); - if (analyze_args(pic, formals, &varg, &args, &locals)) { - scope = pic_alloc(pic, sizeof(analyze_scope)); + if (analyze_args(pic, formals, &varg, &scope->args, &scope->locals)) { scope->up = state->scope; scope->depth = scope->up ? scope->up->depth + 1 : 0; scope->varg = varg; - scope->args = args; - scope->locals = locals; - scope->captures = captures; scope->defer = pic_nil_value(); state->scope = scope; @@ -167,8 +162,10 @@ push_scope(analyze_state *state, pic_value formals) return true; } else { - xv_destroy(args); - xv_destroy(locals); + xv_destroy(scope->args); + xv_destroy(scope->locals); + xv_destroy(scope->captures); + pic_free(pic, scope); return false; } } @@ -921,8 +918,69 @@ destroy_codegen_state(codegen_state *state) } static void -create_activation(codegen_context *cxt) +emit_n(codegen_state *state, enum pic_opcode insn) { + pic_state *pic = state->pic; + codegen_context *cxt = state->cxt; + + if (cxt->clen >= cxt->ccapa) { + cxt->ccapa *= 2; + cxt->code = pic_realloc(pic, cxt->code, sizeof(pic_code) * cxt->ccapa); + } + cxt->code[cxt->clen].insn = insn; + cxt->clen++; +} + +static void +emit_i(codegen_state *state, enum pic_opcode insn, int i) +{ + pic_state *pic = state->pic; + codegen_context *cxt = state->cxt; + + if (cxt->clen >= cxt->ccapa) { + cxt->ccapa *= 2; + cxt->code = pic_realloc(pic, cxt->code, sizeof(pic_code) * cxt->ccapa); + } + cxt->code[cxt->clen].insn = insn; + cxt->code[cxt->clen].u.i = i; + cxt->clen++; +} + +static void +emit_c(codegen_state *state, enum pic_opcode insn, char c) +{ + pic_state *pic = state->pic; + codegen_context *cxt = state->cxt; + + if (cxt->clen >= cxt->ccapa) { + cxt->ccapa *= 2; + cxt->code = pic_realloc(pic, cxt->code, sizeof(pic_code) * cxt->ccapa); + } + cxt->code[cxt->clen].insn = insn; + cxt->code[cxt->clen].u.c = c; + cxt->clen++; +} + +static void +emit_r(codegen_state *state, enum pic_opcode insn, int d, int i) +{ + pic_state *pic = state->pic; + codegen_context *cxt = state->cxt; + + if (cxt->clen >= cxt->ccapa) { + cxt->ccapa *= 2; + cxt->code = pic_realloc(pic, cxt->code, sizeof(pic_code) * cxt->ccapa); + } + cxt->code[cxt->clen].insn = insn; + cxt->code[cxt->clen].u.r.depth = d; + cxt->code[cxt->clen].u.r.idx = i; + cxt->clen++; +} + +static void +create_activation(codegen_state *state) +{ + codegen_context *cxt = state->cxt; size_t i, n; xhash regs; size_t offset; @@ -944,13 +1002,10 @@ create_activation(codegen_context *cxt) n = xh_val(xh_get_ptr(®s, xv_A(cxt->captures, i)), size_t); if (n <= xv_size(cxt->args) || (cxt->varg && n == xv_size(cxt->args) + 1)) { /* copy arguments to capture variable area */ - cxt->code[cxt->clen].insn = OP_LREF; - cxt->code[cxt->clen].u.i = (int)n; - cxt->clen++; + emit_i(state, OP_LREF, (int)n); } else { /* otherwise, just extend the stack */ - cxt->code[cxt->clen].insn = OP_PUSHNONE; - cxt->clen++; + emit_n(state, OP_PUSHNONE); } } @@ -1005,7 +1060,7 @@ push_codegen_context(codegen_state *state, pic_value name, pic_value args, pic_v state->cxt = cxt; - create_activation(cxt); + create_activation(state); } static struct pic_irep * @@ -1111,9 +1166,7 @@ codegen(codegen_state *state, pic_value obj) sym = pic_sym_ptr(pic_car(pic, obj)); if (sym == pic->sGREF) { - cxt->code[cxt->clen].insn = OP_GREF; - cxt->code[cxt->clen].u.i = index_symbol(state, pic_sym_ptr(pic_list_ref(pic, obj, 1))); - cxt->clen++; + emit_i(state, OP_GREF, index_symbol(state, pic_sym_ptr(pic_list_ref(pic, obj, 1)))); return; } else if (sym == pic->sCREF) { pic_sym *name; @@ -1121,10 +1174,7 @@ codegen(codegen_state *state, pic_value obj) depth = pic_int(pic_list_ref(pic, obj, 1)); name = pic_sym_ptr(pic_list_ref(pic, obj, 2)); - cxt->code[cxt->clen].insn = OP_CREF; - cxt->code[cxt->clen].u.r.depth = depth; - cxt->code[cxt->clen].u.r.idx = index_capture(state, name, depth); - cxt->clen++; + emit_r(state, OP_CREF, depth, index_capture(state, name, depth)); return; } else if (sym == pic->sLREF) { pic_sym *name; @@ -1132,14 +1182,10 @@ codegen(codegen_state *state, pic_value obj) name = pic_sym_ptr(pic_list_ref(pic, obj, 1)); if ((i = index_capture(state, name, 0)) != -1) { - cxt->code[cxt->clen].insn = OP_LREF; - cxt->code[cxt->clen].u.i = i + (int)xv_size(cxt->args) + (int)xv_size(cxt->locals) + 1; - cxt->clen++; + emit_i(state, OP_LREF, i + (int)xv_size(cxt->args) + (int)xv_size(cxt->locals) + 1); return; } - cxt->code[cxt->clen].insn = OP_LREF; - cxt->code[cxt->clen].u.i = index_local(state, name); - cxt->clen++; + emit_i(state, OP_LREF, index_local(state, name)); return; } else if (sym == pic->sSETBANG) { pic_value var, val; @@ -1151,11 +1197,8 @@ codegen(codegen_state *state, pic_value obj) var = pic_list_ref(pic, obj, 1); type = pic_sym_ptr(pic_list_ref(pic, var, 0)); if (type == pic->sGREF) { - cxt->code[cxt->clen].insn = OP_GSET; - cxt->code[cxt->clen].u.i = index_symbol(state, pic_sym_ptr(pic_list_ref(pic, var, 1))); - cxt->clen++; - cxt->code[cxt->clen].insn = OP_PUSHNONE; - cxt->clen++; + emit_i(state, OP_GSET, index_symbol(state, pic_sym_ptr(pic_list_ref(pic, var, 1)))); + emit_n(state, OP_PUSHNONE); return; } else if (type == pic->sCREF) { @@ -1164,12 +1207,8 @@ codegen(codegen_state *state, pic_value obj) depth = pic_int(pic_list_ref(pic, var, 1)); name = pic_sym_ptr(pic_list_ref(pic, var, 2)); - cxt->code[cxt->clen].insn = OP_CSET; - cxt->code[cxt->clen].u.r.depth = depth; - cxt->code[cxt->clen].u.r.idx = index_capture(state, name, depth); - cxt->clen++; - cxt->code[cxt->clen].insn = OP_PUSHNONE; - cxt->clen++; + emit_r(state, OP_CSET, depth, index_capture(state, name, depth)); + emit_n(state, OP_PUSHNONE); return; } else if (type == pic->sLREF) { @@ -1178,18 +1217,12 @@ codegen(codegen_state *state, pic_value obj) name = pic_sym_ptr(pic_list_ref(pic, var, 1)); if ((i = index_capture(state, name, 0)) != -1) { - cxt->code[cxt->clen].insn = OP_LSET; - cxt->code[cxt->clen].u.i = i + (int)xv_size(cxt->args) + (int)xv_size(cxt->locals) + 1; - cxt->clen++; - cxt->code[cxt->clen].insn = OP_PUSHNONE; - cxt->clen++; + emit_i(state, OP_LSET, i + (int)xv_size(cxt->args) + (int)xv_size(cxt->locals) + 1); + emit_n(state, OP_PUSHNONE); return; } - cxt->code[cxt->clen].insn = OP_LSET; - cxt->code[cxt->clen].u.i = index_local(state, name); - cxt->clen++; - cxt->code[cxt->clen].insn = OP_PUSHNONE; - cxt->clen++; + emit_i(state, OP_LSET, index_local(state, name)); + emit_n(state, OP_PUSHNONE); return; } } @@ -1201,9 +1234,7 @@ codegen(codegen_state *state, pic_value obj) cxt->irep = pic_realloc(pic, cxt->irep, sizeof(struct pic_irep *) * cxt->icapa); } k = (int)cxt->ilen++; - cxt->code[cxt->clen].insn = OP_LAMBDA; - cxt->code[cxt->clen].u.i = k; - cxt->clen++; + emit_i(state, OP_LAMBDA, k); cxt->irep[k] = codegen_lambda(state, obj); return; @@ -1213,13 +1244,16 @@ codegen(codegen_state *state, pic_value obj) codegen(state, pic_list_ref(pic, obj, 1)); - cxt->code[cxt->clen].insn = OP_JMPIF; - s = (int)cxt->clen++; + s = (int)cxt->clen; + + emit_n(state, OP_JMPIF); /* if false branch */ codegen(state, pic_list_ref(pic, obj, 3)); - cxt->code[cxt->clen].insn = OP_JMP; - t = (int)cxt->clen++; + + t = (int)cxt->clen; + + emit_n(state, OP_JMP); cxt->code[s].u.i = (int)cxt->clen - s; @@ -1234,8 +1268,7 @@ codegen(codegen_state *state, pic_value obj) pic_for_each (elt, pic_cdr(pic, obj), it) { if (i++ != 0) { - cxt->code[cxt->clen].insn = OP_POP; - cxt->clen++; + emit_n(state, OP_POP); } codegen(state, elt); } @@ -1247,26 +1280,16 @@ codegen(codegen_state *state, pic_value obj) obj = pic_list_ref(pic, obj, 1); switch (pic_type(obj)) { case PIC_TT_BOOL: - if (pic_true_p(obj)) { - cxt->code[cxt->clen].insn = OP_PUSHTRUE; - } else { - cxt->code[cxt->clen].insn = OP_PUSHFALSE; - } - cxt->clen++; + emit_n(state, (pic_true_p(obj) ? OP_PUSHTRUE : OP_PUSHFALSE)); return; case PIC_TT_INT: - cxt->code[cxt->clen].insn = OP_PUSHINT; - cxt->code[cxt->clen].u.i = pic_int(obj); - cxt->clen++; + emit_i(state, OP_PUSHINT, pic_int(obj)); return; case PIC_TT_NIL: - cxt->code[cxt->clen].insn = OP_PUSHNIL; - cxt->clen++; + emit_n(state, OP_PUSHNIL); return; case PIC_TT_CHAR: - cxt->code[cxt->clen].insn = OP_PUSHCHAR; - cxt->code[cxt->clen].u.c = pic_char(obj); - cxt->clen++; + emit_c(state, OP_PUSHCHAR, pic_char(obj)); return; default: if (cxt->plen >= cxt->pcapa) { @@ -1275,122 +1298,103 @@ codegen(codegen_state *state, pic_value obj) } pidx = (int)cxt->plen++; cxt->pool[pidx] = obj; - cxt->code[cxt->clen].insn = OP_PUSHCONST; - cxt->code[cxt->clen].u.i = pidx; - cxt->clen++; + emit_i(state, OP_PUSHCONST, pidx); return; } } else if (sym == pic->sCONS) { codegen(state, pic_list_ref(pic, obj, 1)); codegen(state, pic_list_ref(pic, obj, 2)); - cxt->code[cxt->clen].insn = OP_CONS; - cxt->clen++; + emit_n(state, OP_CONS); return; } else if (sym == pic->sCAR) { codegen(state, pic_list_ref(pic, obj, 1)); - cxt->code[cxt->clen].insn = OP_CAR; - cxt->clen++; + emit_n(state, OP_CAR); return; } else if (sym == pic->sCDR) { codegen(state, pic_list_ref(pic, obj, 1)); - cxt->code[cxt->clen].insn = OP_CDR; - cxt->clen++; + emit_n(state, OP_CDR); return; } else if (sym == pic->sNILP) { codegen(state, pic_list_ref(pic, obj, 1)); - cxt->code[cxt->clen].insn = OP_NILP; - cxt->clen++; + emit_n(state, OP_NILP); return; } else if (sym == pic->sSYMBOLP) { codegen(state, pic_list_ref(pic, obj, 1)); - cxt->code[cxt->clen].insn = OP_SYMBOLP; - cxt->clen++; + emit_n(state, OP_SYMBOLP); return; } else if (sym == pic->sPAIRP) { codegen(state, pic_list_ref(pic, obj, 1)); - cxt->code[cxt->clen].insn = OP_PAIRP; - cxt->clen++; + emit_n(state, OP_PAIRP); return; } else if (sym == pic->sADD) { codegen(state, pic_list_ref(pic, obj, 1)); codegen(state, pic_list_ref(pic, obj, 2)); - cxt->code[cxt->clen].insn = OP_ADD; - cxt->clen++; + emit_n(state, OP_ADD); return; } else if (sym == pic->sSUB) { codegen(state, pic_list_ref(pic, obj, 1)); codegen(state, pic_list_ref(pic, obj, 2)); - cxt->code[cxt->clen].insn = OP_SUB; - cxt->clen++; + emit_n(state, OP_SUB); return; } else if (sym == pic->sMUL) { codegen(state, pic_list_ref(pic, obj, 1)); codegen(state, pic_list_ref(pic, obj, 2)); - cxt->code[cxt->clen].insn = OP_MUL; - cxt->clen++; + emit_n(state, OP_MUL); return; } else if (sym == pic->sDIV) { codegen(state, pic_list_ref(pic, obj, 1)); codegen(state, pic_list_ref(pic, obj, 2)); - cxt->code[cxt->clen].insn = OP_DIV; - cxt->clen++; + emit_n(state, OP_DIV); return; } else if (sym == pic->sMINUS) { codegen(state, pic_list_ref(pic, obj, 1)); - cxt->code[cxt->clen].insn = OP_MINUS; - cxt->clen++; + emit_n(state, OP_MINUS); return; } else if (sym == pic->sEQ) { codegen(state, pic_list_ref(pic, obj, 1)); codegen(state, pic_list_ref(pic, obj, 2)); - cxt->code[cxt->clen].insn = OP_EQ; - cxt->clen++; + emit_n(state, OP_EQ); return; } else if (sym == pic->sLT) { codegen(state, pic_list_ref(pic, obj, 1)); codegen(state, pic_list_ref(pic, obj, 2)); - cxt->code[cxt->clen].insn = OP_LT; - cxt->clen++; + emit_n(state, OP_LT); return; } else if (sym == pic->sLE) { codegen(state, pic_list_ref(pic, obj, 1)); codegen(state, pic_list_ref(pic, obj, 2)); - cxt->code[cxt->clen].insn = OP_LE; - cxt->clen++; + emit_n(state, OP_LE); return; } else if (sym == pic->sGT) { codegen(state, pic_list_ref(pic, obj, 2)); codegen(state, pic_list_ref(pic, obj, 1)); - cxt->code[cxt->clen].insn = OP_LT; - cxt->clen++; + emit_n(state, OP_LT); return; } else if (sym == pic->sGE) { codegen(state, pic_list_ref(pic, obj, 2)); codegen(state, pic_list_ref(pic, obj, 1)); - cxt->code[cxt->clen].insn = OP_LE; - cxt->clen++; + emit_n(state, OP_LE); return; } else if (sym == pic->sNOT) { codegen(state, pic_list_ref(pic, obj, 1)); - cxt->code[cxt->clen].insn = OP_NOT; - cxt->clen++; + emit_n(state, OP_NOT); return; } else if (sym == pic->sCALL || sym == pic->sTAILCALL) { @@ -1400,9 +1404,7 @@ codegen(codegen_state *state, pic_value obj) pic_for_each (elt, pic_cdr(pic, obj), it) { codegen(state, elt); } - cxt->code[cxt->clen].insn = (sym == pic->sCALL) ? OP_CALL : OP_TAILCALL; - cxt->code[cxt->clen].u.i = len - 1; - cxt->clen++; + emit_i(state, (sym == pic->sCALL ? OP_CALL : OP_TAILCALL), len - 1); return; } else if (sym == pic->sCALL_WITH_VALUES || sym == pic->sTAILCALL_WITH_VALUES) { @@ -1410,13 +1412,9 @@ codegen(codegen_state *state, pic_value obj) codegen(state, pic_list_ref(pic, obj, 2)); codegen(state, pic_list_ref(pic, obj, 1)); /* call producer */ - cxt->code[cxt->clen].insn = OP_CALL; - cxt->code[cxt->clen].u.i = 1; - cxt->clen++; + emit_i(state, OP_CALL, 1); /* call consumer */ - cxt->code[cxt->clen].insn = (sym == pic->sCALL_WITH_VALUES) ? OP_CALL : OP_TAILCALL; - cxt->code[cxt->clen].u.i = -1; - cxt->clen++; + emit_i(state, (sym == pic->sCALL_WITH_VALUES ? OP_CALL : OP_TAILCALL), -1); return; } else if (sym == pic->sRETURN) { @@ -1426,9 +1424,7 @@ codegen(codegen_state *state, pic_value obj) pic_for_each (elt, pic_cdr(pic, obj), it) { codegen(state, elt); } - cxt->code[cxt->clen].insn = OP_RET; - cxt->code[cxt->clen].u.i = len - 1; - cxt->clen++; + emit_i(state, OP_RET, len - 1); return; } pic_errorf(pic, "codegen: unknown AST type ~s", obj);