diff options
author | Per Bothner <bothner@cygnus.com> | 1998-11-15 14:37:52 +0000 |
---|---|---|
committer | Per Bothner <bothner@gcc.gnu.org> | 1998-11-15 06:37:52 -0800 |
commit | 9bbc7d9f4c30d9cf34a79c8b36a7e4f0857d764d (patch) | |
tree | 57ca81d68872cd1049e8022307078e2a68dd88b8 /gcc/java/jcf-write.c | |
parent | 175135a659ad8d2ba5e827c1404d42d4924d98fc (diff) | |
download | gcc-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.c | 93 |
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); |