avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-gcc-list] using exceptions


From: Gabriel Dos Reis
Subject: Re: [avr-gcc-list] using exceptions
Date: Thu, 3 May 2012 08:29:05 -0500

On Thu, May 3, 2012 at 3:33 AM, Georg-Johann Lay <address@hidden> wrote:
> Gabriel Dos Reis schrieb:
>>
>> Georg-Johann Lay wrote:
>>
>>> Gabriel Dos Reis wrote:
>>>>
>>>>
>>>> I guess I would need to get my feet wet with
>>>> 1. minimal free-standing  C++ implementations without exceptions
>>>> 2. get support for RTTI (without exceptions)
>>>> 3. exceptions (assuming 1 and 2 are done successfully)
>>>>
>>>> Regarding 2., I would like to understand the general policy:  RTTI data
>>>> are
>>>> generally const and should be best stored in read only location.  What
>>>> is
>>>> the general preference for AVR?  Put read only data in program memory or
>>>> data segment?  Apologies for the triviality but the recent discussion
>>>> about
>>>> __func__ got me thinking.
>>>
>>>
>>> The preferred place is program memory, i.e. flash, i.e. something like
>>> .progmem section.
>>>
>>> Read-only data is located in .rodata which is located in RAM.
>>>
>>> This is because const qualifier is not enough to put data in flash,
>>> just assume:
>>>
>>> char bar (const char *p)
>>> {
>>>  return *p;
>>> }
>>>
>>> char foo (char *p)
>>> {
>>>  char c = bar (p);
>>>  *p = 0;
>>>  return c;
>>> }
>>>
>>> bar() must not read from flash.
>>
>>
>> Yes, "const" qualifier on *parameters* is not enough.
>> However "const" qualifier on *objects* should be enough.
>> (and for C++, we now have "constexpr" to statically
>> guarantee that)
>
>
> That's not enough.
>
> The reason is that it's completely legal in C to access a
> non-const object through a const-qualified pointer as
> lined out in bar being called by foo above.
>
> I think this is okay for C++, too?

In C++, you can also access a non-const object with
a const qualified pointer.  But, that is not what I was
suggesting.  I am suggesting that a const(expr) *object* should
go in program memory because it cannot be modified.  The
only requirement is that it is statically initialized (e.g. at most
at link time.)

The only time one can't put a const object in program memory
is when it requires a dynamic initialization. Constexpr objects
do not require dynamic initialization; the same is true for
statically initialized const object.

>
> The only safe setting where an object O may be put into
> flash without the user explicitely requesting it are:
>
> A) *All* use sites of the object are known and they
> never change O.
>
> B) There is no section attribute attached to O.

See above for my elaboration.
There is no way a use sit can modify a const object.
So if we know the object is const qualified, we do not
need to check all use sites.  The attribute section is
indeed a good point.  But, I think we shouldn't require
users to explicitly say so -- this goes back to my earlier
question about "preference".

>
> Besides that, we need
>
> C) The compiler supplies us with this knowledge *and*
> allows us to hook in in oder to produce appropriate
> code to locate the object and access it appropriately,
> e.g. to quality *all* involved pointers targeting the
> object appropriately.
>
> Notice I use "object" in the weak meaning as "something",
> i.e. "object" may also be a string literal or vtable.

Yes, string literals and vtable should definitely be accounted
as object in this discussion.

>
> A, B and C are currently only satisfied for one single
> place in avr-gcc, namely casesi insn:
>
> A is true because because the BE emits code for casesi
> and is able to locate the table, see TARGET_ASM_FUNCTION_RODATA_SECTION.
> This might break C++ if it uses .gnu.linkonce.r. in
> unknown ways.

So, we would have to convince the C++ FE  about AVR needs.

>
> There are several other places that satisfy A and B, but
> C does not hold:
>
> i) Lookp tables resulting from tree-switch-conversion, see PR49857.
> ii) vtables
> iii) rtti tables
>
> The difference between i) and ii), iii) is that putting tables in
> flash for i) is not an ABI change whereas ii) and iii) are:
>
> Suppose you compile a file that generates respective tables and link
> against objects generated by an older compiler version.
>
> In that case the assertion would be that the use site may escape the
> scope, but the out-of-scope places are just as well administered by
> compiler code and not by user code. Thus, the assertion is that the
> handling of the compiler is the same over all modules involved, which
> means a new ABI. Except v/rtti-tables are only present in exactly
> one module and only accessed from there, of course. I don't new enough
> of C++ for this, but in that case the change would just be an
> optimization and not an ABI change, similar to i) and casesi.

There is exactly one vtable per class definition.  The real issue is
which translation unit should contain that definition if virtual
function definitions are spread across several translation units?
The common vendor ABI says the translation unit that contains the
keying function.  The exact definition for the latter is ABI-specific.
Where can I find the AVR C++ ABI?

As for RTTI objects, the ideal is that there exists exactly one type info
object per type.  However, some platforms (e.g. mac os) have
visibility attributes
that can muddy the water.  Consequently, some fake platforms uniqueness; I am
not sure that is good for AVR.  So, I would expect  RTTI objects to
follow the same treatment as vtables.


>
> From the compiler's analysis capabilitied, I'd guess A is satisfied
> for way more cases, e.g. static consts. The compiler knows if
> references escape scope, for example by taking address of such object
> and return or pass it.

yes.


>
>
>>> The issue is not locating the data, it's accessing the data with the
>>> right
>>> instructions, i.e. LPM* for data in flash and LD* and ST* for data in
>>> RAM.
>>
>>
>> yes; I agree.  My question though was whether there was a general
>> policy about where to put things we know are never going to change
>> in program memory because of RAM being so scarce.
>>
>>> Similar issues as with rtti arise with vtables, see PR43745.
>
>
>
> A, B anc C mentioned above.
>
> GCC offers TARGET_VTABLE_USES_DESCRIPTORS, but it appears to be
> very specific, and the vtable hooks don't appear to be generic
> enough as to tell "use this kond of pointer to access that".

If we are able to formulate exactly what we want, I believe we can
bring this to Jason.

>
> FYI, notice that avr does not implement TARGET_PTRMEMFUNC_VBIT_LOCATION
> and instead sets FUNCTION_BOUNDARY to 8. The last setting is
> confusing if you miss TARGET_PTRMEMFUNC_VBIT_LOCATION is undefined
> because the right setting for FUNCTION_BOUNDARY is 16.

Ugh.  Thanks!

>
>
>>> RAM is a very scarce resource on AVRs, but with current GCC it is not
>>> possible to place+access rtti/vtable data in flash.
>>>
>>> The right feature would be something like an internal, "artificial"
>>> address space to qualify/locate respective pointers/data.
>>> This should be easier than adding named address spaces as full-featured
>>> C++ extension.
>>
>>
>> Agreed.  I will talk to Jason to see what can be done here.
>
>
> IMO, the implementation of address spaces in GCC is bit myopic.
> AS are just a kind of target specific qualifiers. While AS
> qualifiers are mutually exclusive, "ordinary" qualifiers are not.
>
> I wonder why there is nothing like target specific qualifiers in GCC
> where the target decised what compination of whalifiers is legal or
> worth an error or warning and how they transform with pointer mess.
>
> One reason might be limited space for TYPE_QUALS? Dunno...

It is more history than specific well-though out design decision.


>
>
>>> However, I'd guess that none of the code to handle address spaces is
>>> present
>>> in C++ part and/or FE as named addresses are not a G++ feature, so there
>>> is no need to have named address code in C++ (or other languages' parts)
>>> in the compiler.
>>
>>
>> Agreed.  I would like to refrain from full fledged named address spaces in
>> the
>> C++ front-end until the WG21 committee got a clear direction.  On the
>> other
>> hand something like the one you describes above should suffice.
>
>
> You got contact to the WG?

yes,  I am on WG21. I generally used to represent France (AFNOR) on WG21.
(Some of my work on WG21 include the introduction of constexpr,
template aliases, new meaning of "auto", etc. and failed "C++0x
concepts" attempt)

> IMO there are some migging spots in the AS specification, for example in
> code like
>
> const __flash char *str = "literal"
>
> This is not allowed in current spec as C/C++ standard is too dominant,
> there is a "string literals are always generic" or similar and the
> AS spec does not cover it.

Agreed.  In general, there is an aversion towards more qualifiers.
I suspect this is mostly because of the committee being burned
by "volatile" and also because qualifiers tend to lead to combinatorial
explosion when it comes to implicit conversions and overload resolution.

The trend has been to use classes (sometimes with compiler
support) to render abstractions such as these.  See for example
how C++11 handles atomics (std::atomic<T>) compared to C11 (_Atomic).


>
> In the example above, the /only/ way to access the literal is through
> str which points to flash. Thus, the canonical and only reasonable
> place to put the literal is __flash address space.
>
> This has been overseen by the WG, obvioulsy the spec was writte for
> some different architecture in mind.

Yes, the current definition clearly does not have multiple data pointers
kinds in mind -- it does however say that a pointer to function is a different
beast from a pointer to data.

I think the "C++ way" would be to have a class type flash<T> (like
atomic<T>) that is used to encapsulate the address space.  Everything
else should work out properly.

>
> Attaching obvious semantics to the line above or making it
> implementation defined and let the backend decide would make
> it much easier to port code
>
> const char *str = "literal";
>
> from big flatform to
>
> const __flash char *str = "literal";
>
> Instead of rewriting to
>
> const __flash char dummy[] = "literal";
> const __flash char *str = dummy;

how about

   std::flass<char[]> str = "literal";

?

> in particular with more elaborate initializers that contain
> string literals.

I think anything that adds new type qualifier would meet
resistance from WG21.  However, if we can work out
the details of something flash<T>, then it might be easier to
get WG21 consider it and extend the framework to other
address spaces.

-- Gaby



reply via email to

[Prev in Thread] Current Thread [Next in Thread]