[named address] rejects-valid: error: initializer element is not computable at load time
Georg-Johann Lay
avr@gjlay.de
Mon Aug 8 19:05:00 GMT 2011
Ulrich Weigand schrieb:
> Georg-Johann Lay wrote:
>
>>Ulrich Weigand wrote:
>>
>>>This is pretty much working as expected. "pallo" is a string literal
>>>which (always) resides in the default address space. According to the
>>>named address space specification (TR 18037) there are no string literals
>>>in non-default address spaces ...
>>
>>The intension of TR 18037 to supply "Extension to Support Embedded Systems"
>>and these are systems where every byte counts -- and it counts *where* the
>>byte will be placed.
>>
>>Basically named AS provide something like target specific qualifiers, and
>>if GCC, maybe under the umbrella of GNU-C, would actually implement a feature
>>like target specific qualifiers, that would be a great gain and much more
>>appreciated than -- users will perceive it that way -- being more catholic
>>than the pope ;-)
>
> The problem with all language extensions is that you really need to be careful
> that the new feature you want to add is fully specified, in all its potential
> interactions with the rest of the (existing) language features. If you don't,
> some of those ambiguities are certain to be causing you problems later on --
> in fact, that's just what has happened time and again with GCC extensions
> that were added early on ... This is why these days, extensions usually are
> accepted only if they *are* fully specified (which usually means providing
> a "diff" to the C standard text that would add the feature to the standard).
>
> This is a non-trivial task. One of the reasons why we decided to follow the
> TR 18037 spec when implementing the __ea extension for SPU is that this task
> had already been done for us. If you want to deviate from that existing spec,
> you're back to doing this work yourself.
>
>
>>For example, you can have any combination of qualifiers like const, restrict
>>or volatile, but it is not possible for named AS. That's clear as long as
>>named AS is as strict as TR 18037. However, users want features to write
>>down their code an a comfortable, type-safe way and not as it is at the moment,
>>i.e. by means of dreaded inline assembler macros (for my specific case).
>
> A named AS qualifier *can* be combined with other qualifiers like const.
> It cannot be combined with *other* named AS qualifiers, because that doesn't
> make sense in the semantics underlying the address space concept of TR 18037.
> What would you expect a combination of two AS qualifiers to mean?
Not two AS qualifiers, but two or more qualifiers, some of which might
be target specific. You cannot use AS qualifiers and "abuse" them to
implement a feature like target specific qualifiers.
>>>The assignment above would therefore need to convert a pointer to the
>>>string literal in the default space to a pointer to the __pgm address
>>>space. This might be impossible (depending on whether __pgm encloses
>>>the generic space), and even if it is possible, it is not guaranteed
>>>that the conversion can be done as a constant expression at compile time.
>>
>>The backend can tell. It likes to implement features to help users.
>>It knows about the semantic and if it's legal or not.
>>
>>And even if it's all strict under TR 18037, the resulting error messages
>>are *really* confusing to users because to them, a string literal's address
>>is known.
>
> It would be possible to the extend named AS implementation to allow AS pointer
> conversions in initializers in those cases where the back-end knows this can
> be done at load time. (Since this is all implementation-defined anyway, it
> would cause no issues with the standard. We simply didn't do it because on
> the SPU, it is not easily possible.)
>
> Of course, that still wouldn't place the string literal into the non-generic
> address space, it just would convert its address.
>
>>>What I'd do to get a string placed into the __pgm space is to explicitly
>>>initialize an *array* in __pgm space, e.g. like so:
>>>
>>>const __pgm char pallo[] = "pallo";
>>>
>>>This is defined to work according to TR 18037, and it does actually
>>>work for me on spu-elf.
>>
>>Ya, but it different to the line above.
>
> Sure, because it allocates only the string data, and not in addition a
> pointer to it as your code did ...
>
>
>>Was just starting with the work and
>>it worked some time ago, so I wondered.
>
> I think some time in the past, there was a bug where initalizers like in
> you original line were silently accepted but then incorrect code was
> generated (i.e. the pointer would just be initialized to an address in
> the generic address space, without any conversion).
>
>>And I must admit I am not familiar
>>will all the dreaded restriction TR 18037 imposes to render it less functional :-(
>
> It's not a restriction so much, it's simply that TR 18037 does not say anything
> about string literals at all, so they keep working as they do in standard C.
Take the following bit more elaborate example where you want to describe
a menu:
typedef struct
{
int id;
const char * labels[];
} menu1_t;
const menu1_t menu1 =
{
1,
{
"Yes",
"No",
"Don't really know and will decide later",
}
};
That's fine in generic AS, but suppose you want the strings in some
other AS (like in out Harvard example in flash memory):
typedef struct
{
int id;
const char __as * labels[];
} menu1_t;
That won't work. Notice that the *only* reasonable place to put the
literals is __as because labels[] is the *only* object that holds
references to the literals. It makes absolute no sense to put these
literals into generic AS (supplied no error was emit).
Changing to
typedef struct
{
int id;
const char __as labels[][40];
} menu2_t;
and a similar initializer like above will work but waste you bunch of
valuable memory. Thus you have no alternative and have to use menu1_t:
const char __as STR_YES[] = "Yes";
const char __as STR_NO[] = "No";
const char __as STR_DUNNO[] = "Don't really know and will decide later";
const menu1_t menu3 =
{
1,
{
STR_YES,
STR_NO,
STR_DUNNO
}
};
With some menues you soon end up with dozens of unnecessary variables
just because TR 18037 has a blank area on it's map.
This means that a line like
const __as char * pallo = "pallo";
can be very useful and that there is exactly one meaning that makes
sense: put "pallo" in __as because otherwise you won't be able to
reference that string.
The point has obviously been overseen by the spec guys...
Anyway, an error message for
const __as char * pallo = "pallo";
is very much preferred over completely useless and nonsensical putting
"pallo" in generic AS, even if it was possible for the target.
Even more preferred would be to assign the only sensible meaning
(provided a target allows it), which should be legal as that extension
is implementation defined, anyway.
Johann
> Bye,
> Ulrich
More information about the Gcc
mailing list