This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH: file unique name


Hi,
In reworking the gcov machinery, I came across some things that it would
be useful to clean up first. Here is the first of them
Yes I know we're at stage3, I needed to get this stuff out of my head.

get_file_function_name produces a name unique across all object files. 
Most times it can do this by using an external symbol discovered in the
source file, but it falls back on a different scheme when no such name
is found. Because of bootstrap comparisons, this unique name must be the
same name on recompilation (we can't just make up a random number). It
is generated from the source file name, plus the inode of the input
file. That inode is not stable, and changes for source files created
during the bootstrap. (This doesn't bite us at the moment, but does on
the gcov reworking.)

Using the inode for uniqueness is no better than
using the full pathname of the file. We can approximate the latter using
the current directory pathname, and the input filename, which is what this
patch does. It generates the crc32 of the main_input_file, input_file and
current directory, and then sprintf's that, along with the basename component
of the main_input_file.

booted & tested on i686-pc-linux-gnu, ok for basic-improvements?

nathan
-- 
Dr Nathan Sidwell   ::   http://www.codesourcery.com   ::   CodeSourcery LLC
         'But that's a lie.' - 'Yes it is. What's your point?'
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org
2002-09-02  Nathan Sidwell  <nathan@codesourcery.com>

	* tree.c (append_random_chars): Remove.
	(clean_symbol_name): Allow '_'. Use invalid char value to generate
	replacement.
	(get_file_function_name_long): Have separate TYPE and SUFFIX
	parameters. Generate unique name from CRC of getcwd.
	(get_file_function_name): Adjust.
	* tree.h (get_file_function_name_long): Adjust prototype.
	* varasm.c (assemble_start_function): Remove memory leak.
	* toplev.c (output_clean_symbol_name): Remove.
	* toplev.h (output_clean_symbol_name): Remove.
	* profile.c (output_func_start_profiler): Use
	get_file_function_name_long.

cp:
	* decl2.c (start_objects): Adjust get_file_function_name_long
	call.

Index: profile.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/profile.c,v
retrieving revision 1.97
diff -c -3 -p -r1.97 profile.c
*** profile.c	9 Aug 2002 08:51:27 -0000	1.97
--- profile.c	2 Sep 2002 21:29:11 -0000
*************** output_func_start_profiler ()
*** 1362,1372 ****
  
       And no, I don't like this either.  */
  
!   fnname = get_file_function_name ('I');
!   cfnname = IDENTIFIER_POINTER (fnname);
!   name = concat (cfnname, "GCOV", NULL);
!   fnname = get_identifier (name);
!   free (name);
  
    fndecl = build_decl (FUNCTION_DECL, fnname,
  		       build_function_type (void_type_node, NULL_TREE));
--- 1362,1368 ----
  
       And no, I don't like this either.  */
  
!   fnname = get_file_function_name_long ('I', "_GCOV");
  
    fndecl = build_decl (FUNCTION_DECL, fnname,
  		       build_function_type (void_type_node, NULL_TREE));
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.668
diff -c -3 -p -r1.668 toplev.c
*** toplev.c	14 Aug 2002 06:36:51 -0000	1.668
--- toplev.c	2 Sep 2002 21:29:28 -0000
*************** output_quoted_string (asm_file, string)
*** 1752,1775 ****
  #endif
  }
  
- /* Output NAME into FILE after having turned it into something
-    usable as an identifier in a target's assembly file.  */
- void
- output_clean_symbol_name (file, name)
-      FILE *file;
-      const char *name;
- {
-   /* Make a copy of NAME.  */
-   char *id = xstrdup (name);
- 
-   /* Make it look like a valid identifier for an assembler.  */
-   clean_symbol_name (id);
- 
-   fputs (id, file);
-   free (id);
- }
- 
- 
  /* Output a file name in the form wanted by System V.  */
  
  void
--- 1752,1757 ----
Index: toplev.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.h,v
retrieving revision 1.89
diff -c -3 -p -r1.89 toplev.h
*** toplev.h	4 Aug 2002 16:21:02 -0000	1.89
--- toplev.h	2 Sep 2002 21:29:29 -0000
*************** extern void warning_for_asm		PARAMS ((st
*** 87,93 ****
  						 const char *, ...));
  extern void warn_deprecated_use		PARAMS ((union tree_node *));
  
- extern void output_clean_symbol_name    PARAMS ((FILE *, const char *));
  #ifdef BUFSIZ
  extern void output_quoted_string	PARAMS ((FILE *, const char *));
  extern void output_file_directive	PARAMS ((FILE *, const char *));
--- 87,92 ----
Index: tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.c,v
retrieving revision 1.271
diff -c -3 -p -r1.271 tree.c
*** tree.c	21 Aug 2002 23:24:10 -0000	1.271
--- tree.c	2 Sep 2002 21:29:38 -0000
*************** static GTY ((if_marked ("type_hash_marke
*** 117,123 ****
       htab_t type_hash_table;
  
  static void set_type_quals PARAMS ((tree, int));
- static void append_random_chars PARAMS ((char *));
  static int type_hash_eq PARAMS ((const void *, const void *));
  static unsigned int type_hash_hash PARAMS ((const void *));
  static void print_type_hash_statistics PARAMS((void));
--- 117,122 ----
*************** dump_tree_statistics ()
*** 4330,4398 ****
    (*lang_hooks.print_statistics) ();
  }
  
- #define FILE_FUNCTION_FORMAT "_GLOBAL__%s_%s"
- 
- /* Appends 6 random characters to TEMPLATE to (hopefully) avoid name
-    clashes in cases where we can't reliably choose a unique name.
- 
-    Derived from mkstemp.c in libiberty.  */
- 
- static void
- append_random_chars (template)
-      char *template;
- {
-   static const char letters[]
-     = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
-   static unsigned HOST_WIDE_INT value;
-   unsigned HOST_WIDE_INT v;
- 
-   if (! value)
-     {
-       struct stat st;
- 
-       /* VALUE should be unique for each file and must not change between
- 	 compiles since this can cause bootstrap comparison errors.  */
- 
-       if (stat (main_input_filename, &st) < 0)
- 	{
- 	  /* This can happen when preprocessed text is shipped between
- 	     machines, e.g. with bug reports.  Assume that uniqueness
- 	     isn't actually an issue.  */
- 	  value = 1;
- 	}
-       else
- 	{
- 	  /* In VMS, ino is an array, so we have to use both values.  We
- 	     conditionalize that.  */
- #ifdef VMS
- #define INO_TO_INT(INO) ((int) (INO)[1] << 16 ^ (int) (INO)[2])
- #else
- #define INO_TO_INT(INO) INO
- #endif
- 	  value = st.st_dev ^ INO_TO_INT (st.st_ino) ^ st.st_mtime;
- 	}
-     }
- 
-   template += strlen (template);
- 
-   v = value;
- 
-   /* Fill in the random bits.  */
-   template[0] = letters[v % 62];
-   v /= 62;
-   template[1] = letters[v % 62];
-   v /= 62;
-   template[2] = letters[v % 62];
-   v /= 62;
-   template[3] = letters[v % 62];
-   v /= 62;
-   template[4] = letters[v % 62];
-   v /= 62;
-   template[5] = letters[v % 62];
- 
-   template[6] = '\0';
- }
- 
  /* P is a string that will be used in a symbol.  Mask out any characters
     that are not valid in that context.  */
  
--- 4329,4334 ----
*************** clean_symbol_name (p)
*** 4403,4465 ****
    for (; *p; p++)
      if (! (ISALNUM (*p)
  #ifndef NO_DOLLAR_IN_LABEL	/* this for `$'; unlikely, but... -- kr */
! 	    || *p == '$'
  #endif
  #ifndef NO_DOT_IN_LABEL		/* this for `.'; unlikely, but...  */
! 	    || *p == '.'
  #endif
! 	   ))
!       *p = '_';
  }
  
  /* Generate a name for a function unique to this translation unit.
     TYPE is some string to identify the purpose of this function to the
!    linker or collect2.  */
  
  tree
! get_file_function_name_long (type)
!      const char *type;
  {
!   char *buf;
!   const char *p;
!   char *q;
! 
    if (first_global_object_name)
!     p = first_global_object_name;
    else
      {
!       /* We don't have anything that we know to be unique to this translation
! 	 unit, so use what we do have and throw in some randomness.  */
! 
!       const char *name = weak_global_object_name;
!       const char *file = main_input_filename;
! 
!       if (! name)
! 	name = "";
!       if (! file)
! 	file = input_filename;
! 
!       q = (char *) alloca (7 + strlen (name) + strlen (file));
  
!       sprintf (q, "%s%s", name, file);
!       append_random_chars (q);
!       p = q;
      }
! 
!   buf = (char *) alloca (sizeof (FILE_FUNCTION_FORMAT) + strlen (p)
! 			 + strlen (type));
! 
!   /* Set up the name of the file-level functions we may need.
!      Use a global object (which is already required to be unique over
!      the program) rather than the file name (which imposes extra
!      constraints).  */
!   sprintf (buf, FILE_FUNCTION_FORMAT, type, p);
! 
!   /* Don't need to pull weird characters out of global names.  */
!   if (p != first_global_object_name)
!     clean_symbol_name (buf + 11);
! 
!   return get_identifier (buf);
  }
  
  /* If KIND=='I', return a suitable global initializer (constructor) name.
--- 4339,4429 ----
    for (; *p; p++)
      if (! (ISALNUM (*p)
  #ifndef NO_DOLLAR_IN_LABEL	/* this for `$'; unlikely, but... -- kr */
! 	   || *p == '$'
  #endif
  #ifndef NO_DOT_IN_LABEL		/* this for `.'; unlikely, but...  */
! 	   || *p == '.'
  #endif
! 	   || *p == '_'))
!       {
! 	unsigned v = (*p & 0xff) % 62;
! 
! 	if (v < 10)
! 	  v += '0';
! 	else if (v < 36)
! 	  v += 'A' - 10;
! 	else
! 	  v += 'a' - 36;
! 	*p = v;
!       }
  }
  
  /* Generate a name for a function unique to this translation unit.
     TYPE is some string to identify the purpose of this function to the
!    linker or collect2. The format is "_GLOBAL__<unique>_<type><suffix>". */
  
  tree
! get_file_function_name_long (typ, suffix)
!      int typ;
!      char const *suffix;
  {
!   tree id;
!   char *string;
!   char type[2];
!   
!   type[0] = typ;
!   type[1] = 0;
!   
    if (first_global_object_name)
!     string = concat ("_GLOBAL__", first_global_object_name,
! 		     "_", type, suffix, NULL);
    else
      {
!       /* We don't have anything that we know to be unique to this
! 	 translation unit.  Make something unique, but repeatable.  */
!       const char *strings[3];
!       const char *filename = NULL;
!       unsigned ix;
!       unsigned long crc32 = 0;
!       char hash[9];
! 
!       strings[0] = main_input_filename;
!       strings[1] = input_filename;
!       strings[2] = getpwd ();
!       
!       for (ix = 0; ix != 3; ix++)
! 	if (strings[ix])
! 	  {
! 	    const char *ptr;
  
! 	    if (!filename)
! 	      filename = strings[ix];
! 	    for (ptr = strings[ix]; *ptr; ptr++)
! 	      {
! 		unsigned jx;
! 		unsigned value = *ptr << 24;
! 		
! 		for (jx = 8; jx--; value <<= 1)
! 		  {
! 		    unsigned long feedback;
! 		    
! 		    feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0;
! 		    crc32 <<= 1;
! 		    crc32 ^= feedback;
! 		  }
! 	      }
! 	  }
!       sprintf (hash, "%08lx", crc32);
!       string = concat ("_GLOBAL__",
! 		       weak_global_object_name ? weak_global_object_name : "",
! 		       lbasename (filename),
! 		       hash, "_", type, suffix, NULL);
!       clean_symbol_name (string);
      }
!   
!   id = get_identifier (string);
!   free (string);
!   return id;
  }
  
  /* If KIND=='I', return a suitable global initializer (constructor) name.
*************** tree
*** 4469,4480 ****
  get_file_function_name (kind)
       int kind;
  {
!   char p[2];
! 
!   p[0] = kind;
!   p[1] = 0;
! 
!   return get_file_function_name_long (p);
  }
  
  /* Expand (the constant part of) a SET_TYPE CONSTRUCTOR node.
--- 4433,4439 ----
  get_file_function_name (kind)
       int kind;
  {
!   return get_file_function_name_long (kind, NULL);
  }
  
  /* Expand (the constant part of) a SET_TYPE CONSTRUCTOR node.
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.349.4.1
diff -c -3 -p -r1.349.4.1 tree.h
*** tree.h	2 Sep 2002 20:32:39 -0000	1.349.4.1
--- tree.h	2 Sep 2002 21:29:46 -0000
*************** extern tree builtin_function		PARAMS ((c
*** 2738,2744 ****
  
  /* In tree.c */
  extern void clean_symbol_name			PARAMS ((char *));
! extern tree get_file_function_name_long 	PARAMS ((const char *));
  extern tree get_set_constructor_bits		PARAMS ((tree, char *, int));
  extern tree get_set_constructor_bytes		PARAMS ((tree,
  						       unsigned char *, int));
--- 2738,2744 ----
  
  /* In tree.c */
  extern void clean_symbol_name			PARAMS ((char *));
! extern tree get_file_function_name_long 	PARAMS ((int, const char *));
  extern tree get_set_constructor_bits		PARAMS ((tree, char *, int));
  extern tree get_set_constructor_bytes		PARAMS ((tree,
  						       unsigned char *, int));
Index: varasm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/varasm.c,v
retrieving revision 1.303.2.2
diff -c -3 -p -r1.303.2.2 varasm.c
*** varasm.c	2 Sep 2002 02:53:53 -0000	1.303.2.2
--- varasm.c	2 Sep 2002 21:29:56 -0000
*************** assemble_start_function (decl, fnname)
*** 1209,1216 ****
  
  	  if (! DECL_WEAK (decl) && ! DECL_ONE_ONLY (decl))
  	    first_global_object_name = name;
! 	  else
  	    weak_global_object_name = name;
  	}
  
        globalize_decl (decl);
--- 1209,1218 ----
  
  	  if (! DECL_WEAK (decl) && ! DECL_ONE_ONLY (decl))
  	    first_global_object_name = name;
! 	  else if (!weak_global_object_name)
  	    weak_global_object_name = name;
+ 	  else
+ 	    free (name);
  	}
  
        globalize_decl (decl);
Index: cp/decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.560.4.1
diff -c -3 -p -r1.560.4.1 decl2.c
*** cp/decl2.c	2 Sep 2002 20:32:41 -0000	1.560.4.1
--- cp/decl2.c	2 Sep 2002 21:30:18 -0000
*************** start_objects (method_type, initp)
*** 2073,2098 ****
  {
    tree fnname;
    tree body;
!   char type[10];
  
    /* Make ctor or dtor function.  METHOD_TYPE may be 'I' or 'D'.  */
  
    if (initp != DEFAULT_INIT_PRIORITY)
      {
!       char joiner;
! 
  #ifdef JOINER
!       joiner = JOINER;
! #else
!       joiner = '_';
  #endif
- 
-       sprintf (type, "%c%c%.5u", method_type, joiner, initp);
      }
-   else
-     sprintf (type, "%c", method_type);
  
!   fnname = get_file_function_name_long (type);
  
    start_function (void_list_node,
  		  make_call_declarator (fnname, void_list_node, NULL_TREE,
--- 2073,2092 ----
  {
    tree fnname;
    tree body;
!   char pri[10];
  
    /* Make ctor or dtor function.  METHOD_TYPE may be 'I' or 'D'.  */
  
    if (initp != DEFAULT_INIT_PRIORITY)
      {
!       sprintf (pri, "_%.5u", initp);
  #ifdef JOINER
!       pri[0] = JOINER;
  #endif
      }
  
!   fnname = get_file_function_name_long
!     (method_type, initp != DEFAULT_INIT_PRIORITY ? pri : NULL);
  
    start_function (void_list_node,
  		  make_call_declarator (fnname, void_list_node, NULL_TREE,

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]