OSDN Git Service

Tue Oct 3 13:44:37 2000 Alexandre Petit-Bianco <apbianco@cygnus.com>
authorapbianco <apbianco@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 5 Oct 2000 07:17:34 +0000 (07:17 +0000)
committerapbianco <apbianco@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 5 Oct 2000 07:17:34 +0000 (07:17 +0000)
        * 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

gcc/java/ChangeLog
gcc/java/decl.c
gcc/java/expr.c
gcc/java/java-tree.h
gcc/java/parse.y

index 94b6a78..c82acb4 100644 (file)
@@ -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:
index da44ca6..8dd349f 100644 (file)
@@ -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;
index 54a3332..1dd26c3 100644 (file)
@@ -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.
 
index d22efec..17b7692 100644 (file)
@@ -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));
index 6ae90d4..5db2edc 100644 (file)
@@ -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)