Added Java 1.1 language features.

From-SVN: r32517
parent e4476d1c
......@@ -374,13 +374,9 @@ check_init (exp, before)
int index = DECL_BIT_INDEX (exp);
if (index >= 0 && ! SET_P (before, index))
{
#if 1
parse_error_context (wfl,
"Variable `%s' may not have been initialized"
, IDENTIFIER_POINTER (DECL_NAME (exp)));
#else
error_with_decl (exp, "variable may be used uninitialized");
#endif
parse_error_context
(wfl, "Variable `%s' may not have been initialized",
IDENTIFIER_POINTER (DECL_NAME (exp)));
/* Suppress further errors. */
DECL_BIT_INDEX (exp) = -1;
}
......@@ -388,11 +384,20 @@ check_init (exp, before)
break;
case MODIFY_EXPR:
tmp = TREE_OPERAND (exp, 0);
if (TREE_CODE (tmp) == VAR_DECL && ! FIELD_STATIC (tmp))
/* We're interested in variable declaration and parameter
declaration when they're declared with the `final' modifier. */
if ((TREE_CODE (tmp) == VAR_DECL && ! FIELD_STATIC (tmp))
|| (TREE_CODE (tmp) == PARM_DECL && LOCAL_FINAL (tmp)))
{
int index;
check_init (TREE_OPERAND (exp, 1), before);
index = DECL_BIT_INDEX (tmp);
/* A final local already assigned or a final parameter
assigned must be reported as errors */
if (LOCAL_FINAL (tmp)
&& (index == -1 || TREE_CODE (tmp) == PARM_DECL))
parse_error_context (wfl, "Can't assign here a value to the `final' variable `%s'", IDENTIFIER_POINTER (DECL_NAME (tmp)));
if (index >= 0)
SET_BIT (before, index);
/* Minor optimization. See comment for start_current_locals. */
......
......@@ -282,6 +282,7 @@ make_class ()
#else
TYPE_BINFO (type) = make_tree_vec (6);
#endif
MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC (type);
pop_obstacks ();
return type;
......@@ -395,6 +396,7 @@ set_super_info (access_flags, this_class, super_class, interfaces_count)
if (access_flags & ACC_SUPER) CLASS_SUPER (class_decl) = 1;
if (access_flags & ACC_INTERFACE) CLASS_INTERFACE (class_decl) = 1;
if (access_flags & ACC_ABSTRACT) CLASS_ABSTRACT (class_decl) = 1;
if (access_flags & ACC_STATIC) CLASS_STATIC (class_decl) = 1;
}
/* Return length of inheritance chain of CLAS, where java.lang.Object is 0,
......@@ -460,6 +462,27 @@ inherits_from_p (type1, type2)
return 0;
}
/* Return a 1 iff TYPE1 is an enclosing context for TYPE2 */
int
enclosing_context_p (type1, type2)
tree type1, type2;
{
if (!INNER_CLASS_TYPE_P (type2))
return 0;
for (type2 = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type2)));
type2;
type2 = (INNER_CLASS_TYPE_P (type2) ?
TREE_TYPE (DECL_CONTEXT (TYPE_NAME (type2))) : NULL_TREE))
{
if (type2 == type1)
return 1;
}
return 0;
}
static void
add_interface_do (basetype_vec, interface_class, i)
tree basetype_vec, interface_class;
......@@ -1016,6 +1039,8 @@ get_access_flags_from_decl (decl)
access_flags |= ACC_INTERFACE;
if (CLASS_ABSTRACT (decl))
access_flags |= ACC_ABSTRACT;
if (CLASS_STATIC (decl))
access_flags |= ACC_STATIC;
return access_flags;
}
if (TREE_CODE (decl) == FUNCTION_DECL)
......@@ -1457,8 +1482,7 @@ is_compiled_class (class)
if (class == current_class)
return 2;
seen_in_zip = (TYPE_LANG_SPECIFIC (class) && TYPE_LANG_SPECIFIC (class)->jcf
&& TYPE_LANG_SPECIFIC (class)->jcf->seen_in_zip);
seen_in_zip = (TYPE_JCF (class) && TYPE_JCF (class)->seen_in_zip);
if (CLASS_FROM_CURRENTLY_COMPILED_SOURCE_P (class) || seen_in_zip)
{
/* The class was seen in the current ZIP file and will be
......@@ -1635,6 +1659,9 @@ push_super_field (this_class, super_class)
tree this_class, super_class;
{
tree base_decl;
/* Don't insert the field if we're just re-laying the class out. */
if (TYPE_FIELDS (this_class) && !DECL_NAME (TYPE_FIELDS (this_class)))
return;
push_obstacks (&permanent_obstack, &permanent_obstack);
base_decl = build_decl (FIELD_DECL, NULL_TREE, super_class);
pop_obstacks ();
......@@ -1668,7 +1695,8 @@ maybe_layout_super_class (super_class, this_class)
super_class = TREE_TYPE (super_class);
else
{
super_class = do_resolve_class (super_class, NULL_TREE, this_class);
super_class = do_resolve_class (NULL_TREE, /* FIXME? */
super_class, NULL_TREE, this_class);
if (!super_class)
return NULL_TREE; /* FIXME, NULL_TREE not checked by caller. */
super_class = TREE_TYPE (super_class);
......@@ -1684,8 +1712,36 @@ void
layout_class (this_class)
tree this_class;
{
static tree list = NULL_TREE;
tree super_class = CLASSTYPE_SUPER (this_class);
tree field;
list = tree_cons (this_class, NULL_TREE, list);
if (CLASS_BEING_LAIDOUT (this_class))
{
char buffer [1024];
tree current;
sprintf (buffer, " with `%s'",
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class))));
obstack_grow (&temporary_obstack, buffer, strlen (buffer));
for (current = TREE_CHAIN (list); current;
current = TREE_CHAIN (current))
{
tree decl = TYPE_NAME (TREE_PURPOSE (current));
sprintf (buffer, "\n which inherits from `%s' (%s:%d)",
IDENTIFIER_POINTER (DECL_NAME (decl)),
DECL_SOURCE_FILE (decl),
DECL_SOURCE_LINE (decl));
obstack_grow (&temporary_obstack, buffer, strlen (buffer));
}
obstack_1grow (&temporary_obstack, '\0');
cyclic_inheritance_report = obstack_finish (&temporary_obstack);
TYPE_SIZE (this_class) = error_mark_node;
return;
}
CLASS_BEING_LAIDOUT (this_class) = 1;
if (super_class)
{
......@@ -1693,6 +1749,8 @@ layout_class (this_class)
if (TREE_CODE (TYPE_SIZE (super_class)) == ERROR_MARK)
{
TYPE_SIZE (this_class) = error_mark_node;
CLASS_BEING_LAIDOUT (this_class) = 0;
list = TREE_CHAIN (list);
return;
}
if (TYPE_SIZE (this_class) == NULL_TREE)
......@@ -1714,6 +1772,9 @@ layout_class (this_class)
/* Convert the size back to an SI integer value */
TYPE_SIZE_UNIT (this_class) =
fold (convert (int_type_node, TYPE_SIZE_UNIT (this_class)));
CLASS_BEING_LAIDOUT (this_class) = 0;
list = TREE_CHAIN (list);
}
void
......@@ -1772,8 +1833,7 @@ layout_class_method (this_class, super_class, method_decl, dtable_count)
if (method_name_is_wfl)
method_name = java_get_real_method_name (method_decl);
if (method_name != init_identifier_node
&& method_name != finit_identifier_node)
if (!ID_INIT_P (method_name) && !ID_FINIT_P (method_name))
{
int encoded_len
= unicode_mangling_length (IDENTIFIER_POINTER (method_name),
......@@ -1794,7 +1854,7 @@ layout_class_method (this_class, super_class, method_decl, dtable_count)
}
obstack_grow (&temporary_obstack, "__", 2);
if (method_name == finit_identifier_node)
if (ID_FINIT_P (method_name))
obstack_grow (&temporary_obstack, "finit", 5);
append_gpp_mangled_type (&temporary_obstack, this_class);
TREE_PUBLIC (method_decl) = 1;
......@@ -1856,11 +1916,11 @@ layout_class_method (this_class, super_class, method_decl, dtable_count)
it's an interface method that isn't clinit. */
if (! METHOD_ABSTRACT (method_decl)
|| (CLASS_INTERFACE (TYPE_NAME (this_class))
&& (IS_CLINIT (method_decl))))
&& (DECL_CLINIT_P (method_decl))))
make_function_rtl (method_decl);
obstack_free (&temporary_obstack, asm_name);
if (method_name == init_identifier_node)
if (ID_INIT_P (method_name))
{
const char *p = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (this_class)));
for (ptr = p; *ptr; )
......
......@@ -390,7 +390,10 @@ alloc_class_constant (clas)
static tree
build_constant_data_ref ()
{
if (current_constant_pool_data_ref == NULL_TREE)
if (TYPE_CPOOL_DATA_REF (current_class))
current_constant_pool_data_ref = TYPE_CPOOL_DATA_REF (current_class);
else if (current_constant_pool_data_ref == NULL_TREE)
{
tree decl;
tree decl_name = mangled_classname ("_CD_", current_class);
......@@ -401,7 +404,7 @@ build_constant_data_ref ()
TREE_STATIC (decl) = 1;
make_decl_rtl (decl, NULL, 1);
pop_obstacks ();
current_constant_pool_data_ref
TYPE_CPOOL_DATA_REF (current_class) = current_constant_pool_data_ref
= build1 (ADDR_EXPR, ptr_type_node, decl);
}
return current_constant_pool_data_ref;
......
......@@ -360,7 +360,7 @@ tree length_identifier_node;
tree this_identifier_node;
tree super_identifier_node;
tree continue_identifier_node;
tree access0_identifier_node; /* 1.1 */
tree end_params_node;
/* References to internal libjava functions we use. */
......@@ -460,6 +460,7 @@ init_decl_processing ()
error_mark_node = make_node (ERROR_MARK);
TREE_TYPE (error_mark_node) = error_mark_node;
initialize_sizetypes ();
/* Create sizetype first - needed for other types. */
initialize_sizetypes ();
set_sizetype (make_unsigned_type (POINTER_SIZE));
......@@ -601,6 +602,7 @@ init_decl_processing ()
this_identifier_node = get_identifier ("this");
super_identifier_node = get_identifier ("super");
continue_identifier_node = get_identifier ("continue");
access0_identifier_node = get_identifier ("access$0");
/* for lack of a better place to put this stub call */
init_expr_processing();
......@@ -965,8 +967,9 @@ pushdecl (x)
register tree t;
register tree name = DECL_NAME (x);
register struct binding_level *b = current_binding_level;
DECL_CONTEXT (x) = current_function_decl;
if (TREE_CODE (x) != TYPE_DECL)
DECL_CONTEXT (x) = current_function_decl;
if (name)
{
const char *file;
......@@ -1629,7 +1632,6 @@ build_result_decl (fndecl)
return (DECL_RESULT (fndecl) = build_decl (RESULT_DECL, NULL_TREE, restype));
}
/* Called for every element in DECL_FUNCTION_INIT_TEST_TABLE in order
to emit initialization code for each test flag. */
......
......@@ -1263,6 +1263,16 @@ lookup_field (typep, name)
if (DECL_NAME (field) == name)
return field;
/* If *typep is an innerclass, lookup the field in its enclosing
contexts */
if (INNER_CLASS_TYPE_P (*typep))
{
tree outer_type = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (*typep)));
if ((field = lookup_field (&outer_type, name)))
return field;
}
/* Process implemented interfaces. */
basetype_vec = TYPE_BINFO_BASETYPES (*typep);
n = TREE_VEC_LENGTH (basetype_vec);
......@@ -1721,7 +1731,7 @@ expand_invoke (opcode, method_ref_index, nargs)
}
layout_class_methods (self_type);
if (method_name == init_identifier_node)
if (ID_INIT_P (method_name))
method = lookup_java_constructor (CLASS_TO_HANDLE_TYPE (self_type),
method_signature);
else
......@@ -1881,7 +1891,7 @@ expand_java_field_op (is_static, is_putting, field_ref_index)
"assignment to final field `%s' not in field's class");
else if (FIELD_STATIC (field_decl))
{
if (!IS_CLINIT (current_function_decl))
if (!DECL_CLINIT_P (current_function_decl))
error_with_decl (field_decl,
"assignment to final static field `%s' not in class initializer");
}
......@@ -2013,10 +2023,8 @@ java_lang_expand_expr (exp, target, tmode, modifier)
if (TREE_CONSTANT (init)
&& ilength >= 10 && JPRIMITIVE_TYPE_P (element_type))
{
tree init_decl;
push_obstacks (&permanent_obstack, &permanent_obstack);
init_decl = build_decl (VAR_DECL, generate_name (),
TREE_TYPE (init));
tree init_decl = build_decl (VAR_DECL, generate_name (),
TREE_TYPE (init));
pushdecl_top_level (init_decl);
TREE_STATIC (init_decl) = 1;
DECL_INITIAL (init_decl) = init;
......@@ -2024,7 +2032,6 @@ java_lang_expand_expr (exp, target, tmode, modifier)
TREE_READONLY (init_decl) = 1;
TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (init_decl)) = 1;
make_decl_rtl (init_decl, NULL, 1);
pop_obstacks ();
init = init_decl;
}
expand_assignment (build (COMPONENT_REF, TREE_TYPE (data_fld),
......
......@@ -22,6 +22,13 @@ DEFTREECODE (UNARY_PLUS_EXPR, "unary_plus_expr", '1', 1)
Once patched, the node will bear the type of the created array. */
DEFTREECODE (NEW_ARRAY_EXPR, "new_array_expr", 'e', 3)
/* New anonymous array creation expression.
Operand 0 is the base type of the anonymous array.
Operand 1 is the signature of the dimensions this array contains.
Operand 2 is the anonymous array initializer.
Once patched, the node will bear the type of the created array. */
DEFTREECODE (NEW_ANONYMOUS_ARRAY_EXPR, "new_anonymous_array", 'e', 3)
/* New class creation expression.
Operand 0 is the name of the class to be created
Operand 1 is the argument list used to select a constructor.
......@@ -75,3 +82,14 @@ DEFTREECODE (INSTANCEOF_EXPR, "instanceof", 'e', 2)
when the node is created.
Operand 1 is a CONSTRUCTOR node. */
DEFTREECODE (NEW_ARRAY_INIT, "new_array_init", '1', 1)
/* Class literal.
Operand 0 is the name of the class we're trying to build a
reference from. */
DEFTREECODE (CLASS_LITERAL, "class_litteral", '1', 1)
/* Instance initializer.
Operand 0 contains the intance initializer statement. This tree node
is used for context detection, so that special rules can be
enforced. */
DEFTREECODE (INSTANCE_INITIALIZERS_EXPR, "instance_initializers_expr", '1', 1)
......@@ -294,6 +294,38 @@ DEFUN(utf8_equal_string, (jcf, index, value),
else \
JCF_SKIP (jcf, 4 * n); }
#define HANDLE_INNERCLASSES_ATTRIBUTE(COUNT) \
{ int n = (COUNT); \
COMMON_HANDLE_ATTRIBUTE(jcf, attribute_name, attribute_length); \
while (n--) \
{ \
uint16 inner_class_info_index = JCF_readu2 (jcf); \
uint16 outer_class_info_index = JCF_readu2 (jcf); \
uint16 inner_name_index = JCF_readu2 (jcf); \
uint16 inner_class_access_flags = JCF_readu2 (jcf); \
\
if (flag_print_class_info) \
{ \
fprintf (out, "\n class: "); \
if (flag_print_constant_pool) \
fprintf (out, "%d=", inner_class_info_index); \
print_constant_terse (out, jcf, \
inner_class_info_index, CONSTANT_Class); \
fprintf (out, " (%d=", inner_name_index); \
print_constant_terse (out, jcf, inner_name_index, CONSTANT_Utf8); \
fprintf (out, "), access flags: 0x%x", inner_class_access_flags); \
print_access_flags (out, inner_class_access_flags, 'c'); \
fprintf (out, ", outer class: "); \
if (flag_print_constant_pool) \
fprintf (out, "%d=", outer_class_info_index); \
print_constant_terse (out, jcf, \
outer_class_info_index, CONSTANT_Class); \
} \
} \
if (flag_print_class_info) \
fputc ('\n', out); \
}
#define PROCESS_OTHER_ATTRIBUTE(JCF, INDEX, LENGTH) \
{ COMMON_HANDLE_ATTRIBUTE(JCF, INDEX, LENGTH); \
fputc ('\n', out); JCF_SKIP (JCF, LENGTH); }
......
......@@ -185,6 +185,32 @@ set_source_filename (jcf, index)
DECL_FUNCTION_THROWS (current_method) = nreverse (list); \
}
/* Link seen inner classes to their outer context and register the
inner class to its outer context. They will be later loaded. */
#define HANDLE_INNERCLASSES_ATTRIBUTE(COUNT) \
{ \
int c = (count); \
while (c--) \
{ \
tree class = get_class_constant (jcf, JCF_readu2 (jcf)); \
if (!CLASS_COMPLETE_P (class)) \
{ \
tree outer = TYPE_NAME (get_class_constant (jcf, \
JCF_readu2 (jcf))); \
tree alias = get_name_constant (jcf, JCF_readu2 (jcf)); \
tree decl = TYPE_NAME (class); \
JCF_SKIP (jcf, 2); \
IDENTIFIER_GLOBAL_VALUE (alias) = decl; \
DECL_CONTEXT (decl) = outer; \
DECL_INNER_CLASS_LIST (outer) = \
tree_cons (decl, alias, DECL_INNER_CLASS_LIST (outer)); \
CLASS_COMPLETE_P (class) = 1; \
} \
else \
JCF_SKIP (jcf, 6); \
} \
}
#include "jcf-reader.c"
static int yydebug;
......@@ -565,6 +591,7 @@ jcf_parse (jcf)
JCF* jcf;
{
int i, code;
tree current;
if (jcf_parse_preamble (jcf) != 0)
fatal ("Not a valid Java .class file.\n");
......@@ -617,23 +644,21 @@ jcf_parse (jcf)
else
all_class_list = tree_cons (NULL_TREE,
TYPE_NAME (current_class), all_class_list );
/* And if we came accross inner classes, load them now. */
for (current = DECL_INNER_CLASS_LIST (TYPE_NAME (current_class)); current;
current = TREE_CHAIN (current))
load_class (DECL_NAME (TREE_PURPOSE (current)), 1);
pop_obstacks ();
}
void
init_outgoing_cpool ()
{
current_constant_pool_data_ref = NULL_TREE;
if (outgoing_cpool == NULL)
{
static CPool outgoing_cpool_buffer;
outgoing_cpool = &outgoing_cpool_buffer;
CPOOL_INIT(outgoing_cpool);
}
else
{
CPOOL_REINIT(outgoing_cpool);
}
current_constant_pool_data_ref = NULL_TREE;
outgoing_cpool = (struct CPool *)xmalloc (sizeof (struct CPool));
bzero (outgoing_cpool, sizeof (struct CPool));
}
static void
......@@ -737,6 +762,7 @@ parse_source_file (file)
java_parse_abort_on_error ();
java_fix_constructors (); /* Fix the constructors */
java_parse_abort_on_error ();
java_reorder_fields (); /* Reorder the fields */
}
static int
......@@ -893,7 +919,7 @@ parse_zip_file_entries (void)
continue;
class = lookup_class (get_identifier (ZIPDIR_FILENAME (zdir)));
current_jcf = TYPE_LANG_SPECIFIC (class)->jcf;
current_jcf = TYPE_JCF (class);
current_class = class;
if ( !CLASS_LOADED_P (class))
......@@ -970,9 +996,7 @@ static void process_zip_dir()
jcf->classname = class_name;
jcf->filename = file_name;
TYPE_LANG_SPECIFIC (class) =
(struct lang_type *) perm_calloc (1, sizeof (struct lang_type));
TYPE_LANG_SPECIFIC (class)->jcf = jcf;
TYPE_JCF (class) = jcf;
}
}
......@@ -994,10 +1018,10 @@ DEFUN(find_in_current_zip, (name, length, jcf),
class = TREE_TYPE (icv);
/* Doesn't have jcf specific info ? It's not ours */
if (!TYPE_LANG_SPECIFIC (class) || !TYPE_LANG_SPECIFIC (class)->jcf)
if (!TYPE_JCF (class))
return 0;
*jcf = local_jcf = TYPE_LANG_SPECIFIC (class)->jcf;
*jcf = local_jcf = TYPE_JCF (class);
fseek (local_jcf->read_state, local_jcf->zip_offset, SEEK_SET);
return 1;
}
......
......@@ -34,6 +34,15 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
#define GET_ENV_PATH_LIST(VAR,NAME) do { (VAR) = getenv (NAME); } while (0)
#endif
/* By default, colon separates directories in a path. */
#ifndef PATH_SEPARATOR
#define PATH_SEPARATOR ':'
#endif
#ifndef DIR_SEPARATOR
#define DIR_SEPARATOR '/'
#endif
#ifndef DIR_UP
#define DIR_UP ".."
#endif
......
......@@ -130,6 +130,14 @@ DEFUN(get_attribute, (jcf),
}
else
#endif
#ifdef HANDLE_INNERCLASSES_ATTRIBUTE
if (name_length == 12 && memcmp (name_data, "InnerClasses", 12) == 0)
{
uint16 count = JCF_readu2 (jcf);
HANDLE_INNERCLASSES_ATTRIBUTE (count);
}
else
#endif
{
#ifdef PROCESS_OTHER_ATTRIBUTE
PROCESS_OTHER_ATTRIBUTE(jcf, attribute_name, attribute_length);
......
......@@ -35,6 +35,10 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
#include "buffer.h"
#include "toplev.h"
#ifndef DIR_SEPARATOR
#define DIR_SEPARATOR '/'
#endif
extern struct obstack temporary_obstack;
/* Base directory in which `.class' files should be written.
......@@ -335,6 +339,9 @@ static void emit_goto PARAMS ((struct jcf_block *, struct jcf_partial *));
static void emit_jsr PARAMS ((struct jcf_block *, struct jcf_partial *));
static void call_cleanups PARAMS ((struct jcf_block *, struct jcf_partial *));
static char *make_class_file_name PARAMS ((tree));
static unsigned char *append_synthetic_attribute PARAMS ((struct jcf_partial *));
static void append_innerclasses_attribute PARAMS ((struct jcf_partial *, tree));
static void append_innerclasses_attribute_entry PARAMS ((struct jcf_partial *, tree, tree));
/* Utility macros for appending (big-endian) data to a buffer.
We assume a local variable 'ptr' points into where we want to
......@@ -665,6 +672,11 @@ get_access_flags (decl)
flags |= ACC_ABSTRACT;
if (CLASS_INTERFACE (decl))
flags |= ACC_INTERFACE;
if (CLASS_STATIC (decl))
flags |= ACC_STATIC;
if (ANONYMOUS_CLASS_P (TREE_TYPE (decl))
|| LOCAL_CLASS_P (TREE_TYPE (decl)))
flags |= ACC_PRIVATE;
}
else
fatal ("internal error - bad argument to get_access_flags");
......@@ -1159,8 +1171,7 @@ generate_bytecode_conditional (exp, true_label, false_label,
}
break;
case TRUTH_NOT_EXPR:
generate_bytecode_conditional (TREE_OPERAND (exp, 0),
false_label, true_label,
generate_bytecode_conditional (TREE_OPERAND (exp, 0), false_label, true_label,
! true_branch_first, state);
break;
case TRUTH_ANDIF_EXPR:
......@@ -1238,7 +1249,7 @@ generate_bytecode_conditional (exp, true_label, false_label,
}
if (integer_zerop (exp1) || integer_zerop (exp0))
{
generate_bytecode_insns (integer_zerop (exp1) ? exp0 : exp1,
generate_bytecode_insns (integer_zerop (exp1) ? exp0 : exp0,
STACK_TARGET, state);
op = op + (OPCODE_ifnull - OPCODE_if_acmpeq);
negop = (op & 1) ? op - 1 : op + 1;
......@@ -1622,7 +1633,6 @@ generate_bytecode_insns (exp, target, state)
define_jcf_label (else_label, state);
generate_bytecode_insns (TREE_OPERAND (exp, 2), target, state);
define_jcf_label (end_label, state);
/* COND_EXPR can be used in a binop. The stack must be adjusted. */
if (TREE_TYPE (exp) != void_type_node)
NOTE_POP (TYPE_IS_WIDE (TREE_TYPE (exp)) ? 2 : 1);
......@@ -2131,6 +2141,9 @@ generate_bytecode_insns (exp, target, state)
OP2 (index);
}
break;
case SAVE_EXPR:
generate_bytecode_insns (TREE_OPERAND (exp, 0), STACK_TARGET, state);
break;
case CONVERT_EXPR:
case NOP_EXPR:
case FLOAT_EXPR:
......@@ -2535,11 +2548,6 @@ generate_bytecode_insns (exp, target, state)
else
OP1 (OPCODE_invokevirtual);
OP2 (index);
if (interface)
{
OP1 (nargs);
OP1 (0);
}
f = TREE_TYPE (TREE_TYPE (f));
if (TREE_CODE (f) != VOID_TYPE)
{
......@@ -2549,6 +2557,11 @@ generate_bytecode_insns (exp, target, state)
else
NOTE_PUSH (size);
}
if (interface)
{
OP1 (nargs);
OP1 (0);
}
break;
}
}
......@@ -2836,16 +2849,24 @@ generate_classfile (clas, state)
for (part = TYPE_FIELDS (clas); part; part = TREE_CHAIN (part))
{
int have_value;
int have_value, attr_count = 0;
if (DECL_NAME (part) == NULL_TREE || DECL_ARTIFICIAL (part))
continue;
ptr = append_chunk (NULL, 8, state);
i = get_access_flags (part); PUT2 (i);
i = find_utf8_constant (&state->cpool, DECL_NAME (part)); PUT2 (i);
i = find_utf8_constant (&state->cpool, build_java_signature (TREE_TYPE (part)));
i = find_utf8_constant (&state->cpool,
build_java_signature (TREE_TYPE (part)));
PUT2(i);
have_value = DECL_INITIAL (part) != NULL_TREE && FIELD_STATIC (part);
PUT2 (have_value); /* attributes_count */
have_value = DECL_INITIAL (part) != NULL_TREE && FIELD_STATIC (part)
&& TREE_CODE (TREE_TYPE (part)) != POINTER_TYPE;
if (have_value)
attr_count++;
if (FIELD_THISN (part) || FIELD_LOCAL_ALIAS (part))
attr_count++;
PUT2 (attr_count); /* attributes_count */
if (have_value)
{
tree init = DECL_INITIAL (part);
......@@ -2858,6 +2879,9 @@ generate_classfile (clas, state)
PUT4 (2); /* attribute_length */
i = find_constant_index (init, state); PUT2 (i);
}
/* Emit the "Synthetic" attribute for val$<x> and this$<n> fields. */
if (FIELD_THISN (part) || FIELD_LOCAL_ALIAS (part))
ptr = append_synthetic_attribute (state);
fields_count++;
}
ptr = fields_count_ptr; UNSAFE_PUT2 (fields_count);
......@@ -2875,6 +2899,7 @@ generate_classfile (clas, state)
: DECL_NAME (part);
tree type = TREE_TYPE (part);
tree save_function = current_function_decl;
int synthetic_p = 0;
current_function_decl = part;
ptr = append_chunk (NULL, 8, state);
i = get_access_flags (part); PUT2 (i);
......@@ -2882,7 +2907,20 @@ generate_classfile (clas, state)
i = find_utf8_constant (&state->cpool, build_java_signature (type));
PUT2 (i);
i = (body != NULL_TREE) + (DECL_FUNCTION_THROWS (part) != NULL_TREE);
/* Make room for the Synthetic attribute (of zero length.) */
if (DECL_FINIT_P (part)
|| OUTER_FIELD_ACCESS_IDENTIFIER_P (DECL_NAME (part)))
{
i++;
synthetic_p = 1;
}
PUT2 (i); /* attributes_count */
if (synthetic_p)
ptr = append_synthetic_attribute (state);
if (body != NULL_TREE)
{
int code_attributes_count = 0;
......@@ -2956,7 +2994,8 @@ generate_classfile (clas, state)
if (state->linenumber_count > 0)
{
static tree LineNumberTable_node = NULL_TREE;
ptr = append_chunk (NULL, 8 + 4 * state->linenumber_count, state);
ptr = append_chunk (NULL,
8 + 4 * state->linenumber_count, state);
if (LineNumberTable_node == NULL_TREE)
LineNumberTable_node = get_identifier ("LineNumberTable");
i = find_utf8_constant (&state->cpool, LineNumberTable_node);
......@@ -3031,7 +3070,10 @@ generate_classfile (clas, state)
source_file = ptr+1;
}
ptr = append_chunk (NULL, 10, state);
PUT2 (1); /* attributes_count */
i = ((INNER_CLASS_TYPE_P (clas)
|| DECL_INNER_CLASS_LIST (TYPE_NAME (clas))) ? 2 : 1);
PUT2 (i); /* attributes_count */
/* generate the SourceFile attribute. */
if (SourceFile_node == NULL_TREE)
......@@ -3041,6 +3083,7 @@ generate_classfile (clas, state)
PUT4 (2);
i = find_utf8_constant (&state->cpool, get_identifier (source_file));
PUT2 (i);
append_innerclasses_attribute (state, clas);
/* New finally generate the contents of the constant pool chunk. */
i = count_constant_pool_bytes (&state->cpool);
......@@ -3051,6 +3094,103 @@ generate_classfile (clas, state)
return state->first;
}
static unsigned char *
append_synthetic_attribute (state)
struct jcf_partial *state;
{
static tree Synthetic_node = NULL_TREE;
unsigned char *ptr = append_chunk (NULL, 6, state);
int i;
if (Synthetic_node == NULL_TREE)
Synthetic_node = get_identifier ("Synthetic");
i = find_utf8_constant (&state->cpool, Synthetic_node);
PUT2 (i); /* Attribute string index */
PUT4 (0); /* Attribute length */
return ptr;
}
static void
append_innerclasses_attribute (state, class)
struct jcf_partial *state;
tree class;
{
static tree InnerClasses_node = NULL_TREE;
tree orig_decl = TYPE_NAME (class);
tree current, decl;
int length = 0, i;
unsigned char *ptr, *length_marker, *number_marker;
if (!INNER_CLASS_TYPE_P (class) && !DECL_INNER_CLASS_LIST (orig_decl))
return;
ptr = append_chunk (NULL, 8, state); /* 2+4+2 */
if (InnerClasses_node == NULL_TREE)
InnerClasses_node = get_identifier ("InnerClasses");
i = find_utf8_constant (&state->cpool, InnerClasses_node);
PUT2 (i);
length_marker = ptr; PUT4 (0); /* length, to be later patched */
number_marker = ptr; PUT2 (0); /* number of classes, tblp */
/* Generate the entries: all inner classes visible from the one we
process: itself, up and down. */
while (class && INNER_CLASS_TYPE_P (class))
{
char *n;
decl = TYPE_NAME (class);
n = IDENTIFIER_POINTER (DECL_NAME (decl)) +
IDENTIFIER_LENGTH (DECL_NAME (decl));
while (n[-1] != '$')
n--;
append_innerclasses_attribute_entry (state, decl, get_identifier (n));
length++;
class = TREE_TYPE (DECL_CONTEXT (TYPE_NAME (class)));
}
decl = orig_decl;
for (current = DECL_INNER_CLASS_LIST (decl);
current; current = TREE_CHAIN (current))
{
append_innerclasses_attribute_entry (state, TREE_PURPOSE (current),
TREE_VALUE (current));
length++;
}
ptr = length_marker; PUT4 (8*length+2);
ptr = number_marker; PUT2 (length);
}
static void
append_innerclasses_attribute_entry (state, decl, name)
struct jcf_partial *state;
tree decl, name;
{
static tree anonymous_name = NULL_TREE;
int icii, ocii, ini, icaf;
unsigned char *ptr = append_chunk (NULL, 8, state);
if (!anonymous_name)
anonymous_name = get_identifier ("");
icii = find_class_constant (&state->cpool, TREE_TYPE (decl));
ocii = find_class_constant (&state->cpool, TREE_TYPE (DECL_CONTEXT (decl)));
/* The specs are saying that if the class is anonymous,
inner_name_index must be zero. But the implementation makes it
point to an empty string. */
ini = find_utf8_constant (&state->cpool,
(ANONYMOUS_CLASS_P (TREE_TYPE (decl)) ?
anonymous_name : name));
icaf = get_access_flags (decl);
PUT2 (icii); PUT2 (ocii); PUT2 (ini); PUT2 (icaf);
}
static char *
make_class_file_name (clas)
tree clas;
......
......@@ -413,7 +413,7 @@ put_decl_node (node)
}
#endif
if (TREE_CODE (node) == FUNCTION_DECL
&& DECL_NAME (node) == init_identifier_node
&& DECL_INIT_P (node)
&& !DECL_ARTIFICIAL (node) && current_class)
put_decl_node (TYPE_NAME (current_class));
else
......
......@@ -72,6 +72,10 @@ java_init_lex ()
java_lang_id = get_identifier ("java.lang");
if (!java_lang_cloneable)
java_lang_cloneable = get_identifier ("java.lang.Cloneable");
if (!inst_id)
inst_id = get_identifier ("inst$");
if (!wpv_id)
wpv_id = get_identifier ("write_parm_value$");
if (!java_lang_imported)
{
......@@ -95,9 +99,9 @@ java_init_lex ()
if (!wfl_to_string)
wfl_to_string = build_expr_wfl (get_identifier ("toString"), NULL, 0, 0);
ctxp->static_initialized = ctxp->non_static_initialized =
ctxp->incomplete_class = NULL_TREE;
CPC_INITIALIZER_LIST (ctxp) = CPC_STATIC_INITIALIZER_LIST (ctxp) =
CPC_INSTANCE_INITIALIZER_LIST (ctxp) = ctxp->incomplete_class = NULL_TREE;
bzero ((PTR) ctxp->modifier_ctx, 11*sizeof (ctxp->modifier_ctx[0]));
bzero ((PTR) current_jcf, sizeof (JCF));
ctxp->current_parsed_class = NULL;
......
......@@ -56,7 +56,7 @@ unicode_mangling_length (name, len)
need_escapes += num_chars == 0;
else if (ch == '_')
underscores++;
else if ((ch < 'a' || ch > 'z') && (ch < 'A' || ch > 'Z'))
else if (ch != '$' && (ch < 'a' || ch > 'z') && (ch < 'A' || ch > 'Z'))
need_escapes++;
num_chars++;
}
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -611,12 +611,8 @@ build_java_signature (type)
push_obstacks (&permanent_obstack, &permanent_obstack);
while (TREE_CODE (type) == POINTER_TYPE)
type = TREE_TYPE (type);
if (TYPE_LANG_SPECIFIC (type) == NULL)
{
TYPE_LANG_SPECIFIC (type) = (struct lang_type *)
perm_calloc (1, sizeof (struct lang_type));
}
sig = TYPE_LANG_SPECIFIC (type)->signature;
MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC (type);
sig = TYPE_SIGNATURE (type);
if (sig == NULL_TREE)
{
char sg[2];
......@@ -682,7 +678,7 @@ build_java_signature (type)
default:
fatal ("internal error - build_java_signature passed invalid type");
}
TYPE_LANG_SPECIFIC (type)->signature = sig;
TYPE_SIGNATURE (type) = sig;
}
pop_obstacks ();
return sig;
......@@ -698,16 +694,11 @@ set_java_signature (type, sig)
tree old_sig;
while (TREE_CODE (type) == POINTER_TYPE)
type = TREE_TYPE (type);
if (TYPE_LANG_SPECIFIC (type) == NULL)
{
TYPE_LANG_SPECIFIC (type) = (struct lang_type *)
perm_calloc (1, sizeof (struct lang_type));
}
old_sig = TYPE_LANG_SPECIFIC (type)->signature;
MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC (type);
old_sig = TYPE_SIGNATURE (type);
if (old_sig != NULL_TREE && old_sig != sig)
fatal ("internal error - set_java_signature");
TYPE_LANG_SPECIFIC (type)->signature = sig;
TYPE_SIGNATURE (type) = sig;
#if 0 /* careful about METHOD_TYPE */
if (IDENTIFIER_SIGNATURE_TYPE (sig) == NULL_TREE && TREE_PERMANENT (type))
IDENTIFIER_SIGNATURE_TYPE (sig) = type;
......
......@@ -940,11 +940,10 @@ verify_jvm_instructions (jcf, byte_ops, length)
pop_argument_types (TYPE_ARG_TYPES (method_type));
/* Can't invoke <clinit> */
if (method_name == clinit_identifier_node)
if (ID_CLINIT_P (method_name))
VERIFICATION_ERROR ("invoke opcode can't invoke <clinit>");
/* Apart invokespecial, can't invoke <init> */
if (op_code != OPCODE_invokespecial
&& method_name == init_identifier_node)
if (op_code != OPCODE_invokespecial && ID_INIT_P (method_name))
VERIFICATION_ERROR ("invoke opcode can't invoke <init>");
if (op_code != OPCODE_invokestatic)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment