Joseph Myers <jos...@codesourcery.com> writes:
> On Thu, 18 Oct 2018, Richard Sandiford wrote:
>> - Type introspection for things like parsing format strings
>> 
>>   It sounded like the type descriptors would be fixed-sized types,
>>   a bit like a C version of std::type_info.
>
> It wasn't clear if people might also want to e.g. extract a list of all 
> members of a structure type from such an object (which of course could 
> either involve variable-sized data, or fixed-size data pointing to arrays, 
> or something else along those lines).

OK.  But wouldn't that basically be a tree structure?  Or a flexible
array if flattened?  It doesn't sound like it would need changes to
the type system.  We can already describe this kind of thing with tree
types in GCC.  (The memory needed to represent the data could of course
be allocated using a single block of stack if that's what's wanted.)

>> So I didn't see anything there that was really related, or anything that
>> relied on sizeof being variable (which as I say seems to be a very high
>> hurdle for C++).
>
> The references you gave regarding the removal of one version of VLAs from 
> C++ didn't seem to make clear whether there were supposed to be general 
> issues with variable-size types fitting in the overall C++ object model, 
> or whether the concerns were more specific to things in the particular 
> proposal - but in either case, the SVE proposals would need to be compared 
> to the actual specific concerns.

But this is also one of my concerns about moving this discussing to the
WG14 list.  It doesn't seem to be publicly readable, and I only knew
about the bignum discussion because you gave me a direct link to the
first article in the thread.  I had to read the rest by wgetting the
individual messages.  So any objections raised there would presumably
be shrouded in mystery to most people, and wouldn't e.g. show up in a
web search.

If we move it to a different forum, I'd rather it be a public one that
would treat C and C++ equally.  But maybe such a thing doesn't exist. :-)

> Anyway, the correct model in C++ need not be the same as the correct model 
> in C.  For example, for decimal floating point, C++ chose a class-based 
> model whereas C chose _Decimal* keywords (and then there's some compiler 
> magic to use appropriate ABIs for std::decimal types, I think).
>
> If you were implementing the SVE API for C++ for non-SVE hardware, you 
> might have a class-based implementation where the class internally 
> contains a pointer to underlying storage and does allocation / 
> deallocation, for example - sizeof would give some fixed small size to the 
> objects with that class type, but e.g. copying them with memcpy would not 
> work correctly (and would be diagnosed with -Wclass-memaccess).

One important point here is that the SVE API isn't a new API whose
primary target happens to be SVE.  It's an API whose *only* target
is SVE.  Anyone wanting to write vector code that runs on non-SVE
hardware should use something that's designed to be cross-platform,
(e.g. P0214 or whatever).  They certainly shouldn't be using this.

Like other vector intrinsics, the SVE ACLE is supposed to be the last
line of defence before resorting to asm, and isn't designed to be any
more portable than asm would be.

> Is there something wrong with a model in C++ where these types have
> some fixed small sizeof (which carries through to sizeof for
> containing types), but where different ABIs are used for them, and
> where much the same raw memory operations on them are disallowed as
> would be disallowed for a class-based implementation?  (Whether
> implemented entirely in the compiler or through some combination of
> the compiler and class implementations in a header - though with the
> latter you might still need some new language feature, albeit only for
> use within the header rather than more generally.)

Having different ABIs would defeat the primary purpose of the extension,
which is to provide access to the single-vector SVE ABI types in C and C++.
We want types that in both C and C++ represent the contents of SVE vector
and predicate registers.  E.g.:

  svfloat64_t vector_sin(svbool_t pg, svfloat64_t vx)

has to map pg to a predicate register (P0), vx to a vector register (Z0)
and return the result in a vector register (Z0), in both C and C++.

The main objection to the details of the sizeless type proposal seems
to be that sizeof was too useful for us to make it invalid.  But if
sizeof has different values for C and C++, wouldn't that defeat the
point?  Users would be forced to use the SVE vector length functions
after all.  Also, for:

  void (*update_vector)(svfloat64_t *px);

how would the caller of update_vector know whether the target
function is using the C or the C++ representation of svfloat64_t
when accessing *px?

> Even if that model doesn't work for some reason, it doesn't mean the only 
> alternatives for C++ are something like VLAs or a new concept of sizeless 
> types for C++ - but I don't have the C++ expertise to judge what other 
> options for interfacing to SVE might fit best into the C++ language.

This is one of the reasons I was raising this as a joint RFC about what
would be acceptable in both the C and C++ frontends (treating it as
either a GNU extension or a target extension for now).

The sizeless type proposal keeps the new built-in vector types in
the common subset of C and C++ by "opting out of" (among other things)
features in one language that would make them problematic in the other.

>> I think it would look something like this (referring back to
>> 
>>     *Object types are further partitioned into sized and
>>     sizeless; all basic and derived types defined in this standard are
>>     sized, but an implementation may provide additional sizeless types.*
>> 
>> in the RFC), not really in standardese yet:
>> 
>>     Each implementation-specific sizeless type may have a set of
>>     implementation-specific "configurations".  The configuration of
>>     such a type may change in implementation-defined ways at any given
>>     sequence point.
>> 
>>     The configuration of a sizeless structure is a tuple containing the
>>     configuration of each member.  Thus the configuration of a sizeless
>>     structure changes if and only if the configuration of one of its
>>     members changes.
>> 
>>     The configuration of an object of sizeless type T is the configuration
>>     of T at the point that the object is created.
>> 
>> And then borrowing slightly from your 6.7.6.2#6 reference:
>> 
>>     If an object of sizeless type T is accessed when T has a different
>>     configuration from the object, the behavior is undefined.
>> 
>> Is that the kind of thing you mean?
>
> Yes.  But I wonder if it would be better to disallow such changing of 
> configurations, so that all code in a program always uses the same 
> configuration as far as the standard is concerned, so that there is indeed 
> a size for a given vector type that's constant throughout the execution of 
> a program (which would be used by calls to sizeof on such types), and so 
> that communicating with a thread using a different configuration is just 
> as much outside the scope of the defined language as processes using 
> different ABIs communicating is today.

The problem isn't just communicating with different threads though.
If the program changes the vector length and consistently uses objects
created with that new vector length, the size of the object would still
be different from the size of the real payload.  We would have to resort
to the type having implementation-defined amounts of padding, with the
amount of padding varying at sequence points in the same way as above.
(This would effectively be (3a) from the RFC FWIW.)

The reason for adding the above was to describe the ways in which
accessing an object with the "wrong length" would invoke undefined
behaviour.  If we say that there never is a wrong length (and thus
no undefined behaviour from using the wrong length) we'd just end
up with a legal fiction.  It'd seem better not to add it at all.

Thanks,
Richard

Reply via email to