On 05/07/2023 11:25, Martin Uecker wrote:
Am Mittwoch, dem 05.07.2023 um 11:11 +0200 schrieb David Brown:
On 05/07/2023 10:05, Rafał Pietrak via Gcc wrote:
...
In my personal opinion (which you are all free to disregard), named
address spaces were an interesting idea that failed. I was
enthusiastic
about a number of the extensions in TR 18307 "C Extensions to support
embedded processors" when the paper was first published. As I
learned
more, however, I saw it was a dead-end. The features are too
under-specified to be useful or portable, gave very little of use to
embedded programmers, and fit badly with C. It was an attempt to
standardise and generalise some of the mess of different extensions
that
proprietary toolchain developers had for a variety of 8-bit CISC
microcontrollers that could not use standard C very effectively. But
it
was all too little, too late - and AFAIK none of these proprietary
toolchains support it. GCC supports some of the features to some
extent
- a few named address spaces on a few devices, for "gnuc" only (not
standard C, and not C++), and has some fixed point support for some
targets (with inefficient generated code - it appears to be little
more
than an initial "proof of concept" implementation).
I do not think named address spaces have a future - in GCC or
anywhere
else. The only real use of them at the moment is for the AVR for
accessing data in flash, and even then it is of limited success since
it
does not work in C++.
Can you explain a little bit why you think it is a dead-end? It
seems an elegant solution to a range of problems to me.
Named address spaces are not standardised in C, and I do not expect they
ever will be. The TR18307 document is not anywhere close to being of a
quality that could be integrated with the C standards, even as optional
features, and much of it makes no sense in practice (I have never heard
of the IO stuff being implemented or used).
The few compilers that implement any of it do so in different ways - the
"__flash" address space in AVR GCC is slightly different from the same
extension in IAR's AVR compiler. For existing compilers, there is a
strong inconsistency as to whether such things are "named address
spaces", "extension keywords", "type qualifiers", "attributes", or other
terms, all with subtly (or not so subtly) different effects on how they
are used, what restrictions exist, conversions between types, and how
errors can be diagnosed. Sometimes these features are considered part
of the data type, sometimes of pointer types, sometimes they are just
about data placement.
Since every compiler targeting these small awkward microcontrollers has
a different idea of what something like "const __flash int x = 123;"
means, and has been implementing their own ideas for a decade or two
before TR18307 ever proposed "named address spaces", the TR hasn't a
hope of being a real standard.
Named address spaces are not implemented at all, anywhere (AFAIK), for
C++. (Some embedded toolchains have limited support for C++ on such
microcontrollers, but these are again not really named address spaces.)
Since C++ usage is heavily increasing in the small embedded system
world, this is important. (GCC has much of the honour for that - as ARM
took a bigger share of the market and GCC for ARM improved, the
toolchain market was no longer at the mercy of big commercial vendors
who charged absurd amounts for their C++ toolchains.) A feature which
is only for C, and not supported by C++, is almost guaranteed to be
dead-end.
And of course the type of processor for which named address spaces or
other related extensions are essential, are a dying breed. The AVR is
probably the only one with a significant future. Part of the appeal of
ARM in the embedded world is it frees you from the pains of
target-specific coding with some of your data in "near" memory, some in
"extended" memory, some in "flash" address spaces or "IO" address
spaces. It all works with standard C or C++. The same applies to
challengers like RISC-V, MIPS, PPC, and any other core - you have a
single flat address space for normal data.
I have no idea how much the GCC features are actually used,
but other compilers for embedded systems such as SDCC also
support named address spaces.
And the targets supported by SDCC are also dead-end devices - there is
not a single one of them that I would consider for a new project. These
microcontrollers are now used almost exclusively for legacy projects -
updates to existing hardware or software, and rely on compatibility with
existing C extensions (whether they are called "named address spaces",
"extension keywords", or anything else).
Now, there are things that I would like to be able to write in my code
that could appear to be candidates for some kind of named address space.
For example, I might want data that is placed in an external eeprom -
it could be nice to be able to define, declare, read and write it like
normal data in the code. But key to this would be the ability to define
the way this works in /user/ code - named address spaces require
changing the toolchain, which is out of the question in almost all
use-cases. And it would spoil one of C's key advantages over
alternative languages - to a fair extent (though not as completely as
many people believe), you can guess what is happening from the code.
You assume that "x = eeprom_var;" is small and efficient, while "x =
read_eeprom(eeprom_var)" might take significant time to execute. People
don't like hidden things in their C code.
It would be conceivable for GCC to add extensions that could be used to
define your own named address spaces in user code. But doing so would
require a lot of syntax and features that already exist in C++.
I would rather see better ways of controlling placement of data added to
the compiler. In another post, I suggested allowing variable attributes
- such as "section" - to be attached to types. I'd also like to see a
way to specify the section name by compile-time evaluated code, not just
a string literal. I'd like to be able to give sub-sections, and section
flags in a convenient way. And - perhaps most importantly - I'd like to
be able to use #pragma's to give sections for code or data for a block
of code and data at a time, rather than having to specify it
individually on each function. (That could perhaps also be done by
allowing section attributes on namespaces in C++.)
David