> From: Andi Kleen <a...@linux.intel.com>
> 
> Currently when reading in LTO sections from ld -r files they can
> get randomly reordered based on hash tables and random IDs.
> This causes reordering later when the final code is generated and
> also makes crashes harder to reproduce.
> 
> This patch maintains explicit lists based on the input order and uses
> those lists to preserve that order when starting the rest of the
> LTO passes.
> 
> This is the first step to working -fno-toplevel-reorder for
> LTO. But this needs more changes because the LTO partitioner
> can still reorder.
> 
> This add two lists: one for the section and another one for
> the file_decl_datas. This is needed because the sections are
> walked twice through different data structures.
> 
> In addition some code becomes slightly cleaner because we don't need
> to pass state through abstract callbacks anymore, but
> can just use direct type safe calls.
> 
> Passes LTO bootstrap and testsuite on x86_64-linux. Ok?

Note that this is also needed to make lto-symtab decisions consistent with 
linker
decisions. So it makes a lot of sense to me, but I can't approve it.
I was running into funny cases where things got resolved differently on
openoffice, so hopefully this will solve it.


Honza
> 
> gcc/lto/:
> 
> 2011-10-02   Andi Kleen <a...@linux.intel.com>
> 
>       * lto-object.c (lto_obj_add_section_data): Add list.
>       (lto_obj_add_section): Fill in list.
>       (ltoobj_build_section_table): Pass through list.
>       * lto.c (file_data_list): Declare.
>       (create_subid_section_table): Pass arguments directly.
>       Fill in list of file_datas.
>       (lwstate): Delete.
>       (lto_create_files_from_ids): Pass in direct arguments.
>       Don't maintain list.
>       (lto_file_read): Use explicit section and file data lists.
>       (lto_read_all_file_options): Pass in section_list.
>       * lto.h (lto_obj_build_section_table): Add list.
>       (lto_section_slot): Add next.
>       (lto_section_list): Declare.
> 
> diff --git a/gcc/lto/lto-object.c b/gcc/lto/lto-object.c
> index 3be58de..daf3bd0 100644
> --- a/gcc/lto/lto-object.c
> +++ b/gcc/lto/lto-object.c
> @@ -204,6 +204,8 @@ struct lto_obj_add_section_data
>    htab_t section_hash_table;
>    /* The offset of this file.  */
>    off_t base_offset;
> +  /* List in linker order */
> +  struct lto_section_list *list;
>  };
>  
>  /* This is called for each section in the file.  */
> @@ -218,6 +220,7 @@ lto_obj_add_section (void *data, const char *name, off_t 
> offset,
>    char *new_name;
>    struct lto_section_slot s_slot;
>    void **slot;
> +  struct lto_section_list *list = loasd->list;
>  
>    if (strncmp (name, LTO_SECTION_NAME_PREFIX,
>              strlen (LTO_SECTION_NAME_PREFIX)) != 0)
> @@ -228,12 +231,21 @@ lto_obj_add_section (void *data, const char *name, 
> off_t offset,
>    slot = htab_find_slot (section_hash_table, &s_slot, INSERT);
>    if (*slot == NULL)
>      {
> -      struct lto_section_slot *new_slot = XNEW (struct lto_section_slot);
> +      struct lto_section_slot *new_slot = XCNEW (struct lto_section_slot);
>  
>        new_slot->name = new_name;
>        new_slot->start = loasd->base_offset + offset;
>        new_slot->len = length;
>        *slot = new_slot;
> +
> +      if (list != NULL)
> +        {
> +          if (!list->first)
> +            list->first = new_slot;
> +          if (list->last)
> +            list->last->next = new_slot;
> +          list->last = new_slot;
> +        }
>      }
>    else
>      {
> @@ -248,7 +260,7 @@ lto_obj_add_section (void *data, const char *name, off_t 
> offset,
>     the start and size of each section in the .o file.  */
>  
>  htab_t
> -lto_obj_build_section_table (lto_file *lto_file)
> +lto_obj_build_section_table (lto_file *lto_file, struct lto_section_list 
> *list)
>  {
>    struct lto_simple_object *lo = (struct lto_simple_object *) lto_file;
>    htab_t section_hash_table;
> @@ -261,6 +273,7 @@ lto_obj_build_section_table (lto_file *lto_file)
>    gcc_assert (lo->sobj_r != NULL && lo->sobj_w == NULL);
>    loasd.section_hash_table = section_hash_table;
>    loasd.base_offset = lo->base.offset;
> +  loasd.list = list;
>    errmsg = simple_object_find_sections (lo->sobj_r, lto_obj_add_section,
>                                       &loasd, &err);
>    if (errmsg != NULL)
> diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
> index 778e33e..a77eeb4 100644
> --- a/gcc/lto/lto.c
> +++ b/gcc/lto/lto.c
> @@ -1052,6 +1052,12 @@ lto_resolution_read (splay_tree file_ids, FILE 
> *resolution, lto_file *file)
>      }
>  }
>  
> +/* List of file_decl_datas */
> +struct file_data_list
> +  {
> +    struct lto_file_decl_data *first, *last;
> +  };
> +
>  /* Is the name for a id'ed LTO section? */
>  
>  static int 
> @@ -1068,11 +1074,10 @@ lto_section_with_id (const char *name, unsigned 
> HOST_WIDE_INT *id)
>  /* Create file_data of each sub file id */
>  
>  static int 
> -create_subid_section_table (void **slot, void *data)
> +create_subid_section_table (struct lto_section_slot *ls, splay_tree file_ids,
> +                            struct file_data_list *list)
>  {
>    struct lto_section_slot s_slot, *new_slot;
> -  struct lto_section_slot *ls = *(struct lto_section_slot **)slot;
> -  splay_tree file_ids = (splay_tree)data;
>    unsigned HOST_WIDE_INT id;
>    splay_tree_node nd;
>    void **hash_slot;
> @@ -1095,6 +1100,13 @@ create_subid_section_table (void **slot, void *data)
>        file_data->id = id;
>        file_data->section_hash_table = lto_obj_create_section_hash_table ();;
>        lto_splay_tree_insert (file_ids, id, file_data);
> +
> +      /* Maintain list in linker order */
> +      if (!list->first)
> +        list->first = file_data;
> +      if (list->last)
> +        list->last->next = file_data;
> +      list->last = file_data;
>      }
>  
>    /* Copy section into sub module hash table */
> @@ -1129,27 +1141,17 @@ lto_file_finalize (struct lto_file_decl_data 
> *file_data, lto_file *file)
>    lto_free_section_data (file_data, LTO_section_decls, NULL, data, len);
>  }
>  
> -struct lwstate
> -{
> -  lto_file *file;
> -  struct lto_file_decl_data **file_data;
> -  int *count;
> -};
> -
> -/* Traverse ids and create a list of file_datas out of it. */      
> +/* Finalize FILE_DATA in FILE and increase COUNT. */
>  
> -static int lto_create_files_from_ids (splay_tree_node node, void *data)
> +static int 
> +lto_create_files_from_ids (lto_file *file, struct lto_file_decl_data 
> *file_data, 
> +                        int *count)
>  {
> -  struct lwstate *lw = (struct lwstate *)data;
> -  struct lto_file_decl_data *file_data = (struct lto_file_decl_data 
> *)node->value;
> -
> -  lto_file_finalize (file_data, lw->file);
> +  lto_file_finalize (file_data, file);
>    if (cgraph_dump_file)
>      fprintf (cgraph_dump_file, "Creating file %s with sub id " 
> HOST_WIDE_INT_PRINT_HEX "\n", 
>            file_data->file_name, file_data->id);
> -  file_data->next = *lw->file_data;
> -  *lw->file_data = file_data;
> -  (*lw->count)++;
> +  (*count)++;
>    return 0;
>  }
>  
> @@ -1166,29 +1168,31 @@ lto_file_read (lto_file *file, FILE *resolution_file, 
> int *count)
>    struct lto_file_decl_data *file_data = NULL;
>    splay_tree file_ids;
>    htab_t section_hash_table;
> -  struct lwstate state;
> -  
> -  section_hash_table = lto_obj_build_section_table (file);
> +  struct lto_section_slot *section;
> +  struct file_data_list file_list;
> +  struct lto_section_list section_list;
> + 
> +  memset (&section_list, 0, sizeof (struct lto_section_list)); 
> +  section_hash_table = lto_obj_build_section_table (file, &section_list);
>  
>    /* Find all sub modules in the object and put their sections into new hash
>       tables in a splay tree. */
>    file_ids = lto_splay_tree_new ();
> -  htab_traverse (section_hash_table, create_subid_section_table, file_ids);
> -  
> +  memset (&file_list, 0, sizeof (struct file_data_list));
> +  for (section = section_list.first; section != NULL; section = 
> section->next)
> +    create_subid_section_table (section, file_ids, &file_list);
> +
>    /* Add resolutions to file ids */
>    lto_resolution_read (file_ids, resolution_file, file);
>  
> -  /* Finalize each lto file for each submodule in the merged object
> -     and create list for returning. */
> -  state.file = file;
> -  state.file_data = &file_data;
> -  state.count = count;
> -  splay_tree_foreach (file_ids, lto_create_files_from_ids, &state);
> -    
> +  /* Finalize each lto file for each submodule in the merged object */
> +  for (file_data = file_list.first; file_data != NULL; file_data = 
> file_data->next)
> +    lto_create_files_from_ids (file, file_data, count);
> + 
>    splay_tree_delete (file_ids);
>    htab_delete (section_hash_table);
>  
> -  return file_data;
> +  return file_list.first;
>  }
>  
>  #if HAVE_MMAP_FILE && HAVE_SYSCONF && defined _SC_PAGE_SIZE
> @@ -2427,7 +2431,7 @@ lto_read_all_file_options (void)
>  
>        file_data = XCNEW (struct lto_file_decl_data);
>        file_data->file_name = file->filename;
> -      file_data->section_hash_table = lto_obj_build_section_table (file);
> +      file_data->section_hash_table = lto_obj_build_section_table (file, 
> NULL);
>  
>        lto_read_file_options (file_data);
>  
> diff --git a/gcc/lto/lto.h b/gcc/lto/lto.h
> index 8110ace..43fcca6 100644
> --- a/gcc/lto/lto.h
> +++ b/gcc/lto/lto.h
> @@ -43,7 +43,8 @@ extern void lto_read_all_file_options (void);
>  /* In lto-elf.c or lto-coff.c  */
>  extern lto_file *lto_obj_file_open (const char *filename, bool writable);
>  extern void lto_obj_file_close (lto_file *file);
> -extern htab_t lto_obj_build_section_table (lto_file *file);
> +struct lto_section_list;
> +extern htab_t lto_obj_build_section_table (lto_file *file, struct 
> lto_section_list *list);
>  extern htab_t lto_obj_create_section_hash_table (void);
>  extern void lto_obj_begin_section (const char *name);
>  extern void lto_obj_append_data (const void *data, size_t len, void *block);
> @@ -58,6 +59,13 @@ struct lto_section_slot
>    const char *name;
>    intptr_t start;
>    size_t len;
> +  struct lto_section_slot *next;
> +};
> +
> +/* A list of section slots */
> +struct lto_section_list
> +{
> +  struct lto_section_slot *first, *last;
>  };
>  
>  int64_t lto_parse_hex (const char *p);

Reply via email to