From: Peter Johnson Date: Thu, 2 May 2002 06:09:07 +0000 (-0000) Subject: A number of fixes to float and integer handling on the output side: X-Git-Tag: v0.2.0~221 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=070322513602a27b7119089d51c1dee9ba25b8e8;p=yasm A number of fixes to float and integer handling on the output side: - expr can now negate floatnums - bin objfmt output_expr now correctly outputs all sizes of integers and does a check for floating point containing exprs before complaining about external references. Also checks for properly sized floatnum output with an ErrorAt instead of an InternalError. svn path=/trunk/yasm/; revision=618 --- diff --git a/libyasm/expr.c b/libyasm/expr.c index 966a6d00..ade3789a 100644 --- a/libyasm/expr.c +++ b/libyasm/expr.c @@ -200,11 +200,20 @@ expr_xform_neg_helper(/*@returned@*/ /*@only@*/ expr *e) e->op = EXPR_IDENT; break; case EXPR_IDENT: - /* Negating an ident? Change it into a MUL w/ -1. */ - e->op = EXPR_MUL; - e->numterms = 2; - e->terms[1].type = EXPR_INT; - e->terms[1].data.intn = intnum_new_int((unsigned long)-1); + /* Negating an ident? Change it into a MUL w/ -1 if there's no + * floatnums present below; if there ARE floatnums, recurse. + */ + if (e->terms[0].type == EXPR_FLOAT) + floatnum_calc(e->terms[0].data.flt, EXPR_NEG, NULL); + else if (e->terms[0].type == EXPR_EXPR && + expr_contains(e->terms[0].data.expn, EXPR_FLOAT)) + expr_xform_neg_helper(e->terms[0].data.expn); + else { + e->op = EXPR_MUL; + e->numterms = 2; + e->terms[1].type = EXPR_INT; + e->terms[1].data.intn = intnum_new_int((unsigned long)-1); + } break; default: /* Everything else. MUL will be combined when it's leveled. diff --git a/modules/objfmts/bin/bin-objfmt.c b/modules/objfmts/bin/bin-objfmt.c index ebdea2e7..3a89917f 100644 --- a/modules/objfmts/bin/bin-objfmt.c +++ b/modules/objfmts/bin/bin-objfmt.c @@ -195,7 +195,6 @@ bin_objfmt_output_expr(expr **ep, unsigned char **bufp, unsigned long valsize, /*@observer@*/ bin_objfmt_expr_data data; /*@dependent@*/ /*@null@*/ const intnum *num; /*@dependent@*/ /*@null@*/ const floatnum *flt; - unsigned long val; assert(info != NULL); @@ -220,6 +219,12 @@ bin_objfmt_output_expr(expr **ep, unsigned char **bufp, unsigned long valsize, flt = expr_get_floatnum(ep); if (flt) { int fltret; + + if (!floatnum_check_size(flt, (size_t)valsize)) { + ErrorAt((*ep)->line, _("invalid floating point constant size")); + return 1; + } + fltret = floatnum_get_sized(flt, *bufp, (size_t)valsize); if (fltret < 0) { ErrorAt((*ep)->line, _("underflow in floating point expression")); @@ -235,33 +240,32 @@ bin_objfmt_output_expr(expr **ep, unsigned char **bufp, unsigned long valsize, /* Handle integer expressions */ num = expr_get_intnum(ep); - if (!num) { - ErrorAt((*ep)->line, - _("binary object format does not support external references")); - return 1; + if (num) { + if (rel) { + unsigned long val; + /* FIXME: Check against BITS setting on x86 */ + if (valsize != 2 && valsize != 4) + InternalError(_("tried to do PC-relative offset from invalid sized value")); + val = intnum_get_uint(num); + val = (unsigned long)((long)(val - (bc->offset + bc->len))); + } + + /* Write value out. */ + intnum_get_sized(num, *bufp, (size_t)valsize); + *bufp += valsize; + return 0; } - val = intnum_get_uint(num); - - if (rel) - val = (unsigned long)((long)(val - (bc->offset + bc->len))); - - /* Write value out. */ - /* FIXME: Should we warn here about truncation if it doesn't fit? */ - switch (valsize) { - case 1: - WRITE_BYTE(*bufp, val); - break; - case 2: - WRITE_SHORT(*bufp, val); - break; - case 4: - WRITE_LONG(*bufp, val); - break; - default: - InternalError(_("unexpected size in bin objfmt output expr")); + + /* Check for complex float expressions */ + if (expr_contains(*ep, EXPR_FLOAT)) { + ErrorAt((*ep)->line, _("floating point expression too complex")); + return 1; } - return 0; + /* Couldn't output, assume it contains an external reference. */ + ErrorAt((*ep)->line, + _("binary object format does not support external references")); + return 1; } static int diff --git a/modules/objfmts/bin/tests/Makefile.inc b/modules/objfmts/bin/tests/Makefile.inc index 483d92e5..e1d510c7 100644 --- a/modules/objfmts/bin/tests/Makefile.inc +++ b/modules/objfmts/bin/tests/Makefile.inc @@ -5,11 +5,26 @@ TESTS += \ EXTRA_DIST += \ src/objfmts/bin/tests/objfmt_test.sh \ + src/objfmts/bin/tests/float-err.asm \ + src/objfmts/bin/tests/float-err.errwarn \ + src/objfmts/bin/tests/float.asm \ + src/objfmts/bin/tests/float.bin.hx \ + src/objfmts/bin/tests/float.errwarn \ + src/objfmts/bin/tests/integer.asm \ + src/objfmts/bin/tests/integer.bin.hx \ + src/objfmts/bin/tests/integer.errwarn \ src/objfmts/bin/tests/reserve.asm \ src/objfmts/bin/tests/reserve.bin.hx \ src/objfmts/bin/tests/reserve.errwarn CLEANFILES += \ + float-err.ew \ + float \ + float.hx \ + float.ew \ + integer \ + integer.hx \ + integer.ew \ reserve \ reserve.ew \ reserve.hx diff --git a/modules/objfmts/bin/tests/float-err.asm b/modules/objfmts/bin/tests/float-err.asm new file mode 100644 index 00000000..56a766c2 --- /dev/null +++ b/modules/objfmts/bin/tests/float-err.asm @@ -0,0 +1,12 @@ +; Tests illegal float handling +db 1.2 +dw 3.14 +dd 5.12e100000 +dq 3.141592653589793e-158105 +dt 5653894745.318293470142875104710284019245e-1999 + +db -1.5 +dw -5593824513450897123075109385109385019324871093470134710984.34981 +dd -47102940.46710358135703124751034875109875103294510984019324 +dq -45102571092751092341095.5827509174509178450917845019e15555 +dt -1.e-100000 diff --git a/modules/objfmts/bin/tests/float-err.errwarn b/modules/objfmts/bin/tests/float-err.errwarn new file mode 100644 index 00000000..469e7e45 --- /dev/null +++ b/modules/objfmts/bin/tests/float-err.errwarn @@ -0,0 +1,8 @@ +./src/objfmts/bin/tests/float-err.asm:2: invalid floating point constant size +./src/objfmts/bin/tests/float-err.asm:3: invalid floating point constant size +./src/objfmts/bin/tests/float-err.asm:4: overflow in floating point expression +./src/objfmts/bin/tests/float-err.asm:5: underflow in floating point expression +./src/objfmts/bin/tests/float-err.asm:8: invalid floating point constant size +./src/objfmts/bin/tests/float-err.asm:9: invalid floating point constant size +./src/objfmts/bin/tests/float-err.asm:11: overflow in floating point expression +./src/objfmts/bin/tests/float-err.asm:12: underflow in floating point expression diff --git a/modules/objfmts/bin/tests/float.asm b/modules/objfmts/bin/tests/float.asm new file mode 100644 index 00000000..a2823f35 --- /dev/null +++ b/modules/objfmts/bin/tests/float.asm @@ -0,0 +1,8 @@ +; Tests float handling +dd 5.12 +dq 3.141592653589793 +dt 5653894745.318293470142875104710284019245e335 + +dd -47102940.467103581 +dq -45102571092751092341095.5827509174509178450917845019 +dt -1.e-1000 diff --git a/modules/objfmts/bin/tests/float.bin.hx b/modules/objfmts/bin/tests/float.bin.hx new file mode 100644 index 00000000..066fa76e --- /dev/null +++ b/modules/objfmts/bin/tests/float.bin.hx @@ -0,0 +1,44 @@ +0a +d7 +a3 +40 +18 +2d +44 +54 +fb +21 +09 +40 +75 +4e +ef +f1 +30 +25 +6e +97 +78 +44 +f7 +ae +33 +cc +4d +63 +8a +d2 +07 +1a +a3 +c4 +67 +14 +9e +a8 +88 +91 +8a +86 +05 +b3 diff --git a/modules/objfmts/bin/tests/float.errwarn b/modules/objfmts/bin/tests/float.errwarn new file mode 100644 index 00000000..e69de29b diff --git a/modules/objfmts/bin/tests/integer.asm b/modules/objfmts/bin/tests/integer.asm new file mode 100644 index 00000000..469887c4 --- /dev/null +++ b/modules/objfmts/bin/tests/integer.asm @@ -0,0 +1,8 @@ +; Tests integer constant handling (for output, not parsing) + +db 0x51 +dw 0x3875 +dd 0x35783134 +dq 0xABCDEF0123456789 +dt 0xa907bc890d0e907f0134 + diff --git a/modules/objfmts/bin/tests/integer.bin.hx b/modules/objfmts/bin/tests/integer.bin.hx new file mode 100644 index 00000000..baad38fd --- /dev/null +++ b/modules/objfmts/bin/tests/integer.bin.hx @@ -0,0 +1,25 @@ +51 +75 +38 +34 +31 +78 +35 +89 +67 +45 +23 +01 +ef +cd +ab +34 +01 +7f +90 +0e +0d +89 +bc +07 +a9 diff --git a/modules/objfmts/bin/tests/integer.errwarn b/modules/objfmts/bin/tests/integer.errwarn new file mode 100644 index 00000000..e69de29b diff --git a/src/expr.c b/src/expr.c index 966a6d00..ade3789a 100644 --- a/src/expr.c +++ b/src/expr.c @@ -200,11 +200,20 @@ expr_xform_neg_helper(/*@returned@*/ /*@only@*/ expr *e) e->op = EXPR_IDENT; break; case EXPR_IDENT: - /* Negating an ident? Change it into a MUL w/ -1. */ - e->op = EXPR_MUL; - e->numterms = 2; - e->terms[1].type = EXPR_INT; - e->terms[1].data.intn = intnum_new_int((unsigned long)-1); + /* Negating an ident? Change it into a MUL w/ -1 if there's no + * floatnums present below; if there ARE floatnums, recurse. + */ + if (e->terms[0].type == EXPR_FLOAT) + floatnum_calc(e->terms[0].data.flt, EXPR_NEG, NULL); + else if (e->terms[0].type == EXPR_EXPR && + expr_contains(e->terms[0].data.expn, EXPR_FLOAT)) + expr_xform_neg_helper(e->terms[0].data.expn); + else { + e->op = EXPR_MUL; + e->numterms = 2; + e->terms[1].type = EXPR_INT; + e->terms[1].data.intn = intnum_new_int((unsigned long)-1); + } break; default: /* Everything else. MUL will be combined when it's leveled. diff --git a/src/objfmts/bin/bin-objfmt.c b/src/objfmts/bin/bin-objfmt.c index ebdea2e7..3a89917f 100644 --- a/src/objfmts/bin/bin-objfmt.c +++ b/src/objfmts/bin/bin-objfmt.c @@ -195,7 +195,6 @@ bin_objfmt_output_expr(expr **ep, unsigned char **bufp, unsigned long valsize, /*@observer@*/ bin_objfmt_expr_data data; /*@dependent@*/ /*@null@*/ const intnum *num; /*@dependent@*/ /*@null@*/ const floatnum *flt; - unsigned long val; assert(info != NULL); @@ -220,6 +219,12 @@ bin_objfmt_output_expr(expr **ep, unsigned char **bufp, unsigned long valsize, flt = expr_get_floatnum(ep); if (flt) { int fltret; + + if (!floatnum_check_size(flt, (size_t)valsize)) { + ErrorAt((*ep)->line, _("invalid floating point constant size")); + return 1; + } + fltret = floatnum_get_sized(flt, *bufp, (size_t)valsize); if (fltret < 0) { ErrorAt((*ep)->line, _("underflow in floating point expression")); @@ -235,33 +240,32 @@ bin_objfmt_output_expr(expr **ep, unsigned char **bufp, unsigned long valsize, /* Handle integer expressions */ num = expr_get_intnum(ep); - if (!num) { - ErrorAt((*ep)->line, - _("binary object format does not support external references")); - return 1; + if (num) { + if (rel) { + unsigned long val; + /* FIXME: Check against BITS setting on x86 */ + if (valsize != 2 && valsize != 4) + InternalError(_("tried to do PC-relative offset from invalid sized value")); + val = intnum_get_uint(num); + val = (unsigned long)((long)(val - (bc->offset + bc->len))); + } + + /* Write value out. */ + intnum_get_sized(num, *bufp, (size_t)valsize); + *bufp += valsize; + return 0; } - val = intnum_get_uint(num); - - if (rel) - val = (unsigned long)((long)(val - (bc->offset + bc->len))); - - /* Write value out. */ - /* FIXME: Should we warn here about truncation if it doesn't fit? */ - switch (valsize) { - case 1: - WRITE_BYTE(*bufp, val); - break; - case 2: - WRITE_SHORT(*bufp, val); - break; - case 4: - WRITE_LONG(*bufp, val); - break; - default: - InternalError(_("unexpected size in bin objfmt output expr")); + + /* Check for complex float expressions */ + if (expr_contains(*ep, EXPR_FLOAT)) { + ErrorAt((*ep)->line, _("floating point expression too complex")); + return 1; } - return 0; + /* Couldn't output, assume it contains an external reference. */ + ErrorAt((*ep)->line, + _("binary object format does not support external references")); + return 1; } static int diff --git a/src/objfmts/bin/tests/Makefile.inc b/src/objfmts/bin/tests/Makefile.inc index 483d92e5..e1d510c7 100644 --- a/src/objfmts/bin/tests/Makefile.inc +++ b/src/objfmts/bin/tests/Makefile.inc @@ -5,11 +5,26 @@ TESTS += \ EXTRA_DIST += \ src/objfmts/bin/tests/objfmt_test.sh \ + src/objfmts/bin/tests/float-err.asm \ + src/objfmts/bin/tests/float-err.errwarn \ + src/objfmts/bin/tests/float.asm \ + src/objfmts/bin/tests/float.bin.hx \ + src/objfmts/bin/tests/float.errwarn \ + src/objfmts/bin/tests/integer.asm \ + src/objfmts/bin/tests/integer.bin.hx \ + src/objfmts/bin/tests/integer.errwarn \ src/objfmts/bin/tests/reserve.asm \ src/objfmts/bin/tests/reserve.bin.hx \ src/objfmts/bin/tests/reserve.errwarn CLEANFILES += \ + float-err.ew \ + float \ + float.hx \ + float.ew \ + integer \ + integer.hx \ + integer.ew \ reserve \ reserve.ew \ reserve.hx diff --git a/src/objfmts/bin/tests/float-err.asm b/src/objfmts/bin/tests/float-err.asm new file mode 100644 index 00000000..56a766c2 --- /dev/null +++ b/src/objfmts/bin/tests/float-err.asm @@ -0,0 +1,12 @@ +; Tests illegal float handling +db 1.2 +dw 3.14 +dd 5.12e100000 +dq 3.141592653589793e-158105 +dt 5653894745.318293470142875104710284019245e-1999 + +db -1.5 +dw -5593824513450897123075109385109385019324871093470134710984.34981 +dd -47102940.46710358135703124751034875109875103294510984019324 +dq -45102571092751092341095.5827509174509178450917845019e15555 +dt -1.e-100000 diff --git a/src/objfmts/bin/tests/float-err.errwarn b/src/objfmts/bin/tests/float-err.errwarn new file mode 100644 index 00000000..469e7e45 --- /dev/null +++ b/src/objfmts/bin/tests/float-err.errwarn @@ -0,0 +1,8 @@ +./src/objfmts/bin/tests/float-err.asm:2: invalid floating point constant size +./src/objfmts/bin/tests/float-err.asm:3: invalid floating point constant size +./src/objfmts/bin/tests/float-err.asm:4: overflow in floating point expression +./src/objfmts/bin/tests/float-err.asm:5: underflow in floating point expression +./src/objfmts/bin/tests/float-err.asm:8: invalid floating point constant size +./src/objfmts/bin/tests/float-err.asm:9: invalid floating point constant size +./src/objfmts/bin/tests/float-err.asm:11: overflow in floating point expression +./src/objfmts/bin/tests/float-err.asm:12: underflow in floating point expression diff --git a/src/objfmts/bin/tests/float.asm b/src/objfmts/bin/tests/float.asm new file mode 100644 index 00000000..a2823f35 --- /dev/null +++ b/src/objfmts/bin/tests/float.asm @@ -0,0 +1,8 @@ +; Tests float handling +dd 5.12 +dq 3.141592653589793 +dt 5653894745.318293470142875104710284019245e335 + +dd -47102940.467103581 +dq -45102571092751092341095.5827509174509178450917845019 +dt -1.e-1000 diff --git a/src/objfmts/bin/tests/float.bin.hx b/src/objfmts/bin/tests/float.bin.hx new file mode 100644 index 00000000..066fa76e --- /dev/null +++ b/src/objfmts/bin/tests/float.bin.hx @@ -0,0 +1,44 @@ +0a +d7 +a3 +40 +18 +2d +44 +54 +fb +21 +09 +40 +75 +4e +ef +f1 +30 +25 +6e +97 +78 +44 +f7 +ae +33 +cc +4d +63 +8a +d2 +07 +1a +a3 +c4 +67 +14 +9e +a8 +88 +91 +8a +86 +05 +b3 diff --git a/src/objfmts/bin/tests/float.errwarn b/src/objfmts/bin/tests/float.errwarn new file mode 100644 index 00000000..e69de29b diff --git a/src/objfmts/bin/tests/integer.asm b/src/objfmts/bin/tests/integer.asm new file mode 100644 index 00000000..469887c4 --- /dev/null +++ b/src/objfmts/bin/tests/integer.asm @@ -0,0 +1,8 @@ +; Tests integer constant handling (for output, not parsing) + +db 0x51 +dw 0x3875 +dd 0x35783134 +dq 0xABCDEF0123456789 +dt 0xa907bc890d0e907f0134 + diff --git a/src/objfmts/bin/tests/integer.bin.hx b/src/objfmts/bin/tests/integer.bin.hx new file mode 100644 index 00000000..baad38fd --- /dev/null +++ b/src/objfmts/bin/tests/integer.bin.hx @@ -0,0 +1,25 @@ +51 +75 +38 +34 +31 +78 +35 +89 +67 +45 +23 +01 +ef +cd +ab +34 +01 +7f +90 +0e +0d +89 +bc +07 +a9 diff --git a/src/objfmts/bin/tests/integer.errwarn b/src/objfmts/bin/tests/integer.errwarn new file mode 100644 index 00000000..e69de29b