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 for compiling multiple .class files


This seems to fix the problem Tom mentioned ("bug in gcj, maybe with
multiple .class inputs") on the Java mailing list.

To summarize:  To handle multiple .class files, we need to process them
in two passes:  The first pass reads the .class file, and creates a
tree node for the class.  The second pass mainly processes method bodies.
We split them up, because if a method in A refers to a class B, and
B is later in the command line, we want to make sure we get the B
later in the command line, rather than whatever random file is
in the path.  (Also, we don't want A to load B before we are ready.)
This is similar to parsing from source:  In both cases pass 1 does
not resolve or load other classes, that is handled in a second pass.

But what does CLASS_LOADED_P mean now - that we're done with it,
or only with pass 2?  The way the existing code works, it assumes
that if CLASS_LOADED_P then layout_class has been called on the class.
But layout_class needs to layout the super-type, which means loading
it.  But we don't want to do that during pass 1, so it has to be
deferred to pass 2.

So I've clarified and re-defined some concepts:  The new flag
CLASS_PARSED_P flag is true if we are done with pass 1 for it
(whether we read a .java or a .class file).  The CLASS_LOADED_P
"flag" now means we are done with pass 1 (parsing) *and* the
class has been laid out.

Alex - does this look reasonable?  If so, I'd like to check this
into both the trunk and the branch.  Bruce, if you other testcases
(besides CRcalc) that fail when compiling multiple .class files,
could you try them?  I've tested the testsuite, Kawa, and CRcalc.

2001-04-06  Per Bothner  <per@bothner.com>

	Fixes to all compile multiple .class files at once.
	* decl.c (init_decl_processing):  Don't set CLASS_LOADED_P.
	* java-tree.h (CLASS_PARSED_P):  New macro.
	(CLASS_LOADED_P):  Re-define to use TYPE_SIZE and CLASS_PARSED_P.
	* jcf-parse.c (jcf_parse_source):  Inline into read_class.
	(read_class):  Avoid some code duplication.
	Don't call JCF_FINISH for a .class file - might be needed later.
	(jcf_parse):  Don't call layout_class here.  Check/set CLASS_PARSED_P
	rather than CLASS_LOADED_P, since latter implies class laid out.
	(yyparse):  Do layout_class and JCF_FINISh here instead, in pass 2.
	* parse.y:  Don't need to set CLASS_LOADED_P for array types.

Index: decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/decl.c,v
retrieving revision 1.87.2.6
diff -u -p -r1.87.2.6 decl.c
--- decl.c	2001/03/20 22:03:51	1.87.2.6
+++ decl.c	2001/04/06 22:57:53
@@ -667,7 +667,6 @@ init_decl_processing ()
   PUSH_FIELD (field_type_node, field, "bsize", unsigned_short_type_node);
   PUSH_FIELD (field_type_node, field, "info", field_info_union_node);
   FINISH_RECORD (field_type_node);
-  CLASS_LOADED_P (field_type_node) = 1;
   build_decl (TYPE_DECL, get_identifier ("Field"), field_type_node);
 
   one_elt_array_domain_type = build_index_type (integer_one_node);
@@ -709,7 +708,6 @@ init_decl_processing ()
   PUSH_FIELD (method_type_node, field, "accflags", access_flags_type_node);
   PUSH_FIELD (method_type_node, field, "ncode", nativecode_ptr_type_node);
   FINISH_RECORD (method_type_node);
-  CLASS_LOADED_P (method_type_node) = 1;
   build_decl (TYPE_DECL, get_identifier ("Method"), method_type_node);
 
   endlink = end_params_node = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
Index: java-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/java-tree.h,v
retrieving revision 1.97.2.8
diff -u -p -r1.97.2.8 java-tree.h
--- java-tree.h	2001/04/05 22:59:22	1.97.2.8
+++ java-tree.h	2001/04/06 22:57:55
@@ -73,7 +73,7 @@ struct JCF;
    Usage of TYPE_LANG_FLAG_?:
    0: CLASS_ACCESS0_GENERATED_P (in RECORD_TYPE)
    1: TYPE_ARRAY_P (in RECORD_TYPE).
-   2: CLASS_LOADED_P (in RECORD_TYPE).
+   2: CLASS_PARSED_P (in RECORD_TYPE).
    3: CLASS_FROM_SOURCE_P (in RECORD_TYPE).
    4: CLASS_P (in RECORD_TYPE).
    5: CLASS_FROM_CURRENTLY_COMPILED_SOURCE_P (in RECORD_TYPE)
@@ -1301,8 +1301,13 @@ extern tree *type_map;
 /* FIXME this use of TREE_TYPE conflicts with something or other. */
 #define TYPE_ARRAY_ELEMENT(ATYPE) TREE_TYPE(ATYPE)
 
-/* True if class TYPE has been loaded. */
-#define CLASS_LOADED_P(TYPE) TYPE_LANG_FLAG_2 (TYPE)
+/* True if class TYPE has been loaded (i.e. parsed plus laid out).
+   (The check for CLASS_PARSED_P is needed because of Object and Class.) */
+#define CLASS_LOADED_P(TYPE) (TYPE_SIZE (TYPE) != NULL_TREE \
+			      && (CLASS_PARSED_P(TYPE) || TYPE_ARRAY_P(TYPE)))
+
+/* True if class TYPE has been parser (first pass). */
+#define CLASS_PARSED_P(TYPE) TYPE_LANG_FLAG_2 (TYPE)
 
 /* True if class TYPE was defined in Java source code. */
 #define CLASS_FROM_SOURCE_P(TYPE) TYPE_LANG_FLAG_3 (TYPE)
Index: jcf-parse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/jcf-parse.c,v
retrieving revision 1.76.2.6
diff -u -p -r1.76.2.6 jcf-parse.c
--- jcf-parse.c	2001/03/23 19:43:44	1.76.2.6
+++ jcf-parse.c	2001/04/06 22:57:56
@@ -93,7 +93,6 @@ static void parse_zip_file_entries PARAM
 static void process_zip_dir PARAMS ((FILE *));
 static void parse_source_file_1 PARAMS ((tree, FILE *));
 static void parse_source_file_2 PARAMS ((void));
-static void jcf_parse_source PARAMS ((void));
 static void parse_class_file PARAMS ((void));
 static void set_source_filename PARAMS ((JCF *, int));
 static int predefined_filename_p PARAMS ((tree));
@@ -559,6 +558,7 @@ read_class (name)
   tree save_current_class = current_class;
   const char *save_input_filename = input_filename;
   JCF *save_current_jcf = current_jcf;
+  int generate;
 
   if ((icv = IDENTIFIER_CLASS_VALUE (name)) != NULL_TREE)
     {
@@ -579,23 +579,50 @@ read_class (name)
 
   current_jcf = jcf;
 
+  java_parser_context_save_global ();
+  java_push_parser_context ();
   if (current_jcf->java_source)
-    jcf_parse_source ();
-  else {
-    java_parser_context_save_global ();
-    java_push_parser_context ();
-    input_filename = current_jcf->filename;
-    current_class = class;
-    if (JCF_SEEN_IN_ZIP (current_jcf))
-      read_zip_member(current_jcf, current_jcf->zipd, current_jcf->zipd->zipf);
-    jcf_parse (current_jcf);
-    load_inner_classes (current_class);
-    java_pop_parser_context (0);
-    java_parser_context_restore_global ();
-  }
-
-  if (! JCF_SEEN_IN_ZIP (current_jcf))
-    JCF_FINISH (current_jcf);
+    {
+      const char *filename = current_jcf->filename;
+      tree file;
+      FILE *finput;
+
+      BUILD_FILENAME_IDENTIFIER_NODE (file, filename);
+      generate = IS_A_COMMAND_LINE_FILENAME_P (file);
+      if (wfl_operator == NULL_TREE)
+	wfl_operator = build_expr_wfl (NULL_TREE, NULL, 0, 0);
+      EXPR_WFL_FILENAME_NODE (wfl_operator) = file;
+      input_filename = ggc_strdup (filename);
+      current_class = NULL_TREE;
+      current_function_decl = NULL_TREE;
+      if (!HAS_BEEN_ALREADY_PARSED_P (file))
+	{
+	  if (!(finput = fopen (input_filename, "r")))
+	    fatal_io_error ("can't reopen %s", input_filename);
+	  parse_source_file_1 (file, finput);
+	  parse_source_file_2 ();
+	  if (fclose (finput))
+	    fatal_io_error ("can't close %s", input_filename);
+	}
+      JCF_FINISH (current_jcf);
+    }
+  else
+    {
+      input_filename = current_jcf->filename;
+      current_class = class;
+      if (class == NULL_TREE || ! CLASS_PARSED_P (class))
+	{
+	  if (JCF_SEEN_IN_ZIP (current_jcf))
+	    read_zip_member(current_jcf,
+			    current_jcf->zipd, current_jcf->zipd->zipf);
+	  jcf_parse (current_jcf);
+	}
+      layout_class (current_class);
+      load_inner_classes (current_class);
+      generate = 0;
+    }
+  java_pop_parser_context (generate);
+  java_parser_context_restore_global ();
 
   current_class = save_current_class;
   input_filename = save_input_filename;
@@ -632,36 +659,6 @@ load_class (class_or_name, verbose)
     error ("Cannot find file for class %s.", IDENTIFIER_POINTER (name));
 }
 
-/* Parse a source file when JCF refers to a source file.  */
-
-static void
-jcf_parse_source ()
-{
-  tree file;
-  FILE *finput;
-
-  java_parser_context_save_global ();
-  java_push_parser_context ();
-  BUILD_FILENAME_IDENTIFIER_NODE (file, current_jcf->filename);
-  if (wfl_operator == NULL_TREE)
-    wfl_operator = build_expr_wfl (NULL_TREE, NULL, 0, 0);
-  EXPR_WFL_FILENAME_NODE (wfl_operator) = file;
-  input_filename = ggc_strdup (current_jcf->filename);
-  current_class = NULL_TREE;
-  current_function_decl = NULL_TREE;
-  if (!HAS_BEEN_ALREADY_PARSED_P (file))
-    {
-      if (!(finput = fopen (input_filename, "r")))
-	fatal_io_error ("can't reopen %s", input_filename);
-      parse_source_file_1 (file, finput);
-      parse_source_file_2 ();
-      if (fclose (finput))
-	fatal_io_error ("can't close %s", input_filename);
-    }
-  java_pop_parser_context (IS_A_COMMAND_LINE_FILENAME_P (file));
-  java_parser_context_restore_global ();
-}
-
 /* Parse the .class file JCF. */
 
 void
@@ -686,9 +683,14 @@ jcf_parse (jcf)
     fprintf (stderr, " %s %s",
 	     (jcf->access_flags & ACC_INTERFACE) ? "interface" : "class", 
 	     IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))));
-  if (CLASS_LOADED_P (current_class))
-    return;
-  CLASS_LOADED_P (current_class) = 1;
+  if (CLASS_PARSED_P (current_class))
+    {
+      /* FIXME - where was first time */
+      fatal_error ("reading class %s for the second time from %s",
+		   IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))),
+		   jcf->filename);
+    }
+  CLASS_PARSED_P (current_class) = 1;
 
   for (i = 1; i < JPOOL_SIZE(jcf); i++)
     {
@@ -714,7 +716,6 @@ jcf_parse (jcf)
   if (current_class != class_type_node && current_class != object_type_node)
     TYPE_FIELDS (current_class) = nreverse (TYPE_FIELDS (current_class));
 
-  layout_class (current_class);
   if (current_class == object_type_node)
     {
       layout_class_methods (object_type_node);
@@ -1123,8 +1124,10 @@ yyparse ()
 	{
 	  current_class = TREE_PURPOSE (node);
 	  current_jcf = TYPE_JCF (current_class);
+	  layout_class (current_class);
 	  load_inner_classes (current_class);
 	  parse_class_file ();
+	  JCF_FINISH (current_jcf);
 	}
     }
   input_filename = main_input_filename;
@@ -1157,8 +1160,12 @@ parse_zip_file_entries (void)
 
       if ( !CLASS_LOADED_P (class))
 	{
-	  read_zip_member(current_jcf, zdir, localToFile);
-	  jcf_parse (current_jcf);
+	  if (! CLASS_PARSED_P (class))
+	    {
+	      read_zip_member(current_jcf, zdir, localToFile);
+	      jcf_parse (current_jcf);
+	    }
+	  layout_class (current_class);
 	  load_inner_classes (current_class);
 	}
 
Index: parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/parse.y,v
retrieving revision 1.251.2.16
diff -u -p -r1.251.2.16 parse.y
--- parse.y	2001/04/06 20:41:42	1.251.2.16
+++ parse.y	2001/04/06 22:58:05
@@ -666,7 +666,6 @@ array_type:
 		{ 
 		  int osb = pop_current_osb (ctxp);
 		  tree t = build_java_array_type (($1), -1);
-		  CLASS_LOADED_P (t) = 1;
 		  while (--osb)
 		    t = build_unresolved_array_type (t);
 		  $$ = t;
@@ -3266,7 +3265,6 @@ build_array_from_name (type, type_wfl, n
       if (JPRIMITIVE_TYPE_P (type))
 	{
 	  type = build_java_array_type (type, -1);
-	  CLASS_LOADED_P (type) = 1;
 	  more_dims--;
 	}
       /* Otherwise, if we have a WFL for this type, use it (the type
@@ -3302,11 +3300,7 @@ build_unresolved_array_type (type_or_wfl
   /* TYPE_OR_WFL might be an array on a resolved type. In this case,
      just create a array type */
   if (TREE_CODE (type_or_wfl) == RECORD_TYPE)
-    {
-      tree type = build_java_array_type (type_or_wfl, -1);
-      CLASS_LOADED_P (type) = CLASS_LOADED_P (type_or_wfl);
-      return type;
-    }
+    return build_java_array_type (type_or_wfl, -1);
 
   obstack_1grow (&temporary_obstack, '[');
   obstack_grow0 (&temporary_obstack,
@@ -3648,6 +3642,7 @@ maybe_create_class_interface_decl (decl,
   else
     DECL_SOURCE_LINE (decl) = EXPR_WFL_LINENO (cl);
   CLASS_FROM_SOURCE_P (TREE_TYPE (decl)) = 1;
+  CLASS_PARSED_P (TREE_TYPE (decl)) = 1;
   CLASS_FROM_CURRENTLY_COMPILED_P (TREE_TYPE (decl)) =
     IS_A_COMMAND_LINE_FILENAME_P (EXPR_WFL_FILENAME_NODE (cl));
 
@@ -5274,7 +5269,6 @@ safe_layout_class (class)
   current_class = save_current_class;
   input_filename = save_input_filename;
   lineno = save_lineno;
-  CLASS_LOADED_P (class) = 1;
 }
 
 static tree
@@ -5495,7 +5489,6 @@ resolve_class (enclosing, class_type, de
       while (base != name)
 	{
 	  resolved_type = build_java_array_type (resolved_type, -1);
-	  CLASS_LOADED_P (resolved_type) = 1;
 	  name--;
 	}
       /* A TYPE_NAME that is a TYPE_DECL was set in
@@ -7317,9 +7310,6 @@ java_layout_classes ()
       current_class = TREE_TYPE (TREE_VALUE (current));
       layout_class (current_class);
 
-      /* From now on, the class is considered completely loaded */
-      CLASS_LOADED_P (current_class) = 1;
-
       /* Error reported by the caller */
       if (java_error_count)
 	return;
@@ -9156,7 +9146,6 @@ resolve_qualified_expression_name (wfl, 
 	  if (decl == error_mark_node)
 	    return 1;
 	  *type_found = type = QUAL_DECL_TYPE (decl);
-	  CLASS_LOADED_P (type) = 1;
 	  continue;
 
 	case CONVERT_EXPR:
@@ -9469,8 +9458,6 @@ resolve_qualified_expression_name (wfl, 
 		  && !CLASS_LOADED_P (field_decl_type)
 		  && !TYPE_ARRAY_P (field_decl_type))
 		resolve_and_layout (field_decl_type, NULL_TREE);
-	      if (TYPE_ARRAY_P (field_decl_type))
-		CLASS_LOADED_P (field_decl_type) = 1;
 	      
 	      /* Check on accessibility here */
 	      if (not_accessible_p (current_class, field_decl,
@@ -13996,12 +13983,8 @@ resolve_type_during_patch (type)
 			       "Class `%s' not found in type declaration",
 			       IDENTIFIER_POINTER (EXPR_WFL_NODE (type)));
 	  return NULL_TREE;
-	}
-      else
-	{
-	  CLASS_LOADED_P (TREE_TYPE (type_decl)) = 1;
-	  return TREE_TYPE (type_decl);
 	}
+      return TREE_TYPE (type_decl);
     }
   return type;
 }

-- 
	--Per Bothner
per@bothner.com   http://www.bothner.com/~per/


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