From 2087526342e3fe3f74e5a609d3025ee964d58e4a Mon Sep 17 00:00:00 2001 From: Masamitsu MURASE Date: Sun, 3 Feb 2013 16:29:46 +0900 Subject: Modify handling of integer literal. Do not assume that significand of `double` is larger than `mrb_int`. --- src/codegen.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 9 deletions(-) (limited to 'src/codegen.c') diff --git a/src/codegen.c b/src/codegen.c index 5803a9c25..1f6d16477 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -959,6 +959,48 @@ readint_float(codegen_scope *s, const char *p, int base) return f; } +static mrb_int +readint_mrb_int(codegen_scope *s, const char *p, int base, int neg, int *overflow) +{ + const char *e = p + strlen(p); + mrb_int result = 0; + int n; + + if (*p == '+') p++; + while (p < e) { + char c = *p; + c = tolower((unsigned char)c); + for (n=0; n result) { + *overflow = TRUE; + return 0; + } + result *= base; + result -= n; + } + else { + if ((MRB_INT_MAX - n)/base < result) { + *overflow = TRUE; + return 0; + } + result *= base; + result += n; + } + p++; + } + *overflow = FALSE; + return result; +} + static void codegen(codegen_scope *s, node *tree, int val) { @@ -1733,18 +1775,18 @@ codegen(codegen_scope *s, node *tree, int val) if (val) { char *p = (char*)tree->car; int base = (intptr_t)tree->cdr->car; - double f; mrb_int i; mrb_code co; + int overflow; - f = readint_float(s, p, base); - if (!FIXABLE(f)) { + i = readint_mrb_int(s, p, base, FALSE, &overflow); + if (overflow) { + double f = readint_float(s, p, base); int off = new_lit(s, mrb_float_value(f)); genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); } else { - i = (mrb_int)f; if (i < MAXARG_sBx && i > -MAXARG_sBx) { co = MKOP_AsBx(OP_LOADI, cursp(), i); } @@ -1789,18 +1831,18 @@ codegen(codegen_scope *s, node *tree, int val) { char *p = (char*)tree->car; int base = (intptr_t)tree->cdr->car; - mrb_float f; mrb_int i; mrb_code co; + int overflow; - f = readint_float(s, p, base); - if (!FIXABLE(f)) { + i = readint_mrb_int(s, p, base, TRUE, &overflow); + if (overflow) { + double f = readint_float(s, p, base); int off = new_lit(s, mrb_float_value(-f)); - + genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); } else { - i = (mrb_int)-f; if (i < MAXARG_sBx && i > -MAXARG_sBx) { co = MKOP_AsBx(OP_LOADI, cursp(), i); } -- cgit v1.2.3