]> granicus.if.org Git - yasm/commitdiff
A number of fixes to float and integer handling on the output side:
authorPeter Johnson <peter@tortall.net>
Thu, 2 May 2002 06:09:07 +0000 (06:09 -0000)
committerPeter Johnson <peter@tortall.net>
Thu, 2 May 2002 06:09:07 +0000 (06:09 -0000)
- 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

22 files changed:
libyasm/expr.c
modules/objfmts/bin/bin-objfmt.c
modules/objfmts/bin/tests/Makefile.inc
modules/objfmts/bin/tests/float-err.asm [new file with mode: 0644]
modules/objfmts/bin/tests/float-err.errwarn [new file with mode: 0644]
modules/objfmts/bin/tests/float.asm [new file with mode: 0644]
modules/objfmts/bin/tests/float.bin.hx [new file with mode: 0644]
modules/objfmts/bin/tests/float.errwarn [new file with mode: 0644]
modules/objfmts/bin/tests/integer.asm [new file with mode: 0644]
modules/objfmts/bin/tests/integer.bin.hx [new file with mode: 0644]
modules/objfmts/bin/tests/integer.errwarn [new file with mode: 0644]
src/expr.c
src/objfmts/bin/bin-objfmt.c
src/objfmts/bin/tests/Makefile.inc
src/objfmts/bin/tests/float-err.asm [new file with mode: 0644]
src/objfmts/bin/tests/float-err.errwarn [new file with mode: 0644]
src/objfmts/bin/tests/float.asm [new file with mode: 0644]
src/objfmts/bin/tests/float.bin.hx [new file with mode: 0644]
src/objfmts/bin/tests/float.errwarn [new file with mode: 0644]
src/objfmts/bin/tests/integer.asm [new file with mode: 0644]
src/objfmts/bin/tests/integer.bin.hx [new file with mode: 0644]
src/objfmts/bin/tests/integer.errwarn [new file with mode: 0644]

index 966a6d00e52ea9a53da34e03eedcdf3adb52d18d..ade3789aa4946d96921f8c64321777564dba8dfb 100644 (file)
@@ -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.
index ebdea2e7320c90ac43174422ad4e8b1ee1b82fad..3a89917f22da8f78079a34877421fb2b5cac82af 100644 (file)
@@ -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
index 483d92e59acadb6950288a9b971cd2a54689818d..e1d510c76ed63030f9f946cdc93b75af73a46db1 100644 (file)
@@ -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 (file)
index 0000000..56a766c
--- /dev/null
@@ -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 (file)
index 0000000..469e7e4
--- /dev/null
@@ -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 (file)
index 0000000..a2823f3
--- /dev/null
@@ -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 (file)
index 0000000..066fa76
--- /dev/null
@@ -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 (file)
index 0000000..e69de29
diff --git a/modules/objfmts/bin/tests/integer.asm b/modules/objfmts/bin/tests/integer.asm
new file mode 100644 (file)
index 0000000..469887c
--- /dev/null
@@ -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 (file)
index 0000000..baad38f
--- /dev/null
@@ -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 (file)
index 0000000..e69de29
index 966a6d00e52ea9a53da34e03eedcdf3adb52d18d..ade3789aa4946d96921f8c64321777564dba8dfb 100644 (file)
@@ -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.
index ebdea2e7320c90ac43174422ad4e8b1ee1b82fad..3a89917f22da8f78079a34877421fb2b5cac82af 100644 (file)
@@ -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
index 483d92e59acadb6950288a9b971cd2a54689818d..e1d510c76ed63030f9f946cdc93b75af73a46db1 100644 (file)
@@ -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 (file)
index 0000000..56a766c
--- /dev/null
@@ -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 (file)
index 0000000..469e7e4
--- /dev/null
@@ -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 (file)
index 0000000..a2823f3
--- /dev/null
@@ -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 (file)
index 0000000..066fa76
--- /dev/null
@@ -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 (file)
index 0000000..e69de29
diff --git a/src/objfmts/bin/tests/integer.asm b/src/objfmts/bin/tests/integer.asm
new file mode 100644 (file)
index 0000000..469887c
--- /dev/null
@@ -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 (file)
index 0000000..baad38f
--- /dev/null
@@ -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 (file)
index 0000000..e69de29