Use ODR for canonical types construction in LTO

Jan Hubicka
Mon Jun 24 15:57:00 GMT 2019

thanks for comitting the patch!
> > > As
> > >
> > >   class a var;
> > >   class b:a {} *bptr;
> > >
> > >;
> > >
> > > Expanding this as would make access path oracle to
> > > disambiguate it from bptr->as_base_b-> which is wrong with
> > > gimple memory moel where we allow placement new replacing var by
> > > instance of b.
> Why do we allow that?  I would expect that to only be allowed if a is
> something like aligned_storage, i.e. a thin wrapper around a char/byte
> buffer.

I think because Richard defined gimple memory model this way after fair
amount of frustration from placement news, stack slot sharing issues 
and non-conforming codebases :)

I think for normal user variables this is overly conservative.
At the moment TBAA is bit of a mess. Once it is cleaner up, we could
see if restricting this more pays back and then we would need to
find way to pass the info to middle-end (as it does not
know difference between aligned_storage and other stuff).

For dynamically allocated memory as well as for stack space after stack
slot sharing done in cfgexpand I see this is necessary since we do not
preserve any information about placement new.

Note that devirtualization machinery is bit more agressive than TBAA
model I am currently aiming for (for example assuming that user variable
of given type are not placement new replaced), but I think here we are
relatively safe because we do so only for non-POD types where
construction/destruction ought to be paired.
> > Ick.  IIRC the as-base types were necessary only for
> > copying and clobber operations that may not touch the possibly
> > re-used tail-padding.
> And temporarily during layout, yes.  This is all closely related to PR 22488.

I think this is what Richard reffers to the code generating clobber
statements that is only leaking as-base types to the middle-end visible
part of IL and the code in call.c copying base structures.
> > Btw, I still wonder what the ODR says in the face of language
> > inter-operation and what this means here?  For C++ I suppose PODs
> > are not ODR?
> The ODR applies to PODs just like other classes.  But the ODR says
> nothing about language interoperation, that's all
> implementation-defined.

My patchset considers all C++ types inter-operating with non-C++ types.
So first we load all types and do the following:

During streaming I populate ODR type hash with ODR types and canonical
type hash with types not originating from C++.

Once all types are in memory I do following:
 1) For every structure/union with linkage
    - see if there is structurally equivalent non-C++ type in canonical
      type hash (where structural equivalence is defined in very
      generous way ignoring pointer types,  type tags and field names so
      interoperability with fortran is safe)

      if there is no mathing type and no detected ODR violation declare
      mark the type to be hanled by ODR name in step 2
 2) for every structure/union originating from C++ compute the canonical
    type by canonical type hash query. If in 1) we decided that given
    ODR type is unique the cnaonical type hash compare type by name
    rather than by structure.
I do not handle enums since those conflicts with integer that is
declared in every translation unit.

So at this time basically every C++ type can inter-operate with non-C++.
I was thinking of relaxing this somewhat but wanted to see if C++
standard says something here. Things that may be sensible include:
 1) perhaps non-POD types especially those with vptr pointers do
    not need to be inter-operable.
 2) anonymous namespace types
 3) types in namespace
> Jason

More information about the Gcc-patches mailing list