1: Sample code that reproduces the problem.
int *object;
int *test(int *p)
{
object = p;
return *(int *volatile *)&object;
}
Save as volatile-read-mos6502.c.
2: Exact command used to run SDCC on this sample code.
sdcc -mmos6502 --c1mode -o volatile-read-mos6502.asm < volatile-read-mos6502.c
The input contains no headers or macros. Add --no-peep to compare the output
without peephole optimisation.
3: SDCC versions tested.
SDCC 4.6.4 r17064, locally built from unmodified compiler sources; the official
SDCC 4.6.4 #17038 snapshot; and SDCC 4.2.0 #13081, all on Linux.
4: Copy of the incorrect output, or a clear description of the observed versus expected behaviour.
The generated function stores the pointer supplied in A/X, but reads back
only its low byte:
sta _object
stx (_object+1)
lda _object
rts
I expected both bytes of the pointer to be read through the volatile-qualified
lvalue in the return expression. With --no-peep, the high-byte read remains:
sta _object
stx (_object+1)
ldx (_object+1)
lda _object
rts
SDCC 4.2.0 #13081 emits both reads with its normal peephole optimisation.
The loss is present by r17038; the first failing revision has not been found.
The same reduced case also loses its high-byte read on mos65c02 and huc6280
with the tested r17064 compiler.
The problem is reproduced with unmodified r17064 sources, before the
Z80-family symbol-lookup candidate. It is not introduced by that candidate.
Possibly related to [bugs:#4156]. In this example, --no-peep retains the
required read; the loss can therefore be isolated to peephole optimisation.
Fixed by [r17075]
Related
Commit: [r17075]