diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2020-11-26 10:34:31 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2020-11-26 10:34:31 +0900 |
| commit | 7150c6753933f12a2ba63769fb7b3a44cfcddd3d (patch) | |
| tree | cddfd89197039d98cac827837e58bd3041d88a2a /mrbgems/mruby-compiler/core | |
| parent | 6dedd6a940194881c3b66124ff277c4cb14d08bd (diff) | |
| download | mruby-7150c6753933f12a2ba63769fb7b3a44cfcddd3d.tar.gz mruby-7150c6753933f12a2ba63769fb7b3a44cfcddd3d.zip | |
Make `OP_JMP*` operand address to be relative.
Jump target address is `operand (16bit)` + `address of next instruction`.
In addition, `ilen` was made `uint32_t` so that `iseq` length limitation
of 65536 is removed. Only jump target address should be within signed
16bit (-32768 .. 32767).
Diffstat (limited to 'mrbgems/mruby-compiler/core')
| -rw-r--r-- | mrbgems/mruby-compiler/core/codegen.c | 84 |
1 files changed, 56 insertions, 28 deletions
diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 2a7b9cf06..2e39e8930 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -39,7 +39,8 @@ enum looptype { struct loopinfo { enum looptype type; - int pc0, pc1, pc2, pc3, acc; + uint32_t pc0, pc1, pc2, pc3; + int acc; struct loopinfo *prev; }; @@ -53,9 +54,9 @@ typedef struct scope { node *lv; uint16_t sp; - uint16_t pc; - uint16_t lastpc; - uint16_t lastlabel; + uint32_t pc; + uint32_t lastpc; + uint32_t lastlabel; int ainfo:15; mrb_bool mscope:1; @@ -168,13 +169,15 @@ new_label(codegen_scope *s) static void emit_B(codegen_scope *s, uint32_t pc, uint8_t i) { - if (pc >= MAXARG_S || s->icapa >= MAXARG_S) { - codegen_error(s, "too big code block"); - } if (pc >= s->icapa) { - s->icapa *= 2; - if (s->icapa > MAXARG_S) { - s->icapa = MAXARG_S; + if (pc == UINT32_MAX) { + codegen_error(s, "too big code block"); + } + if (pc >= UINT32_MAX / 2) { + pc = UINT32_MAX; + } + else { + s->icapa *= 2; } s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa); if (s->lines) { @@ -358,22 +361,39 @@ no_peephole(codegen_scope *s) return no_optimize(s) || s->lastlabel == s->pc || s->pc == 0 || s->pc == s->lastpc; } -static uint16_t -genjmp(codegen_scope *s, mrb_code i, uint16_t pc) +static void +gen_jmpdst(codegen_scope *s, uint32_t pc) { - uint16_t pos; + if (pc == 0) { + gen_S(s, 0); + } + else { + uint32_t pos2 = s->pc+2; + int32_t off = pc - pos2; + + if (off > INT16_MAX || INT16_MIN > off) { + codegen_error(s, "too big jmp offset"); + } + gen_S(s, (uint16_t)off); + } +} + +static uint32_t +genjmp(codegen_scope *s, mrb_code i, uint32_t pc) +{ + uint32_t pos; s->lastpc = s->pc; gen_B(s, i); pos = s->pc; - gen_S(s, pc); + gen_jmpdst(s, pc); return pos; } -static uint16_t -genjmp2(codegen_scope *s, mrb_code i, uint16_t a, int pc, int val) +static uint32_t +genjmp2(codegen_scope *s, mrb_code i, uint16_t a, uint32_t pc, int val) { - uint16_t pos; + uint32_t pos; if (!no_peephole(s) && !val) { struct mrb_insn_data data = mrb_last_insn(s); @@ -393,7 +413,7 @@ genjmp2(codegen_scope *s, mrb_code i, uint16_t a, int pc, int val) gen_B(s, i); gen_B(s, (uint8_t)a); pos = s->pc; - gen_S(s, pc); + gen_jmpdst(s, pc); } return pos; } @@ -496,19 +516,26 @@ gen_addsub(codegen_scope *s, uint8_t op, uint16_t dst) } } -static int -dispatch(codegen_scope *s, uint16_t pos0) +static uint32_t +dispatch(codegen_scope *s, uint32_t pos0) { - uint16_t newpos; + int32_t pos1 = pos0 + 2; + int32_t offset; + int16_t newpos; + offset = s->pc - pos1; + if (offset > INT16_MAX) { + codegen_error(s, "too big jmp offset"); + } s->lastlabel = s->pc; - newpos = PEEK_S(s->iseq+pos0); - emit_S(s, pos0, s->pc); - return newpos; + newpos = (int16_t)PEEK_S(s->iseq+pos0); + emit_S(s, pos0, (uint16_t)offset); + if (newpos == 0) return 0; + return pos1+newpos; } static void -dispatch_linked(codegen_scope *s, uint16_t pos) +dispatch_linked(codegen_scope *s, uint32_t pos) { if (pos==0) return; for (;;) { @@ -1464,7 +1491,8 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_RESCUE: { - int noexc, exend, pos1, pos2, tmp; + int noexc; + uint32_t exend, pos1, pos2, tmp; struct loopinfo *lp; int catch_entry, begin, end; @@ -1739,7 +1767,7 @@ codegen(codegen_scope *s, node *tree, int val) case NODE_CASE: { int head = 0; - int pos1, pos2, pos3, tmp; + uint32_t pos1, pos2, pos3, tmp; node *n; pos3 = 0; @@ -1782,7 +1810,7 @@ codegen(codegen_scope *s, node *tree, int val) tree = tree->cdr; } if (val) { - int pos = cursp(); + uint32_t pos = cursp(); genop_1(s, OP_LOADNIL, cursp()); if (pos3) dispatch_linked(s, pos3); if (head) pop(); |
