gm2
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Unexpected handling of mixed-precision integer arithmetic


From: Nelson H. F. Beebe
Subject: Unexpected handling of mixed-precision integer arithmetic
Date: Thu, 1 Feb 2024 08:34:54 -0700

In most programming languages, the conventions for evaluation of
expressions in integer arithmetic with operands of mixed precision is
that the lower-precision ones are promoted to the higher precision,
before the expression is evaluated.

In gm2-13 and gm2-14 up to builds from January 2024 gcc snapshots, I
found unexpected lower precision for both unsigned and signed
expressions that I believe are due to a compiler bug, rather than
being a misfeature of the Modula-2 language.

Here is a test program that shows the results of two ways of
evaluation of a mixed-precision expression:

        % cat TestCardinalExpr.mod
        MODULE TestCardinalExpr;

        FROM CardinalIO IMPORT WriteLongCardinal, WriteLongHex;
        FROM NumberIO   IMPORT WriteHex;
        FROM StrIO      IMPORT WriteLn, WriteString;
        FROM SYSTEM     IMPORT CARDINAL32, CARDINAL64;

        VAR vv, ww : CARDINAL64;
            h : CARDINAL32;

        BEGIN
            vv := 0000000100000000H;
            h := 7H;

            ww := 16 * vv + h;
            WriteString('16 * 0x');
            WriteLongHex(vv, 16);
            WriteString(' + 0x');
            WriteHex(h, 0);
            WriteString(' = 0x');
            WriteLongHex(ww, 16);
            WriteLn;

            vv := 0000000100000000H;
            h := 7H;

            ww := 16 * vv + VAL(CARDINAL64, h);
            WriteString('16 * 0x');
            WriteLongHex(vv, 16);
            WriteString(' + 0x');
            WriteHex(h, 0);
            WriteString(' = 0x');
            WriteLongHex(ww, 16);
            WriteLn;

        END TestCardinalExpr.

Here is the program output:

        % gm2 TestCardinalExpr.mod  && ./a.out
        16 * 0x0000000100000000 + 0x7 = 0x0000000000000007
        16 * 0x0000000100000000 + 0x7 = 0x0000001000000007

The correct answer is in the second line.  I believe that the
VAL(CARDINAL64, h) wrapper should NOT have been necessary, because the
expression 16 * vv is already in the higher precision, so 16 * vv + h
should be as well.

A similar test program with CARDINAL replaced by INTEGER shows
identical behavior.

During compiler code generation, there is likely to be a node for the
Lisp-like form (* vv h), and I expect that the test for the precision
of the multiplication is wrong, picking that of the shorter operand,
rather than the longer one.

-------------------------------------------------------------------------------
- Nelson H. F. Beebe                    Tel: +1 801 581 5254                  -
- University of Utah                                                          -
- Department of Mathematics, 110 LCB    Internet e-mail: beebe@math.utah.edu  -
- 155 S 1400 E RM 233                       beebe@acm.org  beebe@computer.org -
- Salt Lake City, UT 84112-0090, USA    URL: http://www.math.utah.edu/~beebe/ -
-------------------------------------------------------------------------------



reply via email to

[Prev in Thread] Current Thread [Next in Thread]