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]

Patch: C++ and Java: change name of class object


This patch changes how Java class objects are named.  It also changes
gcj to rename fields and methods which conflict with C++ keywords.
This latter change makes it possible to correctly generate C++ header
files for any Java code (except code that uses non-ASCII characters, I
think).

This patch has a Java component and a C++ component.

The class object is now named `class$' and is treated as though it
were a static field of the class itself.  This lets us refer to it
from gcjh-generated headers in a very natural way.

This patch makes it much easier for us to switch manglings, as once it
is checked in the correspoding libgcj patch will make it so that the
runtime no longer relies on the name mangling scheme.

I tested this by rebuilding the compiler and all of libgcj on PPC Linux.

Alex, if you want to test this you will have to get the corresponding
runtime patch.

Ok to commit?

Tom

For cp/:

2000-09-03  Tom Tromey  <tromey@cygnus.com>

	* init.c (build_java_class_ref): Use `build_static_name' with a
	suffix, not a prefix, to build the class object's name.

Index: cp/init.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/init.c,v
retrieving revision 1.213
diff -u -r1.213 init.c
--- init.c	2000/08/18 09:31:11	1.213
+++ init.c	2000/09/03 22:02:08
@@ -2156,9 +2156,9 @@
      tree type;
 {
   tree name, class_decl;
-  static tree CL_prefix = NULL_TREE;
-  if (CL_prefix == NULL_TREE)
-    CL_prefix = get_identifier("_CL_");
+  static tree CL_suffix = NULL_TREE;
+  if (CL_suffix == NULL_TREE)
+    CL_suffix = get_identifier("class$");
   if (jclass_node == NULL_TREE)
     {
       jclass_node = IDENTIFIER_GLOBAL_VALUE (get_identifier("jclass"));
@@ -2166,7 +2166,7 @@
 	fatal("call to Java constructor, while `jclass' undefined");
       jclass_node = TREE_TYPE (jclass_node);
     }
-  name = build_overload_with_type (CL_prefix, type);
+  name = build_static_name (type, CL_suffix);
   class_decl = IDENTIFIER_GLOBAL_VALUE (name);
   if (class_decl == NULL_TREE)
     {
@@ -2182,7 +2182,7 @@
   return class_decl;
 }
 
-/* Returns teh size of the cookie to use when allocating an array
+/* Returns the size of the cookie to use when allocating an array
    whose elements have the indicated TYPE.  Assumes that it is already
    known that a cookie is needed.  */
 

For java/:

2000-09-03  Tom Tromey  <tromey@cygnus.com>

	* jvspec.c (jvgenmain_spec): Added `-fdollars-in-identifiers'.
	* jvgenmain.c (class_mangling_prefix): Removed.
	(class_mangling_suffix): New global.
	(main): Use it.
	* gjavah.c (cxx_keyword_subst): Mangle C++ keywords by appending
	`$'.
	(print_method_info): Handle overrides for static and final
	methods.
	(process_file): Generate declaration for class object field.
	* class.c (cxx_keywords): New array.
	(utf8_cmp): New function.
	(cxx_keyword_p): New function.
	(layout_class_method): Mangle C++ keywords by appending `$'.
	(mangle_field): New function.
	(mangle_class_field): Use mangle_field.  Mangle class name as
	`class$'.
	(mangle_static_field): Use mangle_field.

Index: java/class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/class.c,v
retrieving revision 1.74
diff -u -r1.74 class.c
--- class.c	2000/08/11 22:01:37	1.74
+++ class.c	2000/09/03 22:02:23
@@ -51,6 +51,9 @@
 static struct hash_entry *init_test_hash_newfunc PARAMS ((struct hash_entry *,
 							  struct hash_table *,
 							  hash_table_key));
+static int utf8_cmp PARAMS ((const unsigned char *, int, const char *));
+static int cxx_keyword_p PARAMS ((const char *, int));
+static tree mangle_field PARAMS ((tree, tree));
 
 static rtx registerClass_libfunc;
 
@@ -1620,29 +1623,13 @@
     }
 }
 
-/* Build the mangled name of the `class' field.  */
-
-static tree
-mangle_class_field (class)
-     tree class;
-{
-  tree name;
-  obstack_grow (&temporary_obstack, "_CL_", 4);
-  append_gpp_mangled_type (&temporary_obstack, class);
-  obstack_1grow (&temporary_obstack, '\0');
-  name = get_identifier (obstack_base (&temporary_obstack));
-  obstack_free (&temporary_obstack, obstack_base (&temporary_obstack));
-  return name;
-}
+/* Build the mangled name of a field, given the class name and the
+   field name.  */
 
-/* Build the mangled (assembly-level) name of the static field FIELD. */
-
 static tree
-mangle_static_field (field)
-     tree field;
+mangle_field (class, name)
+     tree class, name;
 {
-  tree class = DECL_CONTEXT (field);
-  tree name = DECL_NAME (field);
   int encoded_len;
 #if ! defined (NO_DOLLAR_IN_LABEL) || ! defined (NO_DOT_IN_LABEL)
   obstack_1grow (&temporary_obstack, '_');
@@ -1677,12 +1664,39 @@
 		    IDENTIFIER_POINTER (name),
 		    IDENTIFIER_LENGTH (name));
     }
+
+  /* Mangle C++ keywords by appending a `$'.  */
+  /* FIXME: NO_DOLLAR_IN_LABEL */
+  if (cxx_keyword_p (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name)))
+    obstack_grow (&temporary_obstack, "$", 1);
+
   obstack_1grow (&temporary_obstack, '\0');
   name = get_identifier (obstack_base (&temporary_obstack));
   obstack_free (&temporary_obstack, obstack_base (&temporary_obstack));
   return name;
 }
 
+/* Build the mangled name of the `class' field.  */
+
+static tree
+mangle_class_field (class)
+     tree class;
+{
+  /* We know that we can use `class$' to mangle the class object,
+     because `class' is a reserved word in Java and thus can't appear
+     as a field or method name.  */
+  return mangle_field (class, get_identifier ("class$"));
+}
+
+/* Build the mangled (assembly-level) name of the static field FIELD. */
+
+static tree
+mangle_static_field (field)
+     tree field;
+{
+  return mangle_field (DECL_CONTEXT (field), DECL_NAME (field));
+}
+
 /* Build a VAR_DECL for the dispatch table (vtable) for class TYPE. */
 
 tree
@@ -1866,7 +1880,7 @@
     }
   else
     dtable_count = integer_zero_node;
-  
+
   TYPE_METHODS (handle_type) = nreverse (TYPE_METHODS (handle_type));
 
   for (method_decl = TYPE_METHODS (handle_type);
@@ -1882,6 +1896,93 @@
   pop_obstacks ();
 }
 
+/* A sorted list of all C++ keywords.  */
+
+static const char *cxx_keywords[] =
+{
+  "asm",
+  "auto",
+  "bool",
+  "const_cast",
+  "delete",
+  "dynamic_cast",
+  "enum",
+  "explicit",
+  "extern",
+  "friend",
+  "inline",
+  "mutable",
+  "namespace",
+  "overload",
+  "register",
+  "reinterpret_cast",
+  "signed",
+  "sizeof",
+  "static_cast",
+  "struct",
+  "template",
+  "typedef",
+  "typeid",
+  "typename",
+  "typenameopt",
+  "union",
+  "unsigned",
+  "using",
+  "virtual",
+  "volatile",
+  "wchar_t"
+};
+
+/* Return 0 if NAME is equal to STR, -1 if STR is "less" than NAME,
+   and 1 if STR is "greater" than NAME.  */
+
+static int
+utf8_cmp (str, length, name)
+     const unsigned char *str;
+     int length;
+     const char *name;
+{
+  const unsigned char *limit = str + length;
+  int i;
+
+  for (i = 0; name[i]; ++i)
+    {
+      int ch = UTF8_GET (str, limit);
+      if (ch != name[i])
+	return ch - name[i];
+    }
+
+  return str == limit ? 0 : 1;
+}
+
+/* Return true if NAME is a C++ keyword.  */
+
+static int
+cxx_keyword_p (name, length)
+     const char *name;
+     int length;
+{
+  int last = ARRAY_SIZE (cxx_keywords);
+  int first = 0;
+  int mid = (last + first) / 2;
+  int old = -1;
+
+  for (mid = (last + first) / 2;
+       mid != old;
+       old = mid, mid = (last + first) / 2)
+    {
+      int r = utf8_cmp (name, length, cxx_keywords[mid]);
+
+      if (r == 0)
+	return 1;
+      else if (r < 0)
+	last = mid;
+      else
+	first = mid;
+    }
+  return 0;
+}
+
 /* Lay METHOD_DECL out, returning a possibly new value of
    DTABLE_COUNT.  */
 
@@ -1917,8 +2018,14 @@
 			IDENTIFIER_POINTER (method_name),
 			IDENTIFIER_LENGTH (method_name));
 	}
+
+      /* Mangle C++ keywords by appending a `$'.  */
+      /* FIXME: NO_DOLLAR_IN_LABEL */
+      if (cxx_keyword_p (IDENTIFIER_POINTER (method_name),
+			 IDENTIFIER_LENGTH (method_name)))
+	obstack_grow (&temporary_obstack, "$", 1);
     }
-      
+
   obstack_grow (&temporary_obstack, "__", 2);
   if (ID_FINIT_P (method_name))
     obstack_grow (&temporary_obstack, "finit", 5);
Index: java/gjavah.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/gjavah.c,v
retrieving revision 1.59
diff -u -r1.59 gjavah.c
--- gjavah.c	2000/08/25 19:07:04	1.59
+++ gjavah.c	2000/09/03 22:02:27
@@ -440,9 +440,9 @@
 
       if (r == 0)
 	{
-	  char *str = xmalloc (9 + strlen (cxx_keywords[mid]));
-	  strcpy (str, "__dummy_");
-	  strcat (str, cxx_keywords[mid]);
+	  char *str = xmalloc (2 + strlen (cxx_keywords[mid]));
+	  strcpy (str, cxx_keywords[mid]);
+	  strcat (str, "$");
 	  return str;
 	}
       else if (r < 0)
@@ -759,18 +759,6 @@
 	 (not only for calls to this function for for other functions
 	 after it in the vtbl).  So we give it a dummy name instead.  */
       override = cxx_keyword_subst (str, length);
-      if (override)
-	{
-	  /* If the method is static or final, we can safely skip it.
-	     If we don't skip it then we'll have problems since the
-	     mangling will be wrong.  FIXME.  */
-	  if (METHOD_IS_FINAL (jcf->access_flags, flags)
-	      || (flags & ACC_STATIC))
-	    {
-	      free (override);
-	      return;
-	    }
-	}
     }
 
   if (! stubs && ! flag_jni)
@@ -1844,9 +1832,9 @@
     {
       if (flag_jni)
 	{
-	      fprintf (out, "\n#ifdef __cplusplus\n");
-	      fprintf (out, "}\n");
-	      fprintf (out, "#endif\n");
+	  fprintf (out, "\n#ifdef __cplusplus\n");
+	  fprintf (out, "}\n");
+	  fprintf (out, "#endif\n");
 	}
       else
 	{
@@ -1859,9 +1847,12 @@
 	    fputc ('\n', out);
 	  for (i = 0; i < add_count; ++i)
 	    fprintf (out, "  %s\n", add_specs[i]);
+
+	  /* Generate an entry for the class object.  */
+	  generate_access (out, ACC_PUBLIC);
+	  fprintf (out, "\n  static ::java::lang::Class class$;\n");
 
-	  if (! stubs)
-	    fputs ("};\n", out);
+	  fputs ("};\n", out);
 
 	  if (append_count > 0)
 	    fputc ('\n', out);
Index: java/jvgenmain.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/jvgenmain.c,v
retrieving revision 1.15
diff -u -r1.15 jvgenmain.c
--- jvgenmain.c	2000/01/21 20:57:00	1.15
+++ jvgenmain.c	2000/09/03 22:02:27
@@ -34,7 +34,7 @@
 
 const char main_method_prefix[] = "main__";
 const char main_method_suffix[] = "Pt6JArray1ZPQ34java4lang6String";
-const char class_mangling_prefix[] = "_CL_";
+const char class_mangling_suffix[] = ".class$";
 
 struct obstack name_obstack;
 
@@ -155,13 +155,12 @@
     }
   fprintf (stream, "  0\n};\n\n");
 
-  fprintf (stream, "extern struct Class %s%s;\n",
-	   class_mangling_prefix, mangled_classname);
+  fprintf (stream, "extern int class __attribute__ ((alias (\"_%s%s\")));\n",
+	   mangled_classname, class_mangling_suffix);
   fprintf (stream, "int main (int argc, const char **argv)\n");
   fprintf (stream, "{\n");
   fprintf (stream, "   _Jv_Compiler_Properties = props;\n");
-  fprintf (stream, "   JvRunMain (&%s%s, argc, argv);\n",
-	   class_mangling_prefix, mangled_classname);
+  fprintf (stream, "   JvRunMain (&class, argc, argv);\n");
   fprintf (stream, "}\n");
   if (stream != stdout && fclose (stream) != 0)
     {
Index: java/jvspec.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/java/jvspec.c,v
retrieving revision 1.31
diff -u -r1.31 jvspec.c
--- jvspec.c	2000/08/02 20:21:27	1.31
+++ jvspec.c	2000/09/03 22:02:27
@@ -61,7 +61,7 @@
 		   %{<fuse-boehm-gc} %{<fhash-synchronization} %{<fjni}\
 		   %{<fclasspath*} %{<fCLASSPATH*} %{<foutput-class-dir}\
 		   %{<fuse-divide-subroutine} %{<fno-use-divide-subroutine}\
-		   %{f*}\
+		   %{f*} -fdollars-in-identifiers\
 		   %{aux-info*}\
 		   %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}}\
 		   %{S:%W{o*}%{!o*:-o %b.s}}%{!S:-o %{|!pipe:%Umain.s}} |\n\

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