> On 9 Nov 2021, at 08:07, Iain Sandoe <i...@sandoe.co.uk> wrote:
> 
> 
> 
>> On 9 Nov 2021, at 07:12, Richard Biener <rguent...@suse.de> wrote:
>> 
>> On Mon, 8 Nov 2021, Jakub Jelinek wrote:
>> 
>>> On Mon, Nov 08, 2021 at 12:46:04PM +0100, Jakub Jelinek via Gcc-patches 
>>> wrote:
>>>> So, if we want to make PCH work for PIEs, I'd say we can:
>>>> 1) add a new GTY option, say callback, which would act like
>>>>  skip for non-PCH and for PCH would make us skip it but
>>>>  remember for address bias translation
>>>> 2) drop the skip for tree_translation_unit_decl::language
>>>> 3) change get_unnamed_section to have const char * as
>>>>  last argument instead of const void *, change
>>>>  unnamed_section::data also to const char * and update
>>>>  everything related to that
>>>> 4) maybe add a host hook whether it is ok to support binaries
>>>>  changing addresses (the only thing I'm worried is if
>>>>  some host that uses function descriptors allocates them
>>>>  dynamically instead of having them somewhere in the
>>>>  executable)
>>>> 5) maybe add a gengtype warning if it sees in GTY tracked
>>>>  structure a function pointer without that new callback
>>>>  option
>>> 
>>> So, here is 1), 2), 3) implemented.  With this patch alone,
>>> g++.dg/pch/system-2.C test ICEs.  This is because GCC 12 has added
>>> function::x_range_query member, which is set to &global_ranges on
>>> cfun creation and is:
>>> range_query * GTY ((skip)) x_range_query;
>>> which means when a PIE binary writes PCH and a PIE binary loaded
>>> at a different address loads it, cfun->x_range_query might be a garbage
>>> pointer.  We can either apply a patch like the attached one after
>>> this inline patch, but then probably callback is misnamed and we should
>>> rename it to relocate_and_skip or something similar.  Or we could
>>> e.g. during gimplification overwrite cfun->x_range_query = &global_ranges.
>> 
>> I think struct function allocation should initialize it to NULL and
>> the init to &global_ranges be done only when we do init_tree_ssa?
>> In fact x_range_query could be moved to the gimple_df substructure
>> to make that clear.
>> 
>> Hopefully PCH happens before init_tree_ssa.
>> 
>>> Other than that make check-gcc check-g++ passes RUNTESTFLAGS=pch.exp.
>>> 
>>> Not really sure about PA or IA-64 function descriptors, are any of those
>>> allocated by the dynamic linker rather than created by the static linker?
>>> I guess instead of removing the c-pch.c changes we could remember there
>>> not just a function pointer, but also a data pointer and compare if both
>>> are either the same or have the same load bias and punt only if they
>>> have different bias.  Though, on architecture where all function pointers
>>> would be dynamically allocated and could change any time even that wouldn't
>>> be really a reliable check.
>>> 
>>> Note, on stdc++.h.gch/O2g.gch there are just those 10 relocations without
>>> the second patch, with it a few more, but nothing huge.  And for non-PIEs
>>> there isn't really any extra work on the load side except freading two 
>>> scalar
>>> values and fseek.
>>> 
>>> Thoughts on this?
> 
> - thanks for doing it, I still think a working solution is better than a 
> disable.
> 
> - This would be a fix for PR 71934
> 
> - I applied the patches on Darwin and there’s still some case(s) to find and 
> fix
>  cc1/cc1plus hang on pch input, when any diagnostic is emitted (doing some
>  linemap lookup) .. hopefully, I can find some time to figure out what is not 
>  happy.

There were two issues, of which one remains and probably affects all targets.

1.  The Darwin PCH memory allocation scheme used a system that works reliably
    for no-PIE but not for PIE

.. I hacked in a similar scheme to the mmap one used on Linux .. the suspect 
stuff
   there is in choosing some place in the map that is likely to succeed…

  With that I get passes on all c-family pch.exp (I didn’t try to bootstrap).

2. This problem remains.

  - if we try to emit a diagnostic when the PCH read-in has failed, it seems 
that
   cc1 hangs somewhere in trying to lookup line table info.

 - this was happening with the Darwin fixed PCH memory address because it
   was trying to report a fatal error in being unable to read the file (or 
trying to
  execute fancy_abort, in response to a segv).

.. I didn’t try this on Linux - but I would imagine it would be quick to see if 
the
   problem manifests, one would only need to simulate an error.

Iain

> 
>> I'm not keen on further life support for PCH, but then if the work is
>> done it's hard to reject it...
>> 
>> Note there might be still platforms not supporting PCH and so Iains
>> patches still look useful to me.
> 
> Yeah, what would be most useful at this stage is some way to get those
> tested against some wider set of package builds to see if anything fires
> that breaks stuff.
> 
>> I also wonder whether we want to require active marking of types
>> with PCH support and assert when PCH write runs into objects without?
> 
> anything that makes GTY markup more robust is a Good Idea.
> Iain
> 
>> 
>> Richard.
>> 
>>> 2021-11-08  Jakub Jelinek  <ja...@redhat.com>
>>> 
>>> gcc/
>>>     * ggc.h (gt_pch_note_callback): Declare.
>>>     * gengtype.h (enum typekind): Add TYPE_CALLBACK.
>>>     (callback_type): Declare.
>>>     * gengtype.c (dbgprint_count_type_at): Handle TYPE_CALLBACK.
>>>     (callback_type): New variable.
>>>     (process_gc_options): Add CALLBACK argument, handle callback
>>>     option.
>>>     (set_gc_used_type): Adjust process_gc_options caller, if callback,
>>>     set type to &callback_type.
>>>     (output_mangled_typename): Handle TYPE_CALLBACK.
>>>     (walk_type): Likewise.  Handle callback option.
>>>     (write_types_process_field): Handle TYPE_CALLBACK.
>>>     (write_types_local_user_process_field): Likewise.
>>>     (write_types_local_process_field): Likewise.
>>>     (write_root): Likewise.
>>>     (dump_typekind): Likewise.
>>>     (dump_type): Likewise.
>>>     * gengtype-state.c (type_lineloc): Handle TYPE_CALLBACK.
>>>     (state_writer::write_state_callback_type): New method.
>>>     (state_writer::write_state_type): Handle TYPE_CALLBACK.
>>>     (read_state_callback_type): New function.
>>>     (read_state_type): Handle TYPE_CALLBACK.
>>>     * ggc-common.c (callback_vec): New variable.
>>>     (gt_pch_note_callback): New function.
>>>     (gt_pch_save): Stream out gt_pch_save function address and relocation
>>>     table.
>>>     (gt_pch_restore): Stream in saved gt_pch_save function address and
>>>     relocation table and apply relocations if needed.
>>>     * doc/gty.texi (callback): Document new GTY option.
>>>     * varasm.c (get_unnamed_section): Change callback argument's type and
>>>     last argument's type from const void * to const char *.
>>>     (output_section_asm_op): Change argument's type from const void *
>>>     to const char *, remove unnecessary cast.
>>>     * tree-core.h (struct tree_translation_unit_decl): Drop GTY((skip))
>>>     from language member.
>>>     * output.h (unnamed_section_callback): Change argument type from
>>>     const void * to const char *.
>>>     (struct unnamed_section): Use GTY((callback)) instead of GTY((skip))
>>>     for callback member.  Change data member type from const void *
>>>     to const char *.
>>>     (struct noswitch_section): Use GTY((callback)) instead of GTY((skip))
>>>     for callback member.
>>>     (get_unnamed_section): Change callback argument's type and
>>>     last argument's type from const void * to const char *.
>>>     (output_section_asm_op): Change argument's type from const void *
>>>     to const char *.
>>>     * config/avr/avr.c (avr_output_progmem_section_asm_op): Likewise.
>>>     Remove unneeded cast.
>>>     * config/darwin.c (output_objc_section_asm_op): Change argument's type
>>>     from const void * to const char *.
>>>     * config/pa/pa.c (som_output_text_section_asm_op): Likewise.
>>>     (som_output_comdat_data_section_asm_op): Likewise.
>>>     * config/rs6000/rs6000.c (rs6000_elf_output_toc_section_asm_op):
>>>     Likewise.
>>>     (rs6000_xcoff_output_readonly_section_asm_op): Likewise.  Instead
>>>     of dereferencing directive hardcode variable names and decide based on
>>>     whether directive is NULL or not.
>>>     (rs6000_xcoff_output_readwrite_section_asm_op): Change argument's type
>>>     from const void * to const char *.
>>>     (rs6000_xcoff_output_tls_section_asm_op): Likewise.  Instead
>>>     of dereferencing directive hardcode variable names and decide based on
>>>     whether directive is NULL or not.
>>>     (rs6000_xcoff_output_toc_section_asm_op): Change argument's type
>>>     from const void * to const char *.
>>>     (rs6000_xcoff_asm_init_sections): Adjust get_unnamed_section callers.
>>> gcc/c-family/
>>>     * c-pch.c (struct c_pch_validity): Remove pch_init member.
>>>     (pch_init): Don't initialize v.pch_init.
>>>     (c_common_valid_pch): Don't warn and punt if .text addresses change.
>>> libcpp/
>>>     * include/line-map.h (class line_maps): Add GTY((callback)) to
>>>     reallocator and round_alloc_size members.
>>> 
>>> --- gcc/ggc.h.jj    2021-08-19 11:42:27.366422386 +0200
>>> +++ gcc/ggc.h       2021-11-08 16:46:02.604618109 +0100
>>> @@ -46,6 +46,10 @@ typedef void (*gt_handle_reorder) (void
>>> /* Used by the gt_pch_n_* routines.  Register an object in the hash table.  
>>> */
>>> extern int gt_pch_note_object (void *, void *, gt_note_pointers);
>>> 
>>> +/* Used by the gt_pch_p_* routines.  Register address of a callback
>>> +   pointer.  */
>>> +extern void gt_pch_note_callback (void *, void *);
>>> +
>>> /* Used by the gt_pch_n_* routines.  Register that an object has a reorder
>>>   function.  */
>>> extern void gt_pch_note_reorder (void *, void *, gt_handle_reorder);
>>> --- gcc/gengtype.h.jj       2021-07-20 10:08:09.892687719 +0200
>>> +++ gcc/gengtype.h  2021-11-08 15:19:59.194210185 +0100
>>> @@ -154,6 +154,9 @@ enum typekind {
>>>  TYPE_UNION,           /* Type for GTY-ed discriminated unions.  */
>>>  TYPE_POINTER,         /* Pointer type to GTY-ed type.  */
>>>  TYPE_ARRAY,           /* Array of GTY-ed types.  */
>>> +  TYPE_CALLBACK,   /* A function pointer that needs relocation if
>>> +                      the executable has been loaded at a different
>>> +                      address.  */
>>>  TYPE_LANG_STRUCT,     /* GCC front-end language specific structs.
>>>                           Various languages may have homonymous but
>>>                           different structs.  */
>>> @@ -331,6 +334,9 @@ extern struct type string_type;
>>> extern struct type scalar_nonchar;
>>> extern struct type scalar_char;
>>> 
>>> +/* The one and only TYPE_CALLBACK.  */
>>> +extern struct type callback_type;
>>> +
>>> /* Test if a type is a union, either a plain one or a language
>>>   specific one.  */
>>> #define UNION_P(x)                                  \
>>> --- gcc/gengtype.c.jj       2021-10-04 10:16:10.885140187 +0200
>>> +++ gcc/gengtype.c  2021-11-08 16:30:41.981750183 +0100
>>> @@ -172,6 +172,7 @@ dbgprint_count_type_at (const char *fil,
>>>  int nb_struct = 0, nb_union = 0, nb_array = 0, nb_pointer = 0;
>>>  int nb_lang_struct = 0;
>>>  int nb_user_struct = 0, nb_undefined = 0;
>>> +  int nb_callback = 0;
>>>  type_p p = NULL;
>>>  for (p = t; p; p = p->next)
>>>    {
>>> @@ -202,6 +203,9 @@ dbgprint_count_type_at (const char *fil,
>>>     case TYPE_ARRAY:
>>>       nb_array++;
>>>       break;
>>> +   case TYPE_CALLBACK:
>>> +     nb_callback++;
>>> +     break;
>>>     case TYPE_LANG_STRUCT:
>>>       nb_lang_struct++;
>>>       break;
>>> @@ -217,6 +221,8 @@ dbgprint_count_type_at (const char *fil,
>>>    fprintf (stderr, "@@%%@@ %d structs, %d unions\n", nb_struct, nb_union);
>>>  if (nb_pointer > 0 || nb_array > 0)
>>>    fprintf (stderr, "@@%%@@ %d pointers, %d arrays\n", nb_pointer, 
>>> nb_array);
>>> +  if (nb_callback > 0)
>>> +    fprintf (stderr, "@@%%@@ %d callbacks\n", nb_callback);
>>>  if (nb_lang_struct > 0)
>>>    fprintf (stderr, "@@%%@@ %d lang_structs\n", nb_lang_struct);
>>>  if (nb_user_struct > 0)
>>> @@ -495,6 +501,10 @@ struct type scalar_char = {
>>>  TYPE_SCALAR, 0, 0, 0, GC_USED, {0}
>>> };
>>> 
>>> +struct type callback_type = {
>>> +  TYPE_CALLBACK, 0, 0, 0, GC_USED, {0}
>>> +};
>>> +
>>> /* Lists of various things.  */
>>> 
>>> pair_p typedefs = NULL;
>>> @@ -1464,7 +1474,7 @@ static void set_gc_used (pair_p);
>>> 
>>> static void
>>> process_gc_options (options_p opt, enum gc_used_enum level, int 
>>> *maybe_undef,
>>> -               int *length, int *skip, type_p *nested_ptr)
>>> +               int *length, int *skip, int *callback, type_p *nested_ptr)
>>> {
>>>  options_p o;
>>>  for (o = opt; o; o = o->next)
>>> @@ -1478,6 +1488,8 @@ process_gc_options (options_p opt, enum
>>>      *length = 1;
>>>    else if (strcmp (o->name, "skip") == 0)
>>>      *skip = 1;
>>> +    else if (strcmp (o->name, "callback") == 0)
>>> +      *callback = 1;
>>>    else if (strcmp (o->name, "nested_ptr") == 0
>>>          && o->kind == OPTION_NESTED)
>>>      *nested_ptr = ((const struct nested_ptr_data *) o->info.nested)->type;
>>> @@ -1526,7 +1538,7 @@ set_gc_used_type (type_p t, enum gc_used
>>>     type_p dummy2;
>>>     bool allow_undefined_field_types = (t->kind == TYPE_USER_STRUCT);
>>> 
>>> -   process_gc_options (t->u.s.opt, level, &dummy, &dummy, &dummy,
>>> +   process_gc_options (t->u.s.opt, level, &dummy, &dummy, &dummy, &dummy,
>>>                         &dummy2);
>>> 
>>>     if (t->u.s.base_class)
>>> @@ -1542,9 +1554,10 @@ set_gc_used_type (type_p t, enum gc_used
>>>         int maybe_undef = 0;
>>>         int length = 0;
>>>         int skip = 0;
>>> +       int callback = 0;
>>>         type_p nested_ptr = NULL;
>>>         process_gc_options (f->opt, level, &maybe_undef, &length, &skip,
>>> -                           &nested_ptr);
>>> +                           &callback, &nested_ptr);
>>> 
>>>         if (nested_ptr && f->type->kind == TYPE_POINTER)
>>>           set_gc_used_type (nested_ptr, GC_POINTED_TO);
>>> @@ -1554,6 +1567,8 @@ set_gc_used_type (type_p t, enum gc_used
>>>           set_gc_used_type (f->type->u.p, GC_MAYBE_POINTED_TO);
>>>         else if (skip)
>>>           ;                 /* target type is not used through this field */
>>> +       else if (callback)
>>> +         f->type = &callback_type;
>>>         else
>>>           set_gc_used_type (f->type, GC_USED, allow_undefined_field_types);
>>>       }
>>> @@ -2519,6 +2534,7 @@ output_mangled_typename (outf_p of, cons
>>>      {
>>>      case TYPE_NONE:
>>>      case TYPE_UNDEFINED:
>>> +      case TYPE_CALLBACK:
>>>     gcc_unreachable ();
>>>     break;
>>>      case TYPE_POINTER:
>>> @@ -2719,6 +2735,8 @@ walk_type (type_p t, struct walk_type_da
>>>      ;
>>>    else if (strcmp (oo->name, "for_user") == 0)
>>>      ;
>>> +    else if (strcmp (oo->name, "callback") == 0)
>>> +      ;
>>>    else
>>>      error_at_line (d->line, "unknown option `%s'\n", oo->name);
>>> 
>>> @@ -2744,6 +2762,7 @@ walk_type (type_p t, struct walk_type_da
>>>    {
>>>    case TYPE_SCALAR:
>>>    case TYPE_STRING:
>>> +    case TYPE_CALLBACK:
>>>      d->process_field (t, d);
>>>      break;
>>> 
>>> @@ -3275,6 +3294,7 @@ write_types_process_field (type_p f, con
>>>      break;
>>> 
>>>    case TYPE_SCALAR:
>>> +    case TYPE_CALLBACK:
>>>      break;
>>> 
>>>    case TYPE_ARRAY:
>>> @@ -3820,6 +3840,7 @@ write_types_local_user_process_field (ty
>>>      break;
>>> 
>>>    case TYPE_SCALAR:
>>> +    case TYPE_CALLBACK:
>>>      break;
>>> 
>>>    case TYPE_ARRAY:
>>> @@ -3906,6 +3927,13 @@ write_types_local_process_field (type_p
>>>    case TYPE_SCALAR:
>>>      break;
>>> 
>>> +    case TYPE_CALLBACK:
>>> +      oprintf (d->of, "%*sif ((void *)(%s) == this_obj)\n", d->indent, "",
>>> +          d->prev_val[3]);
>>> +      oprintf (d->of, "%*s  gt_pch_note_callback (&(%s), this_obj);\n",
>>> +          d->indent, "", d->val);
>>> +      break;
>>> +
>>>    case TYPE_ARRAY:
>>>    case TYPE_NONE:
>>>    case TYPE_UNDEFINED:
>>> @@ -4434,6 +4462,7 @@ write_root (outf_p f, pair_p v, type_p t
>>>    case TYPE_UNDEFINED:
>>>    case TYPE_UNION:
>>>    case TYPE_LANG_STRUCT:
>>> +    case TYPE_CALLBACK:
>>>      error_at_line (line, "global `%s' is unimplemented type", name);
>>>    }
>>> }
>>> @@ -4728,6 +4757,9 @@ dump_typekind (int indent, enum typekind
>>>    case TYPE_ARRAY:
>>>      printf ("TYPE_ARRAY");
>>>      break;
>>> +    case TYPE_CALLBACK:
>>> +      printf ("TYPE_CALLBACK");
>>> +      break;
>>>    case TYPE_LANG_STRUCT:
>>>      printf ("TYPE_LANG_STRUCT");
>>>      break;
>>> @@ -4894,6 +4926,7 @@ dump_type (int indent, type_p t)
>>>           t->u.scalar_is_char ? "true" : "false");
>>>      break;
>>>    case TYPE_STRING:
>>> +    case TYPE_CALLBACK:
>>>      break;
>>>    case TYPE_STRUCT:
>>>    case TYPE_UNION:
>>> --- gcc/varasm.c.jj 2021-09-28 11:34:29.343147261 +0200
>>> +++ gcc/varasm.c    2021-11-08 13:26:15.032606040 +0100
>>> @@ -250,8 +250,8 @@ object_block_hasher::hash (object_block
>>> /* Return a new unnamed section with the given fields.  */
>>> 
>>> section *
>>> -get_unnamed_section (unsigned int flags, void (*callback) (const void *),
>>> -                const void *data)
>>> +get_unnamed_section (unsigned int flags, void (*callback) (const char *),
>>> +                const char *data)
>>> {
>>>  section *sect;
>>> 
>>> @@ -7778,9 +7778,9 @@ file_end_indicate_split_stack (void)
>>>   a get_unnamed_section callback.  */
>>> 
>>> void
>>> -output_section_asm_op (const void *directive)
>>> +output_section_asm_op (const char *directive)
>>> {
>>> -  fprintf (asm_out_file, "%s\n", (const char *) directive);
>>> +  fprintf (asm_out_file, "%s\n", directive);
>>> }
>>> 
>>> /* Emit assembly code to switch to section NEW_SECTION.  Do nothing if
>>> --- gcc/ggc-common.c.jj     2021-11-08 11:09:50.280318624 +0100
>>> +++ gcc/ggc-common.c        2021-11-08 18:33:51.103390391 +0100
>>> @@ -246,6 +246,7 @@ saving_hasher::equal (const ptr_data *p1
>>> }
>>> 
>>> static hash_table<saving_hasher> *saving_htab;
>>> +static vec<void *> callback_vec;
>>> 
>>> /* Register an object in the hash table.  */
>>> 
>>> @@ -278,6 +279,23 @@ gt_pch_note_object (void *obj, void *not
>>>  return 1;
>>> }
>>> 
>>> +/* Register address of a callback pointer.  */
>>> +void
>>> +gt_pch_note_callback (void *obj, void *base)
>>> +{
>>> +  void *ptr;
>>> +  memcpy (&ptr, obj, sizeof (void *));
>>> +  if (ptr != NULL)
>>> +    {
>>> +      struct ptr_data *data
>>> +   = (struct ptr_data *)
>>> +     saving_htab->find_with_hash (base, POINTER_HASH (base));
>>> +      gcc_assert (data);
>>> +      callback_vec.safe_push ((char *) data->new_addr
>>> +                         + ((char *) obj - (char *) base));
>>> +    }
>>> +}
>>> +
>>> /* Register an object in the hash table.  */
>>> 
>>> void
>>> @@ -592,10 +610,20 @@ gt_pch_save (FILE *f)
>>>  ggc_pch_finish (state.d, state.f);
>>>  gt_pch_fixup_stringpool ();
>>> 
>>> +  unsigned num_callbacks = callback_vec.length ();
>>> +  void (*pch_save) (FILE *) = &gt_pch_save;
>>> +  if (fwrite (&pch_save, sizeof (pch_save), 1, f) != 1
>>> +      || fwrite (&num_callbacks, sizeof (num_callbacks), 1, f) != 1
>>> +      || (num_callbacks
>>> +     && fwrite (callback_vec.address (), sizeof (void *), num_callbacks,
>>> +                f) != num_callbacks))
>>> +    fatal_error (input_location, "cannot write PCH file: %m");
>>> +
>>>  XDELETE (state.ptrs);
>>>  XDELETE (this_object);
>>>  delete saving_htab;
>>>  saving_htab = NULL;
>>> +  callback_vec.release ();
>>> }
>>> 
>>> /* Read the state of the compiler back in from F.  */
>>> @@ -649,6 +677,30 @@ gt_pch_restore (FILE *f)
>>>  ggc_pch_read (f, mmi.preferred_base);
>>> 
>>>  gt_pch_restore_stringpool ();
>>> +
>>> +  void (*pch_save) (FILE *);
>>> +  unsigned num_callbacks;
>>> +  if (fread (&pch_save, sizeof (pch_save), 1, f) != 1
>>> +      || fread (&num_callbacks, sizeof (num_callbacks), 1, f) != 1)
>>> +    fatal_error (input_location, "cannot read PCH file: %m");
>>> +  if (pch_save != &gt_pch_save)
>>> +    {
>>> +      uintptr_t bias = (uintptr_t) &gt_pch_save - (uintptr_t) pch_save;
>>> +      void **ptrs = XNEWVEC (void *, num_callbacks);
>>> +      unsigned i;
>>> +
>>> +      if (fread (ptrs, sizeof (void *), num_callbacks, f) != num_callbacks)
>>> +   fatal_error (input_location, "cannot read PCH file: %m");
>>> +      for (i = 0; i < num_callbacks; ++i)
>>> +   {
>>> +     memcpy (&pch_save, ptrs[i], sizeof (pch_save));
>>> +     pch_save = (void (*) (FILE *)) ((uintptr_t) pch_save + bias);
>>> +     memcpy (ptrs[i], &pch_save, sizeof (pch_save));
>>> +   }
>>> +      XDELETE (ptrs);
>>> +    }
>>> +  else if (fseek (f, num_callbacks * sizeof (void *), SEEK_CUR) != 0)
>>> +    fatal_error (input_location, "cannot read PCH file: %m");
>>> }
>>> 
>>> /* Default version of HOST_HOOKS_GT_PCH_GET_ADDRESS when mmap is not 
>>> present.
>>> --- gcc/doc/gty.texi.jj     2021-08-19 11:42:27.363422428 +0200
>>> +++ gcc/doc/gty.texi        2021-11-08 17:13:46.613882767 +0100
>>> @@ -197,6 +197,15 @@ If @code{skip} is applied to a field, th
>>> This is somewhat dangerous; the only safe use is in a union when one
>>> field really isn't ever used.
>>> 
>>> +@findex callback
>>> +@item callback
>>> +
>>> +@code{callback} should be applied to fields with pointer to function type
>>> +and causes the field to be ignored similarly to @code{skip}, except when
>>> +writing PCH and the field is non-NULL it will remember the field's address
>>> +for relocation purposes if the process writing PCH has different load base
>>> +from a process reading PCH.
>>> +
>>> @findex for_user
>>> @item for_user
>>> 
>>> --- gcc/tree-core.h.jj      2021-11-04 12:27:02.377298411 +0100
>>> +++ gcc/tree-core.h 2021-11-08 13:24:04.496465555 +0100
>>> @@ -1964,7 +1964,7 @@ struct GTY(()) tree_function_decl {
>>> struct GTY(()) tree_translation_unit_decl {
>>>  struct tree_decl_common common;
>>>  /* Source language of this translation unit.  Used for DWARF output.  */
>>> -  const char * GTY((skip(""))) language;
>>> +  const char *language;
>>>  /* TODO: Non-optimization used to build this translation unit.  */
>>>  /* TODO: Root of a partial DWARF tree for global types and decls.  */
>>> };
>>> --- gcc/gengtype-state.c.jj 2021-07-20 10:08:09.891687732 +0200
>>> +++ gcc/gengtype-state.c    2021-11-08 15:19:16.157824146 +0100
>>> @@ -57,6 +57,7 @@ type_lineloc (const_type_p ty)
>>>    case TYPE_STRING:
>>>    case TYPE_POINTER:
>>>    case TYPE_ARRAY:
>>> +    case TYPE_CALLBACK:
>>>      return NULL;
>>>    default:
>>>      gcc_unreachable ();
>>> @@ -171,6 +172,7 @@ private:
>>>  void write_state_version (const char *version);
>>>  void write_state_scalar_type (type_p current);
>>>  void write_state_string_type (type_p current);
>>> +  void write_state_callback_type (type_p current);
>>>  void write_state_undefined_type (type_p current);
>>>  void write_state_struct_union_type (type_p current, const char *kindstr);
>>>  void write_state_struct_type (type_p current);
>>> @@ -898,6 +900,20 @@ state_writer::write_state_string_type (t
>>>    fatal ("Unexpected type in write_state_string_type");
>>> }
>>> 
>>> +/* Write the callback type.  There is only one such thing! */
>>> +void
>>> +state_writer::write_state_callback_type (type_p current)
>>> +{
>>> +  if (current == &callback_type)
>>> +    {
>>> +      write_any_indent (0);
>>> +      fprintf (state_file, "callback ");
>>> +      write_state_common_type_content (current);
>>> +    }
>>> +  else
>>> +    fatal ("Unexpected type in write_state_callback_type");
>>> +}
>>> +
>>> /* Write an undefined type.  */
>>> void
>>> state_writer::write_state_undefined_type (type_p current)
>>> @@ -1143,6 +1159,9 @@ state_writer::write_state_type (type_p c
>>>     case TYPE_STRING:
>>>       write_state_string_type (current);
>>>       break;
>>> +   case TYPE_CALLBACK:
>>> +     write_state_callback_type (current);
>>> +     break;
>>>     }
>>>    }
>>> 
>>> @@ -1477,6 +1496,14 @@ read_state_string_type (type_p *type)
>>>  read_state_common_type_content (*type);
>>> }
>>> 
>>> +/* Read the callback_type.  */
>>> +static void
>>> +read_state_callback_type (type_p *type)
>>> +{
>>> +  *type = &callback_type;
>>> +  read_state_common_type_content (*type);
>>> +}
>>> +
>>> 
>>> /* Read a lang_bitmap representing a set of GCC front-end languages.  */
>>> static void
>>> @@ -1834,6 +1861,11 @@ read_state_type (type_p *current)
>>>           next_state_tokens (1);
>>>           read_state_string_type (current);
>>>         }
>>> +     else if (state_token_is_name (t0, "callback"))
>>> +       {
>>> +         next_state_tokens (1);
>>> +         read_state_callback_type (current);
>>> +       }
>>>       else if (state_token_is_name (t0, "undefined"))
>>>         {
>>>           *current = XCNEW (struct type);
>>> --- gcc/output.h.jj 2021-09-28 11:34:29.235148754 +0200
>>> +++ gcc/output.h    2021-11-08 16:26:01.172755377 +0100
>>> @@ -470,7 +470,7 @@ struct GTY(()) named_section {
>>> 
>>> /* A callback that writes the assembly code for switching to an unnamed
>>>   section.  The argument provides callback-specific data.  */
>>> -typedef void (*unnamed_section_callback) (const void *);
>>> +typedef void (*unnamed_section_callback) (const char *);
>>> 
>>> /* Information about a SECTION_UNNAMED section.  */
>>> struct GTY(()) unnamed_section {
>>> @@ -478,8 +478,8 @@ struct GTY(()) unnamed_section {
>>> 
>>>  /* The callback used to switch to the section, and the data that
>>>     should be passed to the callback.  */
>>> -  unnamed_section_callback GTY ((skip)) callback;
>>> -  const void *GTY ((skip)) data;
>>> +  unnamed_section_callback GTY ((callback)) callback;
>>> +  const char *data;
>>> 
>>>  /* The next entry in the chain of unnamed sections.  */
>>>  section *next;
>>> @@ -503,7 +503,7 @@ struct GTY(()) noswitch_section {
>>>  struct section_common common;
>>> 
>>>  /* The callback used to assemble decls in this section.  */
>>> -  noswitch_section_callback GTY ((skip)) callback;
>>> +  noswitch_section_callback GTY ((callback)) callback;
>>> };
>>> 
>>> /* Information about a section, which may be named or unnamed.  */
>>> @@ -538,8 +538,8 @@ extern GTY(()) section *bss_noswitch_sec
>>> extern GTY(()) section *in_section;
>>> extern GTY(()) bool in_cold_section_p;
>>> 
>>> -extern section *get_unnamed_section (unsigned int, void (*) (const void *),
>>> -                                const void *);
>>> +extern section *get_unnamed_section (unsigned int, void (*) (const char *),
>>> +                                const char *);
>>> extern section *get_section (const char *, unsigned int, tree,
>>>                          bool not_existing = false);
>>> extern section *get_named_section (tree, const char *, int);
>>> @@ -561,7 +561,7 @@ extern section *get_cdtor_priority_secti
>>> 
>>> extern bool unlikely_text_section_p (section *);
>>> extern void switch_to_section (section *, tree = nullptr);
>>> -extern void output_section_asm_op (const void *);
>>> +extern void output_section_asm_op (const char *);
>>> 
>>> extern void record_tm_clone_pair (tree, tree);
>>> extern void finish_tm_clone_pairs (void);
>>> --- gcc/config/avr/avr.c.jj 2021-07-15 10:16:12.873583249 +0200
>>> +++ gcc/config/avr/avr.c    2021-11-08 13:28:30.215676387 +0100
>>> @@ -10114,10 +10114,9 @@ avr_output_bss_section_asm_op (const voi
>>> /* Unnamed section callback for progmem*.data sections.  */
>>> 
>>> static void
>>> -avr_output_progmem_section_asm_op (const void *data)
>>> +avr_output_progmem_section_asm_op (const char *data)
>>> {
>>> -  fprintf (asm_out_file, "\t.section\t%s,\"a\",@progbits\n",
>>> -           (const char*) data);
>>> +  fprintf (asm_out_file, "\t.section\t%s,\"a\",@progbits\n", data);
>>> }
>>> 
>>> 
>>> --- gcc/config/darwin.c.jj  2021-10-21 10:23:27.450834602 +0200
>>> +++ gcc/config/darwin.c     2021-11-08 13:27:19.106691421 +0100
>>> @@ -134,7 +134,7 @@ int emit_aligned_common = false;
>>>   DIRECTIVE is as for output_section_asm_op.  */
>>> 
>>> static void
>>> -output_objc_section_asm_op (const void *directive)
>>> +output_objc_section_asm_op (const char *directive)
>>> {
>>>  static bool been_here = false;
>>> 
>>> --- gcc/config/pa/pa.c.jj   2021-10-27 09:00:28.762277456 +0200
>>> +++ gcc/config/pa/pa.c      2021-11-08 13:29:41.935652629 +0100
>>> @@ -10011,7 +10011,7 @@ pa_arg_partial_bytes (cumulative_args_t
>>>   to the default text subspace.  */
>>> 
>>> static void
>>> -som_output_text_section_asm_op (const void *data ATTRIBUTE_UNUSED)
>>> +som_output_text_section_asm_op (const char *data ATTRIBUTE_UNUSED)
>>> {
>>>  gcc_assert (TARGET_SOM);
>>>  if (TARGET_GAS)
>>> @@ -10055,7 +10055,7 @@ som_output_text_section_asm_op (const vo
>>>   sections.  This function is only used with SOM.  */
>>> 
>>> static void
>>> -som_output_comdat_data_section_asm_op (const void *data)
>>> +som_output_comdat_data_section_asm_op (const char *data)
>>> {
>>>  in_section = NULL;
>>>  output_section_asm_op (data);
>>> --- gcc/config/rs6000/rs6000.c.jj   2021-11-05 00:43:22.476626062 +0100
>>> +++ gcc/config/rs6000/rs6000.c      2021-11-08 13:43:22.415940789 +0100
>>> @@ -20597,7 +20597,7 @@ rs6000_ms_bitfield_layout_p (const_tree
>>> /* A get_unnamed_section callback, used for switching to toc_section.  */
>>> 
>>> static void
>>> -rs6000_elf_output_toc_section_asm_op (const void *data ATTRIBUTE_UNUSED)
>>> +rs6000_elf_output_toc_section_asm_op (const char *data ATTRIBUTE_UNUSED)
>>> {
>>>  if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2)
>>>      && TARGET_MINIMAL_TOC)
>>> @@ -21301,35 +21301,39 @@ rs6000_xcoff_asm_globalize_label (FILE *
>>>   points to the section string variable.  */
>>> 
>>> static void
>>> -rs6000_xcoff_output_readonly_section_asm_op (const void *directive)
>>> +rs6000_xcoff_output_readonly_section_asm_op (const char *directive)
>>> {
>>>  fprintf (asm_out_file, "\t.csect %s[RO],%s\n",
>>> -      *(const char *const *) directive,
>>> +      directive
>>> +      ? xcoff_private_rodata_section_name
>>> +      : xcoff_read_only_section_name,
>>>        XCOFF_CSECT_DEFAULT_ALIGNMENT_STR);
>>> }
>>> 
>>> /* Likewise for read-write sections.  */
>>> 
>>> static void
>>> -rs6000_xcoff_output_readwrite_section_asm_op (const void *directive)
>>> +rs6000_xcoff_output_readwrite_section_asm_op (const char *)
>>> {
>>>  fprintf (asm_out_file, "\t.csect %s[RW],%s\n",
>>> -      *(const char *const *) directive,
>>> +      xcoff_private_data_section_name,
>>>        XCOFF_CSECT_DEFAULT_ALIGNMENT_STR);
>>> }
>>> 
>>> static void
>>> -rs6000_xcoff_output_tls_section_asm_op (const void *directive)
>>> +rs6000_xcoff_output_tls_section_asm_op (const char *directive)
>>> {
>>>  fprintf (asm_out_file, "\t.csect %s[TL],%s\n",
>>> -      *(const char *const *) directive,
>>> +      directive
>>> +      ? xcoff_private_data_section_name
>>> +      : xcoff_tls_data_section_name,
>>>        XCOFF_CSECT_DEFAULT_ALIGNMENT_STR);
>>> }
>>> 
>>> /* A get_unnamed_section callback, used for switching to toc_section.  */
>>> 
>>> static void
>>> -rs6000_xcoff_output_toc_section_asm_op (const void *data ATTRIBUTE_UNUSED)
>>> +rs6000_xcoff_output_toc_section_asm_op (const char *data ATTRIBUTE_UNUSED)
>>> {
>>>  if (TARGET_MINIMAL_TOC)
>>>    {
>>> @@ -21356,26 +21360,26 @@ rs6000_xcoff_asm_init_sections (void)
>>> {
>>>  read_only_data_section
>>>    = get_unnamed_section (0, rs6000_xcoff_output_readonly_section_asm_op,
>>> -                      &xcoff_read_only_section_name);
>>> +                      NULL);
>>> 
>>>  private_data_section
>>>    = get_unnamed_section (SECTION_WRITE,
>>>                        rs6000_xcoff_output_readwrite_section_asm_op,
>>> -                      &xcoff_private_data_section_name);
>>> +                      NULL);
>>> 
>>>  read_only_private_data_section
>>>    = get_unnamed_section (0, rs6000_xcoff_output_readonly_section_asm_op,
>>> -                      &xcoff_private_rodata_section_name);
>>> +                      "");
>>> 
>>>  tls_data_section
>>>    = get_unnamed_section (SECTION_TLS,
>>>                        rs6000_xcoff_output_tls_section_asm_op,
>>> -                      &xcoff_tls_data_section_name);
>>> +                      NULL);
>>> 
>>>  tls_private_data_section
>>>    = get_unnamed_section (SECTION_TLS,
>>>                        rs6000_xcoff_output_tls_section_asm_op,
>>> -                      &xcoff_private_data_section_name);
>>> +                      "");
>>> 
>>>  toc_section
>>>    = get_unnamed_section (0, rs6000_xcoff_output_toc_section_asm_op, NULL);
>>> --- gcc/c-family/c-pch.c.jj 2021-06-02 10:08:14.149450407 +0200
>>> +++ gcc/c-family/c-pch.c    2021-11-08 17:34:17.302343697 +0100
>>> @@ -54,7 +54,6 @@ struct c_pch_validity
>>> {
>>>  uint32_t pch_write_symbols;
>>>  signed char match[MATCH_SIZE];
>>> -  void (*pch_init) (void);
>>>  size_t target_data_length;
>>> };
>>> 
>>> @@ -117,7 +116,6 @@ pch_init (void)
>>>     gcc_assert (v.match[i] == *pch_matching[i].flag_var);
>>>      }
>>>  }
>>> -  v.pch_init = &pch_init;
>>>  target_validity = targetm.get_pch_validity (&v.target_data_length);
>>> 
>>>  if (fwrite (partial_pch, IDENT_LENGTH, 1, f) != 1
>>> @@ -278,19 +276,6 @@ c_common_valid_pch (cpp_reader *pfile, c
>>>     }
>>>  }
>>> 
>>> -  /* If the text segment was not loaded at the same address as it was
>>> -     when the PCH file was created, function pointers loaded from the
>>> -     PCH will not be valid.  We could in theory remap all the function
>>> -     pointers, but no support for that exists at present.
>>> -     Since we have the same executable, it should only be necessary to
>>> -     check one function.  */
>>> -  if (v.pch_init != &pch_init)
>>> -    {
>>> -      cpp_warning (pfile, CPP_W_INVALID_PCH,
>>> -              "%s: had text segment at different address", name);
>>> -      return 2;
>>> -    }
>>> -
>>>  /* Check the target-specific validity data.  */
>>>  {
>>>    void *this_file_data = xmalloc (v.target_data_length);
>>> --- libcpp/include/line-map.h.jj    2021-11-01 14:37:06.697853154 +0100
>>> +++ libcpp/include/line-map.h       2021-11-08 16:16:34.562837006 +0100
>>> @@ -803,11 +803,11 @@ public:
>>>  unsigned int max_column_hint;
>>> 
>>>  /* The allocator to use when resizing 'maps', defaults to xrealloc.  */
>>> -  line_map_realloc reallocator;
>>> +  line_map_realloc GTY((callback)) reallocator;
>>> 
>>>  /* The allocators' function used to know the actual size it
>>>     allocated, for a certain allocation size requested.  */
>>> -  line_map_round_alloc_size_func round_alloc_size;
>>> +  line_map_round_alloc_size_func GTY((callback)) round_alloc_size;
>>> 
>>>  struct location_adhoc_data_map location_adhoc_data_map;
>>> 
>>> 
>>> 
>>>     Jakub
>>> 
>> 
>> -- 
>> Richard Biener <rguent...@suse.de>
>> SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
>> Germany; GF: Ivo Totev; HRB 36809 (AG Nuernberg)

Reply via email to