Two popular compilers (gcc, clang) emit a store instruction in the body of the following function:
void foo(char x) {
*(char *)0xE0000000 = x;
}
This program might behave correctly on some hardware architectures, where the address being written to is memory-mapped IO.
Since this access is performed through a pointer not qualified as volatile
, is the compiler required to emit a store here? Could a sufficiently-aggressive optimizer legally eliminate this store? I'm curious about whether this store constitutes an observable side effect with respect to the abstract machine.
Additionally, do C17 and C 20 differ in this regard?
CodePudding user response:
The C standard does not require an implementation to issue a store because C 2018 5.1.2.3 6 says:
The least requirements on a conforming implementation are:
— Accesses to volatile objects are evaluated strictly according to the rules of the abstract machine.
— At program termination, all data written into files shall be identical to the result that execution of the program according to the abstract semantics would have produced.
— The input and output dynamics of interactive devices shall take place as specified in 7.21.3. The intent of these requirements is that unbuffered or line-buffered output appear as soon as possible, to ensure that prompting messages actually appear prior to a program waiting for input.
This is the observable behavior of the program.
None of these includes assignment to a non-volatile lvalue.
CodePudding user response:
In C, it is expressly permitted to convert an integer to any pointer type, but that does not imply that you can use the resulting pointer to access memory. Unless the conversion appears in the context of a null pointer constant (which canot be used to access memory), the result of the conversion
is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.
(C17, 6.3.2.3/5)
"Implementation-defined" leaves abundant scope for subsequent accesses to the supposedly pointed-to object to have behavior that does not involve accessing memory, well beyond performing a trap or exhibiting the (unspecified) effects of a misaligned access or even exhibiting UB courtesy of a strict-aliasing violation.
Only if you get past all that do you reach the issues surrounding non-volatile
access that @EricPostpischil brings up in his answer.
The bottom line is that if you are writing for a freestanding implementation, which is the only context in which it makes any sense at all to try to perform an access such as in the example code, then you need to consult your implementation's documentation about how to access absolute addresses.
As far as I am aware, the same conclusion applies to C .