This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
[gcjx] Patch: FYI: Class object creation update
- From: Tom Tromey <tromey at redhat dot com>
- To: Java Patch List <java-patches at gcc dot gnu dot org>
- Date: 07 Mar 2005 17:19:19 -0700
- Subject: [gcjx] Patch: FYI: Class object creation update
- Reply-to: tromey at redhat dot com
I'm checking this in on the gcjx branch.
This is patch 2/N from the last couple week's worth of gcjx
hacking... I realize this is the second big batch of checkins, a la
Ada; most of my work on gcjx recently has been off-line I'm afraid.
This adds a bunch of improvements to Class object creation.
Tom
Index: gcjx/ChangeLog
from Tom Tromey <tromey@redhat.com>
* aot/aotclass.cc (add_class): New method.
* aot/aotclass.hh (aot_class::add_class): Declare.
* aot/mangle.cc (mangler): New constructor.
* aot/mangle.hh (mangler): Declare.
* aot/aotclass.hh (aot_class::pool_entry): Now public.
(aot_class::type_assertion_entry): Likewise.
(aot_class::get_constant_pool): New method.
Index: gcjx/aot/aotclass.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/aot/Attic/aotclass.cc,v
retrieving revision 1.1.2.3
diff -u -r1.1.2.3 aotclass.cc
--- gcjx/aot/aotclass.cc 31 Jan 2005 01:13:39 -0000 1.1.2.3
+++ gcjx/aot/aotclass.cc 8 Mar 2005 00:18:53 -0000
@@ -127,6 +127,15 @@
}
int
+aot_class::add_class (const std::string &s)
+{
+ pool_entry e;
+ e.tag = CONSTANT_Class;
+ e.value = s;
+ return add_item (e);
+}
+
+int
aot_class::add (model_class *k)
{
pool_entry e;
Index: gcjx/aot/aotclass.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/aot/Attic/aotclass.hh,v
retrieving revision 1.1.2.2
diff -u -r1.1.2.2 aotclass.hh
--- gcjx/aot/aotclass.hh 30 Jan 2005 03:10:41 -0000 1.1.2.2
+++ gcjx/aot/aotclass.hh 8 Mar 2005 00:18:53 -0000
@@ -36,6 +36,8 @@
/// compiler.
class aot_class
{
+public:
+
/// This represents one entry in the constant pool.
struct pool_entry
{
@@ -53,6 +55,8 @@
model_class *derived;
};
+private:
+
/// The class factory. FIXME: require it as a parameter and not
/// keep it as state?
aot_class_factory *factory;
@@ -105,6 +109,10 @@
/// of the item.
int add (model_class *);
+ /// Add a class reference to the constant pool, given just the
+ /// descriptor of the class. Returns the index of the item.
+ int add_class (const std::string &);
+
/// Add an assertion that BASE is a superclass or superinterface of
/// DERIVED.
void add_type_assertion (model_class *base, model_class *derived);
@@ -161,6 +169,12 @@
{
return klass;
}
+
+ /// Return the constant pool.
+ const std::vector<pool_entry> &get_constant_pool () const
+ {
+ return pool;
+ }
};
#endif // GCJX_AOT_AOTCLASS_HH
Index: gcjx/aot/mangle.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/aot/Attic/mangle.cc,v
retrieving revision 1.1.2.4
diff -u -r1.1.2.4 mangle.cc
--- gcjx/aot/mangle.cc 13 Feb 2005 04:08:17 -0000 1.1.2.4
+++ gcjx/aot/mangle.cc 8 Mar 2005 00:18:53 -0000
@@ -250,10 +250,17 @@
result += "E";
}
-mangler::mangler (model_class *declaring, const std::string &fieldname)
+mangler::mangler (model_class *declaring, const char *fieldname)
: result ("_Z")
{
update (declaring, false);
update (fieldname);
result += "E";
}
+
+mangler::mangler (model_class *klass, bool)
+ : result ("_ZTV")
+{
+ update (klass, false);
+ result += "E";
+}
Index: gcjx/aot/mangle.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcjx/aot/Attic/mangle.hh,v
retrieving revision 1.1.2.2
diff -u -r1.1.2.2 mangle.hh
--- gcjx/aot/mangle.hh 13 Feb 2005 04:08:17 -0000 1.1.2.2
+++ gcjx/aot/mangle.hh 8 Mar 2005 00:18:53 -0000
@@ -55,7 +55,11 @@
// This is a way to create a mangled name for a non-existing field,
// given its declaring class.
- mangler (model_class *, const std::string &);
+ mangler (model_class *, const char *);
+
+ /// This is slightly bogus: the bool argument is ignored; this
+ /// constructor is used to create the name of the class' vtable.
+ mangler (model_class *, bool);
std::string get () const
{
Index: gcc/java/ChangeLog
from Tom Tromey <tromey@redhat.com>
* builtins.cc (map_utf8const): Use 'type', not 'type_utf8const'.
* abi.cc (build_class_reference): Wrote.
* classobj.cc (create_class_instance): Use new get_vtable
argument.
* abi.cc (get_vtable): Updated.
* abi.hh (gcj_abi::get_vtable): Added argument.
(cxx_abi::get_vtable): Likewise.
(bc_abi::get_vtable): Likewise.
* builtins.cc (get_vtable_decl): Updated.
* builtins.hh (tree_builtins::get_vtable): Added argument.
* classobj.cc (handle_interfaces): Updated.
(create_class_instance): Updated.
* abi.cc (build_class_reference): Rewrote.
* abi.hh (gcj_abi::build_class_ref): Changed argument type.
(cxx_abi::build_class_ref): Likewise.
(bc_abi::build_class_ref): Likewise.
* tree.hh (tree_generator::build_class_ref): Updated.
* tree.cc (build_class_ref): Rewrote.
(build_class_ref): Likewise. Changed argument type.
(build_new_array): Updated.
* builtins.hh (tree_builtins::find_abi): Updated.
* builtins.cc (find_abi): Removed argument.
(map_field_ref): Updated.
(map_method_call): Likewise.
(map_new): Likewise.
* abi.cc (get_vtable): New method.
* abi.hh (gcj_abi::get_vtable): New abstract method.
(cxx_abi::get_vtable): Declare.
(bc_abi::get_vtable): Likewise.
* glue.hh: Include version.h.
* decl.cc (initialize_version): Rewrote.
(GCJ_BINARYCOMPAT_ADDITION): New define.
(build_class_type): Changed name of field to "dtable".
* classobj.hh (class_object_creator::create_constants): Declare.
* classobj.cc (create_constants): New method.
(make_decl): Don't set DECL_ASSEMBLER_NAME.
(create_method_throws): Use make_decl.
(create_index_table): Likewise. Handle case where table is
empty.
(create_class_instance): Set vtable fields.
* builtins.cc (tree_builtins): Initialize new field.
(get_symbol): New method.
(get_vtable_decl): New method.
(find_abi): Rewrote.
* builtins.hh (tree_builtins::symbol_count): New field.
(tree_builtins::get_symbol): Declare.
(tree_builtins::get_vtable_decl): Likewise.
* glue.hh: Include output.h.
* builtins.hh (tree_builtins::utf8typemap): New field.
(tree_builtins::build_utf8const_type): Declare.
(tree_builtins::hash_utf8): Likewise.
* builtins.cc (build_utf8const_type): New method.
(hash_utf8): Likewise.
(map_utf8const): Finished.
* hooks.hh (push_field): Declare.
* decl.cc (build_utf8_record): Fix length of "data" field.
(push_field): No longer static.
(build_method_symbol_type): Fixed field name.
* classobj.cc (create_one_method_record): Compute values of
"ncode" and "throws".
(create_method_throws): New method.
Index: gcc/java/abi.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/Attic/abi.cc,v
retrieving revision 1.1.2.5
diff -u -r1.1.2.5 abi.cc
--- gcc/java/abi.cc 13 Feb 2005 04:11:33 -0000 1.1.2.5
+++ gcc/java/abi.cc 8 Mar 2005 00:19:03 -0000
@@ -147,20 +147,28 @@
tree
cxx_abi::build_class_reference (tree_builtins *builtins,
- aot_class *,
- tree klass)
+ aot_class *current,
+ const std::string &classname)
{
- assert (TREE_CODE (klass) == POINTER_TYPE);
- tree decl = TYPE_STUB_DECL (TREE_TYPE (klass));
- return build1 (ADDR_EXPR, type_class_ptr, decl);
+ // Turn the class name into a reference to a real class in the
+ // model.
+ model_class *klass = current->get ();
+ // We know that any call to this method necessarily comes from a
+ // .class file.
+ model_unit_class *unit
+ = assert_cast<model_unit_class *> (klass->get_compilation_unit ());
+ model_type *type = unit->find_class_from_descriptor (NULL, klass, classname);
+ return build_class_reference (builtins, current, type);
}
tree
cxx_abi::build_class_reference (tree_builtins *builtins,
aot_class *,
- model_class *klass)
+ model_type *klass)
{
- tree class_obj = builtins->map_class_object (klass);
+ // FIXME: handle primitive type.
+ tree class_obj
+ = builtins->map_class_object (assert_cast<model_class *> (klass));
return build1 (ADDR_EXPR, type_class_ptr, class_obj);
}
@@ -173,7 +181,8 @@
tree n = build3 (CALL_EXPR, klass, allocator,
build_tree_list (NULL_TREE,
build_class_reference (builtins, current,
- klass)),
+ // FIXME
+ NULL)),
NULL_TREE);
TREE_SIDE_EFFECTS (n) = 1;
// Call the constructor.
@@ -185,6 +194,13 @@
return n;
}
+tree
+cxx_abi::get_vtable (tree_builtins *builtins, model_class *klass,
+ bool lay_out)
+{
+ return build_address_of (builtins->get_vtable_decl (klass, lay_out));
+}
+
tree
@@ -230,17 +246,30 @@
}
tree
-bc_abi::build_class_reference (tree_builtins *, aot_class *current, tree klass)
+bc_abi::build_class_reference (tree_builtins *, aot_class *current,
+ const std::string &classname)
{
- abort ();
+ // FIXME: handle primitive classes
+ int index = current->add_class (classname);
+ // FIXME: find the constant pool
+ tree cpool = NULL_TREE;
+ return build4 (ARRAY_REF, type_class_ptr,
+ cpool, build_int_cst (type_jint, index),
+ NULL_TREE, NULL_TREE);
}
tree
-bc_abi::build_class_reference (tree_builtins *,
- aot_class *,
- model_class *)
+bc_abi::build_class_reference (tree_builtins *builtins,
+ aot_class *current,
+ model_type *klass)
{
- abort ();
+ // FIXME: handle primitive classes
+ int index = current->add (assert_cast<model_class *> (klass));
+ // FIXME: find the constant pool
+ tree cpool = NULL_TREE;
+ return build4 (ARRAY_REF, type_class_ptr,
+ cpool, build_int_cst (type_jint, index),
+ NULL_TREE, NULL_TREE);
}
tree
Index: gcc/java/abi.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/Attic/abi.hh,v
retrieving revision 1.1.2.3
diff -u -r1.1.2.3 abi.hh
--- gcc/java/abi.hh 13 Feb 2005 04:11:33 -0000 1.1.2.3
+++ gcc/java/abi.hh 8 Mar 2005 00:19:03 -0000
@@ -87,13 +87,12 @@
/// Return a tree representing a reference to some other class.
virtual tree build_class_reference (tree_builtins *builtins,
aot_class *current,
- // FIXME: should take a string here
- tree other) = 0;
+ const std::string &class_name) = 0;
/// Return a tree representing a reference to some other class.
virtual tree build_class_reference (tree_builtins *builtins,
aot_class *current,
- model_class *other) = 0;
+ model_type *other) = 0;
/// Return an expression that is used to create a new object given
/// its type, constructor, and arguments to the constructor.
@@ -108,6 +107,12 @@
/// Return the initial 'state' value for a class compiled with this
/// ABI.
virtual int get_class_state () = 0;
+
+ /// Return a pointer to the vtable for the indicated class. If the
+ /// bool argument is true, we are creating the Class object for
+ /// KLASS and need a fully-filled-in vtable, not just a decl.
+ virtual tree get_vtable (tree_builtins *builtins, model_class *klass,
+ bool lay_out = false) = 0;
};
/// This class handles C++ ABI code.
@@ -126,11 +131,12 @@
tree build_field_reference (tree_builtins *, aot_class *,
tree, model_field *);
- tree build_class_reference (tree_builtins *, aot_class *, tree);
+ tree build_class_reference (tree_builtins *, aot_class *,
+ const std::string &);
tree build_class_reference (tree_builtins *builtins,
aot_class *current,
- model_class *other);
+ model_type *other);
tree build_new (tree_builtins *, aot_class *, tree, tree, tree);
@@ -143,6 +149,8 @@
{
return JV_STATE_COMPILED;
}
+
+ tree get_vtable (tree_builtins *, model_class *, bool);
};
/// This class handles the binary compatibility ABI.
@@ -161,11 +169,12 @@
tree build_field_reference (tree_builtins *, aot_class *,
tree, model_field *);
- tree build_class_reference (tree_builtins *, aot_class *, tree);
+ tree build_class_reference (tree_builtins *, aot_class *,
+ const std::string &);
tree build_class_reference (tree_builtins *builtins,
aot_class *current,
- model_class *other);
+ model_type *other);
tree build_new (tree_builtins *, aot_class *, tree, tree, tree);
@@ -178,6 +187,12 @@
{
return JV_STATE_PRELOADING;
}
+
+ tree get_vtable (tree_builtins *, model_class *, bool)
+ {
+ // The BC ABI lays out all vtables at runtime.
+ return null_pointer_node;
+ }
};
#endif // GCC_TREE_ABI_HH
Index: gcc/java/builtins.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/Attic/builtins.cc,v
retrieving revision 1.1.2.10
diff -u -r1.1.2.10 builtins.cc
--- gcc/java/builtins.cc 13 Feb 2005 04:14:58 -0000 1.1.2.10
+++ gcc/java/builtins.cc 8 Mar 2005 00:19:03 -0000
@@ -24,7 +24,8 @@
#include "aot/mangle.hh"
tree_builtins::tree_builtins ()
- : aot_class_factory ()
+ : aot_class_factory (),
+ symbol_count (0)
{
}
@@ -35,9 +36,10 @@
gcj_abi *
-tree_builtins::find_abi (model_type *)
+tree_builtins::find_abi ()
{
- // FIXME: implement
+ if (flag_indirect_dispatch)
+ return &new_abi;
return &old_abi;
}
@@ -306,7 +308,7 @@
tree
tree_builtins::map_field_ref (aot_class *wrapper, tree obj, model_field *field)
{
- gcj_abi *abi = find_abi (field->get_declaring_class ());
+ gcj_abi *abi = find_abi ();
tree result
= abi->build_field_reference (this, wrapper,
@@ -344,7 +346,7 @@
tree obj, tree args, model_method *meth,
bool is_super)
{
- gcj_abi *abi = find_abi (meth->get_declaring_class ());
+ gcj_abi *abi = find_abi ();
tree result = abi->build_method_call (this, wrapper,
meth->static_p () ? NULL_TREE : obj,
args, meth, is_super);
@@ -365,35 +367,163 @@
tree
tree_builtins::map_new (model_class *klass, tree constructor, tree arguments)
{
- gcj_abi *abi = find_abi (klass);
+ gcj_abi *abi = find_abi ();
return abi->build_new (this, get_class (klass),
map_type (klass), constructor, arguments);
}
tree
+tree_builtins::build_utf8const_type (int len)
+{
+ if (utf8typemap.find (len) == utf8typemap.end ())
+ {
+ tree field = NULL_TREE;
+ tree new_type = make_node (RECORD_TYPE);
+ push_field (new_type, field, "hash", type_jushort);
+ push_field (new_type, field, "length", type_jushort);
+ push_field (new_type, field, "data",
+ build_array_type (char_type_node,
+ build_index_type (build_int_cst (type_jint,
+ len))));
+ layout_type (new_type);
+ utf8typemap[len] = new_type;
+ }
+ return utf8typemap[len];
+}
+
+int
+tree_builtins::hash_utf8 (const char *s, int len)
+{
+ const unsigned char *ptr = (const unsigned char *) s;
+ const unsigned char *limit = ptr + len;
+ int hash = 0;
+ while (ptr < limit)
+ {
+ // FIXME
+ // int ch = UTF8_GET (ptr, limit);
+ int ch = *ptr++;
+ /* Updated specification from
+ http://www.javasoft.com/docs/books/jls/clarify.html. */
+ hash = (31 * hash) + ch;
+ }
+ return hash;
+}
+
+tree
tree_builtins::map_utf8const (const std::string &value)
{
- std::map<std::string, tree>::const_iterator it = utf8map.find (value);
- if (it == utf8map.end ())
+ if (utf8map.find (value) == utf8map.end ())
{
- record_creator utf (type_utf8const);
- utf.set_field ("hash", build_int_cst (type_jushort, 0)); // FIXME
+ // Note: add 1 to length here for trailing \0.
+ tree type = build_utf8const_type (value.length () + 1);
+ int hash = hash_utf8 (value.c_str (), value.length ());
+
+ record_creator utf (type);
+ utf.set_field ("hash", build_int_cst (type_jushort, hash & 0xffff));
utf.set_field ("length", build_int_cst (type_jushort, value.length ()));
- tree str = build_string (value.length (), value.c_str ());
- tree strtype = build_index_type (build_int_cst (type_jushort,
- value.length ()));
+ tree str = build_string (value.length () + 1, value.c_str ());
+ tree strtype = TREE_TYPE (find_decl (type, "data"));
TREE_TYPE (str) = strtype;
TREE_CONSTANT (str) = 1;
+ TREE_INVARIANT (str) = 1;
TREE_READONLY (str) = 1;
TREE_STATIC (str) = 1;
utf.set_field ("data", str);
- utf8map[value] = build_address_of (utf.finish_record ());
+ tree init = utf.finish_record ();
+ TREE_CONSTANT (init) = 1;
+ TREE_INVARIANT (init) = 1;
+ TREE_READONLY (init) = 1;
+
+ char buf[20];
+ sprintf (buf, "_Utf%d", utf8map.size ());
+
+ tree decl = build_decl (VAR_DECL, get_identifier (buf), type);
+ TREE_STATIC (decl) = 1;
+ DECL_ARTIFICIAL (decl) = 1;
+ DECL_IGNORED_P (decl) = 1;
+ TREE_READONLY (decl) = 1;
+ DECL_INITIAL (decl) = init;
+
+ if (HAVE_GAS_SHF_MERGE)
+ {
+ int decl_size;
+ // Ensure decl_size is a multiple of utf8const_type's alignment.
+ decl_size = ((value.length () + 5 + TYPE_ALIGN_UNIT (type) - 1)
+ & ~(TYPE_ALIGN_UNIT (type) - 1));
+ if (flag_merge_constants && decl_size < 256)
+ {
+ char buf[32];
+ int flags = (SECTION_OVERRIDE
+ | SECTION_MERGE | (SECTION_ENTSIZE & decl_size));
+ sprintf (buf, ".rodata.jutf8.%d", decl_size);
+ named_section_flags (buf, flags);
+ DECL_SECTION_NAME (decl) = build_string (strlen (buf), buf);
+ }
+ }
+
+ layout_decl (decl, 0);
+ rest_of_decl_compilation (decl, 1, 0);
+ make_decl_rtl (decl);
+
+ utf8map[value] = build_address_of (decl);
}
return utf8map[value];
}
+tree
+tree_builtins::get_vtable_decl (model_class *klass, bool lay_out)
+{
+ if (vtable_map.find (klass) == vtable_map.end ())
+ {
+ tree decl = build_decl (VAR_DECL, NULL_TREE, type_dtable);
+ TREE_STATIC (decl) = 1;
+ DECL_ARTIFICIAL (decl) = 1;
+ DECL_IGNORED_P (decl) = 1;
+ mangler m (klass, true);
+ SET_DECL_ASSEMBLER_NAME (decl,
+ get_identifier (m.get ().c_str ()));
+
+ if (lay_out)
+ {
+ lay_out_class (klass);
+
+ tree klass_ptr_type = map_type (klass);
+ tree vtable = BINFO_VTABLE (TYPE_BINFO (TREE_TYPE (klass_ptr_type)));
+
+ // FIXME: this isn't really correct.
+ // it fails where a pointer-to-function is wider.
+ tree vtype
+ = build_array_type (type_nativecode_ptr,
+ build_index_type (build_int_cst (type_jint,
+ TREE_VEC_LENGTH (vtable))));
+ tree cons = NULL_TREE;
+
+ TREE_TYPE (decl) = vtype;
+
+ // FIXME: set these on the initializer when we make it.
+ // Also set them on the decl?
+ // TREE_CONSTANT (init) = 1;
+ // TREE_INVARIANT (init) = 1;
+ // TREE_READONLY (init) = 1;
+
+ // FIXME: make a helper method for this sequence.
+ // Is it even correct? We do something with cgraph in
+ // treegen.cc.
+ layout_decl (decl, 0);
+ rest_of_decl_compilation (decl, 1, 0);
+ make_decl_rtl (decl);
+ }
+
+ vtable_map[klass] = decl;
+ }
+ return vtable_map[klass];
+}
+
+// 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.
void
tree_builtins::lay_out_vtable (model_class *mklass)
{
@@ -508,3 +638,12 @@
mangler m (klass, "class$");
return m.get ();
}
+
+tree
+tree_builtins::get_symbol ()
+{
+ char buf[50];
+ sprintf (buf, "_temp_%d", symbol_count);
+ ++symbol_count;
+ return get_identifier (buf);
+}
Index: gcc/java/builtins.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/Attic/builtins.hh,v
retrieving revision 1.1.2.7
diff -u -r1.1.2.7 builtins.hh
--- gcc/java/builtins.hh 13 Feb 2005 04:11:33 -0000 1.1.2.7
+++ gcc/java/builtins.hh 8 Mar 2005 00:19:03 -0000
@@ -33,6 +33,9 @@
// FIXME: perhaps this should be attached to the gcc type somehow?
std::map<model_class *, tree> classobj_map;
+ // This maps classes to their vtable decls
+ std::map<model_class *, tree> vtable_map;
+
// This maps a method to its corresponding gcc tree.
std::map<model_method *, tree> methodmap;
@@ -42,10 +45,16 @@
// This maps a variable or parameter to its corresponding gcc tree.
std::map<model_variable_decl *, tree> varmap;
+ // This maps a length to a concrete Utf8Const type.
+ std::map<int, tree> utf8typemap;
+
// This maps a string to a gcc tree representing the corresponding
// Utf8Const.
std::map<std::string, tree> utf8map;
+ // Used when creating symbol names.
+ int symbol_count;
+
// ABI instances.
cxx_abi old_abi;
bc_abi new_abi;
@@ -54,6 +63,8 @@
void add (tree, model_field *);
tree map_param_or_var (tree_code, tree, model_variable_decl *);
void lay_out_vtable (model_class *);
+ tree build_utf8const_type (int);
+ int hash_utf8 (const char *, int);
friend class cxx_abi;
@@ -101,10 +112,18 @@
/// called once, before any classes are entered into the type map.
void initialize_type_map ();
- gcj_abi *find_abi (model_type *);
+ gcj_abi *find_abi ();
/// Return the mangled name of the class object for a given class.
std::string get_class_object_name (model_class *);
+
+ /// Return a new unique symbol name.
+ tree get_symbol ();
+
+ /// Return the decl for a given class' vtable. If the second
+ /// argument is true, assume we are laying out the vtable, so go
+ /// ahead and fill it in.
+ tree get_vtable_decl (model_class *, bool = false);
};
#endif // GCC_TREE_BUILTINS_HH
Index: gcc/java/classobj.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/Attic/classobj.cc,v
retrieving revision 1.1.2.11
diff -u -r1.1.2.11 classobj.cc
--- gcc/java/classobj.cc 13 Feb 2005 04:19:49 -0000 1.1.2.11
+++ gcc/java/classobj.cc 8 Mar 2005 00:19:03 -0000
@@ -84,13 +84,11 @@
tree
class_object_creator::make_decl (tree type, tree value)
{
- tree decl = build_decl (VAR_DECL, NULL_TREE, type);
+ tree decl = build_decl (VAR_DECL, builtins->get_symbol (), type);
DECL_INITIAL (decl) = value;
TREE_STATIC (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
DECL_IGNORED_P (decl) = 1;
- SET_DECL_ASSEMBLER_NAME (decl,
- get_identifier (builtins->get_class_object_name (klass->get ()).c_str ()));
rest_of_decl_compilation (decl, 1, 0);
return build1 (ADDR_EXPR, build_pointer_type (type), decl);
@@ -165,6 +163,32 @@
}
tree
+class_object_creator::create_method_throws (model_method *method)
+{
+ std::list<ref_forwarding_type> throw_list = method->get_throws ();
+
+ if (throw_list.empty ())
+ return null_pointer_node;
+
+ tree cons_list = tree_cons (NULL_TREE, null_pointer_node, NULL_TREE);
+ for (std::list<ref_forwarding_type>::const_iterator i = throw_list.begin ();
+ i != throw_list.end ();
+ ++i)
+ {
+ tree utf = builtins->map_utf8const ((*i)->type ()->get_descriptor ());
+ cons_list = tree_cons (NULL_TREE, utf, cons_list);
+ }
+
+ tree type
+ = build_array_type (type_utf8const_ptr,
+ build_index_type (build_int_cst (type_jint,
+ throw_list.size () + 1)));
+ cons_list = build_constructor (type, cons_list);
+
+ return make_decl (type, cons_list);
+}
+
+tree
class_object_creator::create_one_method_record (model_method *method)
{
record_creator inst (type_method);
@@ -174,9 +198,9 @@
builtins->map_utf8const (method->get_descriptor ()));
inst.set_field ("accflags",
build_int_cst (type_jushort, method->get_modifiers ()));
- inst.set_field ("index", integer_zero_node); // FIXME
- inst.set_field ("ncode", null_pointer_node); // FIXME
- inst.set_field ("throws", null_pointer_node); // FIXME
+ inst.set_field ("index", integer_minus_one_node); // FIXME
+ inst.set_field ("ncode", build_address_of (mdecl));
+ inst.set_field ("throws", create_method_throws (method));
return inst.finish_record ();
}
@@ -214,6 +238,15 @@
tree &result_table,
tree &result_syms)
{
+ tree result_list = NULL_TREE;
+
+ if (table.empty ())
+ {
+ result_table = null_pointer_node;
+ result_syms = null_pointer_node;
+ return;
+ }
+
for (std::vector<model_element *>::const_iterator i = table.begin ();
i != table.end ();
++i)
@@ -237,13 +270,31 @@
descriptor = method->get_descriptor ();
}
- // FIXME: enter new utf8consts.
-
+ tree class_tree = builtins->map_utf8const (class_desc);
+ tree name_tree = builtins->map_utf8const (name);
+ tree desc_tree = builtins->map_utf8const (descriptor);
+
+ record_creator item (type_method_symbol);
+ item.set_field ("class_name", class_tree);
+ item.set_field ("name", name_tree);
+ item.set_field ("signature", desc_tree);
+ tree item_tree = item.finish_record ();
+
+ result_list = tree_cons (NULL_TREE, item_tree, result_list);
}
- // FIXME create the tables and update the arguments
- result_table = null_pointer_node;
- result_syms = null_pointer_node;
+ tree type
+ = build_array_type (type_method_symbol,
+ build_index_type (build_int_cst (type_jint, table.size ())));
+ result_syms = make_decl (type, result);
+
+ tree symtype
+ = build_array_type (ptr_type_node,
+ build_index_type (build_int_cst (type_jint,
+ table.size ())));
+ // FIXME: we need a decl for this somewhere else so that the ABI can
+ // emit references to it...
+ result_table = make_decl (symtype, NULL_TREE);
}
void
@@ -264,10 +315,9 @@
++i)
{
++len;
- gcj_abi *abi = builtins->find_abi ((*i)->type ());
- tree one_iface
- = abi->build_class_reference (builtins, klass,
- builtins->map_type ((*i)->type ()));
+ gcj_abi *abi = builtins->find_abi ();
+ tree one_iface = abi->build_class_reference (builtins, klass,
+ (*i)->type ());
result = tree_cons (NULL_TREE, one_iface, result);
}
result = nreverse (result);
@@ -285,19 +335,60 @@
}
+tree
+class_object_creator::create_constants ()
+{
+ const std::vector<aot_class::pool_entry> &pool (klass->get_constant_pool ());
+
+ if (pool.empty ())
+ return null_pointer_node;
+
+ record_creator inst (type_constants);
+ inst.set_field ("size", build_int_cst (type_juint, pool.size ()));
+
+ tree type_tags
+ = build_array_type (type_jbyte,
+ build_index_type (build_int_cst (type_jint,
+ pool.size ())));
+ tree type_data
+ = build_array_type (ptr_type_node,
+ build_index_type (build_int_cst (type_jint,
+ pool.size ())));
+
+ tree tags_list = NULL_TREE;
+ tree data_list = NULL_TREE;
+ for (std::vector<aot_class::pool_entry>::const_iterator i = pool.begin ();
+ i != pool.end ();
+ ++i)
+ {
+ tags_list = tree_cons (NULL_TREE, build_int_cst (type_jbyte, (*i).tag),
+ tags_list);
+ data_list = tree_cons (NULL_TREE, builtins->map_utf8const ((*i).value),
+ data_list);
+ }
+
+ tags_list = nreverse (tags_list);
+ data_list = nreverse (data_list);
+
+ inst.set_field ("tags", make_decl (type_tags, tags_list));
+ inst.set_field ("data", make_decl (type_data, data_list));
+
+ return inst.finish_record ();
+}
+
void
class_object_creator::create_class_instance (tree class_tree)
{
assert (TREE_CODE (class_tree) == RECORD_TYPE);
- // FIXME: handle fields in Object.
-
model_class *real_class = klass->get ();
- gcj_abi *abi = builtins->find_abi (real_class);
+ gcj_abi *abi = builtins->find_abi ();
record_creator inst (type_class);
// First the fields from Object.
- inst.set_field ("vtable", null_pointer_node); // FIXME
+ inst.set_field ("vtable",
+ abi->get_vtable (builtins,
+ global->get_compiler ()->java_lang_Class ()));
if (! flag_hash_synchronization)
inst.set_field ("sync_info", null_pointer_node);
@@ -318,13 +409,10 @@
if (real_class->interface_p ())
super = global->get_compiler ()->java_lang_Object ();
if (super)
- {
- gcj_abi *abi = builtins->find_abi (super);
- super_tree = abi->build_class_reference (builtins, klass, super);
- }
+ super_tree = abi->build_class_reference (builtins, klass, super);
inst.set_field ("superclass", super_tree);
- inst.set_field ("constants", null_pointer_node); // FIXME
+ inst.set_field ("constants", create_constants ());
int method_len;
tree methods = create_method_array (real_class, method_len);
@@ -344,8 +432,7 @@
inst.set_field ("static_field_count",
build_int_cst (type_jshort, num_static_fields));
- // FIXME abi->get_vtable (blah));
- inst.set_field ("vtable", null_pointer_node);
+ inst.set_field ("dtable", abi->get_vtable (builtins, klass->get (), true));
tree table, syms;
create_index_table (klass->get_otable (), table, syms);
Index: gcc/java/classobj.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/Attic/classobj.hh,v
retrieving revision 1.1.2.4
diff -u -r1.1.2.4 classobj.hh
--- gcc/java/classobj.hh 13 Feb 2005 04:13:23 -0000 1.1.2.4
+++ gcc/java/classobj.hh 8 Mar 2005 00:19:03 -0000
@@ -67,11 +67,13 @@
tree create_one_field_record (model_field *);
tree create_field_array (model_class *, int &, int &);
tree create_one_method_record (model_method *);
+ tree create_method_throws (model_method *);
tree create_method_array (model_class *, int &);
void handle_interfaces (model_class *, tree &, tree &);
void create_index_table (const std::vector<model_element *> &,
tree &, tree &);
void create_class_instance (tree);
+ tree create_constants ();
public:
Index: gcc/java/decl.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/Attic/decl.cc,v
retrieving revision 1.1.2.9
diff -u -r1.1.2.9 decl.cc
--- gcc/java/decl.cc 13 Feb 2005 04:19:49 -0000 1.1.2.9
+++ gcc/java/decl.cc 8 Mar 2005 00:19:03 -0000
@@ -26,6 +26,9 @@
// this explicitly.
extern "C" rtx init_one_libfunc (const char *);
+// Used when computing the ABI version.
+#define GCJ_BINARYCOMPAT_ADDITION 5
+
// FIXME: do we need this? Global decl list.
tree all_decls;
@@ -164,9 +167,9 @@
// It appends a new field to the type. It is invalid to call this
// after layout_type has been called on the type. FIELD is updated to
// be the new field, it can be modified after return.
-static void
+void
push_field (tree record, tree &field, const char *name,
- tree field_type, bool is_private = false)
+ tree field_type, bool is_private)
{
assert (record != NULL_TREE);
assert (field_type != NULL_TREE);
@@ -203,7 +206,8 @@
push_field (type_utf8const, field, "hash", type_jushort);
push_field (type_utf8const, field, "length", type_jushort);
push_field (type_utf8const, field, "data",
- build_array_type (char_type_node, integer_type_node));
+ build_array_type (char_type_node,
+ build_index_type (integer_zero_node)));
layout_type (type_utf8const);
type_utf8const_ptr = build_pointer_type (type_utf8const);
@@ -214,7 +218,7 @@
{
tree field = NULL_TREE;
type_method_symbol = make_node (RECORD_TYPE);
- push_field (type_method_symbol, field, "clname", type_utf8const_ptr);
+ push_field (type_method_symbol, field, "class_name", type_utf8const_ptr);
push_field (type_method_symbol, field, "name", type_utf8const_ptr);
// A misnomer as of 1.5.
push_field (type_method_symbol, field, "signature", type_utf8const_ptr);
@@ -312,7 +316,7 @@
push_field (type_class, field, "size_in_bytes", type_jint, true);
push_field (type_class, field, "field_count", type_jshort, true);
push_field (type_class, field, "static_field_count", type_jshort, true);
- push_field (type_class, field, "vtable", type_dtable_ptr, true);
+ push_field (type_class, field, "dtable", type_dtable_ptr, true);
push_field (type_class, field, "otable", type_otable_ptr, true);
push_field (type_class, field, "otable_syms",
build_pointer_type (type_method_symbol_array), true);
@@ -712,13 +716,44 @@
static void
initialize_version ()
{
- // FIXME: this is wrong, must parse version.c.
- // Take from gcj.
- int version = __GNUC__ * 10000 + __GNUC_MINOR__ * 10;
+ const char *p = version_string;
+ unsigned int major = 0, minor = 0;
+ unsigned int abi_version;
+
+ /* Skip leading junk. */
+ while (*p && !ISDIGIT (*p))
+ ++p;
+ gcc_assert (*p);
+
+ /* Extract major version. */
+ while (ISDIGIT (*p))
+ {
+ major = major * 10 + *p - '0';
+ ++p;
+ }
+
+ gcc_assert (*p == '.' && ISDIGIT (p[1]));
+ ++p;
+
+ /* Extract minor version. */
+ while (ISDIGIT (*p))
+ {
+ minor = minor * 10 + *p - '0';
+ ++p;
+ }
+
+ /* Implicit in this computation is the idea that we won't break the
+ old-style binary ABI in a sub-minor release (e.g., from 4.0.0 to
+ 4.0.1). */
+ abi_version = 10000 * major + 10 * minor;
+ /* It is helpful to distinguish BC ABI from ordinary ABI at this
+ level, since at some point we will recognize a variety of BC ABIs
+ (objects generated by different version of gcj), but will
+ probably always require strict matching for ordinary ABI. */
if (flag_indirect_dispatch)
- version += 5;
- gcj_abi_version = build1 (NOP_EXPR, type_class_ptr,
- build_int_cst (type_jint, version));
+ abi_version += GCJ_BINARYCOMPAT_ADDITION;
+
+ gcj_abi_version = build_int_cstu (ptr_type_node, abi_version);
}
tree
Index: gcc/java/glue.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/Attic/glue.hh,v
retrieving revision 1.1.2.7
diff -u -r1.1.2.7 glue.hh
--- gcc/java/glue.hh 13 Feb 2005 03:46:44 -0000 1.1.2.7
+++ gcc/java/glue.hh 8 Mar 2005 00:19:04 -0000
@@ -60,6 +60,7 @@
#include "langhooks-def.h"
#include "options.h"
#include "toplev.h"
+ //#include "output.h"
#include "except.h"
#include "flags.h"
#include "tree-inline.h"
@@ -68,6 +69,7 @@
#include "convert.h"
#include "ggc.h"
#include "debug.h"
+#include "version.h"
// This gets us alloc_stmt_list(). Shouldn't that be in
// tree-iterator.h?
Index: gcc/java/hooks.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/Attic/hooks.hh,v
retrieving revision 1.1.2.4
diff -u -r1.1.2.4 hooks.hh
--- gcc/java/hooks.hh 13 Feb 2005 04:19:49 -0000 1.1.2.4
+++ gcc/java/hooks.hh 8 Mar 2005 00:19:04 -0000
@@ -101,6 +101,8 @@
extern tree build_address_of (tree);
+extern void push_field (tree record, tree &field, const char *name,
+ tree field_type, bool is_private = false);
namespace gcjx
{
Index: gcc/java/lower.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/Attic/lower.cc,v
retrieving revision 1.1.2.4
diff -u -r1.1.2.4 lower.cc
--- gcc/java/lower.cc 31 Jan 2005 02:26:01 -0000 1.1.2.4
+++ gcc/java/lower.cc 8 Mar 2005 00:19:04 -0000
@@ -1327,11 +1327,12 @@
case op_new:
{
- tree klass = find_class (cpool->get_class (get2u (bytes, pc)));
- insn = push (build3 (CALL_EXPR, klass,
+ tree klass_ref
+ = build_class_ref (cpool->get_class (get2u (bytes, pc)));
+ insn = push (build3 (CALL_EXPR,
+ NULL_TREE, // FIXME!
builtin_Jv_AllocObject,
- build_tree_list (NULL_TREE,
- build_class_ref (klass)),
+ build_tree_list (NULL_TREE, klass_ref),
NULL_TREE));
}
break;
@@ -1457,8 +1458,8 @@
args = tree_cons (NULL_TREE, next, args);
}
- tree klass = find_class (cpool->get_class (kind_index));
- args = tree_cons (NULL_TREE, klass, args);
+ tree klassref = build_class_ref (cpool->get_class (kind_index));
+ args = tree_cons (NULL_TREE, klassref, args);
insn = push (build3 (CALL_EXPR, type_object,
builtin_Jv_NewMultiArray,
@@ -1873,11 +1874,9 @@
}
case CONSTANT_Class:
- // 1.5 only.
- {
- tree klass = find_class (cpool->get_class (index));
- result = build_class_ref (klass);
- }
+ // 1.5 only. The verifier will reject this for pre-1.5 class
+ // 1.files.
+ result = build_class_ref (cpool->get_class (index));
break;
default:
Index: gcc/java/tree.cc
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/Attic/tree.cc,v
retrieving revision 1.1.2.10
diff -u -r1.1.2.10 tree.cc
--- gcc/java/tree.cc 13 Feb 2005 03:58:29 -0000 1.1.2.10
+++ gcc/java/tree.cc 8 Mar 2005 00:19:04 -0000
@@ -1330,12 +1330,6 @@
}
}
-tree
-tree_generator::build_class_ref (model_type *t)
-{
- return build_class_ref (gcc_builtins->map_type (t));
-}
-
void
tree_generator::visit_class_ref (model_class_ref *,
const ref_forwarding_type &req)
@@ -1871,13 +1865,12 @@
assert (elt_type->primitive_p ());
model_type *array_type = elt_type->array ();
- tree elt_type_tree = gcc_builtins->map_type (elt_type);
tree array_type_tree = gcc_builtins->map_type (array_type);
tree insn = build3 (CALL_EXPR, array_type_tree,
builtin_Jv_NewPrimArray,
tree_cons (NULL_TREE,
- build_class_ref (elt_type_tree),
+ build_class_ref (elt_type),
tree_cons (NULL_TREE, size, NULL_TREE)),
NULL_TREE);
TREE_SIDE_EFFECTS (insn) = 1;
@@ -1926,11 +1919,19 @@
}
tree
-tree_generator::build_class_ref (tree klass)
+tree_generator::build_class_ref (model_type *t)
+{
+ gcj_abi *abi = gcc_builtins->find_abi ();
+ // FIXME: we can see "int.class".
+ return abi->build_class_reference (gcc_builtins, class_wrapper,
+ assert_cast<model_class *> (t));
+}
+
+tree
+tree_generator::build_class_ref (const std::string &classname)
{
- // FIXME.
- gcj_abi *abi = gcc_builtins->find_abi (NULL);
- return abi->build_class_reference (gcc_builtins, class_wrapper, klass);
+ gcj_abi *abi = gcc_builtins->find_abi ();
+ return abi->build_class_reference (gcc_builtins, class_wrapper, classname);
}
tree
Index: gcc/java/tree.hh
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/Attic/tree.hh,v
retrieving revision 1.1.2.3
diff -u -r1.1.2.3 tree.hh
--- gcc/java/tree.hh 31 Jan 2005 02:26:01 -0000 1.1.2.3
+++ gcc/java/tree.hh 8 Mar 2005 00:19:04 -0000
@@ -1,6 +1,6 @@
// Tree generation.
-// Copyright (C) 2004 Free Software Foundation, Inc.
+// Copyright (C) 2004, 2005 Free Software Foundation, Inc.
//
// This file is part of GCC.
//
@@ -104,7 +104,7 @@
tree wrap_synchronized (tree, tree);
tree add_var (const ref_variable_decl &);
tree build_class_ref (model_type *);
- tree build_class_ref (tree);
+ tree build_class_ref (const std::string &);
tree handle_instanceof (tree, tree);
void handle_inc_dec (tree_code, const ref_expression &);
void handle_op_assignment (tree_code, const ref_expression &,