OSDN Git Service

* expr.c (expand_byte_code): Set DECL_FUNCTION_LAST_LINE on
[pf3gnuchains/gcc-fork.git] / gcc / java / expr.c
index 329e363..b113df1 100644 (file)
@@ -1,12 +1,12 @@
 /* Process expressions for the GNU compiler for the Java(TM) language.
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
+   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+   2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GCC is distributed in the hope that it will be useful,
@@ -15,9 +15,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  
 
 Java and all Java-based marks are trademarks or registered trademarks
 of Sun Microsystems, Inc. in the United States and other countries.
@@ -74,10 +73,6 @@ static void expand_cond (enum tree_code, tree, int);
 static void expand_java_goto (int);
 static tree expand_java_switch (tree, int);
 static void expand_java_add_case (tree, int, int);
-#if 0
-static void expand_java_call (int, int);
-static void expand_java_ret (tree); 
-#endif
 static tree pop_arguments (tree); 
 static void expand_invoke (int, int, int); 
 static void expand_java_field_op (int, int, int); 
@@ -87,6 +82,7 @@ static tree build_java_throw_out_of_bounds_exception (tree);
 static tree build_java_check_indexed_type (tree, tree); 
 static unsigned char peek_opcode_at_pc (struct JCF *, int, int);
 static void promote_arguments (void);
+static void cache_cpool_data_ref (void);
 
 static GTY(()) tree operand_type[59];
 
@@ -301,6 +297,13 @@ push_value (tree value)
       TREE_CHAIN (node) = quick_stack;
       quick_stack = node;
     }
+  /* If the value has a side effect, then we need to evaluate it
+     whether or not the result is used.  If the value ends up on the
+     quick stack and is then popped, this won't happen -- so we flush
+     the quick stack.  It is safest to simply always flush, though,
+     since TREE_SIDE_EFFECTS doesn't capture COMPONENT_REF, and for
+     the latter we may need to strip conversions.  */
+  flush_quick_stack ();
 }
 
 /* Pop a type from the type stack.
@@ -415,8 +418,8 @@ pop_type (tree type)
 static int
 type_assertion_eq (const void * k1_p, const void * k2_p)
 {
-  type_assertion k1 = *(type_assertion *)k1_p;
-  type_assertion k2 = *(type_assertion *)k2_p;
+  const type_assertion k1 = *(const type_assertion *)k1_p;
+  const type_assertion k2 = *(const type_assertion *)k2_p;
   return (k1.assertion_code == k2.assertion_code
           && k1.op1 == k2.op1
          && k1.op2 == k2.op2);
@@ -430,8 +433,27 @@ type_assertion_hash (const void *p)
   const type_assertion *k_p = p;
   hashval_t hash = iterative_hash (&k_p->assertion_code, sizeof
                                   k_p->assertion_code, 0);
-  hash = iterative_hash (&k_p->op1, sizeof k_p->op1, hash);
-  return iterative_hash (&k_p->op2, sizeof k_p->op2, hash);
+
+  switch (k_p->assertion_code)
+    {
+    case JV_ASSERT_TYPES_COMPATIBLE:
+      hash = iterative_hash (&TYPE_UID (k_p->op2), sizeof TYPE_UID (k_p->op2),
+                            hash);
+      /* Fall through.  */
+
+    case JV_ASSERT_IS_INSTANTIABLE:
+      hash = iterative_hash (&TYPE_UID (k_p->op1), sizeof TYPE_UID (k_p->op1),
+                            hash);
+      /* Fall through.  */
+
+    case JV_ASSERT_END_OF_TABLE:
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  return hash;
 }
 
 /* Add an entry to the type assertion table for the given class.  
@@ -635,9 +657,8 @@ java_stack_swap (void)
   tree decl1, decl2;
 
   if (stack_pointer < 2
-      || (type1 = stack_type_map[stack_pointer - 1]) == TYPE_UNKNOWN
-      || (type2 = stack_type_map[stack_pointer - 2]) == TYPE_UNKNOWN
-      || type1 == TYPE_SECOND || type2 == TYPE_SECOND
+      || (type1 = stack_type_map[stack_pointer - 1]) == TYPE_SECOND
+      || (type2 = stack_type_map[stack_pointer - 2]) == TYPE_SECOND
       || TYPE_IS_WIDE (type1) || TYPE_IS_WIDE (type2))
     /* Bad stack swap.  */
     abort ();
@@ -712,11 +733,9 @@ build_java_athrow (tree node)
 {
   tree call;
 
-  call = build3 (CALL_EXPR,
-                void_type_node,
-                build_address_of (throw_node),
-                build_tree_list (NULL_TREE, node),
-                NULL_TREE);
+  call = build_call_nary (void_type_node,
+                         build_address_of (throw_node),
+                         1, node);
   TREE_SIDE_EFFECTS (call) = 1;
   java_add_stmt (call);
   java_stack_pop (stack_pointer);
@@ -795,9 +814,9 @@ encode_newarray_type (tree type)
 static tree
 build_java_throw_out_of_bounds_exception (tree index)
 {
-  tree node = build3 (CALL_EXPR, int_type_node,
-                     build_address_of (soft_badarrayindex_node), 
-                     build_tree_list (NULL_TREE, index), NULL_TREE);
+  tree node = build_call_nary (int_type_node,
+                              build_address_of (soft_badarrayindex_node),
+                              1, index);
   TREE_SIDE_EFFECTS (node) = 1;        /* Allows expansion within ANDIF */
   return (node);
 }
@@ -846,9 +865,9 @@ java_check_reference (tree expr, int check)
       expr = build3 (COND_EXPR, TREE_TYPE (expr),
                     build2 (EQ_EXPR, boolean_type_node,
                             expr, null_pointer_node),
-                    build3 (CALL_EXPR, void_type_node, 
-                            build_address_of (soft_nullpointer_node),
-                            NULL_TREE, NULL_TREE),
+                    build_call_nary (void_type_node, 
+                                     build_address_of (soft_nullpointer_node),
+                                     0),
                     expr);
     }
 
@@ -878,6 +897,7 @@ build_java_arrayaccess (tree array, tree type, tree index)
   tree data_field;
   tree ref;
   tree array_type = TREE_TYPE (TREE_TYPE (array));
+  tree size_exp = fold_convert (sizetype, size_in_bytes (type));
 
   if (!is_array_type_p (TREE_TYPE (array)))
     {
@@ -912,16 +932,33 @@ build_java_arrayaccess (tree array, tree type, tree index)
      to have the bounds check evaluated first. */
   if (throw != NULL_TREE)
     index = build2 (COMPOUND_EXPR, int_type_node, throw, index);
+
   data_field = lookup_field (&array_type, get_identifier ("data"));
 
   ref = build3 (COMPONENT_REF, TREE_TYPE (data_field),    
                build_java_indirect_ref (array_type, array, 
                                         flag_check_references),
                data_field, NULL_TREE);
-  
-  node = build4 (ARRAY_REF, type, ref, index, NULL_TREE, NULL_TREE);
-  return node;
+
+  /* Take the address of the data field and convert it to a pointer to
+     the element type.  */
+  node = build1 (NOP_EXPR, build_pointer_type (type), build_address_of (ref));
+
+  /* Multiply the index by the size of an element to obtain a byte
+     offset.  Convert the result to a pointer to the element type.  */
+  index = build2 (MULT_EXPR, sizetype, 
+                 fold_convert (sizetype, index), 
+                 size_exp);
+
+  /* Sum the byte offset and the address of the data field.  */
+  node = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (node), node, index);
+
+  /* Finally, return
+
+    *((&array->data) + index*size_exp)
+
+  */
+  return build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (node)), node);
 }
 
 /* Generate code to throw an ArrayStoreException if OBJECT is not assignable
@@ -991,11 +1028,9 @@ build_java_arraystore_check (tree array, tree object)
     }
 
   /* Build an invocation of _Jv_CheckArrayStore */
-  check = build3 (CALL_EXPR, void_type_node,
-                 build_address_of (soft_checkarraystore_node),
-                 tree_cons (NULL_TREE, array,
-                            build_tree_list (NULL_TREE, object)),
-                 NULL_TREE);
+  check = build_call_nary (void_type_node,
+                          build_address_of (soft_checkarraystore_node),
+                          2, array, object);
   TREE_SIDE_EFFECTS (check) = 1;
 
   return check;
@@ -1033,20 +1068,13 @@ build_newarray (int atype_value, tree length)
                             host_integerp (length, 0) == INTEGER_CST
                             ? tree_low_cst (length, 0) : -1);
 
-  /* If compiling to native, pass a reference to the primitive type class 
-     and save the runtime some work. However, the bytecode generator
-     expects to find the type_code int here. */
-  if (flag_emit_class_files)
-    type_arg = build_int_cst (NULL_TREE, atype_value);
-  else
-    type_arg = build_class_ref (prim_type);
+  /* Pass a reference to the primitive type class and save the runtime
+     some work.  */
+  type_arg = build_class_ref (prim_type);
 
-  return build3 (CALL_EXPR, promote_type (type),
-                build_address_of (soft_newarray_node),
-                tree_cons (NULL_TREE, 
-                           type_arg,
-                           build_tree_list (NULL_TREE, length)),
-                NULL_TREE);
+  return build_call_nary (promote_type (type),
+                         build_address_of (soft_newarray_node),
+                         2, type_arg, length);
 }
 
 /* Generates anewarray from a given CLASS_TYPE. Gets from the stack the size
@@ -1060,13 +1088,12 @@ build_anewarray (tree class_type, tree length)
                             host_integerp (length, 0)
                             ? tree_low_cst (length, 0) : -1);
 
-  return build3 (CALL_EXPR, promote_type (type),
-                build_address_of (soft_anewarray_node),
-                tree_cons (NULL_TREE, length,
-                           tree_cons (NULL_TREE, build_class_ref (class_type),
-                                      build_tree_list (NULL_TREE,
-                                                       null_pointer_node))),
-                NULL_TREE);
+  return build_call_nary (promote_type (type),
+                         build_address_of (soft_anewarray_node),
+                         3,
+                         length,
+                         build_class_ref (class_type),
+                         null_pointer_node);
 }
 
 /* Return a node the evaluates 'new TYPE[LENGTH]'. */
@@ -1093,14 +1120,15 @@ expand_java_multianewarray (tree class_type, int ndim)
   for( i = 0; i < ndim; i++ )
     args = tree_cons (NULL_TREE, pop_value (int_type_node), args);
 
-  push_value (build3 (CALL_EXPR,
-                     promote_type (class_type),
-                     build_address_of (soft_multianewarray_node),
-                     tree_cons (NULL_TREE, build_class_ref (class_type),
-                                tree_cons (NULL_TREE, 
-                                           build_int_cst (NULL_TREE, ndim),
-                                           args)),
-                     NULL_TREE));
+  args = tree_cons (NULL_TREE,
+                   build_class_ref (class_type),
+                   tree_cons (NULL_TREE, 
+                              build_int_cst (NULL_TREE, ndim),
+                              args));
+
+  push_value (build_call_list (promote_type (class_type),
+                              build_address_of (soft_multianewarray_node),
+                              args));
 }
 
 /*  ARRAY[INDEX] <- RHS. build_java_check_indexed_type makes sure that
@@ -1120,7 +1148,7 @@ expand_java_arraystore (tree rhs_type_node)
                                 && TYPE_PRECISION (rhs_type_node) <= 32) ? 
                                 int_type_node : rhs_type_node);
   tree index = pop_value (int_type_node);
-  tree array_type, array;
+  tree array_type, array, temp, access;
 
   /* If we're processing an `aaload' we might as well just pick
      `Object'.  */
@@ -1142,14 +1170,31 @@ expand_java_arraystore (tree rhs_type_node)
   index = save_expr (index);
   array = save_expr (array);
 
+  /* We want to perform the bounds check (done by
+     build_java_arrayaccess) before the type check (done by
+     build_java_arraystore_check).  So, we call build_java_arrayaccess
+     -- which returns an ARRAY_REF lvalue -- and we then generate code
+     to stash the address of that lvalue in a temp.  Then we call
+     build_java_arraystore_check, and finally we generate a
+     MODIFY_EXPR to set the array element.  */
+
+  access = build_java_arrayaccess (array, rhs_type_node, index);
+  temp = build_decl (VAR_DECL, NULL_TREE, 
+                    build_pointer_type (TREE_TYPE (access)));
+  java_add_local_var (temp);
+  java_add_stmt (build2 (MODIFY_EXPR, TREE_TYPE (temp),
+                        temp, 
+                        build_fold_addr_expr (access)));
+
   if (TREE_CODE (rhs_type_node) == POINTER_TYPE)
     {
       tree check = build_java_arraystore_check (array, rhs_node);
       java_add_stmt (check);
     }
   
-  array = build_java_arrayaccess (array, rhs_type_node, index);
-  java_add_stmt (build2 (MODIFY_EXPR, TREE_TYPE (array), array, rhs_node));  
+  java_add_stmt (build2 (MODIFY_EXPR, TREE_TYPE (access), 
+                        build1 (INDIRECT_REF, TREE_TYPE (access), temp),
+                        rhs_node));  
 }
 
 /* Expand the evaluation of ARRAY[INDEX]. build_java_check_indexed_type makes 
@@ -1210,11 +1255,9 @@ expand_java_array_length (void)
 static tree
 build_java_monitor (tree call, tree object)
 {
-  return build3 (CALL_EXPR,
-                void_type_node,
-                build_address_of (call),
-                build_tree_list (NULL_TREE, object),
-                NULL_TREE);
+  return build_call_nary (void_type_node,
+                         build_address_of (call),
+                         1, object);
 }
 
 /* Emit code for one of the PUSHC instructions. */
@@ -1260,7 +1303,7 @@ expand_java_return (tree type)
        retval = build1(NOP_EXPR, TREE_TYPE(res), retval);
       
       TREE_SIDE_EFFECTS (retval) = 1;
-      java_add_stmt (build1 (RETURN_EXPR, TREE_TYPE (retval), retval));
+      java_add_stmt (build1 (RETURN_EXPR, void_type_node, retval));
     }
 }
 
@@ -1311,10 +1354,9 @@ java_create_object (tree type)
                     ? alloc_object_node
                     : alloc_no_finalizer_node);
   
-  return build3 (CALL_EXPR, promote_type (type),
-                build_address_of (alloc_node),
-                build_tree_list (NULL_TREE, build_class_ref (type)),
-                NULL_TREE);
+  return build_call_nary (promote_type (type),
+                         build_address_of (alloc_node),
+                         1, build_class_ref (type));
 }
 
 static void
@@ -1327,10 +1369,9 @@ expand_java_NEW (tree type)
   if (! CLASS_LOADED_P (type))
     load_class (type, 1);
   safe_layout_class (type);
-  push_value (build3 (CALL_EXPR, promote_type (type),
-                     build_address_of (alloc_node),
-                     build_tree_list (NULL_TREE, build_class_ref (type)),
-                     NULL_TREE));
+  push_value (build_call_nary (promote_type (type),
+                              build_address_of (alloc_node),
+                              1, build_class_ref (type)));
 }
 
 /* This returns an expression which will extract the class of an
@@ -1409,12 +1450,9 @@ build_instanceof (tree value, tree type)
     }
   else
     {
-      expr = build3 (CALL_EXPR, itype,
-                    build_address_of (soft_instanceof_node),
-                    tree_cons (NULL_TREE, value,
-                               build_tree_list (NULL_TREE,
-                                                build_class_ref (type))),
-                    NULL_TREE);
+      expr = build_call_nary (itype,
+                             build_address_of (soft_instanceof_node),
+                             2, value, build_class_ref (type));
     }
   TREE_SIDE_EFFECTS (expr) = TREE_SIDE_EFFECTS (value);
   return expr;
@@ -1432,11 +1470,9 @@ static void
 expand_java_CHECKCAST (tree type)
 {
   tree value = pop_value (ptr_type_node);
-  value = build3 (CALL_EXPR, promote_type (type),
-                 build_address_of (soft_checkcast_node),
-                 tree_cons (NULL_TREE, build_class_ref (type),
-                            build_tree_list (NULL_TREE, value)),
-                 NULL_TREE);
+  value = build_call_nary (promote_type (type),
+                          build_address_of (soft_checkcast_node),
+                          2, build_class_ref (type), value);
   push_value (value);
 }
 
@@ -1451,7 +1487,6 @@ expand_iinc (unsigned int local_var_index, int ival, int pc)
   constant_value = build_int_cst (NULL_TREE, ival);
   res = fold_build2 (PLUS_EXPR, int_type_node, local_var, constant_value);
   java_add_stmt (build2 (MODIFY_EXPR, TREE_TYPE (local_var), local_var, res));
-  update_aliases (local_var, local_var_index, pc);
 }
 
 
@@ -1492,12 +1527,7 @@ build_java_soft_divmod (enum tree_code op, tree type, tree op1, tree op2)
     }
 
   gcc_assert (call);
-  call = build3 (CALL_EXPR, type,
-                build_address_of (call),
-                tree_cons (NULL_TREE, arg1,
-                           build_tree_list (NULL_TREE, arg2)),
-                NULL_TREE);
-         
+  call = build_call_nary (type, build_address_of (call), 2, arg1, arg2);
   return call;
 }
 
@@ -1509,7 +1539,7 @@ build_java_binop (enum tree_code op, tree type, tree arg1, tree arg2)
     {
     case URSHIFT_EXPR:
       {
-       tree u_type = java_unsigned_type (type);
+       tree u_type = unsigned_type_for (type);
        arg1 = convert (u_type, arg1);
        arg1 = build_java_binop (RSHIFT_EXPR, u_type, arg1, arg2);
        return convert (type, arg1);
@@ -1560,11 +1590,9 @@ build_java_binop (enum tree_code op, tree type, tree arg1, tree arg2)
              arg1 = convert (double_type_node, arg1);
              arg2 = convert (double_type_node, arg2);
            }
-         call = build3 (CALL_EXPR, double_type_node,
-                        build_address_of (soft_fmod_node),
-                        tree_cons (NULL_TREE, arg1,
-                                   build_tree_list (NULL_TREE, arg2)),
-                        NULL_TREE);
+         call = build_call_nary (double_type_node,
+                                 build_address_of (soft_fmod_node),
+                                 2, arg1, arg2);
          if (type != double_type_node)
            call = convert (type, call);
          return call;
@@ -1724,18 +1752,19 @@ build_field_ref (tree self_value, tree self_class, tree name)
              = build3 (COND_EXPR, TREE_TYPE (field_offset),
                        build2 (EQ_EXPR, boolean_type_node,
                                field_offset, integer_zero_node),
-                       build3 (CALL_EXPR, void_type_node, 
-                               build_address_of (soft_nosuchfield_node),
-                               build_tree_list (NULL_TREE, otable_index), 
-                               NULL_TREE),
+                       build_call_nary (void_type_node, 
+                                        build_address_of (soft_nosuchfield_node),
+                                        1, otable_index),
                        field_offset);
          
          field_offset = fold (convert (sizetype, field_offset));
          self_value = java_check_reference (self_value, check);
          address 
-           = fold_build2 (PLUS_EXPR, 
-                          build_pointer_type (TREE_TYPE (field_decl)),
+           = fold_build2 (POINTER_PLUS_EXPR, 
+                          TREE_TYPE (self_value),
                           self_value, field_offset);
+         address = fold_convert (build_pointer_type (TREE_TYPE (field_decl)),
+                                 address);
          return fold_build1 (INDIRECT_REF, TREE_TYPE (field_decl), address);
        }
 
@@ -1761,7 +1790,6 @@ lookup_label (int pc)
     {
       /* The type of the address of a label is return_address_type_node. */
       tree decl = create_label_decl (name);
-      LABEL_PC (decl) = pc;
       return pushdecl (decl);
     }
 }
@@ -1790,9 +1818,15 @@ create_label_decl (tree name)
   return decl;
 }
 
-/* This maps a bytecode offset (PC) to various flags. */
+/* This maps a bytecode offset (PC) to various flags.  */
 char *instruction_bits;
 
+/* This is a vector of type states for the current method.  It is
+   indexed by PC.  Each element is a tree vector holding the type
+   state at that PC.  We only note type states at basic block
+   boundaries.  */
+VEC(tree, gc) *type_states;
+
 static void
 note_label (int current_pc ATTRIBUTE_UNUSED, int target_pc)
 {
@@ -1963,10 +1997,9 @@ build_class_init (tree clas, tree expr)
 
   if (always_initialize_class_p)
     {
-      init = build3 (CALL_EXPR, void_type_node,
-                    build_address_of (soft_initclass_node),
-                    build_tree_list (NULL_TREE, build_class_ref (clas)),
-                    NULL_TREE);
+      init = build_call_nary (void_type_node,
+                             build_address_of (soft_initclass_node),
+                             1, build_class_ref (clas));
       TREE_SIDE_EFFECTS (init) = 1;
     }
   else
@@ -1983,23 +2016,16 @@ build_class_init (tree clas, tree expr)
          decl = build_decl (VAR_DECL, NULL_TREE,
                             boolean_type_node);
          MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (decl);
-         LOCAL_CLASS_INITIALIZATION_FLAG (decl) = 1;
          DECL_CONTEXT (decl) = current_function_decl;
-         DECL_FUNCTION_INIT_TEST_CLASS (decl) = clas;
-         /* Tell the check-init code to ignore this decl when not
-             optimizing class initialization. */
-         if (!STATIC_CLASS_INIT_OPT_P ())
-           DECL_BIT_INDEX (decl) = -1;
          DECL_INITIAL (decl) = boolean_false_node;
          /* Don't emit any symbolic debugging info for this decl.  */
          DECL_IGNORED_P (decl) = 1;      
          *init_test_decl = decl;
        }
 
-      init = build3 (CALL_EXPR, void_type_node,
-                    build_address_of (soft_initclass_node),
-                    build_tree_list (NULL_TREE, build_class_ref (clas)),
-                    NULL_TREE);
+      init = build_call_nary (void_type_node,
+                             build_address_of (soft_initclass_node),
+                             1, build_class_ref (clas));
       TREE_SIDE_EFFECTS (init) = 1;
       init = build3 (COND_EXPR, void_type_node,
                     build2 (EQ_EXPR, boolean_type_node, 
@@ -2042,13 +2068,31 @@ typedef struct
   tree (*rewrite_arglist) (tree arglist);
 } rewrite_rule;
 
+/* Add __builtin_return_address(0) to the end of an arglist.  */
+
+
+static tree 
+rewrite_arglist_getcaller (tree arglist)
+{
+  tree retaddr 
+    = build_call_expr (built_in_decls[BUILT_IN_RETURN_ADDRESS],
+                      1, integer_zero_node);
+  
+  DECL_INLINE (current_function_decl) = 0;
+
+  return chainon (arglist, 
+                 tree_cons (NULL_TREE, retaddr, 
+                            NULL_TREE));
+}
+
 /* Add this.class to the end of an arglist.  */
 
 static tree 
 rewrite_arglist_getclass (tree arglist)
 {
   return chainon (arglist, 
-                 tree_cons (NULL_TREE, build_class_ref (output_class), NULL_TREE));
+                 tree_cons (NULL_TREE, build_class_ref (output_class),
+                            NULL_TREE));
 }
 
 static rewrite_rule rules[] =
@@ -2058,8 +2102,35 @@ static rewrite_rule rules[] =
    {"java.lang.Class", "forName", "(Ljava/lang/String;)Ljava/lang/Class;",
     "(Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Class;",
     ACC_FINAL|ACC_PRIVATE|ACC_STATIC, rewrite_arglist_getclass},
+   {"gnu.classpath.VMStackWalker", "getCallingClass", "()Ljava/lang/Class;",
+    "(Lgnu/gcj/RawData;)Ljava/lang/Class;",
+    ACC_FINAL|ACC_PRIVATE|ACC_STATIC, rewrite_arglist_getcaller},
+   {"gnu.classpath.VMStackWalker", "getCallingClassLoader", 
+    "()Ljava/lang/ClassLoader;",
+    "(Lgnu/gcj/RawData;)Ljava/lang/ClassLoader;",
+    ACC_FINAL|ACC_PRIVATE|ACC_STATIC, rewrite_arglist_getcaller},
+
    {NULL, NULL, NULL, NULL, 0, NULL}};
 
+/* True if this method is special, i.e. it's a private method that
+   should be exported from a DSO.  */
+
+bool
+special_method_p (tree candidate_method)
+{
+  tree context = DECL_NAME (TYPE_NAME (DECL_CONTEXT (candidate_method)));
+  tree method = DECL_NAME (candidate_method);
+  rewrite_rule *p;
+
+  for (p = rules; p->classname; p++)
+    {
+      if (get_identifier (p->classname) == context
+         && get_identifier (p->method) == method)
+       return true;
+    }
+  return false;
+}
+
 /* Scan the rules list for replacements for *METHOD_P and replace the
    args accordingly.  If the rewrite results in an access to a private
    method, update SPECIAL.*/
@@ -2174,8 +2245,8 @@ build_known_method_ref (tree method, tree method_type ATTRIBUTE_UNUSED,
          method_index++;
        }
       method_index *= int_size_in_bytes (method_type_node);
-      ref = fold_build2 (PLUS_EXPR, method_ptr_type_node,
-                        ref, build_int_cst (NULL_TREE, method_index));
+      ref = fold_build2 (POINTER_PLUS_EXPR, method_ptr_type_node,
+                        ref, size_int (method_index));
       ref = build1 (INDIRECT_REF, method_type_node, ref);
       func = build3 (COMPONENT_REF, nativecode_ptr_type_node,
                     ref, lookup_field (&method_type_node, ncode_ident),
@@ -2279,13 +2350,16 @@ build_invokevirtual (tree dtable, tree method, tree special)
                                   size_int (TARGET_VTABLE_USES_DESCRIPTORS));
     }
 
-  func = fold_build2 (PLUS_EXPR, nativecode_ptr_ptr_type_node, dtable,
-                     convert (nativecode_ptr_ptr_type_node, method_index));
+  func = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (dtable), dtable,
+                     convert (sizetype, method_index));
 
   if (TARGET_VTABLE_USES_DESCRIPTORS)
     func = build1 (NOP_EXPR, nativecode_ptr_type_node, func);
   else
-    func = build1 (INDIRECT_REF, nativecode_ptr_type_node, func);
+    {
+      func = fold_convert (nativecode_ptr_ptr_type_node, func);
+      func = build1 (INDIRECT_REF, nativecode_ptr_type_node, func);
+    }
 
   return func;
 }
@@ -2294,7 +2368,6 @@ static GTY(()) tree class_ident;
 tree
 build_invokeinterface (tree dtable, tree method)
 {
-  tree lookup_arg;
   tree interface;
   tree idx;
 
@@ -2339,13 +2412,9 @@ build_invokeinterface (tree dtable, tree method)
       interface = build_class_ref (interface);
     }
                                                          
-  lookup_arg = tree_cons (NULL_TREE, dtable,
-                         tree_cons (NULL_TREE, interface,
-                                    build_tree_list (NULL_TREE, idx)));
-
-  return build3 (CALL_EXPR, ptr_type_node, 
-                build_address_of (soft_lookupinterfacemethod_node),
-                lookup_arg, NULL_TREE);
+  return build_call_nary (ptr_type_node, 
+                         build_address_of (soft_lookupinterfacemethod_node),
+                         3, dtable, interface, idx);
 }
   
 /* Expand one of the invoke_* opcodes.
@@ -2528,8 +2597,7 @@ expand_invoke (int opcode, int method_ref_index, int nargs ATTRIBUTE_UNUSED)
   else
     func = build1 (NOP_EXPR, build_pointer_type (method_type), func);
 
-  call = build3 (CALL_EXPR, TREE_TYPE (method_type),
-                func, arg_list, NULL_TREE);
+  call = build_call_list (TREE_TYPE (method_type), func, arg_list);
   TREE_SIDE_EFFECTS (call) = 1;
   call = check_for_builtin (method, call);
 
@@ -2554,7 +2622,8 @@ expand_invoke (int opcode, int method_ref_index, int nargs ATTRIBUTE_UNUSED)
 tree
 build_jni_stub (tree method)
 {
-  tree jnifunc, call, args, body, lookup_arg, method_sig, arg_types;
+  tree jnifunc, call, args, body, method_sig, arg_types;
+  tree jniarg0, jniarg1, jniarg2, jniarg3;
   tree jni_func_type, tem;
   tree env_var, res_var = NULL_TREE, block;
   tree method_args, res_type;
@@ -2564,7 +2633,6 @@ build_jni_stub (tree method)
   int args_size = 0;
 
   tree klass = DECL_CONTEXT (method);
-  int from_class = ! CLASS_FROM_SOURCE_P (klass);
   klass = build_class_ref (klass);
 
   gcc_assert (METHOD_NATIVE (method) && flag_jni);
@@ -2583,37 +2651,16 @@ build_jni_stub (tree method)
       TREE_CHAIN (env_var) = res_var;
     }
 
-  meth_var = build_decl (VAR_DECL, get_identifier ("meth"), ptr_type_node);
-  TREE_STATIC (meth_var) = 1;
-  TREE_PUBLIC (meth_var) = 0;
-  DECL_EXTERNAL (meth_var) = 0;
-  DECL_CONTEXT (meth_var) = method;
-  DECL_ARTIFICIAL (meth_var) = 1;
-  DECL_INITIAL (meth_var) = null_pointer_node;
-  TREE_USED (meth_var) = 1;
-  chainon (env_var, meth_var);
-  build_result_decl (method);
-
-  /* One strange way that the front ends are different is that they
-     store arguments differently.  */
-  if (from_class)
-    method_args = DECL_ARGUMENTS (method);
-  else
-    method_args = BLOCK_EXPR_DECLS (DECL_FUNCTION_BODY (method));
+  method_args = DECL_ARGUMENTS (method);
   block = build_block (env_var, NULL_TREE, method_args, NULL_TREE);
   TREE_SIDE_EFFECTS (block) = 1;
-  /* When compiling from source we don't set the type of the block,
-     because that will prevent patch_return from ever being run.  */
-  if (from_class)
-    TREE_TYPE (block) = TREE_TYPE (TREE_TYPE (method));
+  TREE_TYPE (block) = TREE_TYPE (TREE_TYPE (method));
 
   /* Compute the local `env' by calling _Jv_GetJNIEnvNewFrame.  */
   body = build2 (MODIFY_EXPR, ptr_type_node, env_var,
-                build3 (CALL_EXPR, ptr_type_node,
-                        build_address_of (soft_getjnienvnewframe_node),
-                        build_tree_list (NULL_TREE, klass),
-                        NULL_TREE));
-  CAN_COMPLETE_NORMALLY (body) = 1;
+                build_call_nary (ptr_type_node,
+                                 build_address_of (soft_getjnienvnewframe_node),
+                                 1, klass));
 
   /* All the arguments to this method become arguments to the
      underlying JNI function.  If we had to wrap object arguments in a
@@ -2651,18 +2698,14 @@ build_jni_stub (tree method)
   /* We call _Jv_LookupJNIMethod to find the actual underlying
      function pointer.  _Jv_LookupJNIMethod will throw the appropriate
      exception if this function is not found at runtime.  */
-  tem = build_tree_list (NULL_TREE, build_int_cst (NULL_TREE, args_size));
   method_sig = build_java_signature (TREE_TYPE (method));
-  lookup_arg = tree_cons (NULL_TREE,
-                          build_utf8_ref (unmangle_classname
-                                          (IDENTIFIER_POINTER (method_sig),
-                                           IDENTIFIER_LENGTH (method_sig))), 
-                          tem);
-  tem = DECL_NAME (method);
-  lookup_arg
-    = tree_cons (NULL_TREE, klass,
-                tree_cons (NULL_TREE, build_utf8_ref (tem), lookup_arg));
-  
+  jniarg0 = klass;
+  jniarg1 = build_utf8_ref (DECL_NAME (method));
+  jniarg2 = build_utf8_ref (unmangle_classname
+                           (IDENTIFIER_POINTER (method_sig),
+                            IDENTIFIER_LENGTH (method_sig)));
+  jniarg3 = build_int_cst (NULL_TREE, args_size);
+
   tem = build_function_type (TREE_TYPE (TREE_TYPE (method)), arg_types);
 
 #ifdef MODIFY_JNI_METHOD_CALL
@@ -2671,19 +2714,40 @@ build_jni_stub (tree method)
 
   jni_func_type = build_pointer_type (tem);
 
-  jnifunc = build3 (COND_EXPR, ptr_type_node,
-                   meth_var, meth_var,
-                   build2 (MODIFY_EXPR, ptr_type_node, meth_var,
-                           build3 (CALL_EXPR, ptr_type_node,
-                                   build_address_of
-                                     (soft_lookupjnimethod_node),
-                                   lookup_arg, NULL_TREE)));
+  /* Use the actual function type, rather than a generic pointer type,
+     such that this decl keeps the actual pointer type from being
+     garbage-collected.  If it is, we end up using canonical types
+     with different uids for equivalent function types, and this in
+     turn causes utf8 identifiers and output order to vary.  */
+  meth_var = build_decl (VAR_DECL, get_identifier ("meth"), jni_func_type);
+  TREE_STATIC (meth_var) = 1;
+  TREE_PUBLIC (meth_var) = 0;
+  DECL_EXTERNAL (meth_var) = 0;
+  DECL_CONTEXT (meth_var) = method;
+  DECL_ARTIFICIAL (meth_var) = 1;
+  DECL_INITIAL (meth_var) = null_pointer_node;
+  TREE_USED (meth_var) = 1;
+  chainon (env_var, meth_var);
+  build_result_decl (method);
+
+  jnifunc = build3 (COND_EXPR, jni_func_type,
+                   build2 (NE_EXPR, boolean_type_node,
+                           meth_var, build_int_cst (TREE_TYPE (meth_var), 0)),
+                   meth_var,
+                   build2 (MODIFY_EXPR, jni_func_type, meth_var,
+                           build1
+                           (NOP_EXPR, jni_func_type,
+                            build_call_nary (ptr_type_node,
+                                             build_address_of
+                                             (soft_lookupjnimethod_node),
+                                             4,
+                                             jniarg0, jniarg1,
+                                             jniarg2, jniarg3))));
 
   /* Now we make the actual JNI call via the resulting function
      pointer.    */
-  call = build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (method)),
-                build1 (NOP_EXPR, jni_func_type, jnifunc),
-                args, NULL_TREE);
+  call = build_call_list (TREE_TYPE (TREE_TYPE (method)),
+                         jnifunc, args);
 
   /* If the JNI call returned a result, capture it here.  If we had to
      unwrap JNI object results, we would do that here.  */
@@ -2692,27 +2756,23 @@ build_jni_stub (tree method)
       /* If the call returns an object, it may return a JNI weak
         reference, in which case we must unwrap it.  */
       if (! JPRIMITIVE_TYPE_P (TREE_TYPE (TREE_TYPE (method))))
-       call = build3 (CALL_EXPR, TREE_TYPE (TREE_TYPE (method)),
-                      build_address_of (soft_unwrapjni_node),
-                      build_tree_list (NULL_TREE, call),
-                      NULL_TREE);
+       call = build_call_nary (TREE_TYPE (TREE_TYPE (method)),
+                               build_address_of (soft_unwrapjni_node),
+                               1, call);
       call = build2 (MODIFY_EXPR, TREE_TYPE (TREE_TYPE (method)),
                     res_var, call);
     }
 
   TREE_SIDE_EFFECTS (call) = 1;
-  CAN_COMPLETE_NORMALLY (call) = 1;
 
   body = build2 (COMPOUND_EXPR, void_type_node, body, call);
   TREE_SIDE_EFFECTS (body) = 1;
 
   /* Now free the environment we allocated.  */
-  call = build3 (CALL_EXPR, ptr_type_node,
-                build_address_of (soft_jnipopsystemframe_node),
-                build_tree_list (NULL_TREE, env_var),
-                NULL_TREE);
+  call = build_call_nary (ptr_type_node,
+                         build_address_of (soft_jnipopsystemframe_node),
+                         1, env_var);
   TREE_SIDE_EFFECTS (call) = 1;
-  CAN_COMPLETE_NORMALLY (call) = 1;
   body = build2 (COMPOUND_EXPR, void_type_node, body, call);
   TREE_SIDE_EFFECTS (body) = 1;
 
@@ -2734,9 +2794,21 @@ build_jni_stub (tree method)
     }
 
   body = build2 (COMPOUND_EXPR, void_type_node, body,
-                build1 (RETURN_EXPR, res_type, res_var));
+                build1 (RETURN_EXPR, void_type_node, res_var));
   TREE_SIDE_EFFECTS (body) = 1;
   
+  /* Prepend class initialization for static methods reachable from
+     other classes.  */
+  if (METHOD_STATIC (method)
+      && (! METHOD_PRIVATE (method)
+          || INNER_CLASS_P (DECL_CONTEXT (method))))
+    {
+      tree init = build_call_expr (soft_initclass_node, 1, 
+                                  klass);
+      body = build2 (COMPOUND_EXPR, void_type_node, init, body);
+      TREE_SIDE_EFFECTS (body) = 1;
+    }
+
   bind = build3 (BIND_EXPR, void_type_node, BLOCK_VARS (block), 
                 body, block);
   return bind;
@@ -2838,7 +2910,13 @@ expand_java_field_op (int is_static, int is_putting, int field_ref_index)
   field_ref = build_field_ref (field_ref, self_type, field_name);
   if (is_static
       && ! flag_indirect_dispatch)
-    field_ref = build_class_init (self_type, field_ref);
+    {
+      tree context = DECL_CONTEXT (field_ref);
+      if (context != self_type && CLASS_INTERFACE (TYPE_NAME (context)))
+       field_ref = build_class_init (context, field_ref);
+      else
+       field_ref = build_class_init (self_type, field_ref);
+    }
   if (is_putting)
     {
       flush_quick_stack ();
@@ -2847,21 +2925,10 @@ expand_java_field_op (int is_static, int is_putting, int field_ref_index)
          if (DECL_CONTEXT (field_decl) != current_class)
             error ("assignment to final field %q+D not in field's class",
                    field_decl);
-         else if (FIELD_STATIC (field_decl))
-           {
-             if (!DECL_CLINIT_P (current_function_decl))
-               warning (0, "assignment to final static field %q+D not in "
-                         "class initializer",
-                         field_decl);
-           }
-         else
-           {
-             tree cfndecl_name = DECL_NAME (current_function_decl);
-             if (! DECL_CONSTRUCTOR_P (current_function_decl)
-                 && !ID_FINIT_P (cfndecl_name))
-                warning (0, "assignment to final field %q+D not in constructor",
-                        field_decl);
-           }
+         /* We used to check for assignments to final fields not
+            occurring in the class initializer or in a constructor
+            here.  However, this constraint doesn't seem to be
+            enforced by the JVM.  */
        }      
 
       if (TREE_THIS_VOLATILE (field_decl))
@@ -2871,11 +2938,8 @@ expand_java_field_op (int is_static, int is_putting, int field_ref_index)
                            field_ref, new_value);
 
       if (TREE_THIS_VOLATILE (field_decl))
-       java_add_stmt 
-         (build3 
-          (CALL_EXPR, void_type_node,
-           build_address_of (built_in_decls[BUILT_IN_SYNCHRONIZE]),
-           NULL_TREE, NULL_TREE));
+       java_add_stmt
+         (build_call_expr (built_in_decls[BUILT_IN_SYNCHRONIZE], 0));
          
       java_add_stmt (modify_expr);
     }
@@ -2893,21 +2957,18 @@ expand_java_field_op (int is_static, int is_putting, int field_ref_index)
 
       if (TREE_THIS_VOLATILE (field_decl))
        java_add_stmt 
-         (build3 
-          (CALL_EXPR, void_type_node,
-           build_address_of (built_in_decls[BUILT_IN_SYNCHRONIZE]),
-           NULL_TREE, NULL_TREE));
+         (build_call_expr (built_in_decls[BUILT_IN_SYNCHRONIZE], 0));
 
       push_value (temp);
     }      
   TREE_THIS_VOLATILE (field_ref) = TREE_THIS_VOLATILE (field_decl);
 }
 
-void
-load_type_state (tree label)
+static void
+load_type_state (int pc)
 {
   int i;
-  tree vec = LABEL_TYPE_STATE (label);
+  tree vec = VEC_index (tree, type_states, pc);
   int cur_length = TREE_VEC_LENGTH (vec);
   stack_pointer = cur_length - DECL_MAX_LOCALS(current_function_decl);
   for (i = 0; i < cur_length; i++)
@@ -2950,6 +3011,8 @@ note_instructions (JCF *jcf, tree method)
   byte_ops = jcf->read_ptr;
   instruction_bits = xrealloc (instruction_bits, length + 1);
   memset (instruction_bits, 0, length + 1);
+  type_states = VEC_alloc (tree, gc, length + 1);
+  VEC_safe_grow_cleared (tree, gc, type_states, length + 1);
 
   /* This pass figures out which PC can be the targets of jumps. */
   for (PC = 0; PC < length;)
@@ -3069,6 +3132,7 @@ expand_byte_code (JCF *jcf, tree method)
   int dead_code_index = -1;
   unsigned char* byte_ops;
   long length = DECL_CODE_LENGTH (method);
+  location_t max_location = input_location;
 
   stack_pointer = 0;
   JCF_SEEK (jcf, DECL_CODE_OFFSET (method));
@@ -3095,6 +3159,8 @@ expand_byte_code (JCF *jcf, tree method)
     return;
 
   promote_arguments ();
+  cache_this_class_ref (method);
+  cache_cpool_data_ref ();
 
   /* Translate bytecodes.  */
   linenumber_pointer = linenumber_table;
@@ -3106,8 +3172,8 @@ expand_byte_code (JCF *jcf, tree method)
           flush_quick_stack ();
          if ((instruction_bits [PC] & BCODE_TARGET) != 0)
            java_add_stmt (build1 (LABEL_EXPR, void_type_node, label));
-         if (LABEL_VERIFIED (label) || PC == 0)
-           load_type_state (label);
+         if ((instruction_bits[PC] & BCODE_VERIFIED) != 0)
+           load_type_state (PC);
        }
 
       if (! (instruction_bits [PC] & BCODE_VERIFIED))
@@ -3153,11 +3219,9 @@ expand_byte_code (JCF *jcf, tree method)
              if (pc == PC)
                {
                  int line = GET_u2 (linenumber_pointer - 2);
-#ifdef USE_MAPPED_LOCATION
-                 input_location = linemap_line_start (&line_table, line, 1);
-#else
-                 input_location.line = line;
-#endif
+                 input_location = linemap_line_start (line_table, line, 1);
+                 if (input_location > max_location)
+                   max_location = input_location;
                  if (!(instruction_bits[PC] & BCODE_HAS_MULTI_LINENUMBERS))
                    break;
                }
@@ -3167,7 +3231,9 @@ expand_byte_code (JCF *jcf, tree method)
       PC = process_jvm_instruction (PC, byte_ops, length);
       maybe_poplevels (PC);
     } /* for */
-  
+
+  uncache_this_class_ref (method);
+
   if (dead_code_index != -1)
     {
       /* We've just reached the end of a region of dead code.  */
@@ -3175,6 +3241,8 @@ expand_byte_code (JCF *jcf, tree method)
        warning (0, "unreachable bytecode from %d to the end of the method", 
                 dead_code_index);
     }
+
+  DECL_FUNCTION_LAST_LINE (method) = max_location;
 }
 
 static void
@@ -3413,7 +3481,6 @@ process_jvm_instruction (int PC, const unsigned char* byte_ops,
     decl = find_local_variable (index, type, oldpc);           \
     set_local_type (index, type);                              \
     java_add_stmt (build2 (MODIFY_EXPR, type, decl, value));   \
-    update_aliases (decl, index, PC);                          \
   }
 
 #define STORE(OPERAND_TYPE, OPERAND_VALUE) \
@@ -3646,45 +3713,40 @@ force_evaluation_order (tree node)
   if (flag_syntax_only)
     return node;
   if (TREE_CODE (node) == CALL_EXPR
-      || TREE_CODE (node) == NEW_CLASS_EXPR
       || (TREE_CODE (node) == COMPOUND_EXPR
          && TREE_CODE (TREE_OPERAND (node, 0)) == CALL_EXPR
          && TREE_CODE (TREE_OPERAND (node, 1)) == SAVE_EXPR)) 
     {
-      tree arg, cmp;
+      tree call, cmp;
+      int i, nargs;
 
-      arg = node;
-      
-      /* Position arg properly, account for wrapped around ctors. */
+      /* Account for wrapped around ctors.  */
       if (TREE_CODE (node) == COMPOUND_EXPR)
-        arg = TREE_OPERAND (node, 0);
-      
-      arg = TREE_OPERAND (arg, 1);
-      
-      /* An empty argument list is ok, just ignore it.  */
-      if (!arg)
-       return node;
+        call = TREE_OPERAND (node, 0);
+      else
+       call = node;
 
-      /* Not having a list of arguments here is an error. */ 
-      gcc_assert (TREE_CODE (arg) == TREE_LIST);
+      nargs = call_expr_nargs (call);
 
       /* This reverses the evaluation order. This is a desired effect. */
-      for (cmp = NULL_TREE; arg; arg = TREE_CHAIN (arg))
+      for (i = 0, cmp = NULL_TREE; i < nargs; i++)
        {
+         tree arg = CALL_EXPR_ARG (call, i);
          /* Promote types smaller than integer.  This is required by
             some ABIs.  */
-         tree type = TREE_TYPE (TREE_VALUE (arg));
+         tree type = TREE_TYPE (arg);
          tree saved;
          if (targetm.calls.promote_prototypes (type)
              && INTEGRAL_TYPE_P (type)
              && INT_CST_LT_UNSIGNED (TYPE_SIZE (type),
                                      TYPE_SIZE (integer_type_node)))
-           TREE_VALUE (arg) = fold_convert (integer_type_node, TREE_VALUE (arg));
+           arg = fold_convert (integer_type_node, arg);
 
-         saved = save_expr (force_evaluation_order (TREE_VALUE (arg)));
+         saved = save_expr (force_evaluation_order (arg));
          cmp = (cmp == NULL_TREE ? saved :
                 build2 (COMPOUND_EXPR, void_type_node, cmp, saved));
-         TREE_VALUE (arg) = saved;
+
+         CALL_EXPR_ARG (call, i) = saved;
        }
       
       if (cmp && TREE_CODE (cmp) == COMPOUND_EXPR)
@@ -3695,7 +3757,6 @@ force_evaluation_order (tree node)
          cmp = build2 (COMPOUND_EXPR, TREE_TYPE (node), cmp, node);
          if (TREE_TYPE (cmp) != void_type_node)
            cmp = save_expr (cmp);
-         CAN_COMPLETE_NORMALLY (cmp) = CAN_COMPLETE_NORMALLY (node);
          TREE_SIDE_EFFECTS (cmp) = 1;
          node = cmp;
        }
@@ -3703,94 +3764,12 @@ force_evaluation_order (tree node)
   return node;
 }
 
-/* EXPR_WITH_FILE_LOCATION are used to keep track of the exact
-   location where an expression or an identifier were encountered. It
-   is necessary for languages where the frontend parser will handle
-   recursively more than one file (Java is one of them).  */
-
-tree
-build_expr_wfl (tree node,
-#ifdef USE_MAPPED_LOCATION
-               source_location location
-#else
-               const char *file, int line, int col
-#endif
-)
-{
-  tree wfl;
-
-#ifdef USE_MAPPED_LOCATION
-  wfl = make_node (EXPR_WITH_FILE_LOCATION);
-  SET_EXPR_LOCATION (wfl, location);
-#else
-  static const char *last_file = 0;
-  static tree last_filenode = NULL_TREE;
-
-  wfl = make_node (EXPR_WITH_FILE_LOCATION);
-
-  EXPR_WFL_SET_LINECOL (wfl, line, col);
-  if (file != last_file)
-    {
-      last_file = file;
-      last_filenode = file ? get_identifier (file) : NULL_TREE;
-    }
-  EXPR_WFL_FILENAME_NODE (wfl) = last_filenode;
-#endif
-  EXPR_WFL_NODE (wfl) = node;
-  if (node)
-    {
-      if (!TYPE_P (node))
-       TREE_SIDE_EFFECTS (wfl) = TREE_SIDE_EFFECTS (node);
-      TREE_TYPE (wfl) = TREE_TYPE (node);
-    }
-
-  return wfl;
-}
-
-#ifdef USE_MAPPED_LOCATION
-tree
-expr_add_location (tree node, source_location location, bool statement)
-{
-  tree wfl;
-#if 0
-  /* FIXME. This optimization causes failures in code that expects an
-     EXPR_WITH_FILE_LOCATION.  E.g. in resolve_qualified_expression_name. */
-  if (node && ! (statement && flag_emit_class_files))
-    {
-      source_location node_loc = EXPR_LOCATION (node);
-      if (node_loc == location || location == UNKNOWN_LOCATION)
-       return node;
-      if (node_loc == UNKNOWN_LOCATION
-         && IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (node))))
-       {
-         SET_EXPR_LOCATION (node, location);
-         return node;
-       }
-    }
-#endif
-  wfl = make_node (EXPR_WITH_FILE_LOCATION);
-  SET_EXPR_LOCATION (wfl, location);
-  EXPR_WFL_NODE (wfl) = node;
-  if (statement && debug_info_level != DINFO_LEVEL_NONE)
-    EXPR_WFL_EMIT_LINE_NOTE (wfl) = 1;
-  if (node)
-    {
-      if (!TYPE_P (node))
-       TREE_SIDE_EFFECTS (wfl) = TREE_SIDE_EFFECTS (node);
-      TREE_TYPE (wfl) = TREE_TYPE (node);
-    }
-
-  return wfl;
-}
-#endif
-
 /* Build a node to represent empty statements and blocks. */
 
 tree
 build_java_empty_stmt (void)
 {
   tree t = build_empty_stmt ();
-  CAN_COMPLETE_NORMALLY (t) = 1;
   return t;
 }
 
@@ -3818,4 +3797,27 @@ promote_arguments (void)
     }
 }
 
+/* Create a local variable that points to the constant pool.  */
+
+static void
+cache_cpool_data_ref (void)
+{
+  if (optimize)
+    {
+      tree cpool;
+      tree d = build_constant_data_ref (flag_indirect_classes);
+      tree cpool_ptr = build_decl (VAR_DECL, NULL_TREE, 
+                                  build_pointer_type (TREE_TYPE (d)));
+      java_add_local_var (cpool_ptr);
+      TREE_INVARIANT (cpool_ptr) = 1;
+      TREE_CONSTANT (cpool_ptr) = 1;
+
+      java_add_stmt (build2 (MODIFY_EXPR, TREE_TYPE (cpool_ptr), 
+                            cpool_ptr, build_address_of (d)));
+      cpool = build1 (INDIRECT_REF, TREE_TYPE (d), cpool_ptr);
+      TREE_THIS_NOTRAP (cpool) = 1;
+      TYPE_CPOOL_DATA_REF (output_class) = cpool;
+    }
+}
+
 #include "gt-java-expr.h"