Fix code generation for certain cases where addresses are stored to local variables that don't fit in the direct page.

There was a bug when storing addresses generated by expressions like &a[i], where a is a global array and i is a variable. In certain cases where the destination location was a local variable that didn't fit in the direct page, the result of the address calculation would be stored to the wrong location on the stack. This failed to give the correct result, and could also sometimes cause crashes or other problems due to stack corruption.

The following program (derived from a csmith-generated test case) illustrates the issues:

#pragma optimize 1
long g_87[5];
static int g_242 = 4;

int main(void) {
    char l_298[256];
    long *l_284[3] = {0, 0, &g_87[g_242]};
    return l_284[2]-g_87; /* should be 4 */
}
This commit is contained in:
Stephen Heumann 2018-03-31 15:45:05 -05:00
parent bfe4416623
commit fd0ff033ad
1 changed files with 15 additions and 6 deletions

21
Gen.pas
View File

@ -3746,19 +3746,25 @@ case optype of
GenImplied(m_tdc);
GenImplied(m_clc);
GenNative(m_adc_imm, immediate, gLong.disp, nil, 0);
if not gLong.fixedDisp then begin
if not gLong.fixedDisp then
GenNative(m_adc_s, direct, 1, nil, 0);
GenImplied(m_ply);
end; {if}
GenNative(m_sta_dirX, direct, 0, nil, 0);
GenNative(m_stz_dirX, direct, 2, nil, 0);
if not gLong.fixedDisp then
GenImplied(m_plx);
end; {else}
globalLabel: begin
if not gLong.fixedDisp then
GenImplied(m_txa)
else if disp > 253 then
GenImplied(m_txa);
if disp > 253 then begin
if op^.opcode = pc_cop then
if not gLong.fixedDisp then
GenImplied(m_tay)
else
GenImplied(m_txy);
GenNative(m_ldx_imm, immediate, disp, nil, 0);
end; {if}
if gLong.fixedDisp then
GenNative(m_lda_imm, immediate, gLong.disp, gLong.lab, 0)
else begin
@ -3774,8 +3780,11 @@ case optype of
GenNative(m_adc_imm, immediate, 0, nil, 0);
if disp < 254 then
GenNative(m_sta_dir, direct, disp+2, nil, 0)
else
else begin
GenNative(m_sta_dirX, direct, 2, nil, 0);
if op^.opcode = pc_cop then
GenImplied(m_tyx);
end; {else}
end;
constant: