diff options
author | apbianco <apbianco@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-10-05 07:17:34 +0000 |
---|---|---|
committer | apbianco <apbianco@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-10-05 07:17:34 +0000 |
commit | bc099162c31da09a5b1792bdc7c45554535d9326 (patch) | |
tree | 4d5c18c324994e5c054b7c48872b57170975b1b9 | |
parent | 5e0bc83fe6ffedc565a20311a87d4a55a70062eb (diff) | |
download | gcc-bc099162c31da09a5b1792bdc7c45554535d9326.tar.gz |
Tue Oct 3 13:44:37 2000 Alexandre Petit-Bianco <apbianco@cygnus.com>
* decl.c (find_local_variable): Removed uncessary type check and
fixed range check typo. From Corey Minyard.
Wed Sep 13 16:06:52 2000 Alexandre Petit-Bianco <apbianco@cygnus.com>
* decl.c (give_name_to_locals): New local `code_offset'. Call
`maybe_adjust_start_pc.'
* expr.c (note_instructions): New function.
(expand_byte_code): Don't collect insn starts here.
(peek_opcode_at_pc): New function.
(maybe_adjust_start_pc): Likewise.
* java-tree.h (maybe_adjust_start_pc): Declare.
(note_instructions): Likewise.
* jcf-parse.c (parse_class_file): Call `note_instructions.'
Wed Sep 13 11:50:35 2000 Alexandre Petit-Bianco <apbianco@cygnus.com>
* parse.y (field_access:): Fixed indentation.
(qualify_ambiguous_name): Properly qualify `this.a[b].c'.
(http://gcc.gnu.org/ml/gcc-patches/2000-10/msg00067.html)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@36717 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/java/ChangeLog | 22 | ||||
-rw-r--r-- | gcc/java/decl.c | 13 | ||||
-rw-r--r-- | gcc/java/expr.c | 209 | ||||
-rw-r--r-- | gcc/java/java-tree.h | 2 | ||||
-rw-r--r-- | gcc/java/parse.y | 14 |
5 files changed, 221 insertions, 39 deletions
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 94b6a787ba6..c82acb4e5d2 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,25 @@ +Tue Oct 3 13:44:37 2000 Alexandre Petit-Bianco <apbianco@cygnus.com> + + * decl.c (find_local_variable): Removed uncessary type check and + fixed range check typo. From Corey Minyard. + +Wed Sep 13 16:06:52 2000 Alexandre Petit-Bianco <apbianco@cygnus.com> + + * decl.c (give_name_to_locals): New local `code_offset'. Call + `maybe_adjust_start_pc.' + * expr.c (note_instructions): New function. + (expand_byte_code): Don't collect insn starts here. + (peek_opcode_at_pc): New function. + (maybe_adjust_start_pc): Likewise. + * java-tree.h (maybe_adjust_start_pc): Declare. + (note_instructions): Likewise. + * jcf-parse.c (parse_class_file): Call `note_instructions.' + +Wed Sep 13 11:50:35 2000 Alexandre Petit-Bianco <apbianco@cygnus.com> + + * parse.y (field_access:): Fixed indentation. + (qualify_ambiguous_name): Properly qualify `this.a[b].c'. + 2000-09-07 Tom Tromey <tromey@cygnus.com> Fix for PR gcj/307: diff --git a/gcc/java/decl.c b/gcc/java/decl.c index da44ca6ac81..8dd349ff8c7 100644 --- a/gcc/java/decl.c +++ b/gcc/java/decl.c @@ -170,9 +170,8 @@ find_local_variable (index, type, pc) && in_range) { if (best == NULL_TREE - || (TREE_TYPE (decl) == type && TREE_TYPE (best) != type) - || DECL_LOCAL_START_PC (decl) > DECL_LOCAL_START_PC (best) - || DECL_LOCAL_END_PC (decl) < DECL_LOCAL_START_PC (decl)) + || (DECL_LOCAL_START_PC (decl) > DECL_LOCAL_START_PC (best) + && DECL_LOCAL_END_PC (decl) < DECL_LOCAL_START_PC (best))) best = decl; } decl = DECL_LOCAL_SLOT_CHAIN (decl); @@ -1517,6 +1516,7 @@ give_name_to_locals (jcf) JCF *jcf; { int i, n = DECL_LOCALVARIABLES_OFFSET (current_function_decl); + int code_offset = DECL_CODE_OFFSET (current_function_decl); tree parm; pending_local_decls = NULL_TREE; if (n == 0) @@ -1553,6 +1553,13 @@ give_name_to_locals (jcf) "bad PC range for debug info for local `%s'"); end_pc = DECL_CODE_LENGTH (current_function_decl); } + + /* Adjust start_pc if necessary so that the local's first + store operation will use the relevant DECL as a + destination. Fore more information, read the leading + comments for expr.c:maybe_adjust_start_pc. */ + start_pc = maybe_adjust_start_pc (jcf, code_offset, start_pc, slot); + DECL_LANG_SPECIFIC (decl) = (struct lang_decl *) ggc_alloc (sizeof (struct lang_decl_var)); DECL_LOCAL_SLOT_NUMBER (decl) = slot; diff --git a/gcc/java/expr.c b/gcc/java/expr.c index 54a3332c51b..1dd26c38c4d 100644 --- a/gcc/java/expr.c +++ b/gcc/java/expr.c @@ -80,6 +80,7 @@ static tree build_java_throw_out_of_bounds_exception PARAMS ((tree)); static tree build_java_check_indexed_type PARAMS ((tree, tree)); static tree java_array_data_offset PARAMS ((tree)); static tree case_identity PARAMS ((tree, tree)); +static unsigned char peek_opcode_at_pc PARAMS ((struct JCF *, int, int)); static tree operand_type[59]; extern struct obstack permanent_obstack; @@ -2479,16 +2480,20 @@ java_lang_expand_expr (exp, target, tmode, modifier) } } +/* Go over METHOD's bytecode and note instruction starts in + instruction_bits[]. */ + void -expand_byte_code (jcf, method) +note_instructions (jcf, method) JCF *jcf; tree method; { - int PC; - int i; + int PC; + unsigned char* byte_ops; + long length = DECL_CODE_LENGTH (method); + int saw_index; - const unsigned char *linenumber_pointer; - int dead_code_index = -1; + jint INT_temp; #undef RET /* Defined by config/i386/i386.h */ #undef AND /* Causes problems with opcodes for iand and land. */ @@ -2503,14 +2508,6 @@ expand_byte_code (jcf, method) #define FLOAT_type_node float_type_node #define DOUBLE_type_node double_type_node #define VOID_type_node void_type_node - jint INT_temp; - unsigned char* byte_ops; - long length = DECL_CODE_LENGTH (method); - - stack_pointer = 0; - JCF_SEEK (jcf, DECL_CODE_OFFSET (method)); - byte_ops = jcf->read_ptr; - #define CONST_INDEX_1 (saw_index = 1, IMMEDIATE_u1) #define CONST_INDEX_2 (saw_index = 1, IMMEDIATE_u2) #define VAR_INDEX_1 (saw_index = 1, IMMEDIATE_u1) @@ -2518,28 +2515,12 @@ expand_byte_code (jcf, method) #define CHECK_PC_IN_RANGE(PC) ((void)1) /* Already handled by verifier. */ + JCF_SEEK (jcf, DECL_CODE_OFFSET (method)); + byte_ops = jcf->read_ptr; instruction_bits = oballoc (length + 1); bzero (instruction_bits, length + 1); - /* We make an initial pass of the line number table, to note - which instructions have associated line number entries. */ - linenumber_pointer = linenumber_table; - for (i = 0; i < linenumber_count; i++) - { - int pc = GET_u2 (linenumber_pointer); - linenumber_pointer += 4; - if (pc >= length) - warning ("invalid PC in line number table"); - else - { - if ((instruction_bits[pc] & BCODE_HAS_LINENUMBER) != 0) - instruction_bits[pc] |= BCODE_HAS_MULTI_LINENUMBERS; - instruction_bits[pc] |= BCODE_HAS_LINENUMBER; - } - } - - /* Do a preliminary pass. - * This figures out which PC can be the targets of jumps. */ + /* This pass figures out which PC can be the targets of jumps. */ for (PC = 0; PC < length;) { int oldpc = PC; /* PC at instruction start. */ @@ -2586,8 +2567,6 @@ expand_byte_code (jcf, method) } \ } -/* nothing */ /* XXX JH */ - #define PRE_IMPL(IGNORE1, IGNORE2) /* nothing */ #define PRE_MONITOR(OPERAND_TYPE, OPERAND_VALUE) /* nothing */ @@ -2647,6 +2626,40 @@ expand_byte_code (jcf, method) #undef JAVAOP } } /* for */ +} + +void +expand_byte_code (jcf, method) + JCF *jcf; + tree method; +{ + int PC; + int i; + const unsigned char *linenumber_pointer; + int dead_code_index = -1; + unsigned char* byte_ops; + long length = DECL_CODE_LENGTH (method); + + stack_pointer = 0; + JCF_SEEK (jcf, DECL_CODE_OFFSET (method)); + byte_ops = jcf->read_ptr; + + /* We make an initial pass of the line number table, to note + which instructions have associated line number entries. */ + linenumber_pointer = linenumber_table; + for (i = 0; i < linenumber_count; i++) + { + int pc = GET_u2 (linenumber_pointer); + linenumber_pointer += 4; + if (pc >= length) + warning ("invalid PC in line number table"); + else + { + if ((instruction_bits[pc] & BCODE_HAS_LINENUMBER) != 0) + instruction_bits[pc] |= BCODE_HAS_MULTI_LINENUMBERS; + instruction_bits[pc] |= BCODE_HAS_LINENUMBER; + } + } if (! verify_jvm_instructions (jcf, byte_ops, length)) return; @@ -3064,6 +3077,134 @@ process_jvm_instruction (PC, byte_ops, length) return PC; } +/* Return the opcode at PC in the code section pointed to by + CODE_OFFSET. */ + +static unsigned char +peek_opcode_at_pc (jcf, code_offset, pc) + JCF *jcf; + int code_offset, pc; +{ + unsigned char opcode; + long absolute_offset = (long)JCF_TELL (jcf); + + JCF_SEEK (jcf, code_offset); + opcode = jcf->read_ptr [pc]; + JCF_SEEK (jcf, absolute_offset); + return opcode; +} + +/* Some bytecode compilers are emitting accurate LocalVariableTable + attributes. Here's an example: + + PC <t>store_<n> + PC+1 ... + + Attribute "LocalVariableTable" + slot #<n>: ... (PC: PC+1 length: L) + + This is accurate because the local in slot <n> really exists after + the opcode at PC is executed, hence from PC+1 to PC+1+L. + + This procedure recognizes this situation and extends the live range + of the local in SLOT to START_PC-1 or START_PC-2 (depending on the + length of the store instruction.) + + This function is used by `give_name_to_locals' so that a local's + DECL features a DECL_LOCAL_START_PC such that the first related + store operation will use DECL as a destination, not a unrelated + temporary created for the occasion. + + This function uses a global (instruction_bits) `note_instructions' should + have allocated and filled properly. */ + +int +maybe_adjust_start_pc (jcf, code_offset, start_pc, slot) + struct JCF *jcf; + int code_offset, start_pc, slot; +{ + int first, index, opcode; + int pc, insn_pc; + int wide_found = 0; + + if (!start_pc) + return start_pc; + + first = index = -1; + + /* Find last previous instruction and remember it */ + for (pc = start_pc-1; pc; pc--) + if (instruction_bits [pc] & BCODE_INSTRUCTION_START) + break; + insn_pc = pc; + + /* Retrieve the instruction, handle `wide'. */ + opcode = (int) peek_opcode_at_pc (jcf, code_offset, pc++); + if (opcode == OPCODE_wide) + { + wide_found = 1; + opcode = (int) peek_opcode_at_pc (jcf, code_offset, pc++); + } + + switch (opcode) + { + case OPCODE_astore_0: + case OPCODE_astore_1: + case OPCODE_astore_2: + case OPCODE_astore_3: + first = OPCODE_astore_0; + break; + + case OPCODE_istore_0: + case OPCODE_istore_1: + case OPCODE_istore_2: + case OPCODE_istore_3: + first = OPCODE_istore_0; + break; + + case OPCODE_lstore_0: + case OPCODE_lstore_1: + case OPCODE_lstore_2: + case OPCODE_lstore_3: + first = OPCODE_lstore_0; + break; + + case OPCODE_fstore_0: + case OPCODE_fstore_1: + case OPCODE_fstore_2: + case OPCODE_fstore_3: + first = OPCODE_fstore_0; + break; + + case OPCODE_dstore_0: + case OPCODE_dstore_1: + case OPCODE_dstore_2: + case OPCODE_dstore_3: + first = OPCODE_dstore_0; + break; + + case OPCODE_astore: + case OPCODE_istore: + case OPCODE_lstore: + case OPCODE_fstore: + case OPCODE_dstore: + index = peek_opcode_at_pc (jcf, code_offset, pc); + if (wide_found) + { + int other = peek_opcode_at_pc (jcf, code_offset, ++pc); + index = (other << 8) + index; + } + break; + } + + /* Now we decide: first >0 means we have a <t>store_<n>, index >0 + means we have a <t>store. */ + if ((first > 0 && opcode - first == slot) || (index > 0 && index == slot)) + start_pc = insn_pc; + + return start_pc; +} + /* Force the (direct) sub-operands of NODE to be evaluated in left-to-right order, as specified by Java Language Specification. diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h index d22efecbc75..17b76925c28 100644 --- a/gcc/java/java-tree.h +++ b/gcc/java/java-tree.h @@ -1003,6 +1003,7 @@ extern void maybe_pushlevels PARAMS ((int)); extern void maybe_poplevels PARAMS ((int)); extern void force_poplevels PARAMS ((int)); extern int process_jvm_instruction PARAMS ((int, const unsigned char *, long)); +extern int maybe_adjust_start_pc PARAMS ((struct JCF *, int, int, int)); extern void set_local_type PARAMS ((int, tree)); extern int merge_type_state PARAMS ((tree)); extern void push_type PARAMS ((tree)); @@ -1016,6 +1017,7 @@ extern int verify_constant_pool PARAMS ((struct JCF *)); extern void start_java_method PARAMS ((tree)); extern void end_java_method PARAMS ((void)); extern void give_name_to_locals PARAMS ((struct JCF *)); +extern void note_instructions PARAMS ((struct JCF *, tree)); extern void expand_byte_code PARAMS ((struct JCF *, tree)); extern int open_in_zip PARAMS ((struct JCF *, const char *, const char *, int)); extern void set_constant_value PARAMS ((tree, tree)); diff --git a/gcc/java/parse.y b/gcc/java/parse.y index 6ae90d44a2f..5db2edcc076 100644 --- a/gcc/java/parse.y +++ b/gcc/java/parse.y @@ -2172,8 +2172,7 @@ field_access: { $$ = build_binop (COMPONENT_REF, $2.location, $1, $3); } */ | SUPER_TK DOT_TK identifier { - tree super_wfl = - build_wfl_node (super_identifier_node); + tree super_wfl = build_wfl_node (super_identifier_node); EXPR_WFL_LINECOL (super_wfl) = $1.location; $$ = make_qualified_name (super_wfl, $3, $2.location); } @@ -10741,6 +10740,17 @@ qualify_ambiguous_name (id) /* If we have a THIS (from a primary), we set the context accordingly */ if (name == this_identifier_node) { + /* This isn't really elegant. One more added irregularity + before I start using COMPONENT_REF (hopefully very soon.) */ + if (TREE_CODE (TREE_PURPOSE (qual)) == ARRAY_REF + && TREE_CODE (TREE_OPERAND (TREE_PURPOSE (qual), 0)) == + EXPR_WITH_FILE_LOCATION + && EXPR_WFL_NODE (TREE_OPERAND (TREE_PURPOSE (qual), 0)) == + this_identifier_node) + { + qual = TREE_OPERAND (TREE_PURPOSE (qual), 0); + qual = EXPR_WFL_QUALIFICATION (qual); + } qual = TREE_CHAIN (qual); qual_wfl = QUAL_WFL (qual); if (TREE_CODE (qual_wfl) == CALL_EXPR) |