Search code examples
c++gccembeddedc++20volatile

Platform-extension-specific replacement for volatile-specifier as hardware-register access without compiler optimizations?


In C++20 and further the volatile-specifier for variables is largely deprecated. Embedded developers using GCC have been relying on this (flawed) specifier for a long time. The concept that side-effects can occur in a code-graph, unclear by C++ statements put down in code, is not a good C++-core-language-standard idea. GCC implements it's own version of the C++ language and gives the volatile-specifier a big meaning. Is there any GCC-specific way (maybe in the works???) to properly mark a C++ object as "do not unreasonably assume content"? I am largely interested in natural C++-language-driven assignment operations, even compound. I am aware that the deprecation was made due to historical problems of mis-interpretation across compilers and MCU/CPU instruction generations and thus we are not criticizing the C++ standard itself.


Solution

  • Is there any GCC-specific way (maybe in the works???) to properly mark a C++ object as "do not unreasonably assume content"?

    That's what volatile means. The need for such a syntactic construct is one of the main reasons why volatile still exists. Indeed, the very proposal that introduced deprecating certain operations on volatile values has this as one of its primary goals:

    Continue supporting the time-honored usage of volatile to load and store variables that are used for shared memory, signal handling, setjmp / longjmp, or other external modifications such as special hardware support.

    So the tool you are looking for is still called volatile. All that has changed is that a few operations on volatile objects have been removed. Not only has there been no declared intent to remove volatile in its entirety from the language, there is a clear recognition that it is a useful tool.


    GCC implements it's own version of the C++ language and gives the volatile-specifier a big meaning.

    This is incorrect. volatile is not a magic flag that tells the compiler to just do whatever. Indeed, it is quite the opposite: it tells the compiler that it cannot just do whatever. It forces the compiler to issue loads and stores as required by the literal text of the code, even if the compiler cannot see any way that a second load could possible get a different value.

    As pointed out above, volatile is a versatile tool which can be used with a variety of constructs that are closely associated with specific hardware. Memory-mapped IO registers can be read through a volatile object whose address is assigned to the address of the MMIO register. While the mapping of that object to that address may require input outside of the C++ standard, the way you say that you want volatile behavior is part of the standard.

    That is, let's say that you're writing code that you want to be portable to two different devices. They both have a MMIO register that does basically the same thing, but they live at different addresses. When you build for each device, you assign the variable the appropriate memory address, perhaps via platform-specific macros or other build commands. But the code you write that accesses them is the same, because volatile isn't platform-specific.

    volatile is a platform-neutral tool that allows you to access platform-specific stuff. There's no reason to have every compiler roll its own way of saying, "I will read from and write to this memory location as your code literally says".