diff options
| -rw-r--r-- | include/mruby/irep.h | 1 | ||||
| -rw-r--r-- | mrbgems/mruby-compiler/core/codegen.c | 49 | ||||
| -rw-r--r-- | src/codedump.c | 2 | ||||
| -rw-r--r-- | src/dump.c | 29 | ||||
| -rw-r--r-- | src/load.c | 13 | ||||
| -rw-r--r-- | src/state.c | 3 | ||||
| -rw-r--r-- | src/vm.c | 2 |
7 files changed, 92 insertions, 7 deletions
diff --git a/include/mruby/irep.h b/include/mruby/irep.h index 640b0177f..d2ea202db 100644 --- a/include/mruby/irep.h +++ b/include/mruby/irep.h @@ -20,6 +20,7 @@ enum irep_pool_type { IREP_TT_SSTR = 2, /* string (static) */ IREP_TT_INT32 = 1, /* 32bit integer */ IREP_TT_INT64 = 3, /* 64bit integer */ + IREP_TT_BIGINT = 7, /* big integer (not yet supported) */ IREP_TT_FLOAT = 5, /* float (double/float) */ }; diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 555479a7e..d02dd82f2 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -589,7 +589,47 @@ pop_n_(codegen_scope *s, int n) #define pop_n(n) pop_n_(s,n) #define cursp() (s->sp) -static inline int +static int +new_litbn(codegen_scope *s, const char *p, int base, mrb_bool neg) +{ + int i, plen; + mrb_pool_value *pv; + + plen = strlen(p); + if (plen > 255) { + codegen_error(s, "integer too big"); + } + for (i=0; i<s->irep->plen; i++) { + mrb_int len; + pv = &s->pool[i]; + if (pv->tt != IREP_TT_BIGINT) continue; + len = pv->u.str[0]; + if (len == strlen(p) && pv->u.str[1] == base && memcmp(pv->u.str+2, p, len) == 0) + return i; + } + + if (s->irep->plen == s->pcapa) { + s->pcapa *= 2; + s->pool = (mrb_pool_value*)codegen_realloc(s, s->pool, sizeof(mrb_pool_value)*s->pcapa); + } + + pv = &s->pool[s->irep->plen]; + i = s->irep->plen++; + { + char *buf; + mrb_int len = strlen(p); + pv->tt = IREP_TT_BIGINT; + buf = (char*)codegen_realloc(s, NULL, len+3); + buf[0] = len; + buf[1] = base; + memcpy(buf+2, p, len); + buf[len+2] = '\0'; + pv->u.str = buf; + } + return i; +} + +static int new_lit(codegen_scope *s, mrb_value val) { int i; @@ -2493,7 +2533,8 @@ codegen(codegen_scope *s, node *tree, int val) i = readint_mrb_int(s, p, base, FALSE, &overflow); if (overflow) { - codegen_error(s, "integer overflow"); + int off = new_litbn(s, p, base, FALSE); + genop_bs(s, OP_LOADL, cursp(), off); } else { if (i < 0) { @@ -2509,7 +2550,6 @@ codegen(codegen_scope *s, node *tree, int val) else if (i <= INT32_MAX) genop_2SS(s, OP_LOADI32, cursp(), (uint32_t)i); else { int off; - lit_int: off = new_lit(s, mrb_int_value(s->mrb, i)); genop_bs(s, OP_LOADL, cursp(), off); @@ -2558,7 +2598,8 @@ codegen(codegen_scope *s, node *tree, int val) i = readint_mrb_int(s, p, base, TRUE, &overflow); if (overflow) { - codegen_error(s, "integer overflow"); + int off = new_litbn(s, p, base, TRUE); + genop_bs(s, OP_LOADL, cursp(), off); } else { if (i == -1) genop_1(s, OP_LOADI__1, cursp()); diff --git a/src/codedump.c b/src/codedump.c index f382bb7eb..3a5f0eadb 100644 --- a/src/codedump.c +++ b/src/codedump.c @@ -6,7 +6,7 @@ #include <mruby/proc.h> #include <mruby/dump.h> -#ifndef MRB_NO_STDIO +#ifndef MRB_NOP_STDIO static void print_r(mrb_state *mrb, const mrb_irep *irep, size_t n) { diff --git a/src/dump.c b/src/dump.c index 51e8dca4e..0822b2fac 100644 --- a/src/dump.c +++ b/src/dump.c @@ -129,6 +129,15 @@ get_pool_block_size(mrb_state *mrb, const mrb_irep *irep) size += 4; /* 32bits = 4bytes */ break; + case IREP_TT_BIGINT: + { + mrb_int len = irep->pool[pool_no].u.str[0]; + mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX); + size += sizeof(uint8_t); + size += (size_t)len+2; + } + break; + case IREP_TT_FLOAT: #ifndef MRB_NO_FLOAT { @@ -187,6 +196,14 @@ write_pool_block(mrb_state *mrb, const mrb_irep *irep, uint8_t *buf) cur += uint32_to_bin(irep->pool[pool_no].u.i32, cur); /* i32 */ break; + case IREP_TT_BIGINT: + cur += uint8_to_bin(IREP_TT_BIGINT, cur); /* data type */ + len = irep->pool[pool_no].u.str[0]; + memcpy(cur, irep->pool[pool_no].u.str, (size_t)len+2); + cur += len+2; + *cur++ = '\0'; + break; + case IREP_TT_FLOAT: cur += uint8_to_bin(IREP_TT_FLOAT, cur); /* data type */ #ifndef MRB_NO_FLOAT @@ -216,7 +233,6 @@ write_pool_block(mrb_state *mrb, const mrb_irep *irep, uint8_t *buf) return cur - buf; } - static size_t get_syms_block_size(mrb_state *mrb, const mrb_irep *irep) { @@ -941,6 +957,17 @@ dump_pool(mrb_state *mrb, const mrb_pool_value *p, FILE *fp) } #endif break; + case IREP_TT_BIGINT: + { + const char *s = p->u.str; + int len = s[0]+2; + fputs("{IREP_TT_BIGINT, {\"", fp); + for (int i=0; i<len; i++) { + fprintf(fp, "\\x%02x", (int)s[i]&0xff); + } + fputs("\"}},\n", fp); + } + break; } } else { /* string */ diff --git a/src/load.c b/src/load.c index 68be23546..f370dc67e 100644 --- a/src/load.c +++ b/src/load.c @@ -161,6 +161,19 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag return FALSE; /* INT64 not supported on MRB_32BIT */ #endif + case IREP_TT_BIGINT: + pool_data_len = bin_to_uint8(src); /* pool data length */ + src += sizeof(uint8_t); + { + char *p; + pool[i].tt = IREP_TT_BIGINT; + p = (char*)mrb_malloc(mrb, pool_data_len+2); + memcpy(p, src, pool_data_len+2); + pool[i].u.str = (const char*)p; + } + src += pool_data_len + 2; + break; + case IREP_TT_FLOAT: #ifndef MRB_NO_FLOAT pool[i].tt = tt; diff --git a/src/state.c b/src/state.c index 0ba6db6ce..1b50eec34 100644 --- a/src/state.c +++ b/src/state.c @@ -154,7 +154,8 @@ mrb_irep_free(mrb_state *mrb, mrb_irep *irep) mrb_free(mrb, (void*)irep->iseq); if (irep->pool) { for (i=0; i<irep->plen; i++) { - if ((irep->pool[i].tt & 3) == IREP_TT_STR) { + if ((irep->pool[i].tt & 3) == IREP_TT_STR || + irep->pool[i].tt == IREP_TT_BIGINT) { mrb_free(mrb, (void*)irep->pool[i].u.str); } } @@ -1143,6 +1143,8 @@ RETRY_TRY_BLOCK: #endif goto L_INT_OVERFLOW; #endif + case IREP_TT_BIGINT: + goto L_INT_OVERFLOW; #ifndef MRB_NO_FLOAT case IREP_TT_FLOAT: regs[a] = mrb_float_value(mrb, pool[b].u.f); |
