Merge from Cygnus internal source tree.

From-SVN: r23025
This commit is contained in:
Per Bothner 1998-10-12 05:43:53 -07:00
parent 8376a32eb1
commit e4de5a1022
10 changed files with 1787 additions and 562 deletions

View File

@ -148,10 +148,12 @@ ALL_CFLAGS = $(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) $(CFLAGS) $(XCFLAGS)
# Likewise.
ALL_CPPFLAGS = $(CPPFLAGS) $(X_CPPFLAGS) $(T_CPPFLAGS)
# CYGNUS LOCAL: SUBDIR_USE_ALLOCA is different from FSF.
# Even if ALLOCA is set, don't use it if compiling with GCC.
SUBDIR_OBSTACK = `if [ x$(OBSTACK) != x ]; then echo ../$(OBSTACK); else true; fi`
SUBDIR_USE_ALLOCA = `case "${CC}" in "${OLDCC}") if [ x$(ALLOCA) != x ]; then echo ../$(ALLOCA); else true; fi ;; esac`
#SUBDIR_USE_ALLOCA = `case "${CC}" in "${OLDCC}") if [ x$(ALLOCA) != x ]; then echo ../$(ALLOCA); else true; fi ;; esac`
SUBDIR_USE_ALLOCA = `if [ x$(ALLOCA) != x ]; then echo ../$(ALLOCA); else true; fi`
SUBDIR_MALLOC = `if [ x$(MALLOC) != x ]; then echo ../$(MALLOC); else true; fi`
# How to link with both our special library facilities
@ -226,19 +228,22 @@ RTL_H = $(srcdir)/../rtl.h $(srcdir)/../rtl.def \
$(srcdir)/../machmode.h $(srcdir)/../machmode.def
EXPR_H = $(srcdir)/../expr.h ../insn-codes.h
# CYGNUS LOCAL: we put these files into the build dir.
PARSE_C = parse.c
PARSE_SCAN_C = parse-scan.c
PARSE_H = $(srcdir)/parse.h
PARSE_C = $(srcdir)/parse.c
PARSE_SCAN_C = $(srcdir)/parse-scan.c
$(PARSE_C): $(srcdir)/parse.y $(srcdir)/lex.c $(PARSE_H) $(srcdir)/lex.h
$(BISON) -t -v $(BISONFLAGS) $(JAVABISONFLAGS) -o $(PARSE_C) \
$(srcdir)/parse.y
$(PARSE_SCAN_C): $(srcdir)/parse-scan.y $(srcdir)/lex.c $(PARSE_H) \
$(srcdir)/lex.h
$(srcdir)/lex.h
$(BISON) -t -v $(BISONFLAGS) -o $(PARSE_SCAN_C) $(srcdir)/parse-scan.y
lex.c: keyword.h lex.h
lang.o: $(srcdir)/java-tree.def
keyword.h: keyword.gperf
gperf -L KR-C -F ', 0' -p -t -j1 -i 1 -g -o -N java_keyword -k1,3,$$ \
keyword.gperf > keyword.h
@ -258,8 +263,9 @@ TAGS: force
mostlyclean:
rm -f *.o
# CYGNUS LOCAL: Remove these files, as they are in the build dir.
clean: mostlyclean
rm -f parse.c
rm -f parse.c parse-scan.c
force:

View File

@ -36,6 +36,9 @@ struct buffer
#define NULL_BUFFER { (void*) 0, (void*) 0, (void*) 0 }
#define BUFFER_INIT(BUFP) \
((BUFP)->data = NULL, (BUFP)->ptr = NULL, (BUFP)->limit = NULL)
#define BUFFER_LENGTH(BUFP) ((BUFP)->ptr - (BUFP)->data)
#define BUFFER_RESET(BUFP) ((BUFP)->ptr = (BUFP)->data)

View File

@ -161,6 +161,12 @@ method_init_exceptions ()
whole_range.first_child = NULL;
whole_range.next_sibling = NULL;
cache_range_start = 0xFFFFFF;
java_set_exception_lang_code ();
}
void
java_set_exception_lang_code ()
{
set_exception_lang_code (EH_LANG_Java);
set_exception_version_code (1);
}
@ -183,6 +189,32 @@ expand_start_java_handler (range)
expand_eh_region_start ();
}
tree
prepare_eh_table_type (type)
tree type;
{
tree exp;
/* The "type" (metch_info) in a (Java) exception table is one:
* a) NULL - meaning match any type in a try-finally.
* b) a pointer to a (ccmpiled) class (low-order bit 0).
* c) a pointer to the Utf8Const name of the class, plus one
* (which yields a value with low-order bit 1). */
push_obstacks (&permanent_obstack, &permanent_obstack);
if (type == NULL_TREE)
exp = null_pointer_node;
else if (is_compiled_class (type))
exp = build_class_ref (type);
else
exp = fold (build
(PLUS_EXPR, ptr_type_node,
build_utf8_ref (build_internal_class_name (type)),
size_one_node));
pop_obstacks ();
return exp;
}
/* if there are any handlers for this range, isssue end of range,
and then all handler blocks */
void
@ -193,24 +225,8 @@ expand_end_java_handler (range)
expand_start_all_catch ();
for ( ; handler != NULL_TREE; handler = TREE_CHAIN (handler))
{
tree type = TREE_PURPOSE (handler);
tree exp;
/* The "type" (metch_info) in a (Java) exception table is one:
* a) NULL - meaning match any type in a try-finally.
* b) a pointer to a (ccmpiled) class (low-order bit 0).
* c) a pointer to the Utf8Const name of the class, plus one
* (which yields a value with low-order bit 1). */
push_obstacks (&permanent_obstack, &permanent_obstack);
if (type == NULL_TREE)
exp = null_pointer_node;
else if (is_compiled_class (type))
exp = build_class_ref (type);
else
exp = fold (build (PLUS_EXPR, ptr_type_node,
build_utf8_ref (build_internal_class_name (type)),
size_one_node));
pop_obstacks ();
start_catch_handler (exp);
start_catch_handler (prepare_eh_table_type (TREE_PURPOSE (handler)));
/* Push the thrown object on the top of the stack */
expand_goto (TREE_VALUE (handler));
}
expand_end_all_catch ();

View File

@ -460,7 +460,7 @@ java_stack_dup (size, offset)
}
}
/* Calls soft_athrow. Discard the contents of the value stack. */
/* Calls _Jv_Throw. Discard the contents of the value stack. */
tree
build_java_athrow (node)
@ -526,15 +526,16 @@ decode_newarray_type (int atype)
}
}
/* Build a call to soft_badarrayindex(), the ArrayIndexOfBoundsException
exception handler. */
/* Build a call to _Jv_ThrowBadArrayIndex(), the
ArrayIndexOfBoundsException exception handler. */
static tree
build_java_throw_out_of_bounds_exception ()
build_java_throw_out_of_bounds_exception (index)
tree index;
{
tree node = build (CALL_EXPR, int_type_node,
build_address_of (soft_badarrayindex_node),
NULL_TREE, NULL_TREE );
build_tree_list (NULL_TREE, index), NULL_TREE);
TREE_SIDE_EFFECTS (node) = 1; /* Allows expansion within ANDIF */
return (node);
}
@ -629,7 +630,7 @@ build_java_arrayaccess (array, type, index)
if (! integer_zerop (test))
{
throw = build (TRUTH_ANDIF_EXPR, int_type_node, test,
build_java_throw_out_of_bounds_exception ());
build_java_throw_out_of_bounds_exception (index));
/* allows expansion within COMPOUND */
TREE_SIDE_EFFECTS( throw ) = 1;
}
@ -677,7 +678,7 @@ build_java_check_indexed_type (array_node, indexed_type)
return indexed_type;
}
/* newarray triggers a call to soft_newarray. This function should be called
/* newarray triggers a call to _Jv_NewArray. This function should be called
with an integer code (the type of array to create) and get from the stack
the size of the dimmension. */
@ -706,7 +707,7 @@ build_anewarray (class_type, length)
tree class_type;
tree length;
{
tree type = build_java_array_type (promote_type (class_type),
tree type = build_java_array_type (class_type,
TREE_CODE (length) == INTEGER_CST
? TREE_INT_CST_LOW (length)
: -1);
@ -719,9 +720,9 @@ build_anewarray (class_type, length)
NULL_TREE);
}
/* Generates a call to multianewarray. multianewarray expects a class pointer,
a number of dimensions and the matching number of dimensions. The argument
list is NULL terminated. */
/* Generates a call to _Jv_NewMultiArray. multianewarray expects a
class pointer, a number of dimensions and the matching number of
dimensions. The argument list is NULL terminated. */
void
expand_java_multianewarray (class_type, ndim)
@ -829,8 +830,8 @@ expand_java_array_length ()
push_value (build_java_arraynull_check (array, length, int_type_node));
}
/* Emit code for the call to soft_monitor{enter,exit}. CALL can be either
soft_monitorenter_node or soft_monitorexit_node. */
/* Emit code for the call to _Jv_Monitor{Enter,Exit}. CALL can be
either soft_monitorenter_node or soft_monitorexit_node. */
tree
build_java_monitor (call, object)
@ -1147,6 +1148,18 @@ lookup_label (pc)
}
}
/* Generate a unique name for the purpose of loops and switches
labels, and try-catch-finally blocks label or temporary variables. */
tree
generate_name ()
{
static int l_number = 0;
char buff [20];
sprintf (buff, "$L%d", l_number++);
return get_identifier (buff);
}
tree
create_label_decl (name)
tree name;
@ -1175,7 +1188,6 @@ note_label (current_pc, target_pc)
/* Emit code to jump to TARGET_PC if VALUE1 CONDITION VALUE2,
where CONDITION is one of one the compare operators. */
void
expand_compare (condition, value1, value2, target_pc)
enum tree_code condition;
@ -1279,7 +1291,14 @@ pop_arguments (arg_types)
if (TREE_CODE (arg_types) == TREE_LIST)
{
tree tail = pop_arguments (TREE_CHAIN (arg_types));
return tree_cons (NULL_TREE, pop_value (TREE_VALUE (arg_types)), tail);
tree type = TREE_VALUE (arg_types);
tree arg = pop_value (type);
#ifdef PROMOTE_PROTOTYPES
if (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)
&& INTEGRAL_TYPE_P (type))
arg = convert (integer_type_node, arg);
#endif
return tree_cons (NULL_TREE, arg, tail);
}
abort ();
}
@ -1490,17 +1509,6 @@ expand_invoke (opcode, method_ref_index, nargs)
arg_list = pop_arguments (TYPE_ARG_TYPES (method_type));
flush_quick_stack ();
if (opcode == OPCODE_invokestatic || opcode == OPCODE_invokespecial
&& ! inherits_from_p (current_class, self_type))
{ /* FIXME probably not needed for invokespecial if done by NEW. */
/* Ensure self_type is initialized. */
func = build (CALL_EXPR, void_type_node, soft_initclass_node,
build_tree_list (NULL_TREE,
build_class_ref (self_type)),
NULL_TREE);
expand_expr_stmt (func);
}
func = NULL_TREE;
if (opcode == OPCODE_invokestatic || opcode == OPCODE_invokespecial
|| (opcode == OPCODE_invokevirtual
@ -1515,9 +1523,9 @@ expand_invoke (opcode, method_ref_index, nargs)
func = build_invokevirtual (dtable, method);
else
{
/* We expand invokeinterface here. soft_lookupinterfacemethod () will
ensure that the selected method exists, is public and not abstract
nor static. */
/* We expand invokeinterface here.
_Jv_LookupInterfaceMethod() will ensure that the selected
method exists, is public and not abstract nor static. */
tree lookup_arg;
@ -1543,12 +1551,6 @@ expand_invoke (opcode, method_ref_index, nargs)
call = build (CALL_EXPR, TREE_TYPE (method_type), func, arg_list, NULL_TREE);
TREE_SIDE_EFFECTS (call) = 1;
if (opcode == OPCODE_invokestatic || opcode == OPCODE_invokespecial)
{ /* FIXME probably not needed for invokespecial if done by NEW. */
/* Ensure self_type is initialized. */
call = build_class_init (self_type, call);
}
if (TREE_CODE (TREE_TYPE (method_type)) == VOID_TYPE)
expand_expr_stmt (call);
else
@ -1600,7 +1602,7 @@ expand_java_field_op (is_static, is_putting, field_ref_index)
if (is_error)
{
if (! is_putting)
push_value (convert (promote_type (field_type), integer_zero_node));
push_value (convert (field_type, integer_zero_node));
flush_quick_stack ();
return;
}
@ -1610,7 +1612,7 @@ expand_java_field_op (is_static, is_putting, field_ref_index)
this is also needed to avoid circularities in the implementation
of these fields in libjava. */
if (field_name == TYPE_identifier_node && ! is_putting
&& field_type == class_type_node
&& field_type == class_ptr_type
&& strncmp (self_name, "java.lang.", 10) == 0)
{
char *class_name = self_name+10;
@ -1693,6 +1695,8 @@ java_lang_expand_expr (exp, target, tmode, modifier)
tree type = TREE_TYPE (exp);
register enum machine_mode mode = TYPE_MODE (type);
int unsignedp = TREE_UNSIGNED (type);
tree node, current;
int has_finally_p;
switch (TREE_CODE (exp))
{
@ -1719,6 +1723,61 @@ java_lang_expand_expr (exp, target, tmode, modifier)
}
break;
case SWITCH_EXPR:
java_expand_switch (exp);
return const0_rtx;
case TRY_EXPR:
/* We expand a try[-catch][-finally] block */
/* Expand the try block */
expand_eh_region_start ();
expand_expr_stmt (TREE_OPERAND (exp, 0));
expand_start_all_catch ();
has_finally_p = (TREE_OPERAND (exp, 2) ? 1 : 0);
/* Expand all catch clauses (EH handlers) */
for (current = TREE_OPERAND (exp, 1); current;
current = TREE_CHAIN (current))
{
extern rtx return_label;
tree type;
/* If we have a finally, the last exception handler is the
one that is supposed to catch everything. */
if (has_finally_p && !TREE_CHAIN (current))
type = NULL_TREE;
else
{
tree catch = java_get_catch_block (current, has_finally_p);
tree decl = BLOCK_EXPR_DECLS (catch);
type = TREE_TYPE (TREE_TYPE (decl));
}
start_catch_handler (prepare_eh_table_type (type));
expand_expr_stmt (TREE_OPERAND (current, 0));
/* Need to expand a goto to the end of the function here,
but not for the catch everything handler. */
if (type)
{
if (return_label)
emit_jump (return_label);
else
fatal ("No return_label for this function - "
"java_lang_expand_expr");
}
end_catch_handler ();
}
/* Expand the finally block, if any */
if (has_finally_p)
{
tree finally = TREE_OPERAND (exp, 2);
emit_label (label_rtx (FINALLY_EXPR_LABEL (finally)));
expand_expr_stmt (FINALLY_EXPR_BLOCK (finally));
}
expand_end_all_catch ();
break;
default:
fatal ("Can't expand '%s' tree - java_lang_expand_expr",
tree_code_name [TREE_CODE (exp)]);
@ -1984,6 +2043,15 @@ process_jvm_instruction (PC, byte_ops, length)
{
char *opname; /* Temporary ??? */
int oldpc = PC; /* PC at instruction start. */
/* If the instruction is at the beginning of a exception handler,
replace the top of the stack with the thrown object reference */
if (instruction_bits [PC] & BCODE_EXCEPTION_TARGET)
{
pop_value (ptr_type_node);
push_value (soft_exceptioninfo_call_node);
}
switch (byte_ops[PC++])
{
#define JAVAOP(OPNAME, OPCODE, OPKIND, OPERAND_TYPE, OPERAND_VALUE) \

View File

@ -84,11 +84,21 @@ static JCF_u2 last_access;
#define ACC_VISIBILITY (ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED)
int seen_fields = 0;
/* We keep a linked list of all method names we have seen. This lets
us determine if a method name and a field name are in conflict. */
struct method_name
{
unsigned char *name;
int length;
struct method_name *next;
};
/* List of method names we've seen. */
static struct method_name *method_name_list;
static void print_field_info PROTO ((FILE *, JCF*, int, int, JCF_u2));
static void print_method_info PROTO ((FILE *, JCF*, int, int, JCF_u2));
static void print_c_decl PROTO ((FILE*, JCF*, int, int, JCF_u2, int));
static void print_c_decl PROTO ((FILE*, JCF*, int, int, JCF_u2, int, char *));
JCF_u2 current_field_name;
JCF_u2 current_field_value;
@ -99,9 +109,15 @@ JCF_u2 current_field_flags;
( current_field_name = (NAME), current_field_signature = (SIGNATURE), \
current_field_flags = (ACCESS_FLAGS), current_field_value = 0)
/* We pass over fields twice. The first time we just note the start
of the methods. Then we go back and parse the fields for real.
This is ugly. */
static int field_pass;
#define HANDLE_END_FIELD() \
print_field_info (out, jcf, current_field_name, current_field_signature, \
current_field_flags);
if (field_pass) print_field_info (out, jcf, current_field_name, \
current_field_signature, \
current_field_flags);
#define HANDLE_CONSTANTVALUE(VALUEINDEX) current_field_value = (VALUEINDEX)
@ -242,11 +258,29 @@ generate_access (stream, flags)
}
}
/* See if NAME is already the name of a method. */
static int
name_is_method_p (name, length)
unsigned char *name;
int length;
{
struct method_name *p;
for (p = method_name_list; p != NULL; p = p->next)
{
if (p->length == length && ! memcmp (p->name, name, length))
return 1;
}
return 0;
}
static void
DEFUN(print_field_info, (stream, jcf, name_index, sig_index, flags),
FILE *stream AND JCF* jcf
AND int name_index AND int sig_index AND JCF_u2 flags)
{
char *override = NULL;
if (flags & ACC_FINAL)
{
if (current_field_value > 0)
@ -305,12 +339,42 @@ DEFUN(print_field_info, (stream, jcf, name_index, sig_index, flags),
generate_access (stream, flags);
fputs (" ", out);
if (flags & ACC_STATIC)
if ((flags & ACC_STATIC))
fputs ("static ", out);
print_c_decl (out, jcf, name_index, sig_index, flags, 0);
if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
{
fprintf (stream, "<not a UTF8 constant>");
found_error = 1;
}
else
{
unsigned char *name = JPOOL_UTF_DATA (jcf, name_index);
int length = JPOOL_UTF_LENGTH (jcf, name_index);
if (name_is_method_p (name, length))
{
/* This field name matches a method. So override the name
with a dummy name. This is yucky, but it isn't clear
what else to do. FIXME: if the field is static, then
we'll be in real trouble. */
if ((flags & ACC_STATIC))
{
fprintf (stderr, "static field has same name as method\n");
found_error = 1;
}
override = (char *) malloc (length + 3);
memcpy (override, name, length);
strcpy (override + length, "__");
}
}
print_c_decl (out, jcf, name_index, sig_index, flags, 0, override);
fputs (";\n", out);
if (! (flags & ACC_STATIC))
seen_fields++;
if (override)
free (override);
}
static void
@ -320,6 +384,7 @@ DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags),
{
unsigned char *str;
int length, is_init = 0;
char *override = NULL;
if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
fprintf (stream, "<not a UTF8 constant>");
@ -334,13 +399,33 @@ DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags),
else
return;
}
else
{
struct method_name *nn;
nn = (struct method_name *) malloc (sizeof (struct method_name));
nn->name = (char *) malloc (length);
memcpy (nn->name, str, length);
nn->length = length;
nn->next = method_name_list;
method_name_list = nn;
}
/* We can't generate a method whose name is a C++ reserved word.
For now the only problem has been `delete'; add more here as
required. FIXME: we need a better solution than just ignoring
the method. */
required. We can't just ignore the function, because that will
cause incorrect code to be generated if the function is virtual
(not only for calls to this function for for other functions
after it in the vtbl). So we give it a dummy name instead. */
if (! utf8_cmp (str, length, "delete"))
return;
{
/* If the method is static, we can safely skip it. If we don't
skip it then we'll have problems since the mangling will be
wrong. FIXME. */
if ((flags & ACC_STATIC))
return;
override = "__dummy_delete";
}
generate_access (stream, flags);
@ -353,7 +438,7 @@ DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags),
if (! is_init)
fputs ("virtual ", out);
}
print_c_decl (out, jcf, name_index, sig_index, flags, is_init);
print_c_decl (out, jcf, name_index, sig_index, flags, is_init, override);
/* FIXME: it would be nice to decompile small methods here. That
would allow for inlining. */
@ -361,154 +446,185 @@ DEFUN(print_method_info, (stream, jcf, name_index, sig_index, flags),
fprintf(out, ";\n");
}
/* Print one piece of a signature. Returns pointer to next parseable
character on success, NULL on error. */
static unsigned char *
decode_signature_piece (stream, signature, limit, need_space)
FILE *stream;
unsigned char *signature, *limit;
int *need_space;
{
char *ctype;
switch (signature[0])
{
case '[':
for (signature++; (signature < limit
&& *signature >= '0'
&& *signature <= '9'); signature++)
;
switch (*signature)
{
case 'B': ctype = "jbyteArray"; goto printit;
case 'C': ctype = "jcharArray"; goto printit;
case 'D': ctype = "jdoubleArray"; goto printit;
case 'F': ctype = "jfloatArray"; goto printit;
case 'I': ctype = "jintArray"; goto printit;
case 'S': ctype = "jshortArray"; goto printit;
case 'J': ctype = "jlongArray"; goto printit;
case 'Z': ctype = "jbooleanArray"; goto printit;
case '[': ctype = "jobjectArray"; goto printit;
case 'L':
/* We have to generate a reference to JArray here,
so that our output matches what the compiler
does. */
++signature;
fputs ("JArray<", stream);
while (signature < limit && *signature != ';')
{
int ch = UTF8_GET (signature, limit);
if (ch == '/')
fputs ("::", stream);
else
jcf_print_char (stream, ch);
}
fputs (" *> *", stream);
*need_space = 0;
++signature;
break;
default:
/* Unparseable signature. */
return NULL;
}
break;
case '(':
case ')':
/* This shouldn't happen. */
return NULL;
case 'B': ctype = "jbyte"; goto printit;
case 'C': ctype = "jchar"; goto printit;
case 'D': ctype = "jdouble"; goto printit;
case 'F': ctype = "jfloat"; goto printit;
case 'I': ctype = "jint"; goto printit;
case 'J': ctype = "jlong"; goto printit;
case 'S': ctype = "jshort"; goto printit;
case 'Z': ctype = "jboolean"; goto printit;
case 'V': ctype = "void"; goto printit;
case 'L':
++signature;
while (*signature && *signature != ';')
{
int ch = UTF8_GET (signature, limit);
if (ch == '/')
fputs ("::", stream);
else
jcf_print_char (stream, ch);
}
fputs (" *", stream);
if (*signature == ';')
signature++;
*need_space = 0;
break;
default:
*need_space = 1;
jcf_print_char (stream, *signature++);
break;
printit:
signature++;
*need_space = 1;
fputs (ctype, stream);
break;
}
return signature;
}
static void
DEFUN(print_c_decl, (stream, jcf, name_index, signature_index, flags, is_init),
DEFUN(print_c_decl, (stream, jcf, name_index, signature_index, flags, is_init,
name_override),
FILE* stream AND JCF* jcf
AND int name_index AND int signature_index AND JCF_u2 flags
AND int is_init)
AND int is_init AND char *name_override)
{
if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
fprintf (stream, "<not a UTF8 constant>");
{
fprintf (stream, "<not a UTF8 constant>");
found_error = 1;
}
else
{
int length = JPOOL_UTF_LENGTH (jcf, signature_index);
unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
register unsigned char *str = str0;
unsigned char *limit = str + length;
int j;
char *ctype;
int need_space = 0;
int is_method = str[0] == '(';
unsigned char *next;
if (is_method)
/* If printing a method, skip to the return signature and print
that first. However, there is no return value if this is a
constructor. */
if (is_method && ! is_init)
{
/* Skip to the return signature, and print that first.
However, don't do this is we are printing a construtcor.
*/
if (is_init)
while (str < limit)
{
str = str0 + 1;
/* FIXME: Most programmers love Celtic knots because
they see their own code in the interconnected loops.
That is, this is spaghetti. */
goto have_constructor;
}
else
{
while (str < limit)
{
int ch = *str++;
if (ch == ')')
break;
}
int ch = *str++;
if (ch == ')')
break;
}
}
again:
while (str < limit)
/* If printing a field or an ordinary method, then print the
"return value" now. */
if (! is_method || ! is_init)
{
switch (str[0])
next = decode_signature_piece (stream, str, limit, &need_space);
if (! next)
{
case '[':
for (str++; str < limit && *str >= '0' && *str <= '9'; str++)
;
switch (*str)
{
case 'B': ctype = "jbyteArray"; goto printit;
case 'C': ctype = "jcharArray"; goto printit;
case 'D': ctype = "jdoubleArray"; goto printit;
case 'F': ctype = "jfloatArray"; goto printit;
case 'I': ctype = "jintArray"; goto printit;
case 'S': ctype = "jshortArray"; goto printit;
case 'J': ctype = "jlongArray"; goto printit;
case 'Z': ctype = "jbooleanArray"; goto printit;
case '[': ctype = "jobjectArray"; goto printit;
case 'L':
/* We have to generate a reference to JArray here,
so that our output matches what the compiler
does. */
++str;
fputs ("JArray<", out);
while (str < limit && *str != ';')
{
int ch = UTF8_GET (str, limit);
if (ch == '/')
fputs ("::", stream);
else
jcf_print_char (stream, ch);
}
fputs (" *> *", out);
need_space = 0;
++str;
break;
default:
fprintf (stderr, "unparseable signature `%s'\n", str0);
found_error = 1;
ctype = "???"; goto printit;
}
break;
case '(':
fputc (*str++, stream);
continue;
case ')':
fputc (*str++, stream);
/* the return signature was printed in the first pass. */
fprintf (stderr, "unparseable signature: `%s'\n", str0);
found_error = 1;
return;
case 'B': ctype = "jbyte"; goto printit;
case 'C': ctype = "jchar"; goto printit;
case 'D': ctype = "jdouble"; goto printit;
case 'F': ctype = "jfloat"; goto printit;
case 'I': ctype = "jint"; goto printit;
case 'J': ctype = "jlong"; goto printit;
case 'S': ctype = "jshort"; goto printit;
case 'Z': ctype = "jboolean"; goto printit;
case 'V': ctype = "void"; goto printit;
case 'L':
++str;
while (*str && *str != ';')
{
int ch = UTF8_GET (str, limit);
if (ch == '/')
fputs ("::", stream);
else
jcf_print_char (stream, ch);
}
fputs (" *", stream);
if (*str == ';')
str++;
need_space = 0;
break;
default:
need_space = 1;
jcf_print_char (stream, *str++);
break;
printit:
str++;
need_space = 1;
fputs (ctype, stream);
break;
}
if (is_method && str < limit && *str != ')')
fputs (", ", stream);
}
have_constructor:
if (name_index)
/* Now print the name of the thing. */
if (need_space)
fputs (" ", stream);
if (name_override)
fputs (name_override, stream);
else if (name_index)
{
if (need_space)
fprintf (stream, " ");
/* Declare constructors specially. */
if (is_init)
print_base_classname (stream, jcf, jcf->this_class);
else
print_name (stream, jcf, name_index);
}
if (is_method)
{
/* Have a method or a constructor. Print signature pieces
until done. */
fputs (" (", stream);
/* Go to beginning, skipping '('. */
str = str0 + 1;
goto again; /* To handle argument signatures. */
while (str < limit && *str != ')')
{
next = decode_signature_piece (stream, str, limit, &need_space);
if (! next)
{
fprintf (stderr, "unparseable signature: `%s'\n", str0);
found_error = 1;
return;
}
if (next < limit && *next != ')')
fputs (", ", stream);
str = next;
}
fputs (")", stream);
}
}
}
@ -613,6 +729,7 @@ DEFUN(process_file, (jcf, out),
JCF *jcf AND FILE *out)
{
int code, i;
uint32 field_start, method_end;
current_jcf = main_jcf = jcf;
@ -700,8 +817,22 @@ DEFUN(process_file, (jcf, out),
as we see them. We have to list the methods in the same order
that they appear in the class file, so that the Java and C++
vtables have the same layout. */
/* We want to parse the methods first. But we need to find where
they start. So first we skip the fields, then parse the
methods. Then we parse the fields and skip the methods. FIXME:
this is ugly. */
field_pass = 0;
field_start = JCF_TELL (jcf);
jcf_parse_fields (jcf);
jcf_parse_methods (jcf);
method_end = JCF_TELL (jcf);
field_pass = 1;
JCF_SEEK (jcf, field_start);
jcf_parse_fields (jcf);
JCF_SEEK (jcf, method_end);
jcf_parse_final_attributes (jcf);
/* Generate friend decl if we still must. */

View File

@ -408,7 +408,7 @@ get_class_constant (JCF *jcf , int i)
char *name = JPOOL_UTF_DATA (jcf, name_index);
int nlength = JPOOL_UTF_LENGTH (jcf, name_index);
if (name[0] == '[') /* Handle array "classes". */
type = parse_signature_string (name, nlength);
type = TREE_TYPE (parse_signature_string (name, nlength));
else
{
tree cname = unmangle_classname (name, nlength);

File diff suppressed because it is too large Load Diff

View File

@ -32,6 +32,40 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
#include "jcf.h"
#include "toplev.h"
/* Table indexed by tree code giving a string containing a character
classifying the tree code. Possibilities are
t, d, s, c, r, <, 1 and 2. See java/java-tree.def for details. */
#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
char java_tree_code_type[] = {
'x',
#include "java-tree.def"
};
#undef DEFTREECODE
/* Table indexed by tree code giving number of expression
operands beyond the fixed part of the node structure.
Not used for types or decls. */
#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
int java_tree_code_length[] = {
0,
#include "java-tree.def"
};
#undef DEFTREECODE
/* Names of tree components.
Used for printing out the tree and error messages. */
#define DEFTREECODE(SYM, NAME, TYPE, LEN) NAME,
char *java_tree_code_name[] = {
"@@dummy",
#include "java-tree.def"
};
#undef DEFTREECODE
int compiling_from_source;
char *language_string = "GNU Java";
@ -320,6 +354,20 @@ lang_init ()
current_jcf = main_jcf;
flag_exceptions = 1;
/* Append to Gcc tree node definition arrays */
bcopy (java_tree_code_type,
tree_code_type + (int) LAST_AND_UNUSED_TREE_CODE,
(int)LAST_JAVA_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE);
bcopy ((char *)java_tree_code_length,
(char *)(tree_code_length + (int) LAST_AND_UNUSED_TREE_CODE),
(LAST_JAVA_TREE_CODE -
(int)LAST_AND_UNUSED_TREE_CODE) * sizeof (int));
bcopy ((char *)java_tree_code_name,
(char *)(tree_code_name + (int) LAST_AND_UNUSED_TREE_CODE),
(LAST_JAVA_TREE_CODE -
(int)LAST_AND_UNUSED_TREE_CODE) * sizeof (char *));
}
/* This doesn't do anything on purpose. It's used to satisfy the

View File

@ -148,22 +148,32 @@ extern tree stabilize_reference PROTO ((tree));
EXPR_WFL_EMIT_LINE_NOTE (node) = 1, node : node)
/* Types classification, according to the JLS, section 4.2 */
#define JFLOAT_TYPE_P(TYPE) (TREE_CODE ((TYPE)) == REAL_TYPE)
#define JINTEGRAL_TYPE_P(TYPE) ((TREE_CODE ((TYPE)) == INTEGER_TYPE) \
|| (TREE_CODE ((TYPE)) == CHAR_TYPE))
#define JNUMERIC_TYPE_P(TYPE) (JFLOAT_TYPE_P ((TYPE)) \
|| JINTEGRAL_TYPE_P ((TYPE)))
#define JPRIMITIVE_TYPE_P(TYPE) (JNUMERIC_TYPE_P ((TYPE)) \
|| (TREE_CODE ((TYPE)) == BOOLEAN_TYPE))
#define JFLOAT_TYPE_P(TYPE) (TYPE && TREE_CODE ((TYPE)) == REAL_TYPE)
#define JINTEGRAL_TYPE_P(TYPE) ((TYPE) \
&& (TREE_CODE ((TYPE)) == INTEGER_TYPE \
|| TREE_CODE ((TYPE)) == CHAR_TYPE))
#define JNUMERIC_TYPE_P(TYPE) ((TYPE) \
&& (JFLOAT_TYPE_P ((TYPE)) \
|| JINTEGRAL_TYPE_P ((TYPE))))
#define JPRIMITIVE_TYPE_P(TYPE) ((TYPE) \
&& (JNUMERIC_TYPE_P ((TYPE)) \
|| TREE_CODE ((TYPE)) == BOOLEAN_TYPE))
/* Not defined in the LRM */
#define JSTRING_TYPE_P(TYPE) ((TYPE) == string_type_node || \
(TREE_CODE (TYPE) == POINTER_TYPE && \
TREE_TYPE (op1_type) == string_type_node))
#define JSTRING_TYPE_P(TYPE) ((TYPE) \
&& ((TYPE) == string_type_node || \
(TREE_CODE (TYPE) == POINTER_TYPE && \
TREE_TYPE (TYPE) == string_type_node)))
#define JSTRING_P(NODE) ((NODE) \
&& (TREE_CODE (NODE) == STRING_CST \
|| IS_CRAFTED_STRING_BUFFER_P (NODE) \
|| JSTRING_TYPE_P (TREE_TYPE (NODE))))
#define JREFERENCE_TYPE_P(TYPE) (TREE_CODE (TYPE) == RECORD_TYPE || \
(TREE_CODE (TYPE) == POINTER_TYPE && \
TREE_CODE (TREE_TYPE (TYPE)) == RECORD_TYPE))
#define JREFERENCE_TYPE_P(TYPE) ((TYPE) \
&& (TREE_CODE (TYPE) == RECORD_TYPE \
|| (TREE_CODE (TYPE) == POINTER_TYPE \
&& TREE_CODE (TREE_TYPE (TYPE)) == \
RECORD_TYPE)))
/* Other predicate */
#define DECL_P(NODE) (NODE && (TREE_CODE (NODE) == PARM_DECL \
@ -198,12 +208,12 @@ extern tree stabilize_reference PROTO ((tree));
#define ERROR_VARIABLE_NOT_INITIALIZED(WFL, V) \
parse_error_context \
((WFL), "Variable `%s' may not have been initialized", \
((WFL), "Variable `%s' may not have been initialized", \
IDENTIFIER_POINTER (V))
/* Definition for loop handling. This Java's own definition of a loop
body. See parse.y for documentation. It's valid once you hold a
loop's body (LOOP_EXPR_BODY) */
/* Definition for loop handling. This is Java's own definition of a
loop body. See parse.y for documentation. It's valid once you hold
a loop's body (LOOP_EXPR_BODY) */
/* The loop main block is the one hold the condition and the loop body */
#define LOOP_EXPR_BODY_MAIN_BLOCK(NODE) TREE_OPERAND (NODE, 0)
@ -252,7 +262,6 @@ extern tree stabilize_reference PROTO ((tree));
}
#define POP_LOOP() ctxp->current_loop = TREE_CHAIN (ctxp->current_loop)
/* Invocation modes, as returned by invocation_mode (). */
enum {
INVOKE_STATIC,
@ -414,6 +423,14 @@ static jdeplist *reverse_jdep_list ();
#define COMPLETE_CHECK_OP_0(NODE) COMPLETE_CHECK_OP(NODE, 0)
#define COMPLETE_CHECK_OP_1(NODE) COMPLETE_CHECK_OP(NODE, 1)
/* Building invocations: append(ARG) and StringBuffer(ARG) */
#define BUILD_APPEND(ARG) \
build_method_invocation (wfl_append, \
(ARG ? build_tree_list (NULL, (ARG)): NULL_TREE))
#define BUILD_STRING_BUFFER(ARG) \
build_new_invocation (wfl_string_buffer, \
(ARG ? build_tree_list (NULL, (ARG)) : NULL_TREE))
/* Parser context data structure. */
struct parser_ctxt {
@ -472,7 +489,8 @@ struct parser_ctxt {
#ifndef JC1_LITE
static char *java_accstring_lookup PROTO ((int));
static void parse_error PROTO ((char *));
static void redefinition_error PROTO ((char *,tree, tree, tree));
static void classitf_redefinition_error PROTO ((char *,tree, tree, tree));
static void variable_redefinition_error PROTO ((tree, tree, tree, int));
static void check_modifiers PROTO ((char *, int, int));
static tree create_class PROTO ((int, tree, tree, tree));
static tree create_interface PROTO ((int, tree, tree));
@ -490,6 +508,7 @@ static tree method_header PROTO ((int, tree, tree, tree));
static tree method_declarator PROTO ((tree, tree));
static void parse_error_context VPROTO ((tree cl, char *msg, ...));
static void parse_warning_context VPROTO ((tree cl, char *msg, ...));
static tree parse_jdk1_1_error PROTO ((char *));
static void complete_class_report_errors PROTO ((jdep *));
static int process_imports PROTO ((void));
static void read_import_dir PROTO ((tree));
@ -514,7 +533,9 @@ static tree resolve_and_layout PROTO ((tree, tree));
static tree resolve_no_layout PROTO ((tree, tree));
static int identical_subpath_p PROTO ((tree, tree));
static int invocation_mode PROTO ((tree, int));
static tree refine_accessible_methods_list PROTO ((int, tree));
static tree find_applicable_accessible_methods_list PROTO ((tree, tree, tree));
static tree find_most_specific_methods_list PROTO ((tree));
static int argument_types_convertible PROTO ((tree, tree));
static tree patch_invoke PROTO ((tree, tree, tree, tree));
static tree lookup_method_invoke PROTO ((int, tree, tree, tree, tree));
static tree register_incomplete_type PROTO ((int, tree, tree, tree));
@ -525,10 +546,12 @@ static int unresolved_type_p PROTO ((tree, tree *));
static void create_jdep_list PROTO ((struct parser_ctxt *));
static tree build_expr_block PROTO ((tree, tree));
static tree enter_block PROTO ((void));
static tree enter_a_block PROTO ((tree));
static tree exit_block PROTO ((void));
static tree lookup_name_in_blocks PROTO ((tree));
static void maybe_absorb_scoping_blocks PROTO ((void));
static tree build_method_invocation PROTO ((tree, tree));
static tree build_new_invocation PROTO ((tree, tree));
static tree build_assignment PROTO ((int, int, tree, tree));
static tree build_binop PROTO ((enum tree_code, int, tree, tree));
static tree patch_assignment PROTO ((tree, tree, tree ));
@ -539,7 +562,11 @@ static tree patch_unaryop PROTO ((tree, tree));
static tree build_cast PROTO ((int, tree, tree));
static tree patch_cast PROTO ((tree, tree, tree));
static int valid_ref_assignconv_cast_p PROTO ((tree, tree, int));
static int can_cast_to_p PROTO ((tree, tree));
static int valid_builtin_assignconv_identity_widening_p PROTO ((tree, tree));
static int valid_cast_to_p PROTO ((tree, tree));
static int valid_method_invocation_conversion_p PROTO ((tree, tree));
static tree try_builtin_assignconv PROTO ((tree, tree, tree));
static tree try_reference_assignconv PROTO ((tree, tree));
static tree build_unresolved_array_type PROTO ((tree));
static tree build_array_ref PROTO ((int, tree, tree));
static tree patch_array_ref PROTO ((tree, tree, tree));
@ -565,6 +592,7 @@ static int class_in_current_package PROTO ((tree));
static tree build_if_else_statement PROTO ((int, tree, tree, tree));
static tree patch_if_else_statement PROTO ((tree));
static tree add_stmt_to_compound PROTO ((tree, tree, tree));
static tree add_stmt_to_block PROTO ((tree, tree, tree));
static tree patch_exit_expr PROTO ((tree));
static tree build_labeled_block PROTO ((int, tree, tree));
static tree generate_labeled_block PROTO (());
@ -577,6 +605,14 @@ static tree build_loop_body PROTO ((int, tree, int));
static tree complete_loop_body PROTO ((int, tree, tree, int));
static tree build_debugable_stmt PROTO ((int, tree));
static tree complete_for_loop PROTO ((int, tree, tree, tree));
static tree patch_switch_statement PROTO ((tree));
static tree string_constant_concatenation PROTO ((tree, tree));
static tree build_string_concatenation PROTO ((tree, tree));
static tree patch_string_cst PROTO ((tree));
static tree patch_string PROTO ((tree));
static tree build_jump_to_finally PROTO ((tree, tree, tree, tree));
static tree build_try_statement PROTO ((int, tree, tree, tree));
static tree patch_try_statement PROTO ((tree));
void safe_layout_class PROTO ((tree));
void java_complete_class PROTO ((void));
@ -586,6 +622,8 @@ void java_check_methods PROTO ((void));
void java_layout_classes PROTO ((void));
tree java_method_add_stmt PROTO ((tree, tree));
char *java_get_line_col PROTO ((char *, int, int));
void java_expand_switch PROTO ((tree));
tree java_get_catch_block PROTO ((tree, int));
#endif /* JC1_LITE */
/* Always in use, no matter what you compile */

View File

@ -930,14 +930,14 @@ verify_jvm_instructions (jcf, byte_ops, length)
case OPCODE_instanceof:
pop_type (ptr_type_node);
get_class_constant (current_jcf, IMMEDIATE_u2);
push_type (integer_type_node);
push_type (int_type_node);
break;
case OPCODE_tableswitch:
{
jint default_val, low, high;
pop_type (integer_type_node);
pop_type (int_type_node);
while (PC%4)
{
if (byte_ops[PC++])
@ -959,7 +959,7 @@ verify_jvm_instructions (jcf, byte_ops, length)
{
jint npairs, last, not_registered = 1;
pop_type (integer_type_node);
pop_type (int_type_node);
while (PC%4)
{
if (byte_ops[PC++])