[gcjx] Patch: FYI: change 'catch' type handling

Tom Tromey tromey@redhat.com
Sun Apr 17 21:29:00 GMT 2005


I'm checking this in on the gcjx branch.

This changes 'catch' handling in the tree-lowering code to work the
same way as the current gcj does.  Apparently there are constraints in
gcc itself about what kinds of references can be emitted in these
areas, and an array reference into the constant pool did not work, at
least when -fPIC was used.

Tom

Index: ChangeLog
from  Tom Tromey  <tromey@redhat.com>

	* hooks.hh (type_catch_class): Declare.
	* decl.cc (build_catch_class_type): New function.
	(initialize_decls): Call it.
	(type_catch_class): New global.
	* classobj.hh (class_object_creator::compute_catch_classes):
	Declare.
	* classobj.cc (compute_catch_classes): New method.
	(create_class_instance): Use it.
	* tree.cc (visit_catch): Use map_catch_class.
	* builtins.cc (map_catch_class): New method.
	(get_catch_map): Likewise.
	* builtins.hh (tree_builtins::catch_map): New field.
	(tree_builtins::catch_map_type): Declare.
	(tree_builtins::map_catch_class): Declare.
	(tree_builtins::get_catch_map): Likewise.

Index: builtins.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/Attic/builtins.cc,v
retrieving revision 1.1.2.31
diff -u -r1.1.2.31 builtins.cc
--- builtins.cc 17 Apr 2005 16:16:49 -0000 1.1.2.31
+++ builtins.cc 17 Apr 2005 21:26:54 -0000
@@ -598,6 +598,52 @@
   return itable_map[klass];
 }
 
+tree
+tree_builtins::map_catch_class (model_class *current, model_class *caught)
+{
+  catch_map_type::iterator it = catch_map.find (current);
+  if (it != catch_map.end ())
+    {
+      std::map<model_class *, tree> &inner_map ((*it).second);
+      std::map<model_class *, tree>::iterator inner_it
+	= inner_map.find (caught);
+      if (inner_it != inner_map.end ())
+	return (*inner_it).second;
+
+      tree decl = build_decl (VAR_DECL, get_symbol (), type_class_ptr);
+      TREE_STATIC (decl) = 1;
+      DECL_ARTIFICIAL (decl) = 1;
+      DECL_IGNORED_P (decl) = 1;
+      rest_of_decl_compilation (decl, 1, 0);
+      pushdecl (decl);
+
+      inner_map[caught] = decl;
+      return decl;
+    }
+
+  std::map<model_class *, tree> inner_map;
+  // FIXME: duplicated code.
+  tree decl = build_decl (VAR_DECL, get_symbol (), type_class_ptr);
+  TREE_STATIC (decl) = 1;
+  DECL_ARTIFICIAL (decl) = 1;
+  DECL_IGNORED_P (decl) = 1;
+  pushdecl (decl);
+  rest_of_decl_compilation (decl, 1, 0);
+  inner_map[caught] = decl;
+  catch_map[current] = inner_map;
+
+  return decl;
+}
+
+std::map<model_class *, tree> *
+tree_builtins::get_catch_map (model_class *current)
+{
+  catch_map_type::iterator it = catch_map.find (current);
+  if (it == catch_map.end ())
+    return NULL;
+  return &(*it).second;
+}
+
 // FIXME: this whole method should probably migrate into the ABI or
 // into classobj.cc.  There's no need, I think, for it to be a generic
 // part of the builtins.
Index: builtins.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/Attic/builtins.hh,v
retrieving revision 1.1.2.16
diff -u -r1.1.2.16 builtins.hh
--- builtins.hh 4 Apr 2005 04:30:32 -0000 1.1.2.16
+++ builtins.hh 17 Apr 2005 21:26:54 -0000
@@ -60,6 +60,13 @@
   std::map<model_class *, tree> otable_map;
   std::map<model_class *, tree> itable_map;
 
+  // This maps a containing class to a sub-map, which maps exception
+  // classes to individual DECLs for _Jv_CatchClass.
+  typedef std::map<model_class *, std::map<model_class *, tree> >
+    catch_map_type;
+  catch_map_type catch_map;
+
+
   // Used when creating symbol names.
   int symbol_count;
 
@@ -143,6 +150,10 @@
   tree get_atable_decl (model_class *);
   tree get_otable_decl (model_class *);
   tree get_itable_decl (model_class *);
+
+  tree map_catch_class (model_class *, model_class *);
+
+  std::map<model_class *, tree> *get_catch_map (model_class *);
 };
 
 #endif // GCC_JAVA_BUILTINS_HH
Index: classobj.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/Attic/classobj.cc,v
retrieving revision 1.1.2.21
diff -u -r1.1.2.21 classobj.cc
--- classobj.cc 3 Apr 2005 23:52:15 -0000 1.1.2.21
+++ classobj.cc 17 Apr 2005 21:26:54 -0000
@@ -469,6 +469,44 @@
   make_decl_rtl (decl);
 }
 
+tree
+class_object_creator::compute_catch_classes ()
+{
+  std::map<model_class *, tree> *catch_map
+    = builtins->get_catch_map (klass->get ());
+  if (catch_map == NULL)
+    return NULL_TREE;
+
+  tree value_type
+    = build_array_type (type_catch_class,
+			build_index_type (build_int_cst (type_jint,
+							 catch_map->size ())));
+
+  tree result = NULL_TREE;
+  int index = 0;
+  for (std::map<model_class *, tree>::const_iterator i = catch_map->begin ();
+       i != catch_map->end ();
+       ++i, ++index)
+    {
+      record_creator inst (type_catch_class);
+      inst.set_field ("address", build_address_of ((*i).second));
+      inst.set_field ("classname",
+		      builtins->map_utf8const ((*i).first->get_fully_qualified_name ()));
+      tree one_value = inst.finish_record ();
+
+      result = tree_cons (build_int_cst (type_jint, index), one_value, result);
+    }
+  result = nreverse (result);
+
+  tree init = build_constructor (value_type, result);
+  // Also set these on the decl?
+  TREE_CONSTANT (init) = 1;
+  TREE_INVARIANT (init) = 1;
+  TREE_READONLY (init) = 1;
+
+  return make_decl (value_type, init);
+}
+
 void
 class_object_creator::create_class_instance (tree class_tree)
 {
@@ -546,7 +584,7 @@
   inst.set_field ("itable", table);
   inst.set_field ("itable_syms", syms);
 
-  inst.set_field ("catch_classes", null_pointer_node);  // FIXME
+  inst.set_field ("catch_classes", compute_catch_classes ());
 
   tree interfaces, interface_count;
   handle_interfaces (real_class, interfaces, interface_count);
Index: classobj.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/Attic/classobj.hh,v
retrieving revision 1.1.2.8
diff -u -r1.1.2.8 classobj.hh
--- classobj.hh 4 Apr 2005 04:30:32 -0000 1.1.2.8
+++ classobj.hh 17 Apr 2005 21:26:54 -0000
@@ -75,6 +75,7 @@
   void create_class_instance (tree);
   tree create_constants ();
   void fill_in_vtable (tree);
+  tree compute_catch_classes ();
 
 public:
 
Index: decl.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/Attic/decl.cc,v
retrieving revision 1.1.2.18
diff -u -r1.1.2.18 decl.cc
--- decl.cc 3 Apr 2005 23:47:45 -0000 1.1.2.18
+++ decl.cc 17 Apr 2005 21:26:54 -0000
@@ -111,6 +111,9 @@
 // Type of _Jv_Constants structure.
 tree type_constants;
 
+// Type of _Jv_CatchClass.
+tree type_catch_class;
+
 // Type of java.lang.Object, and type of pointer to it.
 tree type_object;
 tree type_object_ptr;
@@ -346,6 +349,17 @@
 }
 
 static void
+build_catch_class_type ()
+{
+  tree field = NULL_TREE;
+  type_catch_class = make_node (RECORD_TYPE);
+  push_field (type_catch_class, field, "address",
+	      build_pointer_type (type_class_ptr));
+  push_field (type_catch_class, field, "classname", type_utf8const_ptr);
+  layout_type (type_catch_class);
+}
+
+static void
 build_object_type ()
 {
   tree field = NULL_TREE;
@@ -996,6 +1010,7 @@
   build_method_type ();
   build_field_type ();
   build_constant_type ();
+  build_catch_class_type ();
   build_object_type ();
   build_class_type ();
   build_class_union ();
Index: hooks.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/Attic/hooks.hh,v
retrieving revision 1.1.2.10
diff -u -r1.1.2.10 hooks.hh
--- hooks.hh 4 Apr 2005 04:30:32 -0000 1.1.2.10
+++ hooks.hh 17 Apr 2005 21:26:54 -0000
@@ -37,6 +37,7 @@
 extern GTY (()) tree type_field_ptr;
 extern GTY (()) tree type_field_info_union;
 extern GTY (()) tree type_constants;
+extern GTY (()) tree type_catch_class;
 extern GTY (()) tree type_object;
 extern GTY (()) tree type_object_ptr;
 extern GTY (()) tree type_class;
Index: tree.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/Attic/tree.cc,v
retrieving revision 1.1.2.40
diff -u -r1.1.2.40 tree.cc
--- tree.cc 4 Apr 2005 00:50:33 -0000 1.1.2.40
+++ tree.cc 17 Apr 2005 21:26:55 -0000
@@ -489,18 +489,13 @@
 		      BLOCK_VARS (current_block),
 		      body_tree, current_block);
 
-  // We always emit the catch type as a pointer to a constant pool
-  // entry of type Class.  These will be linked at runtime.  FIXME: ok
-  // for C++ ABI?  Better to emit plain pointer-to-pointer-to-class?
-  // FIXME: this is an ABI change from ordinary gcj.
+  // It would be nice to emit this as a pointer into the constant
+  // pool, but GCC apparently crashes when this is compiled with
+  // -fPIC.
   model_class *vklass = assert_cast<model_class *> (vardecl->type ());
-  vtype = build_ref_from_constant_pool (type_class_ptr,
-					class_wrapper->add (vklass));
-  // FIXME: big hack: strip the NOP and add indirection.
-  assert (TREE_CODE (vtype) == NOP_EXPR);
-  vtype = build_address_of (TREE_OPERAND (vtype, 0));
+  tree decl = gcc_builtins->map_catch_class (class_wrapper->get (), vklass);
 
-  current = build2 (CATCH_EXPR, void_type_node, vtype, bind);
+  current = build2 (CATCH_EXPR, void_type_node, build_address_of (decl), bind);
   annotate (current, stmt);
 }
 



More information about the Java-patches mailing list