Menu

#436 volatile does not work

closed-fixed
8
2013-05-25
2003-01-07
No

SDCC version 2.3.0 for 8051:

volatile xdata char x;
void test ( void )
{
x;
}

This should generate an access to _x_, but it doesn't. It
is a problem when _x_ is a hardware register.

Discussion

  • Johan Knol

    Johan Knol - 2003-01-10

    Logged In: YES
    user_id=63512

    GCC doesn't do that either, so I think this is correct. Use
    dummy=x instead.

     
  • Johan Knol

    Johan Knol - 2003-01-10
    • milestone: --> 100455
    • priority: 5 --> 2
     
  • Tzvetan Mikov

    Tzvetan Mikov - 2003-01-11

    Logged In: YES
    user_id=675109

    SDCC is not correct.

    Relevant abstracts from the standard:

    5.1.2.3 Program execution

    1 The semantic descriptions in this International Standard
    describe the behavior of an abstract machine in which issues
    of optimization are irrelevant.

    2 Accessing a volatile object, modifying an object, modifying
    a file, or calling a function that does any of those operations
    are all side effects,11) which are changes in the state of the
    execution environment. Evaluation of an expression may
    produce side effects. At certain specified points in the
    execution sequence called sequence points, all side effects
    of previous evaluations shall be complete and no side effects
    of subsequent evaluations shall have taken place. (A
    summary of the sequence points is given in annex C.)

    3 In the abstract machine, all expressions are evaluated as
    specified by the semantics. An actual implementation need
    not evaluate part of an expression if it can deduce that its
    value is not used and that no needed side effects are
    produced (including any caused by calling a function or
    accessing a volatile object).

    6.7.3 Type qualifiers

    6 An object that has volatile-qualified type may be modified in
    ways unknown to the implementation or have other unknown
    side effects. Therefore any expressionreferring to such an
    object shall be evaluated strictly according to the rules of the
    abstract machine, as described in 5.1.2.3. Furthermore, at
    every sequence point the value last stored in the object shall
    agree with that prescribed by the abstract machine, except
    as modified by the unknown factors mentioned
    previously.114) What constitutes an access to an object that
    has volatile-qualified type is implementation-defined.

    In fact GCC does comply with this. GCC 2.95.3 generates
    the following
    *correct* code:

    volatile int x;
    void test ( void )
    {
    x;
    }

    _test:
    pushl %ebp
    movl %esp,%ebp
    movl _x,%eax
    movl %ebp,%esp
    popl %ebp
    ret

    If newer versions of GCC behave otherwise, then they are
    broken.

    Further on, the proposed solution of using "dummy=x"
    doesn't actually change anything. If "dummy" is a non-volatile
    local variable, then it can be optimized out, bringing us back
    to the same problem. If "dummy" is global variable, then we
    are changing the desired semantics of the program (which in
    this case are to read from "x" and ignore the value), which is
    unacceptable.

    This bug may be difficult to fix, but there is no other standard
    way to access memory-mapped hardware registers. I believe
    this is very important for an embedded compiler.

     
  • Tzvetan Mikov

    Tzvetan Mikov - 2003-01-11
    • milestone: 100455 --> known_bugs
     
  • Johan Knol

    Johan Knol - 2003-01-11
    • priority: 2 --> 8
     
  • Johan Knol

    Johan Knol - 2003-01-11

    Logged In: YES
    user_id=63512

    You are right, this is a bug. Sorry about my premature
    conclusion.

    The problem starts in ast2iCode where it is NULLOP. This
    can be handled by inserting a dummy assignment to an
    iTemp, however a volatile iTemp is misinterpreted in the
    optimizer and if handled correctly there, later on in the code
    generator. The following code shows that clearly:

    sfr at 0x80 MYREG;

    void oops (void) {
    MYREG=MYREG;
    }

    The aopPut() and aopGet() methods in the code generator
    have no knowledge about the volatile-ness of the symbol. This
    requires a major redesign.

    So I raised the bug with three points above average.

     
  • Tzvetan Mikov

    Tzvetan Mikov - 2003-01-14

    Logged In: YES
    user_id=675109

    In this context it is an interresting question whether sfr-s
    should be volatile by default. I think that ideally it should be
    decided on a case by case basis - for example SBUF should
    be declared volatile, but "pure" registers like DPTR, ACC, B,
    etc should not be.

    Volatile has always been a pain in the a** :-) Note that the
    Standard actually allows an implementation to
    ignore "volatile", as long as this is a documented and
    deliberate choice ("What constitutes an access to an object
    that has volatile-qualified type is implementation-defined").
    Unfortunately this is not very useful in practice...

    I am thinking that for now a possibly easy workaround might
    be to ignore "volatile" altogether but add several inline
    intrinsic functions like __volatile_read_char(),
    __volatile_write_char(), etc, with precisely defined semantics.
    This however still could be defeated by a peephole
    optimization like this seemingly safe one:

    replace {
    mov a,%1
    mov a,%1
    } by {
    mov a,%1
    }

    so a predicate "operandsNotVolatile" may have to be added.

     
  • Erik Petrich

    Erik Petrich - 2003-10-03
    • assigned_to: nobody --> epetrich
     
  • Erik Petrich

    Erik Petrich - 2003-10-03

    Logged In: YES
    user_id=635249

    Fixed for mcs51, ds390, z80, & their associated targets. See
    ChangeLog 1.444

    pic & pic16 still need a real genDummyRead and support for
    dummy iTemps.

     
  • Maarten Brock

    Maarten Brock - 2005-03-21

    Logged In: YES
    user_id=888171

    I see genDummyRead in avr, ds390, hc08, mcs51, pic,
    pic16, xa51 and z80. Does this mean every port has this bug
    fixed and this report can be closed? Has anyone any idea for
    a regression test for this bug.

     
  • Erik Petrich

    Erik Petrich - 2005-06-10
    • status: open --> closed-fixed
     
  • Frieder Ferlemann

    Logged In: YES
    user_id=589052

    > Has anyone any idea for a regression test for this bug.

    This one is a rude check whether there's any code generated:

    volatile xdata char x;
    volatile data char check_me;

    void test ( void )
    {
    _asm
    MY_UNIQUE_1 = .
    _endasm;

    x;

    _asm
    MY_UNIQUE_2 = .
    mov _check_me,#MY_UNIQUE_2-MY_UNIQUE_1
    _endasm;
    }

     
  • Maarten Brock

    Maarten Brock - 2005-06-14

    Logged In: YES
    user_id=888171

    How about this: If I'm not mistaken the simulator ends a
    simulation when a certain specific address is accessed. By
    placing the volatile variable at that specific address using
    __at we can end the simulation: a side-effect we can check.
    Otherwise the test must hang and generate a timeout.

    volatile xdata at 0x7654 char x;
    void test (void)
    {
    x;
    while (1); //let the "watchdog" bite
    }

    Unfortunately this seems only true for mcs51 alike mcu's.

     

Log in to post a comment.