Fix issues with addressing/pointer arithmetic using unsigned indexes that generate a displacement of 32K to 64K.

These cases should now always work when using an expression of type unsigned as the index. They will work in some cases but not others when using an int as the index: making those cases work consistently would require more extensive changes and/or a speed hit, so I haven't done it for now.

Note that this now uses an "unsigned multiply" operation for all 16-bit index computations. This should actually work even when the index is a negative signed value, because it will wind up producing (the low-order 16 bits of) the right answer. The signed multiply, on the other hand, generally does not produce the low-order 16 bits of the right answer in cases where it overflows.

The following program is an example that was miscompiled (both with and without optimization):

int c[20000] = {3};

int main(void) {
    int *p;
    unsigned i = 17000;

    p = c + 17000u;
    return *(p-i); /* should return 3 */
}
This commit is contained in:
Stephen Heumann 2017-11-12 17:21:05 -06:00
parent df42ce257f
commit ba09d5ee6d
2 changed files with 2 additions and 2 deletions

View File

@ -1487,7 +1487,7 @@ case op^.opcode of {check for optimizations of this node}
pc_ixa: begin {pc_ixa}
if op^.right^.opcode = pc_ldc then begin
optype := op^.right^.optype;
optype := op^.optype;
if optype in [cgUByte, cgByte, cgUWord, cgWord] then begin
lval := op^.right^.q;
if optype = cgUByte then

View File

@ -2185,7 +2185,7 @@ case tp of
else if smallMemoryModel and (size = long(size).lsw) then begin
if size <> 1 then begin
Gen1t(pc_ldc, long(size).lsw, cgWord);
Gen0(pc_mpi);
Gen0(pc_umi);
end; {if}
Gen2(pc_cnv, ord(tp), ord(cgLong));
Gen0(op);