Commit 9bbc7d9f by Per Bothner Committed by Per Bothner

decl.c (error_mark_node): New global.

�
	* decl.c (error_mark_node), java-tree.h:  New global.
	* parse.y:  Use empty_stmt_node instead of size_zero_node.
	(build_if_else_statement):  If missing else, use empty_stmt_node.
	* parse.y (not_initialized_as_it_should_p):  Removed, with its callers.
	(java_complete_expand_method):  Complain if return is missing.
	(java_check_regular_methods):  Comment out incorrect error check.
	(not_accessible_p):  Fix incorrect handling of protected methods.
	(patch_method_invocation):  Pass correct context to not_accessible_p.
	(find_applicable_accessible_methods_list):  Likewise.
	(qualify_ambiguous_name):  If ARRAY_REF, it's an expression name.
	(java_complete_tree):  For CASE_EXPR and DEFAULT_EXPR, set
	TREE_TYPE (to void_type_node);  otherwise expand_expr crashes.
	(patch_if_else_statement):  Fix setting of CAN_COMPLETE_NORMALLY.
	* jcf-write.c (CHECK_OP, CHECK_PUT):  Add some error checking.
	(push_int_const):  Remove reundant NOTE_PUSH.
	(generate_bytecode_insns - case STRING_CST):  Do NOTE_PUSH.
	(- case SWITCH_EXPR):  Fix code generation bug.
	(- case PREDECREMENT_EXPR etc):  Remove redundant NOTE_PUSH.
	(generate_classfile):  More robust for abstract methods.

From-SVN: r23661
parent 175135a6
Sun Nov 15 14:36:29 1998 Per Bothner <bothner@cygnus.com>
* decl.c (error_mark_node), java-tree.h: New global.
* parse.y: Use empty_stmt_node instead of size_zero_node.
(build_if_else_statement): If missing else, use empty_stmt_node.
* parse.y (not_initialized_as_it_should_p): Removed, with its callers.
(java_complete_expand_method): Complain if return is missing.
(java_check_regular_methods): Comment out incorrect error check.
(not_accessible_p): Fix incorrect handling of protected methods.
(patch_method_invocation): Pass correct context to not_accessible_p.
(find_applicable_accessible_methods_list): Likewise.
(qualify_ambiguous_name): If ARRAY_REF, it's an expression name.
(java_complete_tree): For CASE_EXPR and DEFAULT_EXPR, set
TREE_TYPE (to void_type_node); otherwise expand_expr crashes.
(patch_if_else_statement): Fix setting of CAN_COMPLETE_NORMALLY.
* jcf-write.c (CHECK_OP, CHECK_PUT): Add some error checking.
(push_int_const): Remove reundant NOTE_PUSH.
(generate_bytecode_insns - case STRING_CST): Do NOTE_PUSH.
(- case SWITCH_EXPR): Fix code generation bug.
(- case PREDECREMENT_EXPR etc): Remove redundant NOTE_PUSH.
(generate_classfile): More robust for abstract methods.
Sun Nov 15 13:52:39 1998 Anthony Green <green@cygnus.com> Sun Nov 15 13:52:39 1998 Anthony Green <green@cygnus.com>
* Makefile.in: jv-scan and jvgenmain all require libiberty. * Makefile.in: jv-scan and jvgenmain all require libiberty.
......
...@@ -318,6 +318,7 @@ tree error_mark_node; ...@@ -318,6 +318,7 @@ tree error_mark_node;
The first is of type `int', the second of type `void *'. */ The first is of type `int', the second of type `void *'. */
tree integer_zero_node; tree integer_zero_node;
tree null_pointer_node; tree null_pointer_node;
tree empty_stmt_node;
/* Nodes for boolean constants TRUE and FALSE. */ /* Nodes for boolean constants TRUE and FALSE. */
tree boolean_true_node, boolean_false_node; tree boolean_true_node, boolean_false_node;
...@@ -431,8 +432,6 @@ init_decl_processing () ...@@ -431,8 +432,6 @@ init_decl_processing ()
TREE_TYPE (size_zero_node) = sizetype; TREE_TYPE (size_zero_node) = sizetype;
size_one_node = build_int_2 (1, 0); size_one_node = build_int_2 (1, 0);
TREE_TYPE (size_one_node) = sizetype; TREE_TYPE (size_one_node) = sizetype;
/* Used by the parser to represent empty statements and blocks. */
CAN_COMPLETE_NORMALLY (size_zero_node) = 1;
byte_type_node = make_signed_type (8); byte_type_node = make_signed_type (8);
pushdecl (build_decl (TYPE_DECL, get_identifier ("byte"), byte_type_node)); pushdecl (build_decl (TYPE_DECL, get_identifier ("byte"), byte_type_node));
...@@ -475,6 +474,10 @@ init_decl_processing () ...@@ -475,6 +474,10 @@ init_decl_processing ()
null_pointer_node = build_int_2 (0, 0); null_pointer_node = build_int_2 (0, 0);
TREE_TYPE (null_pointer_node) = ptr_type_node; TREE_TYPE (null_pointer_node) = ptr_type_node;
/* Used by the parser to represent empty statements and blocks. */
empty_stmt_node = build1 (NOP_EXPR, void_type_node, size_zero_node);
CAN_COMPLETE_NORMALLY (empty_stmt_node) = 1;
#if 0 #if 0
/* Make a type to be the domain of a few array types /* Make a type to be the domain of a few array types
whose domains don't really matter. whose domains don't really matter.
......
...@@ -220,6 +220,7 @@ extern tree boolean_true_node, boolean_false_node; ...@@ -220,6 +220,7 @@ extern tree boolean_true_node, boolean_false_node;
extern tree integer_negative_one_node; extern tree integer_negative_one_node;
extern tree integer_two_node; extern tree integer_two_node;
extern tree integer_four_node; extern tree integer_four_node;
extern tree empty_stmt_node;
/* The type for struct methodtable. */ /* The type for struct methodtable. */
extern tree methodtable_type; extern tree methodtable_type;
......
...@@ -50,34 +50,25 @@ char *jcf_write_base_directory = NULL; ...@@ -50,34 +50,25 @@ char *jcf_write_base_directory = NULL;
/* Make sure bytecode.data is big enough for at least N more bytes. */ /* Make sure bytecode.data is big enough for at least N more bytes. */
#define RESERVE(N) \ #define RESERVE(N) \
do { if (state->bytecode.ptr + (N) > state->bytecode.limit) \ do { CHECK_OP(state); \
if (state->bytecode.ptr + (N) > state->bytecode.limit) \
buffer_grow (&state->bytecode, N); } while (0) buffer_grow (&state->bytecode, N); } while (0)
/* Add a 1-byte instruction/operand I to bytecode.data, /* Add a 1-byte instruction/operand I to bytecode.data,
assuming space has already been RESERVE'd. */ assuming space has already been RESERVE'd. */
#define OP1(I) (*state->bytecode.ptr++ = (I)) #define OP1(I) (*state->bytecode.ptr++ = (I), CHECK_OP(state))
/* Like OP1, but I is a 2-byte big endian integer. */ /* Like OP1, but I is a 2-byte big endian integer. */
#define OP2(I) \ #define OP2(I) \
do { int _i = (I); OP1 (_i >> 8); OP1 (_i); } while (0) do { int _i = (I); OP1 (_i >> 8); OP1 (_i); CHECK_OP(state); } while (0)
/* Like OP1, but I is a 4-byte big endian integer. */ /* Like OP1, but I is a 4-byte big endian integer. */
#define OP4(I) \ #define OP4(I) \
do { int _i = (I); OP1 (_i >> 24); OP1 (_i >> 16); \ do { int _i = (I); OP1 (_i >> 24); OP1 (_i >> 16); \
OP1 (_i >> 8); OP1 (_i); } while (0) OP1 (_i >> 8); OP1 (_i); CHECK_OP(state); } while (0)
/* The current stack size (stack pointer) in the current method. */
int code_SP = 0;
/* The largest extent of stack size (stack pointer) in the current method. */
int code_SP_max = 0;
CPool *code_cpool;
/* Macro to call each time we push I words on the JVM stack. */ /* Macro to call each time we push I words on the JVM stack. */
...@@ -138,7 +129,13 @@ struct jcf_block ...@@ -138,7 +129,13 @@ struct jcf_block
} u; } u;
}; };
/* A "relocation" type for the 0-3 bytes of padding at the start
of a tableswitch or a lookupswitch. */
#define SWITCH_ALIGN_RELOC 4 #define SWITCH_ALIGN_RELOC 4
/* A relocation type for the labels in a tableswitch or a lookupswitch;
these are relative to the start of the instruction, but (due to
th 0-3 bytes of padding), we don't know the offset before relocation. */
#define BLOCK_START_RELOC 1 #define BLOCK_START_RELOC 1
struct jcf_relocation struct jcf_relocation
...@@ -253,10 +250,26 @@ static void generate_bytecode_insns PROTO ((tree, int, struct jcf_partial *)); ...@@ -253,10 +250,26 @@ static void generate_bytecode_insns PROTO ((tree, int, struct jcf_partial *));
We assume a local variable 'ptr' points into where we want to We assume a local variable 'ptr' points into where we want to
write next, and we assume enoygh space has been allocated. */ write next, and we assume enoygh space has been allocated. */
#define PUT1(X) (*ptr++ = (X)) #ifdef ENABLE_CHECKING
int
CHECK_PUT(ptr, state, i)
void *ptr;
struct jcf_partial *state;
int i;
{
if (ptr < state->chunk->data
|| (char*)ptr + i > state->chunk->data + state->chunk->size)
fatal ("internal error - CHECK_PUT failed");
return 0;
}
#else
#define CHECK_PUT(PTR, STATE, I) 0
#endif
#define PUT1(X) (CHECK_PUT(ptr, state, 1), *ptr++ = (X))
#define PUT2(X) (PUT1((X) >> 8), PUT1((X) & 0xFF)) #define PUT2(X) (PUT1((X) >> 8), PUT1((X) & 0xFF))
#define PUT4(X) (PUT2((X) >> 16), PUT2((X) & 0xFFFF)) #define PUT4(X) (PUT2((X) >> 16), PUT2((X) & 0xFFFF))
#define PUTN(P, N) (memcpy(ptr, P, N), ptr += (N)) #define PUTN(P, N) (CHECK_PUT(ptr, state, N), memcpy(ptr, P, N), ptr += (N))
/* Allocate a new chunk on obstack WORK, and link it in after LAST. /* Allocate a new chunk on obstack WORK, and link it in after LAST.
...@@ -284,6 +297,20 @@ alloc_chunk (last, data, size, work) ...@@ -284,6 +297,20 @@ alloc_chunk (last, data, size, work)
return chunk; return chunk;
} }
#ifdef ENABLE_CHECKING
int
CHECK_OP(struct jcf_partial *state)
{
if (state->bytecode.ptr > state->bytecode.limit)
{
fatal("internal error - CHECK_OP failed");
}
return 0;
}
#else
#define CHECK_OP(STATE) 0
#endif
unsigned char * unsigned char *
append_chunk (data, size, state) append_chunk (data, size, state)
unsigned char *data; unsigned char *data;
...@@ -574,6 +601,9 @@ write_chunks (stream, chunks) ...@@ -574,6 +601,9 @@ write_chunks (stream, chunks)
fwrite (chunks->data, chunks->size, 1, stream); fwrite (chunks->data, chunks->size, 1, stream);
} }
/* Push a 1-word constant in the constant pool at the given INDEX.
(Caller is responsible for doing NOTE_PUSH.) */
static void static void
push_constant1 (index, state) push_constant1 (index, state)
int index; int index;
...@@ -592,6 +622,9 @@ push_constant1 (index, state) ...@@ -592,6 +622,9 @@ push_constant1 (index, state)
} }
} }
/* Push a 2-word constant in the constant pool at the given INDEX.
(Caller is responsible for doing NOTE_PUSH.) */
static void static void
push_constant2 (index, state) push_constant2 (index, state)
int index; int index;
...@@ -622,7 +655,6 @@ push_int_const (i, state) ...@@ -622,7 +655,6 @@ push_int_const (i, state)
{ {
OP1(OPCODE_sipush); OP1(OPCODE_sipush);
OP2(i); OP2(i);
NOTE_PUSH (1);
} }
else else
{ {
...@@ -1257,6 +1289,7 @@ generate_bytecode_insns (exp, target, state) ...@@ -1257,6 +1289,7 @@ generate_bytecode_insns (exp, target, state)
break; break;
case STRING_CST: case STRING_CST:
push_constant1 (find_string_constant (&state->cpool, exp), state); push_constant1 (find_string_constant (&state->cpool, exp), state);
NOTE_PUSH (1);
break; break;
case VAR_DECL: case VAR_DECL:
if (TREE_STATIC (exp)) if (TREE_STATIC (exp))
...@@ -1473,12 +1506,16 @@ generate_bytecode_insns (exp, target, state) ...@@ -1473,12 +1506,16 @@ generate_bytecode_insns (exp, target, state)
OP4 (sw_state.max_case); OP4 (sw_state.max_case);
for (i = sw_state.min_case; ; ) for (i = sw_state.min_case; ; )
{ {
if (i == sw_state.min_case + index) reloc = relocs[index];
emit_case_reloc (relocs[index++], state); if (i == reloc->offset)
{
emit_case_reloc (reloc, state);
if (i == sw_state.max_case)
break;
index++;
}
else else
emit_switch_reloc (sw_state.default_label, state); emit_switch_reloc (sw_state.default_label, state);
if (i == sw_state.max_case)
break;
i++; i++;
} }
} }
...@@ -1619,12 +1656,8 @@ generate_bytecode_insns (exp, target, state) ...@@ -1619,12 +1656,8 @@ generate_bytecode_insns (exp, target, state)
if (target != IGNORE_TARGET && post_op) if (target != IGNORE_TARGET && post_op)
emit_load (exp, state); emit_load (exp, state);
emit_iinc (exp, value, state); emit_iinc (exp, value, state);
if (target != IGNORE_TARGET) if (target != IGNORE_TARGET && ! post_op)
{ emit_load (exp, state);
if (! post_op)
emit_load (exp, state);
NOTE_PUSH (1);
}
break; break;
} }
if (TREE_CODE (exp) == COMPONENT_REF) if (TREE_CODE (exp) == COMPONENT_REF)
...@@ -2225,6 +2258,8 @@ perform_relocations (state) ...@@ -2225,6 +2258,8 @@ perform_relocations (state)
*--new_ptr = 0; *--new_ptr = 0;
*--new_ptr = - reloc->kind; *--new_ptr = - reloc->kind;
} }
if (new_ptr != chunk->data)
fatal ("internal error - perform_relocations");
} }
} }
state->code_length = pc; state->code_length = pc;
...@@ -2352,7 +2387,9 @@ generate_classfile (clas, state) ...@@ -2352,7 +2387,9 @@ generate_classfile (clas, state)
for (part = TYPE_METHODS (clas); part; part = TREE_CHAIN (part)) for (part = TYPE_METHODS (clas); part; part = TREE_CHAIN (part))
{ {
struct jcf_block *block; struct jcf_block *block;
tree body = BLOCK_EXPR_BODY (DECL_FUNCTION_BODY (part)); tree function_body = DECL_FUNCTION_BODY (part);
tree body = function_body == NULL_TREE ? NULL_TREE
: BLOCK_EXPR_BODY (function_body);
tree name = DECL_CONSTRUCTOR_P (part) ? init_identifier_node tree name = DECL_CONSTRUCTOR_P (part) ? init_identifier_node
: DECL_NAME (part); : DECL_NAME (part);
tree type = TREE_TYPE (part); tree type = TREE_TYPE (part);
......
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