aboutsummaryrefslogtreecommitdiff
path: root/gcc/java/jcf-write.c
diff options
context:
space:
mode:
authorPer Bothner <bothner@cygnus.com>1998-11-15 14:37:52 +0000
committerPer Bothner <bothner@gcc.gnu.org>1998-11-15 06:37:52 -0800
commit9bbc7d9f4c30d9cf34a79c8b36a7e4f0857d764d (patch)
tree57ca81d68872cd1049e8022307078e2a68dd88b8 /gcc/java/jcf-write.c
parent175135a659ad8d2ba5e827c1404d42d4924d98fc (diff)
downloadgcc-9bbc7d9f4c30d9cf34a79c8b36a7e4f0857d764d.zip
gcc-9bbc7d9f4c30d9cf34a79c8b36a7e4f0857d764d.tar.gz
gcc-9bbc7d9f4c30d9cf34a79c8b36a7e4f0857d764d.tar.bz2
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
Diffstat (limited to 'gcc/java/jcf-write.c')
-rw-r--r--gcc/java/jcf-write.c93
1 files changed, 65 insertions, 28 deletions
diff --git a/gcc/java/jcf-write.c b/gcc/java/jcf-write.c
index 5e76337..64c9e06 100644
--- a/gcc/java/jcf-write.c
+++ b/gcc/java/jcf-write.c
@@ -50,34 +50,25 @@ char *jcf_write_base_directory = NULL;
/* Make sure bytecode.data is big enough for at least N more bytes. */
#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)
/* Add a 1-byte instruction/operand I to bytecode.data,
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. */
#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. */
#define OP4(I) \
do { int _i = (I); OP1 (_i >> 24); OP1 (_i >> 16); \
- OP1 (_i >> 8); OP1 (_i); } 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;
+ OP1 (_i >> 8); OP1 (_i); CHECK_OP(state); } while (0)
/* Macro to call each time we push I words on the JVM stack. */
@@ -138,7 +129,13 @@ struct jcf_block
} 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
+
+/* 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
struct jcf_relocation
@@ -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
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 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.
@@ -284,6 +297,20 @@ alloc_chunk (last, data, size, work)
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 *
append_chunk (data, size, state)
unsigned char *data;
@@ -574,6 +601,9 @@ write_chunks (stream, chunks)
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
push_constant1 (index, state)
int index;
@@ -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
push_constant2 (index, state)
int index;
@@ -622,7 +655,6 @@ push_int_const (i, state)
{
OP1(OPCODE_sipush);
OP2(i);
- NOTE_PUSH (1);
}
else
{
@@ -1257,6 +1289,7 @@ generate_bytecode_insns (exp, target, state)
break;
case STRING_CST:
push_constant1 (find_string_constant (&state->cpool, exp), state);
+ NOTE_PUSH (1);
break;
case VAR_DECL:
if (TREE_STATIC (exp))
@@ -1473,12 +1506,16 @@ generate_bytecode_insns (exp, target, state)
OP4 (sw_state.max_case);
for (i = sw_state.min_case; ; )
{
- if (i == sw_state.min_case + index)
- emit_case_reloc (relocs[index++], state);
+ reloc = relocs[index];
+ if (i == reloc->offset)
+ {
+ emit_case_reloc (reloc, state);
+ if (i == sw_state.max_case)
+ break;
+ index++;
+ }
else
emit_switch_reloc (sw_state.default_label, state);
- if (i == sw_state.max_case)
- break;
i++;
}
}
@@ -1619,12 +1656,8 @@ generate_bytecode_insns (exp, target, state)
if (target != IGNORE_TARGET && post_op)
emit_load (exp, state);
emit_iinc (exp, value, state);
- if (target != IGNORE_TARGET)
- {
- if (! post_op)
- emit_load (exp, state);
- NOTE_PUSH (1);
- }
+ if (target != IGNORE_TARGET && ! post_op)
+ emit_load (exp, state);
break;
}
if (TREE_CODE (exp) == COMPONENT_REF)
@@ -2225,6 +2258,8 @@ perform_relocations (state)
*--new_ptr = 0;
*--new_ptr = - reloc->kind;
}
+ if (new_ptr != chunk->data)
+ fatal ("internal error - perform_relocations");
}
}
state->code_length = pc;
@@ -2352,7 +2387,9 @@ generate_classfile (clas, state)
for (part = TYPE_METHODS (clas); part; part = TREE_CHAIN (part))
{
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
: DECL_NAME (part);
tree type = TREE_TYPE (part);