public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* [named address] rejects-valid: error: initializer element is not computable at load time
@ 2011-08-04  9:44 Georg-Johann Lay
  2011-08-04 16:10 ` Ulrich Weigand
  0 siblings, 1 reply; 6+ messages in thread
From: Georg-Johann Lay @ 2011-08-04  9:44 UTC (permalink / raw)
  To: gcc

For the following 1-liner I get an error with current trunk r177267:

const __pgm char * pallo = "pallo";

__pgm as a named address space qualifier.


>$TV/xgcc -B$TV pgm.c -c -save-temps -dp -mmcu=atmega8
 <addr_space_convert_expr 0xb74cdfc0
    type <pointer_type 0xb74c7f60
        type <integer_type 0xb74c7f00 char readonly address-space-1 string-flag QI
            size <integer_cst 0xb745b1a4 constant 8>
            unit size <integer_cst 0xb745b1b8 constant 1>
            align 8 symtab 0 alias set -1 canonical type 0xb74c7f00 precision 8 min <integer_cst
0xb745b17c -128> max <integer_cst 0xb745b208 127>
            pointer_to_this <pointer_type 0xb74c7f60>>
        unsigned PHI
        size <integer_cst 0xb745b064 constant 16>
        unit size <integer_cst 0xb745b078 constant 2>
        align 8 symtab 0 alias set -1 canonical type 0xb74c7f60>
    readonly constant
    arg 0 <nop_expr 0xb74cdfa8
        type <pointer_type 0xb7473f00 type <integer_type 0xb746a240 char>
            unsigned HI size <integer_cst 0xb745b064 16> unit size <integer_cst 0xb745b078 2>
            align 8 symtab 0 alias set -1 canonical type 0xb7473f00>
        readonly constant
        arg 0 <addr_expr 0xb74cdf90 type <pointer_type 0xb74db120>
            readonly constant
            arg 0 <string_cst 0xb74cdf78 type <array_type 0xb74db0c0>
                readonly constant static "pallo\000">
            pgm.c:1:28>
        pgm.c:1:28>
    pgm.c:1:28>
pgm.c:1:1: error: initializer element is not computable at load time

Is that a flaw in c-typeck.c?

I know the line worked some time ago; from time to time I merge trunk into
the named address space support for AVR which is not in SVN.

If you need the patch to reproduce the bug I will upload the patch, of course.

No BE hook is called for the tree.

Moreover, if a user writes a line like
   const __pgm char * pallo = "pallo";
he wants the string literal to be placed in the non-default address
space.  There is no other way to express that except something like
   const __pgm char * pallo = (const __pgm char*) "pallo";
which doesn't work either and triggers

pgm.c:1:1: error: initializer element is not constant

with a tree dump similar to above.


Johann

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [named address] rejects-valid: error: initializer element is not computable at load time
  2011-08-04  9:44 [named address] rejects-valid: error: initializer element is not computable at load time Georg-Johann Lay
@ 2011-08-04 16:10 ` Ulrich Weigand
  2011-08-04 17:03   ` Georg-Johann Lay
  0 siblings, 1 reply; 6+ messages in thread
From: Ulrich Weigand @ 2011-08-04 16:10 UTC (permalink / raw)
  To: Georg-Johann Lay; +Cc: gcc

Georg-Johann Lay wrote:

> For the following 1-liner I get an error with current trunk r177267:
> 
> const __pgm char * pallo = "pallo";
> 
> __pgm as a named address space qualifier.
[snip]
> Moreover, if a user writes a line like
>    const __pgm char * pallo = "pallo";
> he wants the string literal to be placed in the non-default address
> space.  There is no other way to express that except something like
>    const __pgm char * pallo = (const __pgm char*) "pallo";
> which doesn't work either and triggers
> 
> pgm.c:1:1: error: initializer element is not constant
> 
> with a tree dump similar to above.

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 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.

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.

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [named address] rejects-valid: error: initializer element is not computable at load time
  2011-08-04 16:10 ` Ulrich Weigand
@ 2011-08-04 17:03   ` Georg-Johann Lay
  2011-08-05 10:07     ` Ulrich Weigand
  0 siblings, 1 reply; 6+ messages in thread
From: Georg-Johann Lay @ 2011-08-04 17:03 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gcc

Ulrich Weigand wrote:
> Georg-Johann Lay wrote:
> 
>> For the following 1-liner I get an error with current trunk r177267:
>>
>> const __pgm char * pallo = "pallo";
>>
>> __pgm as a named address space qualifier.
> [snip]
>> Moreover, if a user writes a line like
>>    const __pgm char * pallo = "pallo";
>> he wants the string literal to be placed in the non-default address
>> space.  There is no other way to express that except something like
>>    const __pgm char * pallo = (const __pgm char*) "pallo";
>> which doesn't work either and triggers
>>
>> pgm.c:1:1: error: initializer element is not constant
>>
>> with a tree dump similar to above.
> 
> 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 ;-)

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).

For example, the backend could decide what qualifier combinations are valid
and what machine mode is associated to them or emit a diagnostic.

It's target specific, the backend knows it!

> 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.

> 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.  Was just starting with the work and
it worked some time ago, so I wondered.  And I must admit I am not familiar
will all the dreaded restriction TR 18037 imposes to render it less functional :-(
> 
> Bye,
> Ulrich
> 

Anyway, thanks for your explanations.

Do you think a feature like "target specific qualifier" would be reasonable?
IMO it would be greatly appreciated by users.
Should not be too hard atop the work already being done for named addresses.

Johann

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [named address] rejects-valid: error: initializer element is not computable at load time
  2011-08-04 17:03   ` Georg-Johann Lay
@ 2011-08-05 10:07     ` Ulrich Weigand
  2011-08-08 19:05       ` Georg-Johann Lay
  0 siblings, 1 reply; 6+ messages in thread
From: Ulrich Weigand @ 2011-08-05 10:07 UTC (permalink / raw)
  To: Georg-Johann Lay; +Cc: gcc

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?

> > 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.

> Do you think a feature like "target specific qualifier" would be reasonable?
> IMO it would be greatly appreciated by users.
> Should not be too hard atop the work already being done for named addresses.

As I said, any further extension would need to be carefully specified ...
In any case, whether this would then be accepted would be up to the
front-end maintainers, of course.

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [named address] rejects-valid: error: initializer element is not computable at load time
  2011-08-05 10:07     ` Ulrich Weigand
@ 2011-08-08 19:05       ` Georg-Johann Lay
  2011-08-09 15:18         ` [named address] rejects-valid: error: initializer element is not computable@load time Ulrich Weigand
  0 siblings, 1 reply; 6+ messages in thread
From: Georg-Johann Lay @ 2011-08-08 19:05 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gcc

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

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [named address] rejects-valid: error: initializer element is not computable@load time
  2011-08-08 19:05       ` Georg-Johann Lay
@ 2011-08-09 15:18         ` Ulrich Weigand
  0 siblings, 0 replies; 6+ messages in thread
From: Ulrich Weigand @ 2011-08-09 15:18 UTC (permalink / raw)
  To: Georg-Johann Lay; +Cc: gcc

Georg-Johann Lay wrote:
> Ulrich Weigand schrieb:
> > 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:
[snip]
> 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.

I agree that this is best approach.  You can even avoid the unnecessary
variables by using a compound literal with AS-qualified char array type,
and initialize the AS pointer to its address, like e.g. so:

const __as char *pallo = (const __as char []){"pallo"};

That's still a bit awkward, but that could be hidden via a macro ...

> 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.

That's not really true: on some targets, the generic address space
will indeed be a subset of __as, so you *can* assign the address of
a string literal in the generic space to an __as pointer variable.

Even on the SPU, this works when the assignment is not done at
initialization time:

const __ea char *p;
int test (void)
{
  p = "test";
}

This will generate code to convert the address of the literal "test"
in the generic address space into a __ea address and assign it to
the __ea pointer.

> 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.

What is implementation defined is whether conversion of a pointer
to a different address space is allowed at *initialization* time
or not.

What is *not* implementation defined is that string literals are
always in the generic address space -- that's simply a requirement
of the standard.

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2011-08-09 15:18 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-08-04  9:44 [named address] rejects-valid: error: initializer element is not computable at load time Georg-Johann Lay
2011-08-04 16:10 ` Ulrich Weigand
2011-08-04 17:03   ` Georg-Johann Lay
2011-08-05 10:07     ` Ulrich Weigand
2011-08-08 19:05       ` Georg-Johann Lay
2011-08-09 15:18         ` [named address] rejects-valid: error: initializer element is not computable@load time Ulrich Weigand

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).