xref: /openbsd/gnu/usr.bin/gcc/gcc/java/expr.c (revision c87b03e5)
1*c87b03e5Sespie /* Process expressions for the GNU compiler for the Java(TM) language.
2*c87b03e5Sespie    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002
3*c87b03e5Sespie    Free Software Foundation, Inc.
4*c87b03e5Sespie 
5*c87b03e5Sespie This file is part of GNU CC.
6*c87b03e5Sespie 
7*c87b03e5Sespie GNU CC is free software; you can redistribute it and/or modify
8*c87b03e5Sespie it under the terms of the GNU General Public License as published by
9*c87b03e5Sespie the Free Software Foundation; either version 2, or (at your option)
10*c87b03e5Sespie any later version.
11*c87b03e5Sespie 
12*c87b03e5Sespie GNU CC is distributed in the hope that it will be useful,
13*c87b03e5Sespie but WITHOUT ANY WARRANTY; without even the implied warranty of
14*c87b03e5Sespie MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*c87b03e5Sespie GNU General Public License for more details.
16*c87b03e5Sespie 
17*c87b03e5Sespie You should have received a copy of the GNU General Public License
18*c87b03e5Sespie along with GNU CC; see the file COPYING.  If not, write to
19*c87b03e5Sespie the Free Software Foundation, 59 Temple Place - Suite 330,
20*c87b03e5Sespie Boston, MA 02111-1307, USA.
21*c87b03e5Sespie 
22*c87b03e5Sespie Java and all Java-based marks are trademarks or registered trademarks
23*c87b03e5Sespie of Sun Microsystems, Inc. in the United States and other countries.
24*c87b03e5Sespie The Free Software Foundation is independent of Sun Microsystems, Inc.  */
25*c87b03e5Sespie 
26*c87b03e5Sespie /* Hacked by Per Bothner <bothner@cygnus.com> February 1996. */
27*c87b03e5Sespie 
28*c87b03e5Sespie #include "config.h"
29*c87b03e5Sespie #include "system.h"
30*c87b03e5Sespie #include "tree.h"
31*c87b03e5Sespie #include "real.h"
32*c87b03e5Sespie #include "rtl.h"
33*c87b03e5Sespie #include "flags.h"
34*c87b03e5Sespie #include "expr.h"
35*c87b03e5Sespie #include "java-tree.h"
36*c87b03e5Sespie #include "javaop.h"
37*c87b03e5Sespie #include "java-opcodes.h"
38*c87b03e5Sespie #include "jcf.h"
39*c87b03e5Sespie #include "java-except.h"
40*c87b03e5Sespie #include "parse.h"
41*c87b03e5Sespie #include "toplev.h"
42*c87b03e5Sespie #include "except.h"
43*c87b03e5Sespie #include "ggc.h"
44*c87b03e5Sespie 
45*c87b03e5Sespie static void flush_quick_stack PARAMS ((void));
46*c87b03e5Sespie static void push_value PARAMS ((tree));
47*c87b03e5Sespie static tree pop_value PARAMS ((tree));
48*c87b03e5Sespie static void java_stack_swap PARAMS ((void));
49*c87b03e5Sespie static void java_stack_dup PARAMS ((int, int));
50*c87b03e5Sespie static void build_java_athrow PARAMS ((tree));
51*c87b03e5Sespie static void build_java_jsr PARAMS ((int, int));
52*c87b03e5Sespie static void build_java_ret PARAMS ((tree));
53*c87b03e5Sespie static void expand_java_multianewarray PARAMS ((tree, int));
54*c87b03e5Sespie static void expand_java_arraystore PARAMS ((tree));
55*c87b03e5Sespie static void expand_java_arrayload PARAMS ((tree));
56*c87b03e5Sespie static void expand_java_array_length PARAMS ((void));
57*c87b03e5Sespie static tree build_java_monitor PARAMS ((tree, tree));
58*c87b03e5Sespie static void expand_java_pushc PARAMS ((int, tree));
59*c87b03e5Sespie static void expand_java_return PARAMS ((tree));
60*c87b03e5Sespie static void expand_load_internal PARAMS ((int, tree, int));
61*c87b03e5Sespie static void expand_java_NEW PARAMS ((tree));
62*c87b03e5Sespie static void expand_java_INSTANCEOF PARAMS ((tree));
63*c87b03e5Sespie static void expand_java_CHECKCAST PARAMS ((tree));
64*c87b03e5Sespie static void expand_iinc PARAMS ((unsigned int, int, int));
65*c87b03e5Sespie static void expand_java_binop PARAMS ((tree, enum tree_code));
66*c87b03e5Sespie static void note_label PARAMS ((int, int));
67*c87b03e5Sespie static void expand_compare PARAMS ((enum tree_code, tree, tree, int));
68*c87b03e5Sespie static void expand_test PARAMS ((enum tree_code, tree, int));
69*c87b03e5Sespie static void expand_cond PARAMS ((enum tree_code, tree, int));
70*c87b03e5Sespie static void expand_java_goto PARAMS ((int));
71*c87b03e5Sespie #if 0
72*c87b03e5Sespie static void expand_java_call PARAMS ((int, int));
73*c87b03e5Sespie static void expand_java_ret PARAMS ((tree));
74*c87b03e5Sespie #endif
75*c87b03e5Sespie static tree pop_arguments PARAMS ((tree));
76*c87b03e5Sespie static void expand_invoke PARAMS ((int, int, int));
77*c87b03e5Sespie static void expand_java_field_op PARAMS ((int, int, int));
78*c87b03e5Sespie static void java_push_constant_from_pool PARAMS ((struct JCF *, int));
79*c87b03e5Sespie static void java_stack_pop PARAMS ((int));
80*c87b03e5Sespie static tree build_java_throw_out_of_bounds_exception PARAMS ((tree));
81*c87b03e5Sespie static tree build_java_check_indexed_type PARAMS ((tree, tree));
82*c87b03e5Sespie static tree case_identity PARAMS ((tree, tree));
83*c87b03e5Sespie static unsigned char peek_opcode_at_pc PARAMS ((struct JCF *, int, int));
84*c87b03e5Sespie static int emit_init_test_initialization PARAMS ((void **entry,
85*c87b03e5Sespie 						  void * ptr));
86*c87b03e5Sespie static int get_offset_table_index PARAMS ((tree));
87*c87b03e5Sespie 
88*c87b03e5Sespie static GTY(()) tree operand_type[59];
89*c87b03e5Sespie 
90*c87b03e5Sespie static GTY(()) tree methods_ident;
91*c87b03e5Sespie static GTY(()) tree ncode_ident;
92*c87b03e5Sespie tree dtable_ident = NULL_TREE;
93*c87b03e5Sespie 
94*c87b03e5Sespie /* Set to nonzero value in order to emit class initilization code
95*c87b03e5Sespie    before static field references.  */
96*c87b03e5Sespie int always_initialize_class_p;
97*c87b03e5Sespie 
98*c87b03e5Sespie /* We store the stack state in two places:
99*c87b03e5Sespie    Within a basic block, we use the quick_stack, which is a
100*c87b03e5Sespie    pushdown list (TREE_LISTs) of expression nodes.
101*c87b03e5Sespie    This is the top part of the stack;  below that we use find_stack_slot.
102*c87b03e5Sespie    At the end of a basic block, the quick_stack must be flushed
103*c87b03e5Sespie    to the stack slot array (as handled by find_stack_slot).
104*c87b03e5Sespie    Using quick_stack generates better code (especially when
105*c87b03e5Sespie    compiled without optimization), because we do not have to
106*c87b03e5Sespie    explicitly store and load trees to temporary variables.
107*c87b03e5Sespie 
108*c87b03e5Sespie    If a variable is on the quick stack, it means the value of variable
109*c87b03e5Sespie    when the quick stack was last flushed.  Conceptually, flush_quick_stack
110*c87b03e5Sespie    saves all the the quick_stack elements in parellel.  However, that is
111*c87b03e5Sespie    complicated, so it actually saves them (i.e. copies each stack value
112*c87b03e5Sespie    to is home virtual register) from low indexes.  This allows a quick_stack
113*c87b03e5Sespie    element at index i (counting from the bottom of stack the) to references
114*c87b03e5Sespie    slot virtuals for register that are >= i, but not those that are deeper.
115*c87b03e5Sespie    This convention makes most operations easier.  For example iadd works
116*c87b03e5Sespie    even when the stack contains (reg[0], reg[1]):  It results in the
117*c87b03e5Sespie    stack containing (reg[0]+reg[1]), which is OK.  However, some stack
118*c87b03e5Sespie    operations are more complicated.  For example dup given a stack
119*c87b03e5Sespie    containing (reg[0]) would yield (reg[0], reg[0]), which would violate
120*c87b03e5Sespie    the convention, since stack value 1 would refer to a register with
121*c87b03e5Sespie    lower index (reg[0]), which flush_quick_stack does not safely handle.
122*c87b03e5Sespie    So dup cannot just add an extra element to the quick_stack, but iadd can.
123*c87b03e5Sespie */
124*c87b03e5Sespie 
125*c87b03e5Sespie static GTY(()) tree quick_stack;
126*c87b03e5Sespie 
127*c87b03e5Sespie /* A free-list of unused permamnet TREE_LIST nodes. */
128*c87b03e5Sespie static GTY((deletable (""))) tree tree_list_free_list;
129*c87b03e5Sespie 
130*c87b03e5Sespie /* The stack pointer of the Java virtual machine.
131*c87b03e5Sespie    This does include the size of the quick_stack. */
132*c87b03e5Sespie 
133*c87b03e5Sespie int stack_pointer;
134*c87b03e5Sespie 
135*c87b03e5Sespie const unsigned char *linenumber_table;
136*c87b03e5Sespie int linenumber_count;
137*c87b03e5Sespie 
138*c87b03e5Sespie void
init_expr_processing()139*c87b03e5Sespie init_expr_processing()
140*c87b03e5Sespie {
141*c87b03e5Sespie   operand_type[21] = operand_type[54] = int_type_node;
142*c87b03e5Sespie   operand_type[22] = operand_type[55] = long_type_node;
143*c87b03e5Sespie   operand_type[23] = operand_type[56] = float_type_node;
144*c87b03e5Sespie   operand_type[24] = operand_type[57] = double_type_node;
145*c87b03e5Sespie   operand_type[25] = operand_type[58] = ptr_type_node;
146*c87b03e5Sespie }
147*c87b03e5Sespie 
148*c87b03e5Sespie tree
java_truthvalue_conversion(expr)149*c87b03e5Sespie java_truthvalue_conversion (expr)
150*c87b03e5Sespie      tree expr;
151*c87b03e5Sespie {
152*c87b03e5Sespie   /* It is simpler and generates better code to have only TRUTH_*_EXPR
153*c87b03e5Sespie      or comparison expressions as truth values at this level.
154*c87b03e5Sespie 
155*c87b03e5Sespie      This function should normally be identity for Java.  */
156*c87b03e5Sespie 
157*c87b03e5Sespie   switch (TREE_CODE (expr))
158*c87b03e5Sespie     {
159*c87b03e5Sespie     case EQ_EXPR:
160*c87b03e5Sespie     case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
161*c87b03e5Sespie     case TRUTH_ANDIF_EXPR:
162*c87b03e5Sespie     case TRUTH_ORIF_EXPR:
163*c87b03e5Sespie     case TRUTH_AND_EXPR:
164*c87b03e5Sespie     case TRUTH_OR_EXPR:
165*c87b03e5Sespie     case ERROR_MARK:
166*c87b03e5Sespie       return expr;
167*c87b03e5Sespie 
168*c87b03e5Sespie     case INTEGER_CST:
169*c87b03e5Sespie       return integer_zerop (expr) ? boolean_false_node : boolean_true_node;
170*c87b03e5Sespie 
171*c87b03e5Sespie     case REAL_CST:
172*c87b03e5Sespie       return real_zerop (expr) ? boolean_false_node : boolean_true_node;
173*c87b03e5Sespie 
174*c87b03e5Sespie     /* are these legal? XXX JH */
175*c87b03e5Sespie     case NEGATE_EXPR:
176*c87b03e5Sespie     case ABS_EXPR:
177*c87b03e5Sespie     case FLOAT_EXPR:
178*c87b03e5Sespie     case FFS_EXPR:
179*c87b03e5Sespie       /* These don't change whether an object is nonzero or zero.  */
180*c87b03e5Sespie       return java_truthvalue_conversion (TREE_OPERAND (expr, 0));
181*c87b03e5Sespie 
182*c87b03e5Sespie     case COND_EXPR:
183*c87b03e5Sespie       /* Distribute the conversion into the arms of a COND_EXPR.  */
184*c87b03e5Sespie       return fold (build (COND_EXPR, boolean_type_node, TREE_OPERAND (expr, 0),
185*c87b03e5Sespie                           java_truthvalue_conversion (TREE_OPERAND (expr, 1)),
186*c87b03e5Sespie                           java_truthvalue_conversion (TREE_OPERAND (expr, 2))));
187*c87b03e5Sespie 
188*c87b03e5Sespie     case NOP_EXPR:
189*c87b03e5Sespie       /* If this is widening the argument, we can ignore it.  */
190*c87b03e5Sespie       if (TYPE_PRECISION (TREE_TYPE (expr))
191*c87b03e5Sespie           >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
192*c87b03e5Sespie         return java_truthvalue_conversion (TREE_OPERAND (expr, 0));
193*c87b03e5Sespie       /* fall through to default */
194*c87b03e5Sespie 
195*c87b03e5Sespie     default:
196*c87b03e5Sespie       return fold (build (NE_EXPR, boolean_type_node, expr, boolean_false_node));
197*c87b03e5Sespie     }
198*c87b03e5Sespie }
199*c87b03e5Sespie 
200*c87b03e5Sespie /* Save any stack slots that happen to be in the quick_stack into their
201*c87b03e5Sespie    home virtual register slots.
202*c87b03e5Sespie 
203*c87b03e5Sespie    The copy order is from low stack index to high, to support the invariant
204*c87b03e5Sespie    that the expression for a slot may contain decls for stack slots with
205*c87b03e5Sespie    higher (or the same) index, but not lower. */
206*c87b03e5Sespie 
207*c87b03e5Sespie static void
flush_quick_stack()208*c87b03e5Sespie flush_quick_stack ()
209*c87b03e5Sespie {
210*c87b03e5Sespie   int stack_index = stack_pointer;
211*c87b03e5Sespie   register tree prev, cur, next;
212*c87b03e5Sespie 
213*c87b03e5Sespie   /* First reverse the quick_stack, and count the number of slots it has. */
214*c87b03e5Sespie   for (cur = quick_stack, prev = NULL_TREE; cur != NULL_TREE; cur = next)
215*c87b03e5Sespie     {
216*c87b03e5Sespie       next = TREE_CHAIN (cur);
217*c87b03e5Sespie       TREE_CHAIN (cur) = prev;
218*c87b03e5Sespie       prev = cur;
219*c87b03e5Sespie       stack_index -= 1 + TYPE_IS_WIDE (TREE_TYPE (TREE_VALUE (cur)));
220*c87b03e5Sespie     }
221*c87b03e5Sespie   quick_stack = prev;
222*c87b03e5Sespie 
223*c87b03e5Sespie   while (quick_stack != NULL_TREE)
224*c87b03e5Sespie     {
225*c87b03e5Sespie       tree decl;
226*c87b03e5Sespie       tree node = quick_stack, type;
227*c87b03e5Sespie       quick_stack = TREE_CHAIN (node);
228*c87b03e5Sespie       TREE_CHAIN (node) = tree_list_free_list;
229*c87b03e5Sespie       tree_list_free_list = node;
230*c87b03e5Sespie       node = TREE_VALUE (node);
231*c87b03e5Sespie       type = TREE_TYPE (node);
232*c87b03e5Sespie 
233*c87b03e5Sespie       decl = find_stack_slot (stack_index, type);
234*c87b03e5Sespie       if (decl != node)
235*c87b03e5Sespie 	  expand_assignment (decl, node, 0, 0);
236*c87b03e5Sespie       stack_index += 1 + TYPE_IS_WIDE (type);
237*c87b03e5Sespie     }
238*c87b03e5Sespie }
239*c87b03e5Sespie 
240*c87b03e5Sespie /* Push TYPE on the type stack.
241*c87b03e5Sespie    Return true on success, 0 on overflow. */
242*c87b03e5Sespie 
243*c87b03e5Sespie int
push_type_0(type)244*c87b03e5Sespie push_type_0 (type)
245*c87b03e5Sespie      tree type;
246*c87b03e5Sespie {
247*c87b03e5Sespie   int n_words;
248*c87b03e5Sespie   type = promote_type (type);
249*c87b03e5Sespie   n_words = 1 + TYPE_IS_WIDE (type);
250*c87b03e5Sespie   if (stack_pointer + n_words > DECL_MAX_STACK (current_function_decl))
251*c87b03e5Sespie     return 0;
252*c87b03e5Sespie   stack_type_map[stack_pointer++] = type;
253*c87b03e5Sespie   n_words--;
254*c87b03e5Sespie   while (--n_words >= 0)
255*c87b03e5Sespie     stack_type_map[stack_pointer++] = TYPE_SECOND;
256*c87b03e5Sespie   return 1;
257*c87b03e5Sespie }
258*c87b03e5Sespie 
259*c87b03e5Sespie void
push_type(type)260*c87b03e5Sespie push_type (type)
261*c87b03e5Sespie      tree type;
262*c87b03e5Sespie {
263*c87b03e5Sespie   if (! push_type_0 (type))
264*c87b03e5Sespie     abort ();
265*c87b03e5Sespie }
266*c87b03e5Sespie 
267*c87b03e5Sespie static void
push_value(value)268*c87b03e5Sespie push_value (value)
269*c87b03e5Sespie      tree value;
270*c87b03e5Sespie {
271*c87b03e5Sespie   tree type = TREE_TYPE (value);
272*c87b03e5Sespie   if (TYPE_PRECISION (type) < 32 && INTEGRAL_TYPE_P (type))
273*c87b03e5Sespie     {
274*c87b03e5Sespie       type = promote_type (type);
275*c87b03e5Sespie       value = convert (type, value);
276*c87b03e5Sespie     }
277*c87b03e5Sespie   push_type (type);
278*c87b03e5Sespie   if (tree_list_free_list == NULL_TREE)
279*c87b03e5Sespie     quick_stack = tree_cons (NULL_TREE, value, quick_stack);
280*c87b03e5Sespie   else
281*c87b03e5Sespie     {
282*c87b03e5Sespie       tree node = tree_list_free_list;
283*c87b03e5Sespie       tree_list_free_list = TREE_CHAIN (tree_list_free_list);
284*c87b03e5Sespie       TREE_VALUE (node) = value;
285*c87b03e5Sespie       TREE_CHAIN (node) = quick_stack;
286*c87b03e5Sespie       quick_stack = node;
287*c87b03e5Sespie     }
288*c87b03e5Sespie }
289*c87b03e5Sespie 
290*c87b03e5Sespie /* Pop a type from the type stack.
291*c87b03e5Sespie    TYPE is the expected type.   Return the actual type, which must be
292*c87b03e5Sespie    convertible to TYPE.
293*c87b03e5Sespie    On an error, *MESSAGEP is set to a freshly malloc'd error message. */
294*c87b03e5Sespie 
295*c87b03e5Sespie tree
pop_type_0(type,messagep)296*c87b03e5Sespie pop_type_0 (type, messagep)
297*c87b03e5Sespie      tree type;
298*c87b03e5Sespie      char **messagep;
299*c87b03e5Sespie {
300*c87b03e5Sespie   int n_words;
301*c87b03e5Sespie   tree t;
302*c87b03e5Sespie   *messagep = NULL;
303*c87b03e5Sespie   if (TREE_CODE (type) == RECORD_TYPE)
304*c87b03e5Sespie     type = promote_type (type);
305*c87b03e5Sespie   n_words = 1 + TYPE_IS_WIDE (type);
306*c87b03e5Sespie   if (stack_pointer < n_words)
307*c87b03e5Sespie     {
308*c87b03e5Sespie       *messagep = xstrdup ("stack underflow");
309*c87b03e5Sespie       return type;
310*c87b03e5Sespie     }
311*c87b03e5Sespie   while (--n_words > 0)
312*c87b03e5Sespie     {
313*c87b03e5Sespie       if (stack_type_map[--stack_pointer] != void_type_node)
314*c87b03e5Sespie 	{
315*c87b03e5Sespie 	  *messagep = xstrdup ("Invalid multi-word value on type stack");
316*c87b03e5Sespie 	  return type;
317*c87b03e5Sespie 	}
318*c87b03e5Sespie     }
319*c87b03e5Sespie   t = stack_type_map[--stack_pointer];
320*c87b03e5Sespie   if (type == NULL_TREE || t == type)
321*c87b03e5Sespie     return t;
322*c87b03e5Sespie   if (INTEGRAL_TYPE_P (type) && INTEGRAL_TYPE_P (t)
323*c87b03e5Sespie       && TYPE_PRECISION (type) <= 32 && TYPE_PRECISION (t) <= 32)
324*c87b03e5Sespie       return t;
325*c87b03e5Sespie   if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (t) == POINTER_TYPE)
326*c87b03e5Sespie     {
327*c87b03e5Sespie       if (type == ptr_type_node || type == object_ptr_type_node)
328*c87b03e5Sespie 	return t;
329*c87b03e5Sespie       else if (t == ptr_type_node)  /* Special case for null reference. */
330*c87b03e5Sespie 	return type;
331*c87b03e5Sespie       else if (can_widen_reference_to (t, type))
332*c87b03e5Sespie 	return t;
333*c87b03e5Sespie       /* This is a kludge, but matches what Sun's verifier does.
334*c87b03e5Sespie 	 It can be tricked, but is safe as long as type errors
335*c87b03e5Sespie 	 (i.e. interface method calls) are caught at run-time. */
336*c87b03e5Sespie       else if (CLASS_INTERFACE (TYPE_NAME (TREE_TYPE (type))))
337*c87b03e5Sespie 	return object_ptr_type_node;
338*c87b03e5Sespie     }
339*c87b03e5Sespie 
340*c87b03e5Sespie   /* lang_printable_name uses a static buffer, so we must save the result
341*c87b03e5Sespie      from calling it the first time.  */
342*c87b03e5Sespie   {
343*c87b03e5Sespie     char *temp = xstrdup (lang_printable_name (type, 0));
344*c87b03e5Sespie     *messagep = concat ("expected type '", temp,
345*c87b03e5Sespie 			"' but stack contains '", lang_printable_name (t, 0),
346*c87b03e5Sespie 			"'", NULL);
347*c87b03e5Sespie     free (temp);
348*c87b03e5Sespie   }
349*c87b03e5Sespie   return type;
350*c87b03e5Sespie }
351*c87b03e5Sespie 
352*c87b03e5Sespie /* Pop a type from the type stack.
353*c87b03e5Sespie    TYPE is the expected type.  Return the actual type, which must be
354*c87b03e5Sespie    convertible to TYPE, otherwise call error. */
355*c87b03e5Sespie 
356*c87b03e5Sespie tree
pop_type(type)357*c87b03e5Sespie pop_type (type)
358*c87b03e5Sespie      tree type;
359*c87b03e5Sespie {
360*c87b03e5Sespie   char *message = NULL;
361*c87b03e5Sespie   type = pop_type_0 (type, &message);
362*c87b03e5Sespie   if (message != NULL)
363*c87b03e5Sespie     {
364*c87b03e5Sespie       error ("%s", message);
365*c87b03e5Sespie       free (message);
366*c87b03e5Sespie     }
367*c87b03e5Sespie   return type;
368*c87b03e5Sespie }
369*c87b03e5Sespie 
370*c87b03e5Sespie /* Return 1f if SOURCE_TYPE can be safely widened to TARGET_TYPE.
371*c87b03e5Sespie    Handles array types and interfaces.  */
372*c87b03e5Sespie 
373*c87b03e5Sespie int
can_widen_reference_to(source_type,target_type)374*c87b03e5Sespie can_widen_reference_to (source_type, target_type)
375*c87b03e5Sespie      tree source_type, target_type;
376*c87b03e5Sespie {
377*c87b03e5Sespie   if (source_type == ptr_type_node || target_type == object_ptr_type_node)
378*c87b03e5Sespie     return 1;
379*c87b03e5Sespie 
380*c87b03e5Sespie   /* Get rid of pointers  */
381*c87b03e5Sespie   if (TREE_CODE (source_type) == POINTER_TYPE)
382*c87b03e5Sespie     source_type = TREE_TYPE (source_type);
383*c87b03e5Sespie   if (TREE_CODE (target_type) == POINTER_TYPE)
384*c87b03e5Sespie     target_type = TREE_TYPE (target_type);
385*c87b03e5Sespie 
386*c87b03e5Sespie   if (source_type == target_type)
387*c87b03e5Sespie     return 1;
388*c87b03e5Sespie   else
389*c87b03e5Sespie     {
390*c87b03e5Sespie       if (TYPE_ARRAY_P (source_type) || TYPE_ARRAY_P (target_type))
391*c87b03e5Sespie 	{
392*c87b03e5Sespie 	  HOST_WIDE_INT source_length, target_length;
393*c87b03e5Sespie 	  if (TYPE_ARRAY_P (source_type) != TYPE_ARRAY_P (target_type))
394*c87b03e5Sespie 	    {
395*c87b03e5Sespie 	      /* An array implements Cloneable and Serializable.  */
396*c87b03e5Sespie 	      tree name = DECL_NAME (TYPE_NAME (target_type));
397*c87b03e5Sespie 	      return (name == java_lang_cloneable_identifier_node
398*c87b03e5Sespie 		      || name == java_io_serializable_identifier_node);
399*c87b03e5Sespie 	    }
400*c87b03e5Sespie 	  target_length = java_array_type_length (target_type);
401*c87b03e5Sespie 	  if (target_length >= 0)
402*c87b03e5Sespie 	    {
403*c87b03e5Sespie 	      source_length = java_array_type_length (source_type);
404*c87b03e5Sespie 	      if (source_length != target_length)
405*c87b03e5Sespie 		return 0;
406*c87b03e5Sespie 	    }
407*c87b03e5Sespie 	  source_type = TYPE_ARRAY_ELEMENT (source_type);
408*c87b03e5Sespie 	  target_type = TYPE_ARRAY_ELEMENT (target_type);
409*c87b03e5Sespie 	  if (source_type == target_type)
410*c87b03e5Sespie 	    return 1;
411*c87b03e5Sespie 	  if (TREE_CODE (source_type) != POINTER_TYPE
412*c87b03e5Sespie 	      || TREE_CODE (target_type) != POINTER_TYPE)
413*c87b03e5Sespie 	    return 0;
414*c87b03e5Sespie 	  return can_widen_reference_to (source_type, target_type);
415*c87b03e5Sespie 	}
416*c87b03e5Sespie       else
417*c87b03e5Sespie 	{
418*c87b03e5Sespie 	  int source_depth = class_depth (source_type);
419*c87b03e5Sespie 	  int target_depth = class_depth (target_type);
420*c87b03e5Sespie 
421*c87b03e5Sespie 	  /* class_depth can return a negative depth if an error occurred */
422*c87b03e5Sespie 	  if (source_depth < 0 || target_depth < 0)
423*c87b03e5Sespie 	    return 0;
424*c87b03e5Sespie 
425*c87b03e5Sespie 	  if (CLASS_INTERFACE (TYPE_NAME (target_type)))
426*c87b03e5Sespie 	    {
427*c87b03e5Sespie 	      /* target_type is OK if source_type or source_type ancestors
428*c87b03e5Sespie 		 implement target_type. We handle multiple sub-interfaces  */
429*c87b03e5Sespie 
430*c87b03e5Sespie 	      tree basetype_vec = TYPE_BINFO_BASETYPES (source_type);
431*c87b03e5Sespie 	      int n = TREE_VEC_LENGTH (basetype_vec), i;
432*c87b03e5Sespie 	      for (i=0 ; i < n; i++)
433*c87b03e5Sespie 	        if (can_widen_reference_to
434*c87b03e5Sespie 		    (TREE_TYPE (TREE_VEC_ELT (basetype_vec, i)),
435*c87b03e5Sespie 		     target_type))
436*c87b03e5Sespie 		  return 1;
437*c87b03e5Sespie 	      if (n == 0)
438*c87b03e5Sespie 		return 0;
439*c87b03e5Sespie 	    }
440*c87b03e5Sespie 
441*c87b03e5Sespie 	  for ( ; source_depth > target_depth;  source_depth--)
442*c87b03e5Sespie 	    {
443*c87b03e5Sespie 	      source_type = TYPE_BINFO_BASETYPE (source_type, 0);
444*c87b03e5Sespie 	    }
445*c87b03e5Sespie 	  return source_type == target_type;
446*c87b03e5Sespie 	}
447*c87b03e5Sespie     }
448*c87b03e5Sespie }
449*c87b03e5Sespie 
450*c87b03e5Sespie static tree
pop_value(type)451*c87b03e5Sespie pop_value (type)
452*c87b03e5Sespie      tree type;
453*c87b03e5Sespie {
454*c87b03e5Sespie   type = pop_type (type);
455*c87b03e5Sespie   if (quick_stack)
456*c87b03e5Sespie     {
457*c87b03e5Sespie       tree node = quick_stack;
458*c87b03e5Sespie       quick_stack = TREE_CHAIN (quick_stack);
459*c87b03e5Sespie       TREE_CHAIN (node) = tree_list_free_list;
460*c87b03e5Sespie       tree_list_free_list = node;
461*c87b03e5Sespie       node = TREE_VALUE (node);
462*c87b03e5Sespie       return node;
463*c87b03e5Sespie     }
464*c87b03e5Sespie   else
465*c87b03e5Sespie     return find_stack_slot (stack_pointer, promote_type (type));
466*c87b03e5Sespie }
467*c87b03e5Sespie 
468*c87b03e5Sespie 
469*c87b03e5Sespie /* Pop and discrad the top COUNT stack slots. */
470*c87b03e5Sespie 
471*c87b03e5Sespie static void
java_stack_pop(count)472*c87b03e5Sespie java_stack_pop (count)
473*c87b03e5Sespie      int count;
474*c87b03e5Sespie {
475*c87b03e5Sespie   while (count > 0)
476*c87b03e5Sespie     {
477*c87b03e5Sespie       tree type, val;
478*c87b03e5Sespie 
479*c87b03e5Sespie       if (stack_pointer == 0)
480*c87b03e5Sespie 	abort ();
481*c87b03e5Sespie 
482*c87b03e5Sespie       type = stack_type_map[stack_pointer - 1];
483*c87b03e5Sespie       if (type == TYPE_SECOND)
484*c87b03e5Sespie 	{
485*c87b03e5Sespie 	  count--;
486*c87b03e5Sespie 	  if (stack_pointer == 1 || count <= 0)
487*c87b03e5Sespie 	    abort ();
488*c87b03e5Sespie 
489*c87b03e5Sespie 	  type = stack_type_map[stack_pointer - 2];
490*c87b03e5Sespie 	}
491*c87b03e5Sespie       val = pop_value (type);
492*c87b03e5Sespie       count--;
493*c87b03e5Sespie     }
494*c87b03e5Sespie }
495*c87b03e5Sespie 
496*c87b03e5Sespie /* Implement the 'swap' operator (to swap two top stack slots). */
497*c87b03e5Sespie 
498*c87b03e5Sespie static void
java_stack_swap()499*c87b03e5Sespie java_stack_swap ()
500*c87b03e5Sespie {
501*c87b03e5Sespie   tree type1, type2;
502*c87b03e5Sespie   rtx temp;
503*c87b03e5Sespie   tree decl1, decl2;
504*c87b03e5Sespie 
505*c87b03e5Sespie   if (stack_pointer < 2
506*c87b03e5Sespie       || (type1 = stack_type_map[stack_pointer - 1]) == TYPE_UNKNOWN
507*c87b03e5Sespie       || (type2 = stack_type_map[stack_pointer - 2]) == TYPE_UNKNOWN
508*c87b03e5Sespie       || type1 == TYPE_SECOND || type2 == TYPE_SECOND
509*c87b03e5Sespie       || TYPE_IS_WIDE (type1) || TYPE_IS_WIDE (type2))
510*c87b03e5Sespie     /* Bad stack swap.  */
511*c87b03e5Sespie     abort ();
512*c87b03e5Sespie 
513*c87b03e5Sespie   flush_quick_stack ();
514*c87b03e5Sespie   decl1 = find_stack_slot (stack_pointer - 1, type1);
515*c87b03e5Sespie   decl2 = find_stack_slot (stack_pointer - 2, type2);
516*c87b03e5Sespie   temp = copy_to_reg (DECL_RTL (decl1));
517*c87b03e5Sespie   emit_move_insn (DECL_RTL (decl1), DECL_RTL (decl2));
518*c87b03e5Sespie   emit_move_insn (DECL_RTL (decl2), temp);
519*c87b03e5Sespie   stack_type_map[stack_pointer - 1] = type2;
520*c87b03e5Sespie   stack_type_map[stack_pointer - 2] = type1;
521*c87b03e5Sespie }
522*c87b03e5Sespie 
523*c87b03e5Sespie static void
java_stack_dup(size,offset)524*c87b03e5Sespie java_stack_dup (size, offset)
525*c87b03e5Sespie      int size, offset;
526*c87b03e5Sespie {
527*c87b03e5Sespie   int low_index = stack_pointer - size - offset;
528*c87b03e5Sespie   int dst_index;
529*c87b03e5Sespie   if (low_index < 0)
530*c87b03e5Sespie     error ("stack underflow - dup* operation");
531*c87b03e5Sespie 
532*c87b03e5Sespie   flush_quick_stack ();
533*c87b03e5Sespie 
534*c87b03e5Sespie   stack_pointer += size;
535*c87b03e5Sespie   dst_index = stack_pointer;
536*c87b03e5Sespie 
537*c87b03e5Sespie   for (dst_index = stack_pointer;  --dst_index >= low_index; )
538*c87b03e5Sespie     {
539*c87b03e5Sespie       tree type;
540*c87b03e5Sespie       int src_index = dst_index - size;
541*c87b03e5Sespie       if (src_index < low_index)
542*c87b03e5Sespie 	src_index = dst_index + size + offset;
543*c87b03e5Sespie       type = stack_type_map [src_index];
544*c87b03e5Sespie       if (type == TYPE_SECOND)
545*c87b03e5Sespie 	{
546*c87b03e5Sespie 	  if (src_index <= low_index)
547*c87b03e5Sespie 	    /* Dup operation splits 64-bit number.  */
548*c87b03e5Sespie 	    abort ();
549*c87b03e5Sespie 
550*c87b03e5Sespie 	  stack_type_map[dst_index] = type;
551*c87b03e5Sespie 	  src_index--;  dst_index--;
552*c87b03e5Sespie 	  type = stack_type_map[src_index];
553*c87b03e5Sespie 	  if (! TYPE_IS_WIDE (type))
554*c87b03e5Sespie 	    abort ();
555*c87b03e5Sespie 	}
556*c87b03e5Sespie       else if (TYPE_IS_WIDE (type))
557*c87b03e5Sespie 	abort ();
558*c87b03e5Sespie 
559*c87b03e5Sespie       if (src_index != dst_index)
560*c87b03e5Sespie 	{
561*c87b03e5Sespie 	  tree src_decl = find_stack_slot (src_index, type);
562*c87b03e5Sespie 	  tree dst_decl = find_stack_slot (dst_index, type);
563*c87b03e5Sespie 	  emit_move_insn (DECL_RTL (dst_decl), DECL_RTL (src_decl));
564*c87b03e5Sespie 	  stack_type_map[dst_index] = type;
565*c87b03e5Sespie 	}
566*c87b03e5Sespie     }
567*c87b03e5Sespie }
568*c87b03e5Sespie 
569*c87b03e5Sespie /* Calls _Jv_Throw or _Jv_Sjlj_Throw.  Discard the contents of the
570*c87b03e5Sespie    value stack. */
571*c87b03e5Sespie 
572*c87b03e5Sespie static void
build_java_athrow(node)573*c87b03e5Sespie build_java_athrow (node)
574*c87b03e5Sespie     tree node;
575*c87b03e5Sespie {
576*c87b03e5Sespie   tree call;
577*c87b03e5Sespie 
578*c87b03e5Sespie   call = build (CALL_EXPR,
579*c87b03e5Sespie 		void_type_node,
580*c87b03e5Sespie 		build_address_of (throw_node),
581*c87b03e5Sespie 		build_tree_list (NULL_TREE, node),
582*c87b03e5Sespie 		NULL_TREE);
583*c87b03e5Sespie   TREE_SIDE_EFFECTS (call) = 1;
584*c87b03e5Sespie   expand_expr_stmt (call);
585*c87b03e5Sespie   java_stack_pop (stack_pointer);
586*c87b03e5Sespie }
587*c87b03e5Sespie 
588*c87b03e5Sespie /* Implementation for jsr/ret */
589*c87b03e5Sespie 
590*c87b03e5Sespie static void
build_java_jsr(target_pc,return_pc)591*c87b03e5Sespie build_java_jsr (target_pc, return_pc)
592*c87b03e5Sespie      int target_pc, return_pc;
593*c87b03e5Sespie {
594*c87b03e5Sespie   tree where =  lookup_label (target_pc);
595*c87b03e5Sespie   tree ret = lookup_label (return_pc);
596*c87b03e5Sespie   tree ret_label = fold (build1 (ADDR_EXPR, return_address_type_node, ret));
597*c87b03e5Sespie   push_value (ret_label);
598*c87b03e5Sespie   flush_quick_stack ();
599*c87b03e5Sespie   emit_jump (label_rtx (where));
600*c87b03e5Sespie   expand_label (ret);
601*c87b03e5Sespie   if (instruction_bits [return_pc] & BCODE_VERIFIED)
602*c87b03e5Sespie     load_type_state (ret);
603*c87b03e5Sespie }
604*c87b03e5Sespie 
605*c87b03e5Sespie static void
build_java_ret(location)606*c87b03e5Sespie build_java_ret (location)
607*c87b03e5Sespie   tree location;
608*c87b03e5Sespie {
609*c87b03e5Sespie   expand_computed_goto (location);
610*c87b03e5Sespie }
611*c87b03e5Sespie 
612*c87b03e5Sespie /* Implementation of operations on array: new, load, store, length */
613*c87b03e5Sespie 
614*c87b03e5Sespie tree
decode_newarray_type(atype)615*c87b03e5Sespie decode_newarray_type (atype)
616*c87b03e5Sespie   int atype;
617*c87b03e5Sespie {
618*c87b03e5Sespie   switch (atype)
619*c87b03e5Sespie     {
620*c87b03e5Sespie     case 4:  return boolean_type_node;
621*c87b03e5Sespie     case 5:  return char_type_node;
622*c87b03e5Sespie     case 6:  return float_type_node;
623*c87b03e5Sespie     case 7:  return double_type_node;
624*c87b03e5Sespie     case 8:  return byte_type_node;
625*c87b03e5Sespie     case 9:  return short_type_node;
626*c87b03e5Sespie     case 10: return int_type_node;
627*c87b03e5Sespie     case 11: return long_type_node;
628*c87b03e5Sespie     default: return NULL_TREE;
629*c87b03e5Sespie     }
630*c87b03e5Sespie }
631*c87b03e5Sespie 
632*c87b03e5Sespie /* Map primitive type to the code used by OPCODE_newarray. */
633*c87b03e5Sespie 
634*c87b03e5Sespie int
encode_newarray_type(type)635*c87b03e5Sespie encode_newarray_type (type)
636*c87b03e5Sespie      tree type;
637*c87b03e5Sespie {
638*c87b03e5Sespie   if (type == boolean_type_node)
639*c87b03e5Sespie     return 4;
640*c87b03e5Sespie   else if (type == char_type_node)
641*c87b03e5Sespie     return 5;
642*c87b03e5Sespie   else if (type == float_type_node)
643*c87b03e5Sespie     return 6;
644*c87b03e5Sespie   else if (type == double_type_node)
645*c87b03e5Sespie     return 7;
646*c87b03e5Sespie   else if (type == byte_type_node)
647*c87b03e5Sespie     return 8;
648*c87b03e5Sespie   else if (type == short_type_node)
649*c87b03e5Sespie     return 9;
650*c87b03e5Sespie   else if (type == int_type_node)
651*c87b03e5Sespie     return 10;
652*c87b03e5Sespie   else if (type == long_type_node)
653*c87b03e5Sespie     return 11;
654*c87b03e5Sespie   else
655*c87b03e5Sespie     abort ();
656*c87b03e5Sespie }
657*c87b03e5Sespie 
658*c87b03e5Sespie /* Build a call to _Jv_ThrowBadArrayIndex(), the
659*c87b03e5Sespie    ArrayIndexOfBoundsException exception handler.  */
660*c87b03e5Sespie 
661*c87b03e5Sespie static tree
build_java_throw_out_of_bounds_exception(index)662*c87b03e5Sespie build_java_throw_out_of_bounds_exception (index)
663*c87b03e5Sespie     tree index;
664*c87b03e5Sespie {
665*c87b03e5Sespie   tree node = build (CALL_EXPR, int_type_node,
666*c87b03e5Sespie 		     build_address_of (soft_badarrayindex_node),
667*c87b03e5Sespie 		     build_tree_list (NULL_TREE, index), NULL_TREE);
668*c87b03e5Sespie   TREE_SIDE_EFFECTS (node) = 1;	/* Allows expansion within ANDIF */
669*c87b03e5Sespie   return (node);
670*c87b03e5Sespie }
671*c87b03e5Sespie 
672*c87b03e5Sespie /* Return the length of an array. Doesn't perform any checking on the nature
673*c87b03e5Sespie    or value of the array NODE. May be used to implement some bytecodes.  */
674*c87b03e5Sespie 
675*c87b03e5Sespie tree
build_java_array_length_access(node)676*c87b03e5Sespie build_java_array_length_access (node)
677*c87b03e5Sespie     tree node;
678*c87b03e5Sespie {
679*c87b03e5Sespie   tree type = TREE_TYPE (node);
680*c87b03e5Sespie   tree array_type = TREE_TYPE (type);
681*c87b03e5Sespie   HOST_WIDE_INT length;
682*c87b03e5Sespie 
683*c87b03e5Sespie   /* JVM spec: If the arrayref is null, the arraylength instruction
684*c87b03e5Sespie      throws a NullPointerException.  The only way we could get a node
685*c87b03e5Sespie      of type ptr_type_node at this point is `aconst_null; arraylength'
686*c87b03e5Sespie      or something equivalent.  */
687*c87b03e5Sespie   if (type == ptr_type_node)
688*c87b03e5Sespie     return build (CALL_EXPR, int_type_node,
689*c87b03e5Sespie 		  build_address_of (soft_nullpointer_node),
690*c87b03e5Sespie 		  NULL_TREE, NULL_TREE);
691*c87b03e5Sespie 
692*c87b03e5Sespie   if (!is_array_type_p (type))
693*c87b03e5Sespie     abort ();
694*c87b03e5Sespie 
695*c87b03e5Sespie   length = java_array_type_length (type);
696*c87b03e5Sespie   if (length >= 0)
697*c87b03e5Sespie     return build_int_2 (length, 0);
698*c87b03e5Sespie 
699*c87b03e5Sespie   node = build (COMPONENT_REF, int_type_node,
700*c87b03e5Sespie 		build_java_indirect_ref (array_type, node,
701*c87b03e5Sespie 					 flag_check_references),
702*c87b03e5Sespie 		lookup_field (&array_type, get_identifier ("length")));
703*c87b03e5Sespie   IS_ARRAY_LENGTH_ACCESS (node) = 1;
704*c87b03e5Sespie   return node;
705*c87b03e5Sespie }
706*c87b03e5Sespie 
707*c87b03e5Sespie /* Optionally checks a reference against the NULL pointer.  ARG1: the
708*c87b03e5Sespie    expr, ARG2: we should check the reference.  Don't generate extra
709*c87b03e5Sespie    checks if we're not generating code.  */
710*c87b03e5Sespie 
711*c87b03e5Sespie tree
java_check_reference(expr,check)712*c87b03e5Sespie java_check_reference (expr, check)
713*c87b03e5Sespie      tree expr;
714*c87b03e5Sespie      int check;
715*c87b03e5Sespie {
716*c87b03e5Sespie   if (!flag_syntax_only && check)
717*c87b03e5Sespie     {
718*c87b03e5Sespie       tree cond;
719*c87b03e5Sespie       expr = save_expr (expr);
720*c87b03e5Sespie       cond = build (COND_EXPR, void_type_node,
721*c87b03e5Sespie 		    build (EQ_EXPR, boolean_type_node, expr, null_pointer_node),
722*c87b03e5Sespie 		    build (CALL_EXPR, void_type_node,
723*c87b03e5Sespie 			   build_address_of (soft_nullpointer_node),
724*c87b03e5Sespie 			   NULL_TREE, NULL_TREE),
725*c87b03e5Sespie 		    empty_stmt_node);
726*c87b03e5Sespie       expr = build (COMPOUND_EXPR, TREE_TYPE (expr), cond, expr);
727*c87b03e5Sespie     }
728*c87b03e5Sespie 
729*c87b03e5Sespie   return expr;
730*c87b03e5Sespie }
731*c87b03e5Sespie 
732*c87b03e5Sespie /* Reference an object: just like an INDIRECT_REF, but with checking.  */
733*c87b03e5Sespie 
734*c87b03e5Sespie tree
build_java_indirect_ref(type,expr,check)735*c87b03e5Sespie build_java_indirect_ref (type, expr, check)
736*c87b03e5Sespie      tree type;
737*c87b03e5Sespie      tree expr;
738*c87b03e5Sespie      int check;
739*c87b03e5Sespie {
740*c87b03e5Sespie   return build1 (INDIRECT_REF, type, java_check_reference (expr, check));
741*c87b03e5Sespie }
742*c87b03e5Sespie 
743*c87b03e5Sespie /* Implement array indexing (either as l-value or r-value).
744*c87b03e5Sespie    Returns a tree for ARRAY[INDEX], assume TYPE is the element type.
745*c87b03e5Sespie    Optionally performs bounds checking and/or test to NULL.
746*c87b03e5Sespie    At this point, ARRAY should have been verified as an array.  */
747*c87b03e5Sespie 
748*c87b03e5Sespie tree
build_java_arrayaccess(array,type,index)749*c87b03e5Sespie build_java_arrayaccess (array, type, index)
750*c87b03e5Sespie     tree array, type, index;
751*c87b03e5Sespie {
752*c87b03e5Sespie   tree node, throw = NULL_TREE;
753*c87b03e5Sespie   tree data_field;
754*c87b03e5Sespie   tree ref;
755*c87b03e5Sespie   tree array_type = TREE_TYPE (TREE_TYPE (array));
756*c87b03e5Sespie 
757*c87b03e5Sespie   if (flag_bounds_check)
758*c87b03e5Sespie     {
759*c87b03e5Sespie       /* Generate:
760*c87b03e5Sespie        * (unsigned jint) INDEX >= (unsigned jint) LEN
761*c87b03e5Sespie        *    && throw ArrayIndexOutOfBoundsException.
762*c87b03e5Sespie        * Note this is equivalent to and more efficient than:
763*c87b03e5Sespie        * INDEX < 0 || INDEX >= LEN && throw ... */
764*c87b03e5Sespie       tree test;
765*c87b03e5Sespie       tree len = build_java_array_length_access (array);
766*c87b03e5Sespie       TREE_TYPE (len) = unsigned_int_type_node;
767*c87b03e5Sespie       test = fold (build (GE_EXPR, boolean_type_node,
768*c87b03e5Sespie 			       convert (unsigned_int_type_node, index),
769*c87b03e5Sespie 			       len));
770*c87b03e5Sespie       if (! integer_zerop (test))
771*c87b03e5Sespie 	{
772*c87b03e5Sespie 	  throw = build (TRUTH_ANDIF_EXPR, int_type_node, test,
773*c87b03e5Sespie 			 build_java_throw_out_of_bounds_exception (index));
774*c87b03e5Sespie 	  /* allows expansion within COMPOUND */
775*c87b03e5Sespie 	  TREE_SIDE_EFFECTS( throw ) = 1;
776*c87b03e5Sespie 	}
777*c87b03e5Sespie     }
778*c87b03e5Sespie 
779*c87b03e5Sespie   /* If checking bounds, wrap the index expr with a COMPOUND_EXPR in order
780*c87b03e5Sespie      to have the bounds check evaluated first. */
781*c87b03e5Sespie   if (throw != NULL_TREE)
782*c87b03e5Sespie     index = build (COMPOUND_EXPR, int_type_node, throw, index);
783*c87b03e5Sespie 
784*c87b03e5Sespie   data_field = lookup_field (&array_type, get_identifier ("data"));
785*c87b03e5Sespie 
786*c87b03e5Sespie   ref = build (COMPONENT_REF, TREE_TYPE (data_field),
787*c87b03e5Sespie 	       build_java_indirect_ref (array_type, array,
788*c87b03e5Sespie 					flag_check_references),
789*c87b03e5Sespie 	       data_field);
790*c87b03e5Sespie 
791*c87b03e5Sespie   node = build (ARRAY_REF, type, ref, index);
792*c87b03e5Sespie   return node;
793*c87b03e5Sespie }
794*c87b03e5Sespie 
795*c87b03e5Sespie /* Generate code to throw an ArrayStoreException if OBJECT is not assignable
796*c87b03e5Sespie    (at runtime) to an element of ARRAY.  A NOP_EXPR is returned if it can
797*c87b03e5Sespie    determine that no check is required. */
798*c87b03e5Sespie 
799*c87b03e5Sespie tree
build_java_arraystore_check(array,object)800*c87b03e5Sespie build_java_arraystore_check (array, object)
801*c87b03e5Sespie    tree array;
802*c87b03e5Sespie    tree object;
803*c87b03e5Sespie {
804*c87b03e5Sespie   tree check, element_type, source;
805*c87b03e5Sespie   tree array_type_p = TREE_TYPE (array);
806*c87b03e5Sespie   tree object_type = TYPE_NAME (TREE_TYPE (TREE_TYPE (object)));
807*c87b03e5Sespie 
808*c87b03e5Sespie   if (! is_array_type_p (array_type_p))
809*c87b03e5Sespie     abort ();
810*c87b03e5Sespie 
811*c87b03e5Sespie   /* Get the TYPE_DECL for ARRAY's element type. */
812*c87b03e5Sespie   element_type = TYPE_NAME (TREE_TYPE (TREE_TYPE (TREE_TYPE (array_type_p))));
813*c87b03e5Sespie 
814*c87b03e5Sespie   if (TREE_CODE (element_type) != TYPE_DECL
815*c87b03e5Sespie       || TREE_CODE (object_type) != TYPE_DECL)
816*c87b03e5Sespie     abort ();
817*c87b03e5Sespie 
818*c87b03e5Sespie   if (!flag_store_check)
819*c87b03e5Sespie     return build1 (NOP_EXPR, array_type_p, array);
820*c87b03e5Sespie 
821*c87b03e5Sespie   /* No check is needed if the element type is final or is itself an array.
822*c87b03e5Sespie      Also check that element_type matches object_type, since in the bytecode
823*c87b03e5Sespie      compilation case element_type may be the actual element type of the arra
824*c87b03e5Sespie      rather than its declared type. */
825*c87b03e5Sespie   if (element_type == object_type
826*c87b03e5Sespie       && (TYPE_ARRAY_P (TREE_TYPE (element_type))
827*c87b03e5Sespie 	  || CLASS_FINAL (element_type)))
828*c87b03e5Sespie     return build1 (NOP_EXPR, array_type_p, array);
829*c87b03e5Sespie 
830*c87b03e5Sespie   /* OBJECT might be wrapped by a SAVE_EXPR. */
831*c87b03e5Sespie   if (TREE_CODE (object) == SAVE_EXPR)
832*c87b03e5Sespie     source = TREE_OPERAND (object, 0);
833*c87b03e5Sespie   else
834*c87b03e5Sespie     source = object;
835*c87b03e5Sespie 
836*c87b03e5Sespie   /* Avoid the check if OBJECT was just loaded from the same array. */
837*c87b03e5Sespie   if (TREE_CODE (source) == ARRAY_REF)
838*c87b03e5Sespie     {
839*c87b03e5Sespie       tree target;
840*c87b03e5Sespie       source = TREE_OPERAND (source, 0); /* COMPONENT_REF. */
841*c87b03e5Sespie       source = TREE_OPERAND (source, 0); /* INDIRECT_REF. */
842*c87b03e5Sespie       source = TREE_OPERAND (source, 0); /* Source array's DECL or SAVE_EXPR. */
843*c87b03e5Sespie       if (TREE_CODE (source) == SAVE_EXPR)
844*c87b03e5Sespie 	source = TREE_OPERAND (source, 0);
845*c87b03e5Sespie 
846*c87b03e5Sespie       target = array;
847*c87b03e5Sespie       if (TREE_CODE (target) == SAVE_EXPR)
848*c87b03e5Sespie 	target = TREE_OPERAND (target, 0);
849*c87b03e5Sespie 
850*c87b03e5Sespie       if (source == target)
851*c87b03e5Sespie         return build1 (NOP_EXPR, array_type_p, array);
852*c87b03e5Sespie     }
853*c87b03e5Sespie 
854*c87b03e5Sespie   /* Build an invocation of _Jv_CheckArrayStore */
855*c87b03e5Sespie   check = build (CALL_EXPR, void_type_node,
856*c87b03e5Sespie 		 build_address_of (soft_checkarraystore_node),
857*c87b03e5Sespie 		 tree_cons (NULL_TREE, array,
858*c87b03e5Sespie 		 	    build_tree_list (NULL_TREE, object)),
859*c87b03e5Sespie 		 NULL_TREE);
860*c87b03e5Sespie   TREE_SIDE_EFFECTS (check) = 1;
861*c87b03e5Sespie 
862*c87b03e5Sespie   return check;
863*c87b03e5Sespie }
864*c87b03e5Sespie 
865*c87b03e5Sespie /* Makes sure that INDEXED_TYPE is appropriate. If not, make it from
866*c87b03e5Sespie    ARRAY_NODE. This function is used to retrieve something less vague than
867*c87b03e5Sespie    a pointer type when indexing the first dimension of something like [[<t>.
868*c87b03e5Sespie    May return a corrected type, if necessary, otherwise INDEXED_TYPE is
869*c87b03e5Sespie    return unchanged.
870*c87b03e5Sespie    As a side effect, it also makes sure that ARRAY_NODE is an array.  */
871*c87b03e5Sespie 
872*c87b03e5Sespie static tree
build_java_check_indexed_type(array_node,indexed_type)873*c87b03e5Sespie build_java_check_indexed_type (array_node, indexed_type)
874*c87b03e5Sespie     tree array_node;
875*c87b03e5Sespie     tree indexed_type;
876*c87b03e5Sespie {
877*c87b03e5Sespie   tree elt_type;
878*c87b03e5Sespie 
879*c87b03e5Sespie   if (!is_array_type_p (TREE_TYPE (array_node)))
880*c87b03e5Sespie     abort ();
881*c87b03e5Sespie 
882*c87b03e5Sespie   elt_type = (TYPE_ARRAY_ELEMENT (TREE_TYPE (TREE_TYPE (array_node))));
883*c87b03e5Sespie 
884*c87b03e5Sespie   if (indexed_type == ptr_type_node )
885*c87b03e5Sespie       return promote_type (elt_type);
886*c87b03e5Sespie 
887*c87b03e5Sespie   /* BYTE/BOOLEAN store and load are used for both type */
888*c87b03e5Sespie   if (indexed_type == byte_type_node && elt_type == boolean_type_node )
889*c87b03e5Sespie     return boolean_type_node;
890*c87b03e5Sespie 
891*c87b03e5Sespie   if (indexed_type != elt_type )
892*c87b03e5Sespie     abort ();
893*c87b03e5Sespie   else
894*c87b03e5Sespie     return indexed_type;
895*c87b03e5Sespie }
896*c87b03e5Sespie 
897*c87b03e5Sespie /* newarray triggers a call to _Jv_NewPrimArray. This function should be
898*c87b03e5Sespie    called with an integer code (the type of array to create), and the length
899*c87b03e5Sespie    of the array to create.  */
900*c87b03e5Sespie 
901*c87b03e5Sespie tree
build_newarray(atype_value,length)902*c87b03e5Sespie build_newarray (atype_value, length)
903*c87b03e5Sespie      int atype_value;
904*c87b03e5Sespie      tree length;
905*c87b03e5Sespie {
906*c87b03e5Sespie   tree type_arg;
907*c87b03e5Sespie 
908*c87b03e5Sespie   tree prim_type = decode_newarray_type (atype_value);
909*c87b03e5Sespie   tree type
910*c87b03e5Sespie     = build_java_array_type (prim_type,
911*c87b03e5Sespie 			     host_integerp (length, 0) == INTEGER_CST
912*c87b03e5Sespie 			     ? tree_low_cst (length, 0) : -1);
913*c87b03e5Sespie 
914*c87b03e5Sespie   /* If compiling to native, pass a reference to the primitive type class
915*c87b03e5Sespie      and save the runtime some work. However, the bytecode generator
916*c87b03e5Sespie      expects to find the type_code int here. */
917*c87b03e5Sespie   if (flag_emit_class_files)
918*c87b03e5Sespie     type_arg = build_int_2 (atype_value, 0);
919*c87b03e5Sespie   else
920*c87b03e5Sespie     type_arg = build_class_ref (prim_type);
921*c87b03e5Sespie 
922*c87b03e5Sespie   return build (CALL_EXPR, promote_type (type),
923*c87b03e5Sespie 		build_address_of (soft_newarray_node),
924*c87b03e5Sespie 		tree_cons (NULL_TREE,
925*c87b03e5Sespie 			   type_arg,
926*c87b03e5Sespie 			   build_tree_list (NULL_TREE, length)),
927*c87b03e5Sespie 		NULL_TREE);
928*c87b03e5Sespie }
929*c87b03e5Sespie 
930*c87b03e5Sespie /* Generates anewarray from a given CLASS_TYPE. Gets from the stack the size
931*c87b03e5Sespie    of the dimension. */
932*c87b03e5Sespie 
933*c87b03e5Sespie tree
build_anewarray(class_type,length)934*c87b03e5Sespie build_anewarray (class_type, length)
935*c87b03e5Sespie     tree class_type;
936*c87b03e5Sespie     tree length;
937*c87b03e5Sespie {
938*c87b03e5Sespie   tree type
939*c87b03e5Sespie     = build_java_array_type (class_type,
940*c87b03e5Sespie 			     host_integerp (length, 0)
941*c87b03e5Sespie 			     ? tree_low_cst (length, 0) : -1);
942*c87b03e5Sespie 
943*c87b03e5Sespie   return build (CALL_EXPR, promote_type (type),
944*c87b03e5Sespie 		build_address_of (soft_anewarray_node),
945*c87b03e5Sespie 		tree_cons (NULL_TREE, length,
946*c87b03e5Sespie 			   tree_cons (NULL_TREE, build_class_ref (class_type),
947*c87b03e5Sespie 				      build_tree_list (NULL_TREE,
948*c87b03e5Sespie 						       null_pointer_node))),
949*c87b03e5Sespie 		NULL_TREE);
950*c87b03e5Sespie }
951*c87b03e5Sespie 
952*c87b03e5Sespie /* Return a node the evaluates 'new TYPE[LENGTH]'. */
953*c87b03e5Sespie 
954*c87b03e5Sespie tree
build_new_array(type,length)955*c87b03e5Sespie build_new_array (type, length)
956*c87b03e5Sespie      tree type;
957*c87b03e5Sespie      tree length;
958*c87b03e5Sespie {
959*c87b03e5Sespie   if (JPRIMITIVE_TYPE_P (type))
960*c87b03e5Sespie     return build_newarray (encode_newarray_type (type), length);
961*c87b03e5Sespie   else
962*c87b03e5Sespie     return build_anewarray (TREE_TYPE (type), length);
963*c87b03e5Sespie }
964*c87b03e5Sespie 
965*c87b03e5Sespie /* Generates a call to _Jv_NewMultiArray. multianewarray expects a
966*c87b03e5Sespie    class pointer, a number of dimensions and the matching number of
967*c87b03e5Sespie    dimensions. The argument list is NULL terminated.  */
968*c87b03e5Sespie 
969*c87b03e5Sespie static void
expand_java_multianewarray(class_type,ndim)970*c87b03e5Sespie expand_java_multianewarray (class_type, ndim)
971*c87b03e5Sespie     tree class_type;
972*c87b03e5Sespie     int  ndim;
973*c87b03e5Sespie {
974*c87b03e5Sespie   int i;
975*c87b03e5Sespie   tree args = build_tree_list( NULL_TREE, null_pointer_node );
976*c87b03e5Sespie 
977*c87b03e5Sespie   for( i = 0; i < ndim; i++ )
978*c87b03e5Sespie     args = tree_cons (NULL_TREE, pop_value (int_type_node), args);
979*c87b03e5Sespie 
980*c87b03e5Sespie   push_value (build (CALL_EXPR,
981*c87b03e5Sespie 		     promote_type (class_type),
982*c87b03e5Sespie 		     build_address_of (soft_multianewarray_node),
983*c87b03e5Sespie 		     tree_cons (NULL_TREE, build_class_ref (class_type),
984*c87b03e5Sespie 				tree_cons (NULL_TREE,
985*c87b03e5Sespie 					   build_int_2 (ndim, 0), args )),
986*c87b03e5Sespie 		     NULL_TREE));
987*c87b03e5Sespie }
988*c87b03e5Sespie 
989*c87b03e5Sespie /*  ARRAY[INDEX] <- RHS. build_java_check_indexed_type makes sure that
990*c87b03e5Sespie     ARRAY is an array type. May expand some bound checking and NULL
991*c87b03e5Sespie     pointer checking. RHS_TYPE_NODE we are going to store. In the case
992*c87b03e5Sespie     of the CHAR/BYTE/BOOLEAN SHORT, the type popped of the stack is an
993*c87b03e5Sespie     INT. In those cases, we make the convertion.
994*c87b03e5Sespie 
995*c87b03e5Sespie     if ARRAy is a reference type, the assignment is checked at run-time
996*c87b03e5Sespie     to make sure that the RHS can be assigned to the array element
997*c87b03e5Sespie     type. It is not necessary to generate this code if ARRAY is final.  */
998*c87b03e5Sespie 
999*c87b03e5Sespie static void
expand_java_arraystore(rhs_type_node)1000*c87b03e5Sespie expand_java_arraystore (rhs_type_node)
1001*c87b03e5Sespie      tree rhs_type_node;
1002*c87b03e5Sespie {
1003*c87b03e5Sespie   tree rhs_node    = pop_value ((INTEGRAL_TYPE_P (rhs_type_node)
1004*c87b03e5Sespie 				 && TYPE_PRECISION (rhs_type_node) <= 32) ?
1005*c87b03e5Sespie 				 int_type_node : rhs_type_node);
1006*c87b03e5Sespie   tree index = pop_value (int_type_node);
1007*c87b03e5Sespie   tree array = pop_value (ptr_type_node);
1008*c87b03e5Sespie 
1009*c87b03e5Sespie   rhs_type_node    = build_java_check_indexed_type (array, rhs_type_node);
1010*c87b03e5Sespie 
1011*c87b03e5Sespie   flush_quick_stack ();
1012*c87b03e5Sespie 
1013*c87b03e5Sespie   index = save_expr (index);
1014*c87b03e5Sespie   array = save_expr (array);
1015*c87b03e5Sespie 
1016*c87b03e5Sespie   if (TREE_CODE (rhs_type_node) == POINTER_TYPE)
1017*c87b03e5Sespie     {
1018*c87b03e5Sespie       tree check = build_java_arraystore_check (array, rhs_node);
1019*c87b03e5Sespie       expand_expr_stmt (check);
1020*c87b03e5Sespie     }
1021*c87b03e5Sespie 
1022*c87b03e5Sespie   expand_assignment (build_java_arrayaccess (array,
1023*c87b03e5Sespie 					     rhs_type_node,
1024*c87b03e5Sespie 					     index),
1025*c87b03e5Sespie 		     rhs_node, 0, 0);
1026*c87b03e5Sespie }
1027*c87b03e5Sespie 
1028*c87b03e5Sespie /* Expand the evaluation of ARRAY[INDEX]. build_java_check_indexed_type makes
1029*c87b03e5Sespie    sure that LHS is an array type. May expand some bound checking and NULL
1030*c87b03e5Sespie    pointer checking.
1031*c87b03e5Sespie    LHS_TYPE_NODE is the type of ARRAY[INDEX]. But in the case of CHAR/BYTE/
1032*c87b03e5Sespie    BOOLEAN/SHORT, we push a promoted type back to the stack.
1033*c87b03e5Sespie */
1034*c87b03e5Sespie 
1035*c87b03e5Sespie static void
expand_java_arrayload(lhs_type_node)1036*c87b03e5Sespie expand_java_arrayload (lhs_type_node )
1037*c87b03e5Sespie     tree lhs_type_node;
1038*c87b03e5Sespie {
1039*c87b03e5Sespie   tree load_node;
1040*c87b03e5Sespie   tree index_node = pop_value (int_type_node);
1041*c87b03e5Sespie   tree array_node = pop_value (ptr_type_node);
1042*c87b03e5Sespie 
1043*c87b03e5Sespie   index_node = save_expr (index_node);
1044*c87b03e5Sespie   array_node = save_expr (array_node);
1045*c87b03e5Sespie 
1046*c87b03e5Sespie   if (TREE_TYPE (array_node) == ptr_type_node)
1047*c87b03e5Sespie     /* The only way we could get a node of type ptr_type_node at this
1048*c87b03e5Sespie        point is `aconst_null; arraylength' or something equivalent, so
1049*c87b03e5Sespie        unconditionally throw NullPointerException.  */
1050*c87b03e5Sespie     load_node = build (CALL_EXPR, lhs_type_node,
1051*c87b03e5Sespie 		       build_address_of (soft_nullpointer_node),
1052*c87b03e5Sespie 		       NULL_TREE, NULL_TREE);
1053*c87b03e5Sespie   else
1054*c87b03e5Sespie     {
1055*c87b03e5Sespie       lhs_type_node = build_java_check_indexed_type (array_node, lhs_type_node);
1056*c87b03e5Sespie       load_node = build_java_arrayaccess (array_node,
1057*c87b03e5Sespie 					  lhs_type_node,
1058*c87b03e5Sespie 					  index_node);
1059*c87b03e5Sespie     }
1060*c87b03e5Sespie   if (INTEGRAL_TYPE_P (lhs_type_node) && TYPE_PRECISION (lhs_type_node) <= 32)
1061*c87b03e5Sespie     load_node = fold (build1 (NOP_EXPR, int_type_node, load_node));
1062*c87b03e5Sespie   push_value (load_node);
1063*c87b03e5Sespie }
1064*c87b03e5Sespie 
1065*c87b03e5Sespie /* Expands .length. Makes sure that we deal with and array and may expand
1066*c87b03e5Sespie    a NULL check on the array object.  */
1067*c87b03e5Sespie 
1068*c87b03e5Sespie static void
expand_java_array_length()1069*c87b03e5Sespie expand_java_array_length ()
1070*c87b03e5Sespie {
1071*c87b03e5Sespie   tree array  = pop_value (ptr_type_node);
1072*c87b03e5Sespie   tree length = build_java_array_length_access (array);
1073*c87b03e5Sespie 
1074*c87b03e5Sespie   push_value (length);
1075*c87b03e5Sespie }
1076*c87b03e5Sespie 
1077*c87b03e5Sespie /* Emit code for the call to _Jv_Monitor{Enter,Exit}. CALL can be
1078*c87b03e5Sespie    either soft_monitorenter_node or soft_monitorexit_node.  */
1079*c87b03e5Sespie 
1080*c87b03e5Sespie static tree
build_java_monitor(call,object)1081*c87b03e5Sespie build_java_monitor (call, object)
1082*c87b03e5Sespie     tree call;
1083*c87b03e5Sespie     tree object;
1084*c87b03e5Sespie {
1085*c87b03e5Sespie   return (build (CALL_EXPR,
1086*c87b03e5Sespie 		 void_type_node,
1087*c87b03e5Sespie 		 build_address_of (call),
1088*c87b03e5Sespie 		 build_tree_list (NULL_TREE, object),
1089*c87b03e5Sespie 		 NULL_TREE));
1090*c87b03e5Sespie }
1091*c87b03e5Sespie 
1092*c87b03e5Sespie /* Emit code for one of the PUSHC instructions. */
1093*c87b03e5Sespie 
1094*c87b03e5Sespie static void
expand_java_pushc(ival,type)1095*c87b03e5Sespie expand_java_pushc (ival, type)
1096*c87b03e5Sespie      int ival;
1097*c87b03e5Sespie      tree type;
1098*c87b03e5Sespie {
1099*c87b03e5Sespie   tree value;
1100*c87b03e5Sespie   if (type == ptr_type_node && ival == 0)
1101*c87b03e5Sespie     value = null_pointer_node;
1102*c87b03e5Sespie   else if (type == int_type_node || type == long_type_node)
1103*c87b03e5Sespie     {
1104*c87b03e5Sespie       value = build_int_2 (ival, ival < 0 ? -1 : 0);
1105*c87b03e5Sespie       TREE_TYPE (value) = type;
1106*c87b03e5Sespie     }
1107*c87b03e5Sespie   else if (type == float_type_node || type == double_type_node)
1108*c87b03e5Sespie     {
1109*c87b03e5Sespie       REAL_VALUE_TYPE x;
1110*c87b03e5Sespie       REAL_VALUE_FROM_INT (x, ival, 0, TYPE_MODE (type));
1111*c87b03e5Sespie       value = build_real (type, x);
1112*c87b03e5Sespie     }
1113*c87b03e5Sespie   else
1114*c87b03e5Sespie     abort ();
1115*c87b03e5Sespie 
1116*c87b03e5Sespie   push_value (value);
1117*c87b03e5Sespie }
1118*c87b03e5Sespie 
1119*c87b03e5Sespie static void
expand_java_return(type)1120*c87b03e5Sespie expand_java_return (type)
1121*c87b03e5Sespie      tree type;
1122*c87b03e5Sespie {
1123*c87b03e5Sespie   if (type == void_type_node)
1124*c87b03e5Sespie     expand_null_return ();
1125*c87b03e5Sespie   else
1126*c87b03e5Sespie     {
1127*c87b03e5Sespie       tree retval = pop_value (type);
1128*c87b03e5Sespie       tree res = DECL_RESULT (current_function_decl);
1129*c87b03e5Sespie       retval = build (MODIFY_EXPR, TREE_TYPE (res), res, retval);
1130*c87b03e5Sespie 
1131*c87b03e5Sespie       /* Handle the situation where the native integer type is smaller
1132*c87b03e5Sespie 	 than the JVM integer. It can happen for many cross compilers.
1133*c87b03e5Sespie 	 The whole if expression just goes away if INT_TYPE_SIZE < 32
1134*c87b03e5Sespie 	 is false. */
1135*c87b03e5Sespie       if (INT_TYPE_SIZE < 32
1136*c87b03e5Sespie 	  && (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (res)))
1137*c87b03e5Sespie 	      < GET_MODE_SIZE (TYPE_MODE (type))))
1138*c87b03e5Sespie 	retval = build1(NOP_EXPR, TREE_TYPE(res), retval);
1139*c87b03e5Sespie 
1140*c87b03e5Sespie       TREE_SIDE_EFFECTS (retval) = 1;
1141*c87b03e5Sespie       expand_return (retval);
1142*c87b03e5Sespie     }
1143*c87b03e5Sespie }
1144*c87b03e5Sespie 
1145*c87b03e5Sespie static void
expand_load_internal(index,type,pc)1146*c87b03e5Sespie expand_load_internal (index, type, pc)
1147*c87b03e5Sespie      int index;
1148*c87b03e5Sespie      tree type;
1149*c87b03e5Sespie      int pc;
1150*c87b03e5Sespie {
1151*c87b03e5Sespie   tree copy;
1152*c87b03e5Sespie   tree var = find_local_variable (index, type, pc);
1153*c87b03e5Sespie 
1154*c87b03e5Sespie   /* Now VAR is the VAR_DECL (or PARM_DECL) that we are going to push
1155*c87b03e5Sespie      on the stack.  If there is an assignment to this VAR_DECL between
1156*c87b03e5Sespie      the stack push and the use, then the wrong code could be
1157*c87b03e5Sespie      generated.  To avoid this we create a new local and copy our
1158*c87b03e5Sespie      value into it.  Then we push this new local on the stack.
1159*c87b03e5Sespie      Hopefully this all gets optimized out.  */
1160*c87b03e5Sespie   copy = build_decl (VAR_DECL, NULL_TREE, type);
1161*c87b03e5Sespie   DECL_CONTEXT (copy) = current_function_decl;
1162*c87b03e5Sespie   layout_decl (copy, 0);
1163*c87b03e5Sespie   DECL_REGISTER (copy) = 1;
1164*c87b03e5Sespie   expand_decl (copy);
1165*c87b03e5Sespie   MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (copy);
1166*c87b03e5Sespie   DECL_INITIAL (copy) = var;
1167*c87b03e5Sespie   expand_decl_init (copy);
1168*c87b03e5Sespie   push_value (copy);
1169*c87b03e5Sespie }
1170*c87b03e5Sespie 
1171*c87b03e5Sespie tree
build_address_of(value)1172*c87b03e5Sespie build_address_of (value)
1173*c87b03e5Sespie      tree value;
1174*c87b03e5Sespie {
1175*c87b03e5Sespie   return build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (value)), value);
1176*c87b03e5Sespie }
1177*c87b03e5Sespie 
class_has_finalize_method(type)1178*c87b03e5Sespie bool class_has_finalize_method (type)
1179*c87b03e5Sespie      tree type;
1180*c87b03e5Sespie {
1181*c87b03e5Sespie   tree super = CLASSTYPE_SUPER (type);
1182*c87b03e5Sespie 
1183*c87b03e5Sespie   if (super == NULL_TREE)
1184*c87b03e5Sespie     return false;	/* Every class with a real finalizer inherits	*/
1185*c87b03e5Sespie    			/* from java.lang.Object.			*/
1186*c87b03e5Sespie   else
1187*c87b03e5Sespie     return HAS_FINALIZER_P (type) || class_has_finalize_method (super);
1188*c87b03e5Sespie }
1189*c87b03e5Sespie 
1190*c87b03e5Sespie static void
expand_java_NEW(type)1191*c87b03e5Sespie expand_java_NEW (type)
1192*c87b03e5Sespie      tree type;
1193*c87b03e5Sespie {
1194*c87b03e5Sespie   tree alloc_node;
1195*c87b03e5Sespie 
1196*c87b03e5Sespie   alloc_node = (class_has_finalize_method (type) ? alloc_object_node
1197*c87b03e5Sespie 		  				 : alloc_no_finalizer_node);
1198*c87b03e5Sespie   if (! CLASS_LOADED_P (type))
1199*c87b03e5Sespie     load_class (type, 1);
1200*c87b03e5Sespie   safe_layout_class (type);
1201*c87b03e5Sespie   push_value (build (CALL_EXPR, promote_type (type),
1202*c87b03e5Sespie 		     build_address_of (alloc_node),
1203*c87b03e5Sespie 		     tree_cons (NULL_TREE, build_class_ref (type),
1204*c87b03e5Sespie 				build_tree_list (NULL_TREE,
1205*c87b03e5Sespie 						 size_in_bytes (type))),
1206*c87b03e5Sespie 		     NULL_TREE));
1207*c87b03e5Sespie }
1208*c87b03e5Sespie 
1209*c87b03e5Sespie /* This returns an expression which will extract the class of an
1210*c87b03e5Sespie    object.  */
1211*c87b03e5Sespie 
1212*c87b03e5Sespie tree
build_get_class(value)1213*c87b03e5Sespie build_get_class (value)
1214*c87b03e5Sespie      tree value;
1215*c87b03e5Sespie {
1216*c87b03e5Sespie   tree class_field = lookup_field (&dtable_type, get_identifier ("class"));
1217*c87b03e5Sespie   tree vtable_field = lookup_field (&object_type_node,
1218*c87b03e5Sespie 				    get_identifier ("vtable"));
1219*c87b03e5Sespie   return build (COMPONENT_REF, class_ptr_type,
1220*c87b03e5Sespie 		build1 (INDIRECT_REF, dtable_type,
1221*c87b03e5Sespie 			build (COMPONENT_REF, dtable_ptr_type,
1222*c87b03e5Sespie 			       build_java_indirect_ref (object_type_node, value,
1223*c87b03e5Sespie 							flag_check_references),
1224*c87b03e5Sespie 			       vtable_field)),
1225*c87b03e5Sespie 		class_field);
1226*c87b03e5Sespie }
1227*c87b03e5Sespie 
1228*c87b03e5Sespie /* This builds the tree representation of the `instanceof' operator.
1229*c87b03e5Sespie    It tries various tricks to optimize this in cases where types are
1230*c87b03e5Sespie    known.  */
1231*c87b03e5Sespie 
1232*c87b03e5Sespie tree
build_instanceof(value,type)1233*c87b03e5Sespie build_instanceof (value, type)
1234*c87b03e5Sespie      tree value, type;
1235*c87b03e5Sespie {
1236*c87b03e5Sespie   tree expr;
1237*c87b03e5Sespie   tree itype = TREE_TYPE (TREE_TYPE (soft_instanceof_node));
1238*c87b03e5Sespie   tree valtype = TREE_TYPE (TREE_TYPE (value));
1239*c87b03e5Sespie   tree valclass = TYPE_NAME (valtype);
1240*c87b03e5Sespie   tree klass;
1241*c87b03e5Sespie 
1242*c87b03e5Sespie   /* When compiling from bytecode, we need to ensure that TYPE has
1243*c87b03e5Sespie      been loaded.  */
1244*c87b03e5Sespie   if (CLASS_P (type) && ! CLASS_LOADED_P (type))
1245*c87b03e5Sespie     {
1246*c87b03e5Sespie       load_class (type, 1);
1247*c87b03e5Sespie       safe_layout_class (type);
1248*c87b03e5Sespie       if (! TYPE_SIZE (type) || TREE_CODE (TYPE_SIZE (type)) == ERROR_MARK)
1249*c87b03e5Sespie 	return error_mark_node;
1250*c87b03e5Sespie     }
1251*c87b03e5Sespie   klass = TYPE_NAME (type);
1252*c87b03e5Sespie 
1253*c87b03e5Sespie   if (type == object_type_node || inherits_from_p (valtype, type))
1254*c87b03e5Sespie     {
1255*c87b03e5Sespie       /* Anything except `null' is an instance of Object.  Likewise,
1256*c87b03e5Sespie 	 if the object is known to be an instance of the class, then
1257*c87b03e5Sespie 	 we only need to check for `null'.  */
1258*c87b03e5Sespie       expr = build (NE_EXPR, itype, value, null_pointer_node);
1259*c87b03e5Sespie     }
1260*c87b03e5Sespie   else if (! TYPE_ARRAY_P (type)
1261*c87b03e5Sespie 	   && ! TYPE_ARRAY_P (valtype)
1262*c87b03e5Sespie 	   && DECL_P (klass) && DECL_P (valclass)
1263*c87b03e5Sespie 	   && ! CLASS_INTERFACE (valclass)
1264*c87b03e5Sespie 	   && ! CLASS_INTERFACE (klass)
1265*c87b03e5Sespie 	   && ! inherits_from_p (type, valtype)
1266*c87b03e5Sespie 	   && (CLASS_FINAL (klass)
1267*c87b03e5Sespie 	       || ! inherits_from_p (valtype, type)))
1268*c87b03e5Sespie     {
1269*c87b03e5Sespie       /* The classes are from different branches of the derivation
1270*c87b03e5Sespie 	 tree, so we immediately know the answer.  */
1271*c87b03e5Sespie       expr = boolean_false_node;
1272*c87b03e5Sespie     }
1273*c87b03e5Sespie   else if (DECL_P (klass) && CLASS_FINAL (klass))
1274*c87b03e5Sespie     {
1275*c87b03e5Sespie       tree save = save_expr (value);
1276*c87b03e5Sespie       expr = build (COND_EXPR, itype,
1277*c87b03e5Sespie 		    save,
1278*c87b03e5Sespie 		    build (EQ_EXPR, itype,
1279*c87b03e5Sespie 			   build_get_class (save),
1280*c87b03e5Sespie 			   build_class_ref (type)),
1281*c87b03e5Sespie 		    boolean_false_node);
1282*c87b03e5Sespie     }
1283*c87b03e5Sespie   else
1284*c87b03e5Sespie     {
1285*c87b03e5Sespie       expr = build (CALL_EXPR, itype,
1286*c87b03e5Sespie 		    build_address_of (soft_instanceof_node),
1287*c87b03e5Sespie 		    tree_cons (NULL_TREE, value,
1288*c87b03e5Sespie 			       build_tree_list (NULL_TREE,
1289*c87b03e5Sespie 						build_class_ref (type))),
1290*c87b03e5Sespie 		    NULL_TREE);
1291*c87b03e5Sespie     }
1292*c87b03e5Sespie   TREE_SIDE_EFFECTS (expr) = TREE_SIDE_EFFECTS (value);
1293*c87b03e5Sespie   return expr;
1294*c87b03e5Sespie }
1295*c87b03e5Sespie 
1296*c87b03e5Sespie static void
expand_java_INSTANCEOF(type)1297*c87b03e5Sespie expand_java_INSTANCEOF (type)
1298*c87b03e5Sespie      tree type;
1299*c87b03e5Sespie {
1300*c87b03e5Sespie   tree value = pop_value (object_ptr_type_node);
1301*c87b03e5Sespie   value = build_instanceof (value, type);
1302*c87b03e5Sespie   push_value (value);
1303*c87b03e5Sespie }
1304*c87b03e5Sespie 
1305*c87b03e5Sespie static void
expand_java_CHECKCAST(type)1306*c87b03e5Sespie expand_java_CHECKCAST (type)
1307*c87b03e5Sespie      tree type;
1308*c87b03e5Sespie {
1309*c87b03e5Sespie   tree value = pop_value (ptr_type_node);
1310*c87b03e5Sespie   value = build (CALL_EXPR, promote_type (type),
1311*c87b03e5Sespie 		 build_address_of (soft_checkcast_node),
1312*c87b03e5Sespie 		 tree_cons (NULL_TREE, build_class_ref (type),
1313*c87b03e5Sespie 			    build_tree_list (NULL_TREE, value)),
1314*c87b03e5Sespie 		 NULL_TREE);
1315*c87b03e5Sespie   push_value (value);
1316*c87b03e5Sespie }
1317*c87b03e5Sespie 
1318*c87b03e5Sespie static void
expand_iinc(local_var_index,ival,pc)1319*c87b03e5Sespie expand_iinc (local_var_index, ival, pc)
1320*c87b03e5Sespie      unsigned int local_var_index;
1321*c87b03e5Sespie      int ival;
1322*c87b03e5Sespie      int pc;
1323*c87b03e5Sespie {
1324*c87b03e5Sespie     tree local_var, res;
1325*c87b03e5Sespie     tree constant_value;
1326*c87b03e5Sespie 
1327*c87b03e5Sespie     flush_quick_stack ();
1328*c87b03e5Sespie     local_var = find_local_variable (local_var_index, int_type_node, pc);
1329*c87b03e5Sespie     constant_value = build_int_2 (ival, ival < 0 ? -1 : 0);
1330*c87b03e5Sespie     res = fold (build (PLUS_EXPR, int_type_node, local_var, constant_value));
1331*c87b03e5Sespie     expand_assignment (local_var, res, 0, 0);
1332*c87b03e5Sespie }
1333*c87b03e5Sespie 
1334*c87b03e5Sespie 
1335*c87b03e5Sespie tree
build_java_soft_divmod(op,type,op1,op2)1336*c87b03e5Sespie build_java_soft_divmod (op, type, op1, op2)
1337*c87b03e5Sespie     enum tree_code op;
1338*c87b03e5Sespie     tree type, op1, op2;
1339*c87b03e5Sespie {
1340*c87b03e5Sespie   tree call = NULL;
1341*c87b03e5Sespie   tree arg1 = convert (type, op1);
1342*c87b03e5Sespie   tree arg2 = convert (type, op2);
1343*c87b03e5Sespie 
1344*c87b03e5Sespie   if (type == int_type_node)
1345*c87b03e5Sespie     {
1346*c87b03e5Sespie       switch (op)
1347*c87b03e5Sespie 	{
1348*c87b03e5Sespie 	case TRUNC_DIV_EXPR:
1349*c87b03e5Sespie 	  call = soft_idiv_node;
1350*c87b03e5Sespie 	  break;
1351*c87b03e5Sespie 	case TRUNC_MOD_EXPR:
1352*c87b03e5Sespie 	  call = soft_irem_node;
1353*c87b03e5Sespie 	  break;
1354*c87b03e5Sespie 	default:
1355*c87b03e5Sespie 	  break;
1356*c87b03e5Sespie 	}
1357*c87b03e5Sespie     }
1358*c87b03e5Sespie   else if (type == long_type_node)
1359*c87b03e5Sespie     {
1360*c87b03e5Sespie       switch (op)
1361*c87b03e5Sespie 	{
1362*c87b03e5Sespie 	case TRUNC_DIV_EXPR:
1363*c87b03e5Sespie 	  call = soft_ldiv_node;
1364*c87b03e5Sespie 	  break;
1365*c87b03e5Sespie 	case TRUNC_MOD_EXPR:
1366*c87b03e5Sespie 	  call = soft_lrem_node;
1367*c87b03e5Sespie 	  break;
1368*c87b03e5Sespie 	default:
1369*c87b03e5Sespie 	  break;
1370*c87b03e5Sespie 	}
1371*c87b03e5Sespie     }
1372*c87b03e5Sespie 
1373*c87b03e5Sespie   if (! call)
1374*c87b03e5Sespie     abort ();
1375*c87b03e5Sespie 
1376*c87b03e5Sespie   call = build (CALL_EXPR, type,
1377*c87b03e5Sespie 		build_address_of (call),
1378*c87b03e5Sespie 		tree_cons (NULL_TREE, arg1,
1379*c87b03e5Sespie 			   build_tree_list (NULL_TREE, arg2)),
1380*c87b03e5Sespie 		NULL_TREE);
1381*c87b03e5Sespie 
1382*c87b03e5Sespie   return call;
1383*c87b03e5Sespie }
1384*c87b03e5Sespie 
1385*c87b03e5Sespie tree
build_java_binop(op,type,arg1,arg2)1386*c87b03e5Sespie build_java_binop (op, type, arg1, arg2)
1387*c87b03e5Sespie      enum tree_code op;
1388*c87b03e5Sespie      tree type, arg1, arg2;
1389*c87b03e5Sespie {
1390*c87b03e5Sespie   tree mask;
1391*c87b03e5Sespie   switch (op)
1392*c87b03e5Sespie     {
1393*c87b03e5Sespie     case URSHIFT_EXPR:
1394*c87b03e5Sespie       {
1395*c87b03e5Sespie 	tree u_type = java_unsigned_type (type);
1396*c87b03e5Sespie 	arg1 = convert (u_type, arg1);
1397*c87b03e5Sespie 	arg1 = build_java_binop (RSHIFT_EXPR, u_type, arg1, arg2);
1398*c87b03e5Sespie 	return convert (type, arg1);
1399*c87b03e5Sespie       }
1400*c87b03e5Sespie     case LSHIFT_EXPR:
1401*c87b03e5Sespie     case RSHIFT_EXPR:
1402*c87b03e5Sespie       mask = build_int_2 (TYPE_PRECISION (TREE_TYPE (arg1)) - 1, 0);
1403*c87b03e5Sespie       arg2 = fold (build (BIT_AND_EXPR, int_type_node, arg2, mask));
1404*c87b03e5Sespie       break;
1405*c87b03e5Sespie 
1406*c87b03e5Sespie     case COMPARE_L_EXPR:  /* arg1 > arg2 ?  1 : arg1 == arg2 ? 0 : -1 */
1407*c87b03e5Sespie     case COMPARE_G_EXPR:  /* arg1 < arg2 ? -1 : arg1 == arg2 ? 0 :  1 */
1408*c87b03e5Sespie       arg1 = save_expr (arg1);  arg2 = save_expr (arg2);
1409*c87b03e5Sespie       {
1410*c87b03e5Sespie 	tree ifexp1 = fold ( build (op == COMPARE_L_EXPR ? GT_EXPR : LT_EXPR,
1411*c87b03e5Sespie 				    boolean_type_node, arg1, arg2));
1412*c87b03e5Sespie 	tree ifexp2 = fold ( build (EQ_EXPR, boolean_type_node, arg1, arg2));
1413*c87b03e5Sespie 	tree second_compare = fold (build (COND_EXPR, int_type_node,
1414*c87b03e5Sespie 					   ifexp2, integer_zero_node,
1415*c87b03e5Sespie 					   op == COMPARE_L_EXPR
1416*c87b03e5Sespie 					   ? integer_minus_one_node
1417*c87b03e5Sespie 					   : integer_one_node));
1418*c87b03e5Sespie 	return fold (build (COND_EXPR, int_type_node, ifexp1,
1419*c87b03e5Sespie 			    op == COMPARE_L_EXPR ? integer_one_node
1420*c87b03e5Sespie 			    : integer_minus_one_node,
1421*c87b03e5Sespie 			    second_compare));
1422*c87b03e5Sespie       }
1423*c87b03e5Sespie     case COMPARE_EXPR:
1424*c87b03e5Sespie       arg1 = save_expr (arg1);  arg2 = save_expr (arg2);
1425*c87b03e5Sespie       {
1426*c87b03e5Sespie 	tree ifexp1 = fold ( build (LT_EXPR, boolean_type_node, arg1, arg2));
1427*c87b03e5Sespie 	tree ifexp2 = fold ( build (GT_EXPR, boolean_type_node, arg1, arg2));
1428*c87b03e5Sespie 	tree second_compare = fold ( build (COND_EXPR, int_type_node,
1429*c87b03e5Sespie 					    ifexp2, integer_one_node,
1430*c87b03e5Sespie 					    integer_zero_node));
1431*c87b03e5Sespie 	return fold (build (COND_EXPR, int_type_node,
1432*c87b03e5Sespie 			    ifexp1, integer_minus_one_node, second_compare));
1433*c87b03e5Sespie       }
1434*c87b03e5Sespie     case TRUNC_DIV_EXPR:
1435*c87b03e5Sespie     case TRUNC_MOD_EXPR:
1436*c87b03e5Sespie       if (TREE_CODE (type) == REAL_TYPE
1437*c87b03e5Sespie 	  && op == TRUNC_MOD_EXPR)
1438*c87b03e5Sespie 	{
1439*c87b03e5Sespie 	  tree call;
1440*c87b03e5Sespie 	  if (type != double_type_node)
1441*c87b03e5Sespie 	    {
1442*c87b03e5Sespie 	      arg1 = convert (double_type_node, arg1);
1443*c87b03e5Sespie 	      arg2 = convert (double_type_node, arg2);
1444*c87b03e5Sespie 	    }
1445*c87b03e5Sespie 	  call = build (CALL_EXPR, double_type_node,
1446*c87b03e5Sespie 			build_address_of (soft_fmod_node),
1447*c87b03e5Sespie 			tree_cons (NULL_TREE, arg1,
1448*c87b03e5Sespie 				   build_tree_list (NULL_TREE, arg2)),
1449*c87b03e5Sespie 			NULL_TREE);
1450*c87b03e5Sespie 	  if (type != double_type_node)
1451*c87b03e5Sespie 	    call = convert (type, call);
1452*c87b03e5Sespie 	  return call;
1453*c87b03e5Sespie 	}
1454*c87b03e5Sespie 
1455*c87b03e5Sespie       if (TREE_CODE (type) == INTEGER_TYPE
1456*c87b03e5Sespie 	  && flag_use_divide_subroutine
1457*c87b03e5Sespie 	  && ! flag_syntax_only)
1458*c87b03e5Sespie 	return build_java_soft_divmod (op, type, arg1, arg2);
1459*c87b03e5Sespie 
1460*c87b03e5Sespie       break;
1461*c87b03e5Sespie     default:  ;
1462*c87b03e5Sespie     }
1463*c87b03e5Sespie   return fold (build (op, type, arg1, arg2));
1464*c87b03e5Sespie }
1465*c87b03e5Sespie 
1466*c87b03e5Sespie static void
expand_java_binop(type,op)1467*c87b03e5Sespie expand_java_binop (type, op)
1468*c87b03e5Sespie      tree type;  enum tree_code op;
1469*c87b03e5Sespie {
1470*c87b03e5Sespie   tree larg, rarg;
1471*c87b03e5Sespie   tree ltype = type;
1472*c87b03e5Sespie   tree rtype = type;
1473*c87b03e5Sespie   switch (op)
1474*c87b03e5Sespie     {
1475*c87b03e5Sespie     case LSHIFT_EXPR:
1476*c87b03e5Sespie     case RSHIFT_EXPR:
1477*c87b03e5Sespie     case URSHIFT_EXPR:
1478*c87b03e5Sespie       rtype = int_type_node;
1479*c87b03e5Sespie       rarg = pop_value (rtype);
1480*c87b03e5Sespie       break;
1481*c87b03e5Sespie     default:
1482*c87b03e5Sespie       rarg = pop_value (rtype);
1483*c87b03e5Sespie     }
1484*c87b03e5Sespie   larg = pop_value (ltype);
1485*c87b03e5Sespie   push_value (build_java_binop (op, type, larg, rarg));
1486*c87b03e5Sespie }
1487*c87b03e5Sespie 
1488*c87b03e5Sespie /* Lookup the field named NAME in *TYPEP or its super classes.
1489*c87b03e5Sespie    If not found, return NULL_TREE.
1490*c87b03e5Sespie    (If the *TYPEP is not found, or if the field reference is
1491*c87b03e5Sespie    ambiguous, return error_mark_node.)
1492*c87b03e5Sespie    If found, return the FIELD_DECL, and set *TYPEP to the
1493*c87b03e5Sespie    class containing the field. */
1494*c87b03e5Sespie 
1495*c87b03e5Sespie tree
lookup_field(typep,name)1496*c87b03e5Sespie lookup_field (typep, name)
1497*c87b03e5Sespie      tree *typep;
1498*c87b03e5Sespie      tree name;
1499*c87b03e5Sespie {
1500*c87b03e5Sespie   if (CLASS_P (*typep) && !CLASS_LOADED_P (*typep))
1501*c87b03e5Sespie     {
1502*c87b03e5Sespie       load_class (*typep, 1);
1503*c87b03e5Sespie       safe_layout_class (*typep);
1504*c87b03e5Sespie       if (!TYPE_SIZE (*typep) || TREE_CODE (TYPE_SIZE (*typep)) == ERROR_MARK)
1505*c87b03e5Sespie 	return error_mark_node;
1506*c87b03e5Sespie     }
1507*c87b03e5Sespie   do
1508*c87b03e5Sespie     {
1509*c87b03e5Sespie       tree field, basetype_vec;
1510*c87b03e5Sespie       tree save_field;
1511*c87b03e5Sespie       int n, i;
1512*c87b03e5Sespie 
1513*c87b03e5Sespie       for (field = TYPE_FIELDS (*typep); field; field = TREE_CHAIN (field))
1514*c87b03e5Sespie 	if (DECL_NAME (field) == name)
1515*c87b03e5Sespie 	  return field;
1516*c87b03e5Sespie 
1517*c87b03e5Sespie       /* Process implemented interfaces. */
1518*c87b03e5Sespie       basetype_vec = TYPE_BINFO_BASETYPES (*typep);
1519*c87b03e5Sespie       n = TREE_VEC_LENGTH (basetype_vec);
1520*c87b03e5Sespie       save_field = NULL_TREE;
1521*c87b03e5Sespie       for (i = 0; i < n; i++)
1522*c87b03e5Sespie 	{
1523*c87b03e5Sespie 	  tree t = BINFO_TYPE (TREE_VEC_ELT (basetype_vec, i));
1524*c87b03e5Sespie 	  if ((field = lookup_field (&t, name)))
1525*c87b03e5Sespie 	    {
1526*c87b03e5Sespie 	      if (save_field == field)
1527*c87b03e5Sespie 		continue;
1528*c87b03e5Sespie 	      if (save_field == NULL_TREE)
1529*c87b03e5Sespie 		save_field = field;
1530*c87b03e5Sespie 	      else
1531*c87b03e5Sespie 		{
1532*c87b03e5Sespie 		  tree i1 = DECL_CONTEXT (save_field);
1533*c87b03e5Sespie 		  tree i2 = DECL_CONTEXT (field);
1534*c87b03e5Sespie 		  error ("reference `%s' is ambiguous: appears in interface `%s' and interface `%s'",
1535*c87b03e5Sespie 			 IDENTIFIER_POINTER (name),
1536*c87b03e5Sespie 			 IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (i1))),
1537*c87b03e5Sespie 			 IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (i2))));
1538*c87b03e5Sespie 		  return error_mark_node;
1539*c87b03e5Sespie 		}
1540*c87b03e5Sespie 	    }
1541*c87b03e5Sespie 	}
1542*c87b03e5Sespie 
1543*c87b03e5Sespie       if (save_field != NULL_TREE)
1544*c87b03e5Sespie 	return save_field;
1545*c87b03e5Sespie 
1546*c87b03e5Sespie       *typep = CLASSTYPE_SUPER (*typep);
1547*c87b03e5Sespie     } while (*typep);
1548*c87b03e5Sespie   return NULL_TREE;
1549*c87b03e5Sespie }
1550*c87b03e5Sespie 
1551*c87b03e5Sespie /* Look up the field named NAME in object SELF_VALUE,
1552*c87b03e5Sespie    which has class SELF_CLASS (a non-handle RECORD_TYPE).
1553*c87b03e5Sespie    SELF_VALUE is NULL_TREE if looking for a static field. */
1554*c87b03e5Sespie 
1555*c87b03e5Sespie tree
build_field_ref(self_value,self_class,name)1556*c87b03e5Sespie build_field_ref (self_value, self_class, name)
1557*c87b03e5Sespie      tree self_value, self_class, name;
1558*c87b03e5Sespie {
1559*c87b03e5Sespie   tree base_class = self_class;
1560*c87b03e5Sespie   tree field_decl = lookup_field (&base_class, name);
1561*c87b03e5Sespie   if (field_decl == NULL_TREE)
1562*c87b03e5Sespie     {
1563*c87b03e5Sespie       error ("field `%s' not found", IDENTIFIER_POINTER (name));
1564*c87b03e5Sespie       return error_mark_node;
1565*c87b03e5Sespie     }
1566*c87b03e5Sespie   if (self_value == NULL_TREE)
1567*c87b03e5Sespie     {
1568*c87b03e5Sespie       return build_static_field_ref (field_decl);
1569*c87b03e5Sespie     }
1570*c87b03e5Sespie   else
1571*c87b03e5Sespie     {
1572*c87b03e5Sespie       int check = (flag_check_references
1573*c87b03e5Sespie 		   && ! (DECL_P (self_value)
1574*c87b03e5Sespie 			 && DECL_NAME (self_value) == this_identifier_node));
1575*c87b03e5Sespie 
1576*c87b03e5Sespie       tree base_type = promote_type (base_class);
1577*c87b03e5Sespie       if (base_type != TREE_TYPE (self_value))
1578*c87b03e5Sespie 	self_value = fold (build1 (NOP_EXPR, base_type, self_value));
1579*c87b03e5Sespie       self_value = build_java_indirect_ref (TREE_TYPE (TREE_TYPE (self_value)),
1580*c87b03e5Sespie 					    self_value, check);
1581*c87b03e5Sespie       return fold (build (COMPONENT_REF, TREE_TYPE (field_decl),
1582*c87b03e5Sespie 			  self_value, field_decl));
1583*c87b03e5Sespie     }
1584*c87b03e5Sespie }
1585*c87b03e5Sespie 
1586*c87b03e5Sespie tree
lookup_label(pc)1587*c87b03e5Sespie lookup_label (pc)
1588*c87b03e5Sespie      int pc;
1589*c87b03e5Sespie {
1590*c87b03e5Sespie   tree name;
1591*c87b03e5Sespie   char buf[32];
1592*c87b03e5Sespie   ASM_GENERATE_INTERNAL_LABEL(buf, "LJpc=", pc);
1593*c87b03e5Sespie   name = get_identifier (buf);
1594*c87b03e5Sespie   if (IDENTIFIER_LOCAL_VALUE (name))
1595*c87b03e5Sespie     return IDENTIFIER_LOCAL_VALUE (name);
1596*c87b03e5Sespie   else
1597*c87b03e5Sespie     {
1598*c87b03e5Sespie       /* The type of the address of a label is return_address_type_node. */
1599*c87b03e5Sespie       tree decl = create_label_decl (name);
1600*c87b03e5Sespie       LABEL_PC (decl) = pc;
1601*c87b03e5Sespie       label_rtx (decl);
1602*c87b03e5Sespie       return pushdecl (decl);
1603*c87b03e5Sespie     }
1604*c87b03e5Sespie }
1605*c87b03e5Sespie 
1606*c87b03e5Sespie /* Generate a unique name for the purpose of loops and switches
1607*c87b03e5Sespie    labels, and try-catch-finally blocks label or temporary variables.  */
1608*c87b03e5Sespie 
1609*c87b03e5Sespie tree
generate_name()1610*c87b03e5Sespie generate_name ()
1611*c87b03e5Sespie {
1612*c87b03e5Sespie   static int l_number = 0;
1613*c87b03e5Sespie   char buff [32];
1614*c87b03e5Sespie   ASM_GENERATE_INTERNAL_LABEL(buff, "LJv", l_number);
1615*c87b03e5Sespie   l_number++;
1616*c87b03e5Sespie   return get_identifier (buff);
1617*c87b03e5Sespie }
1618*c87b03e5Sespie 
1619*c87b03e5Sespie tree
create_label_decl(name)1620*c87b03e5Sespie create_label_decl (name)
1621*c87b03e5Sespie      tree name;
1622*c87b03e5Sespie {
1623*c87b03e5Sespie   tree decl;
1624*c87b03e5Sespie   decl = build_decl (LABEL_DECL, name,
1625*c87b03e5Sespie 		     TREE_TYPE (return_address_type_node));
1626*c87b03e5Sespie   DECL_CONTEXT (decl) = current_function_decl;
1627*c87b03e5Sespie   DECL_IGNORED_P (decl) = 1;
1628*c87b03e5Sespie   return decl;
1629*c87b03e5Sespie }
1630*c87b03e5Sespie 
1631*c87b03e5Sespie /* This maps a bytecode offset (PC) to various flags. */
1632*c87b03e5Sespie char *instruction_bits;
1633*c87b03e5Sespie 
1634*c87b03e5Sespie static void
note_label(current_pc,target_pc)1635*c87b03e5Sespie note_label (current_pc, target_pc)
1636*c87b03e5Sespie      int current_pc ATTRIBUTE_UNUSED, target_pc;
1637*c87b03e5Sespie {
1638*c87b03e5Sespie   lookup_label (target_pc);
1639*c87b03e5Sespie   instruction_bits [target_pc] |= BCODE_JUMP_TARGET;
1640*c87b03e5Sespie }
1641*c87b03e5Sespie 
1642*c87b03e5Sespie /* Emit code to jump to TARGET_PC if VALUE1 CONDITION VALUE2,
1643*c87b03e5Sespie    where CONDITION is one of one the compare operators. */
1644*c87b03e5Sespie 
1645*c87b03e5Sespie static void
expand_compare(condition,value1,value2,target_pc)1646*c87b03e5Sespie expand_compare (condition, value1, value2, target_pc)
1647*c87b03e5Sespie      enum tree_code condition;
1648*c87b03e5Sespie      tree value1, value2;
1649*c87b03e5Sespie      int target_pc;
1650*c87b03e5Sespie {
1651*c87b03e5Sespie   tree target = lookup_label (target_pc);
1652*c87b03e5Sespie   tree cond = fold (build (condition, boolean_type_node, value1, value2));
1653*c87b03e5Sespie   expand_start_cond (java_truthvalue_conversion (cond), 0);
1654*c87b03e5Sespie   expand_goto (target);
1655*c87b03e5Sespie   expand_end_cond ();
1656*c87b03e5Sespie }
1657*c87b03e5Sespie 
1658*c87b03e5Sespie /* Emit code for a TEST-type opcode. */
1659*c87b03e5Sespie 
1660*c87b03e5Sespie static void
expand_test(condition,type,target_pc)1661*c87b03e5Sespie expand_test (condition, type, target_pc)
1662*c87b03e5Sespie      enum tree_code condition;
1663*c87b03e5Sespie      tree type;
1664*c87b03e5Sespie      int target_pc;
1665*c87b03e5Sespie {
1666*c87b03e5Sespie   tree value1, value2;
1667*c87b03e5Sespie   flush_quick_stack ();
1668*c87b03e5Sespie   value1 = pop_value (type);
1669*c87b03e5Sespie   value2 = (type == ptr_type_node) ? null_pointer_node : integer_zero_node;
1670*c87b03e5Sespie   expand_compare (condition, value1, value2, target_pc);
1671*c87b03e5Sespie }
1672*c87b03e5Sespie 
1673*c87b03e5Sespie /* Emit code for a COND-type opcode. */
1674*c87b03e5Sespie 
1675*c87b03e5Sespie static void
expand_cond(condition,type,target_pc)1676*c87b03e5Sespie expand_cond (condition, type, target_pc)
1677*c87b03e5Sespie      enum tree_code condition;
1678*c87b03e5Sespie      tree type;
1679*c87b03e5Sespie      int target_pc;
1680*c87b03e5Sespie {
1681*c87b03e5Sespie   tree value1, value2;
1682*c87b03e5Sespie   flush_quick_stack ();
1683*c87b03e5Sespie   /* note: pop values in opposite order */
1684*c87b03e5Sespie   value2 = pop_value (type);
1685*c87b03e5Sespie   value1 = pop_value (type);
1686*c87b03e5Sespie   /* Maybe should check value1 and value2 for type compatibility ??? */
1687*c87b03e5Sespie   expand_compare (condition, value1, value2, target_pc);
1688*c87b03e5Sespie }
1689*c87b03e5Sespie 
1690*c87b03e5Sespie static void
expand_java_goto(target_pc)1691*c87b03e5Sespie expand_java_goto (target_pc)
1692*c87b03e5Sespie      int target_pc;
1693*c87b03e5Sespie {
1694*c87b03e5Sespie   tree target_label = lookup_label (target_pc);
1695*c87b03e5Sespie   flush_quick_stack ();
1696*c87b03e5Sespie   expand_goto (target_label);
1697*c87b03e5Sespie }
1698*c87b03e5Sespie 
1699*c87b03e5Sespie #if 0
1700*c87b03e5Sespie static void
1701*c87b03e5Sespie expand_java_call (target_pc, return_address)
1702*c87b03e5Sespie      int target_pc, return_address;
1703*c87b03e5Sespie {
1704*c87b03e5Sespie   tree target_label = lookup_label (target_pc);
1705*c87b03e5Sespie   tree value = build_int_2 (return_address, return_address < 0 ? -1 : 0);
1706*c87b03e5Sespie   push_value (value);
1707*c87b03e5Sespie   flush_quick_stack ();
1708*c87b03e5Sespie   expand_goto (target_label);
1709*c87b03e5Sespie }
1710*c87b03e5Sespie 
1711*c87b03e5Sespie static void
1712*c87b03e5Sespie expand_java_ret (return_address)
1713*c87b03e5Sespie      tree return_address ATTRIBUTE_UNUSED;
1714*c87b03e5Sespie {
1715*c87b03e5Sespie   warning ("ret instruction not implemented");
1716*c87b03e5Sespie #if 0
1717*c87b03e5Sespie   tree target_label = lookup_label (target_pc);
1718*c87b03e5Sespie   flush_quick_stack ();
1719*c87b03e5Sespie   expand_goto (target_label);
1720*c87b03e5Sespie #endif
1721*c87b03e5Sespie }
1722*c87b03e5Sespie #endif
1723*c87b03e5Sespie 
1724*c87b03e5Sespie static tree
pop_arguments(arg_types)1725*c87b03e5Sespie pop_arguments (arg_types)
1726*c87b03e5Sespie      tree arg_types;
1727*c87b03e5Sespie {
1728*c87b03e5Sespie   if (arg_types == end_params_node)
1729*c87b03e5Sespie     return NULL_TREE;
1730*c87b03e5Sespie   if (TREE_CODE (arg_types) == TREE_LIST)
1731*c87b03e5Sespie     {
1732*c87b03e5Sespie       tree tail = pop_arguments (TREE_CHAIN (arg_types));
1733*c87b03e5Sespie       tree type = TREE_VALUE (arg_types);
1734*c87b03e5Sespie       tree arg = pop_value (type);
1735*c87b03e5Sespie       if (PROMOTE_PROTOTYPES
1736*c87b03e5Sespie 	  && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)
1737*c87b03e5Sespie 	  && INTEGRAL_TYPE_P (type))
1738*c87b03e5Sespie 	arg = convert (integer_type_node, arg);
1739*c87b03e5Sespie       return tree_cons (NULL_TREE, arg, tail);
1740*c87b03e5Sespie     }
1741*c87b03e5Sespie   abort ();
1742*c87b03e5Sespie }
1743*c87b03e5Sespie 
1744*c87b03e5Sespie /* Build an expression to initialize the class CLAS.
1745*c87b03e5Sespie    if EXPR is non-NULL, returns an expression to first call the initializer
1746*c87b03e5Sespie    (if it is needed) and then calls EXPR. */
1747*c87b03e5Sespie 
1748*c87b03e5Sespie tree
build_class_init(clas,expr)1749*c87b03e5Sespie build_class_init (clas, expr)
1750*c87b03e5Sespie      tree clas, expr;
1751*c87b03e5Sespie {
1752*c87b03e5Sespie   tree init;
1753*c87b03e5Sespie 
1754*c87b03e5Sespie   /* An optimization: if CLAS is a superclass of the class we're
1755*c87b03e5Sespie      compiling, we don't need to initialize it.  However, if CLAS is
1756*c87b03e5Sespie      an interface, it won't necessarily be initialized, even if we
1757*c87b03e5Sespie      implement it.  */
1758*c87b03e5Sespie   if ((! CLASS_INTERFACE (TYPE_NAME (clas))
1759*c87b03e5Sespie        && inherits_from_p (current_class, clas))
1760*c87b03e5Sespie       || current_class == clas)
1761*c87b03e5Sespie     return expr;
1762*c87b03e5Sespie 
1763*c87b03e5Sespie   if (always_initialize_class_p)
1764*c87b03e5Sespie     {
1765*c87b03e5Sespie       init = build (CALL_EXPR, void_type_node,
1766*c87b03e5Sespie 		    build_address_of (soft_initclass_node),
1767*c87b03e5Sespie 		    build_tree_list (NULL_TREE, build_class_ref (clas)),
1768*c87b03e5Sespie 		    NULL_TREE);
1769*c87b03e5Sespie       TREE_SIDE_EFFECTS (init) = 1;
1770*c87b03e5Sespie     }
1771*c87b03e5Sespie   else
1772*c87b03e5Sespie     {
1773*c87b03e5Sespie       tree *init_test_decl;
1774*c87b03e5Sespie       init_test_decl = java_treetreehash_new
1775*c87b03e5Sespie 	(DECL_FUNCTION_INIT_TEST_TABLE (current_function_decl), clas);
1776*c87b03e5Sespie 
1777*c87b03e5Sespie       if (*init_test_decl == NULL)
1778*c87b03e5Sespie 	{
1779*c87b03e5Sespie 	  /* Build a declaration and mark it as a flag used to track
1780*c87b03e5Sespie 	     static class initializations. */
1781*c87b03e5Sespie 	  *init_test_decl = build_decl (VAR_DECL, NULL_TREE,
1782*c87b03e5Sespie 				       boolean_type_node);
1783*c87b03e5Sespie 	  MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (*init_test_decl);
1784*c87b03e5Sespie 	  LOCAL_CLASS_INITIALIZATION_FLAG (*init_test_decl) = 1;
1785*c87b03e5Sespie 	  DECL_CONTEXT (*init_test_decl) = current_function_decl;
1786*c87b03e5Sespie 	  DECL_FUNCTION_INIT_TEST_CLASS (*init_test_decl) = clas;
1787*c87b03e5Sespie 	  /* Tell the check-init code to ignore this decl when not
1788*c87b03e5Sespie              optimizing class initialization. */
1789*c87b03e5Sespie 	  if (!STATIC_CLASS_INIT_OPT_P ())
1790*c87b03e5Sespie 	    DECL_BIT_INDEX(*init_test_decl) = -1;
1791*c87b03e5Sespie 	}
1792*c87b03e5Sespie 
1793*c87b03e5Sespie       init = build (CALL_EXPR, void_type_node,
1794*c87b03e5Sespie 		    build_address_of (soft_initclass_node),
1795*c87b03e5Sespie 		    build_tree_list (NULL_TREE, build_class_ref (clas)),
1796*c87b03e5Sespie 		    NULL_TREE);
1797*c87b03e5Sespie       TREE_SIDE_EFFECTS (init) = 1;
1798*c87b03e5Sespie       init = build (COND_EXPR, void_type_node,
1799*c87b03e5Sespie 		    build (EQ_EXPR, boolean_type_node,
1800*c87b03e5Sespie 			   *init_test_decl, boolean_false_node),
1801*c87b03e5Sespie 		    init, integer_zero_node);
1802*c87b03e5Sespie       TREE_SIDE_EFFECTS (init) = 1;
1803*c87b03e5Sespie       init = build (COMPOUND_EXPR, TREE_TYPE (expr), init,
1804*c87b03e5Sespie 		    build (MODIFY_EXPR, boolean_type_node,
1805*c87b03e5Sespie 			   *init_test_decl, boolean_true_node));
1806*c87b03e5Sespie       TREE_SIDE_EFFECTS (init) = 1;
1807*c87b03e5Sespie     }
1808*c87b03e5Sespie 
1809*c87b03e5Sespie   if (expr != NULL_TREE)
1810*c87b03e5Sespie     {
1811*c87b03e5Sespie       expr = build (COMPOUND_EXPR, TREE_TYPE (expr), init, expr);
1812*c87b03e5Sespie       TREE_SIDE_EFFECTS (expr) = 1;
1813*c87b03e5Sespie       return expr;
1814*c87b03e5Sespie     }
1815*c87b03e5Sespie   return init;
1816*c87b03e5Sespie }
1817*c87b03e5Sespie 
1818*c87b03e5Sespie tree
build_known_method_ref(method,method_type,self_type,method_signature,arg_list)1819*c87b03e5Sespie build_known_method_ref (method, method_type, self_type,
1820*c87b03e5Sespie 			method_signature, arg_list)
1821*c87b03e5Sespie      tree method, method_type ATTRIBUTE_UNUSED, self_type,
1822*c87b03e5Sespie           method_signature ATTRIBUTE_UNUSED, arg_list ATTRIBUTE_UNUSED;
1823*c87b03e5Sespie {
1824*c87b03e5Sespie   tree func;
1825*c87b03e5Sespie   if (is_compiled_class (self_type))
1826*c87b03e5Sespie     {
1827*c87b03e5Sespie       make_decl_rtl (method, NULL);
1828*c87b03e5Sespie       func = build1 (ADDR_EXPR, method_ptr_type_node, method);
1829*c87b03e5Sespie     }
1830*c87b03e5Sespie   else
1831*c87b03e5Sespie     {
1832*c87b03e5Sespie       /* We don't know whether the method has been (statically) compiled.
1833*c87b03e5Sespie 	 Compile this code to get a reference to the method's code:
1834*c87b03e5Sespie 
1835*c87b03e5Sespie 	 SELF_TYPE->methods[METHOD_INDEX].ncode
1836*c87b03e5Sespie 
1837*c87b03e5Sespie 	 This is guaranteed to work (assuming SELF_TYPE has
1838*c87b03e5Sespie 	 been initialized), since if the method is not compiled yet,
1839*c87b03e5Sespie 	 its ncode points to a trampoline that forces compilation. */
1840*c87b03e5Sespie 
1841*c87b03e5Sespie       int method_index = 0;
1842*c87b03e5Sespie       tree meth;
1843*c87b03e5Sespie       tree ref = build_class_ref (self_type);
1844*c87b03e5Sespie       ref = build1 (INDIRECT_REF, class_type_node, ref);
1845*c87b03e5Sespie       if (ncode_ident == NULL_TREE)
1846*c87b03e5Sespie 	ncode_ident = get_identifier ("ncode");
1847*c87b03e5Sespie       if (methods_ident == NULL_TREE)
1848*c87b03e5Sespie 	methods_ident = get_identifier ("methods");
1849*c87b03e5Sespie       ref = build (COMPONENT_REF, method_ptr_type_node, ref,
1850*c87b03e5Sespie 		   lookup_field (&class_type_node, methods_ident));
1851*c87b03e5Sespie       for (meth = TYPE_METHODS (self_type);
1852*c87b03e5Sespie 	   ; meth = TREE_CHAIN (meth))
1853*c87b03e5Sespie 	{
1854*c87b03e5Sespie 	  if (method == meth)
1855*c87b03e5Sespie 	    break;
1856*c87b03e5Sespie 	  if (meth == NULL_TREE)
1857*c87b03e5Sespie 	    fatal_error ("method '%s' not found in class",
1858*c87b03e5Sespie 			 IDENTIFIER_POINTER (DECL_NAME (method)));
1859*c87b03e5Sespie 	  method_index++;
1860*c87b03e5Sespie 	}
1861*c87b03e5Sespie       method_index *= int_size_in_bytes (method_type_node);
1862*c87b03e5Sespie       ref = fold (build (PLUS_EXPR, method_ptr_type_node,
1863*c87b03e5Sespie 			 ref, build_int_2 (method_index, 0)));
1864*c87b03e5Sespie       ref = build1 (INDIRECT_REF, method_type_node, ref);
1865*c87b03e5Sespie       func = build (COMPONENT_REF, nativecode_ptr_type_node,
1866*c87b03e5Sespie 		    ref,
1867*c87b03e5Sespie 		    lookup_field (&method_type_node, ncode_ident));
1868*c87b03e5Sespie     }
1869*c87b03e5Sespie   return func;
1870*c87b03e5Sespie }
1871*c87b03e5Sespie 
1872*c87b03e5Sespie tree
invoke_build_dtable(is_invoke_interface,arg_list)1873*c87b03e5Sespie invoke_build_dtable (is_invoke_interface, arg_list)
1874*c87b03e5Sespie      int is_invoke_interface;
1875*c87b03e5Sespie      tree arg_list;
1876*c87b03e5Sespie {
1877*c87b03e5Sespie   tree dtable, objectref;
1878*c87b03e5Sespie 
1879*c87b03e5Sespie   TREE_VALUE (arg_list) = save_expr (TREE_VALUE (arg_list));
1880*c87b03e5Sespie 
1881*c87b03e5Sespie   /* If we're dealing with interfaces and if the objectref
1882*c87b03e5Sespie      argument is an array then get the dispatch table of the class
1883*c87b03e5Sespie      Object rather than the one from the objectref.  */
1884*c87b03e5Sespie   objectref = (is_invoke_interface
1885*c87b03e5Sespie 	       && is_array_type_p (TREE_TYPE (TREE_VALUE (arg_list))) ?
1886*c87b03e5Sespie 	       object_type_node : TREE_VALUE (arg_list));
1887*c87b03e5Sespie 
1888*c87b03e5Sespie   if (dtable_ident == NULL_TREE)
1889*c87b03e5Sespie     dtable_ident = get_identifier ("vtable");
1890*c87b03e5Sespie   dtable = build_java_indirect_ref (object_type_node, objectref,
1891*c87b03e5Sespie 				    flag_check_references);
1892*c87b03e5Sespie   dtable = build (COMPONENT_REF, dtable_ptr_type, dtable,
1893*c87b03e5Sespie 		  lookup_field (&object_type_node, dtable_ident));
1894*c87b03e5Sespie 
1895*c87b03e5Sespie   return dtable;
1896*c87b03e5Sespie }
1897*c87b03e5Sespie 
1898*c87b03e5Sespie /* Determine the index in the virtual offset table (otable) for a call to
1899*c87b03e5Sespie    METHOD. If this method has not been seen before, it will be added to the
1900*c87b03e5Sespie    otable_methods. If it has, the existing otable slot will be reused. */
1901*c87b03e5Sespie 
1902*c87b03e5Sespie int
get_offset_table_index(method)1903*c87b03e5Sespie get_offset_table_index (method)
1904*c87b03e5Sespie      tree method;
1905*c87b03e5Sespie {
1906*c87b03e5Sespie   int i = 1;
1907*c87b03e5Sespie   tree method_list;
1908*c87b03e5Sespie 
1909*c87b03e5Sespie   if (otable_methods == NULL_TREE)
1910*c87b03e5Sespie     {
1911*c87b03e5Sespie       otable_methods = build_tree_list (method, method);
1912*c87b03e5Sespie       return 1;
1913*c87b03e5Sespie     }
1914*c87b03e5Sespie 
1915*c87b03e5Sespie   method_list = otable_methods;
1916*c87b03e5Sespie 
1917*c87b03e5Sespie   while (1)
1918*c87b03e5Sespie     {
1919*c87b03e5Sespie       if (TREE_VALUE (method_list) == method)
1920*c87b03e5Sespie         return i;
1921*c87b03e5Sespie       i++;
1922*c87b03e5Sespie       if (TREE_CHAIN (method_list) == NULL_TREE)
1923*c87b03e5Sespie         break;
1924*c87b03e5Sespie       else
1925*c87b03e5Sespie         method_list = TREE_CHAIN (method_list);
1926*c87b03e5Sespie     }
1927*c87b03e5Sespie 
1928*c87b03e5Sespie   TREE_CHAIN (method_list) = build_tree_list (method, method);
1929*c87b03e5Sespie   return i;
1930*c87b03e5Sespie }
1931*c87b03e5Sespie 
1932*c87b03e5Sespie tree
build_invokevirtual(dtable,method)1933*c87b03e5Sespie build_invokevirtual (dtable, method)
1934*c87b03e5Sespie      tree dtable, method;
1935*c87b03e5Sespie {
1936*c87b03e5Sespie   tree func;
1937*c87b03e5Sespie   tree nativecode_ptr_ptr_type_node
1938*c87b03e5Sespie     = build_pointer_type (nativecode_ptr_type_node);
1939*c87b03e5Sespie   tree method_index;
1940*c87b03e5Sespie   tree otable_index;
1941*c87b03e5Sespie 
1942*c87b03e5Sespie   if (flag_indirect_dispatch)
1943*c87b03e5Sespie     {
1944*c87b03e5Sespie       otable_index = build_int_2 (get_offset_table_index (method), 0);
1945*c87b03e5Sespie       method_index = build (ARRAY_REF, integer_type_node, otable_decl,
1946*c87b03e5Sespie 			    otable_index);
1947*c87b03e5Sespie     }
1948*c87b03e5Sespie   else
1949*c87b03e5Sespie     {
1950*c87b03e5Sespie       method_index = convert (sizetype, DECL_VINDEX (method));
1951*c87b03e5Sespie 
1952*c87b03e5Sespie       if (TARGET_VTABLE_USES_DESCRIPTORS)
1953*c87b03e5Sespie 	/* Add one to skip bogus descriptor for class and GC descriptor. */
1954*c87b03e5Sespie 	method_index = size_binop (PLUS_EXPR, method_index, size_int (1));
1955*c87b03e5Sespie       else
1956*c87b03e5Sespie 	/* Add 1 to skip "class" field of dtable, and 1 to skip GC descriptor.  */
1957*c87b03e5Sespie 	method_index = size_binop (PLUS_EXPR, method_index, size_int (2));
1958*c87b03e5Sespie 
1959*c87b03e5Sespie       method_index = size_binop (MULT_EXPR, method_index,
1960*c87b03e5Sespie 				 TYPE_SIZE_UNIT (nativecode_ptr_ptr_type_node));
1961*c87b03e5Sespie 
1962*c87b03e5Sespie       if (TARGET_VTABLE_USES_DESCRIPTORS)
1963*c87b03e5Sespie 	method_index = size_binop (MULT_EXPR, method_index,
1964*c87b03e5Sespie 				   size_int (TARGET_VTABLE_USES_DESCRIPTORS));
1965*c87b03e5Sespie     }
1966*c87b03e5Sespie 
1967*c87b03e5Sespie   func = fold (build (PLUS_EXPR, nativecode_ptr_ptr_type_node, dtable,
1968*c87b03e5Sespie 		      convert (nativecode_ptr_ptr_type_node, method_index)));
1969*c87b03e5Sespie 
1970*c87b03e5Sespie   if (TARGET_VTABLE_USES_DESCRIPTORS)
1971*c87b03e5Sespie     func = build1 (NOP_EXPR, nativecode_ptr_type_node, func);
1972*c87b03e5Sespie   else
1973*c87b03e5Sespie     func = build1 (INDIRECT_REF, nativecode_ptr_type_node, func);
1974*c87b03e5Sespie 
1975*c87b03e5Sespie   return func;
1976*c87b03e5Sespie }
1977*c87b03e5Sespie 
1978*c87b03e5Sespie static GTY(()) tree class_ident;
1979*c87b03e5Sespie tree
build_invokeinterface(dtable,method)1980*c87b03e5Sespie build_invokeinterface (dtable, method)
1981*c87b03e5Sespie      tree dtable, method;
1982*c87b03e5Sespie {
1983*c87b03e5Sespie   tree lookup_arg;
1984*c87b03e5Sespie   tree interface;
1985*c87b03e5Sespie   tree idx;
1986*c87b03e5Sespie   tree meth;
1987*c87b03e5Sespie   tree otable_index;
1988*c87b03e5Sespie   int i;
1989*c87b03e5Sespie 
1990*c87b03e5Sespie   /* We expand invokeinterface here.  _Jv_LookupInterfaceMethod() will
1991*c87b03e5Sespie      ensure that the selected method exists, is public and not
1992*c87b03e5Sespie      abstract nor static.  */
1993*c87b03e5Sespie 
1994*c87b03e5Sespie   if (class_ident == NULL_TREE)
1995*c87b03e5Sespie     {
1996*c87b03e5Sespie       class_ident = get_identifier ("class");
1997*c87b03e5Sespie     }
1998*c87b03e5Sespie 
1999*c87b03e5Sespie   dtable = build_java_indirect_ref (dtable_type, dtable, flag_check_references);
2000*c87b03e5Sespie   dtable = build (COMPONENT_REF, class_ptr_type, dtable,
2001*c87b03e5Sespie 		  lookup_field (&dtable_type, class_ident));
2002*c87b03e5Sespie 
2003*c87b03e5Sespie   interface = DECL_CONTEXT (method);
2004*c87b03e5Sespie   layout_class_methods (interface);
2005*c87b03e5Sespie 
2006*c87b03e5Sespie   if (flag_indirect_dispatch)
2007*c87b03e5Sespie     {
2008*c87b03e5Sespie       otable_index = build_int_2 (get_offset_table_index (method), 0);
2009*c87b03e5Sespie       idx = build (ARRAY_REF, integer_type_node, otable_decl, otable_index);
2010*c87b03e5Sespie     }
2011*c87b03e5Sespie   else
2012*c87b03e5Sespie     {
2013*c87b03e5Sespie       i = 1;
2014*c87b03e5Sespie       for (meth = TYPE_METHODS (interface); ; meth = TREE_CHAIN (meth), i++)
2015*c87b03e5Sespie 	{
2016*c87b03e5Sespie 	  if (meth == method)
2017*c87b03e5Sespie             {
2018*c87b03e5Sespie 	      idx = build_int_2 (i, 0);
2019*c87b03e5Sespie 	      break;
2020*c87b03e5Sespie 	    }
2021*c87b03e5Sespie 	  if (meth == NULL_TREE)
2022*c87b03e5Sespie 	    abort ();
2023*c87b03e5Sespie 	}
2024*c87b03e5Sespie     }
2025*c87b03e5Sespie 
2026*c87b03e5Sespie   lookup_arg = tree_cons (NULL_TREE, dtable,
2027*c87b03e5Sespie                           tree_cons (NULL_TREE, build_class_ref (interface),
2028*c87b03e5Sespie 			             build_tree_list (NULL_TREE, idx)));
2029*c87b03e5Sespie 
2030*c87b03e5Sespie   return build (CALL_EXPR, ptr_type_node,
2031*c87b03e5Sespie 		build_address_of (soft_lookupinterfacemethod_node),
2032*c87b03e5Sespie 		lookup_arg, NULL_TREE);
2033*c87b03e5Sespie }
2034*c87b03e5Sespie 
2035*c87b03e5Sespie /* Expand one of the invoke_* opcodes.
2036*c87b03e5Sespie    OCPODE is the specific opcode.
2037*c87b03e5Sespie    METHOD_REF_INDEX is an index into the constant pool.
2038*c87b03e5Sespie    NARGS is the number of arguments, or -1 if not specified. */
2039*c87b03e5Sespie 
2040*c87b03e5Sespie static void
expand_invoke(opcode,method_ref_index,nargs)2041*c87b03e5Sespie expand_invoke (opcode, method_ref_index, nargs)
2042*c87b03e5Sespie      int opcode;
2043*c87b03e5Sespie      int method_ref_index;
2044*c87b03e5Sespie      int nargs ATTRIBUTE_UNUSED;
2045*c87b03e5Sespie {
2046*c87b03e5Sespie   tree method_signature = COMPONENT_REF_SIGNATURE(&current_jcf->cpool, method_ref_index);
2047*c87b03e5Sespie   tree method_name = COMPONENT_REF_NAME (&current_jcf->cpool, method_ref_index);
2048*c87b03e5Sespie   tree self_type = get_class_constant
2049*c87b03e5Sespie     (current_jcf, COMPONENT_REF_CLASS_INDEX(&current_jcf->cpool, method_ref_index));
2050*c87b03e5Sespie   const char *const self_name
2051*c87b03e5Sespie     = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (self_type)));
2052*c87b03e5Sespie   tree call, func, method, arg_list, method_type;
2053*c87b03e5Sespie   tree check = NULL_TREE;
2054*c87b03e5Sespie 
2055*c87b03e5Sespie   if (! CLASS_LOADED_P (self_type))
2056*c87b03e5Sespie     {
2057*c87b03e5Sespie       load_class (self_type, 1);
2058*c87b03e5Sespie       safe_layout_class (self_type);
2059*c87b03e5Sespie       if (TREE_CODE (TYPE_SIZE (self_type)) == ERROR_MARK)
2060*c87b03e5Sespie 	fatal_error ("failed to find class '%s'", self_name);
2061*c87b03e5Sespie     }
2062*c87b03e5Sespie   layout_class_methods (self_type);
2063*c87b03e5Sespie 
2064*c87b03e5Sespie   if (ID_INIT_P (method_name))
2065*c87b03e5Sespie     method = lookup_java_constructor (self_type, method_signature);
2066*c87b03e5Sespie   else
2067*c87b03e5Sespie     method = lookup_java_method (self_type, method_name, method_signature);
2068*c87b03e5Sespie   if (method == NULL_TREE)
2069*c87b03e5Sespie     {
2070*c87b03e5Sespie       error ("class '%s' has no method named '%s' matching signature '%s'",
2071*c87b03e5Sespie 	     self_name,
2072*c87b03e5Sespie 	     IDENTIFIER_POINTER (method_name),
2073*c87b03e5Sespie 	     IDENTIFIER_POINTER (method_signature));
2074*c87b03e5Sespie     }
2075*c87b03e5Sespie   /* Invoke static can't invoke static/abstract method */
2076*c87b03e5Sespie   else if (opcode == OPCODE_invokestatic)
2077*c87b03e5Sespie     {
2078*c87b03e5Sespie       if (!METHOD_STATIC (method))
2079*c87b03e5Sespie 	{
2080*c87b03e5Sespie 	  error ("invokestatic on non static method");
2081*c87b03e5Sespie 	  method = NULL_TREE;
2082*c87b03e5Sespie 	}
2083*c87b03e5Sespie       else if (METHOD_ABSTRACT (method))
2084*c87b03e5Sespie 	{
2085*c87b03e5Sespie 	  error ("invokestatic on abstract method");
2086*c87b03e5Sespie 	  method = NULL_TREE;
2087*c87b03e5Sespie 	}
2088*c87b03e5Sespie     }
2089*c87b03e5Sespie   else
2090*c87b03e5Sespie     {
2091*c87b03e5Sespie       if (METHOD_STATIC (method))
2092*c87b03e5Sespie 	{
2093*c87b03e5Sespie 	  error ("invoke[non-static] on static method");
2094*c87b03e5Sespie 	  method = NULL_TREE;
2095*c87b03e5Sespie 	}
2096*c87b03e5Sespie     }
2097*c87b03e5Sespie 
2098*c87b03e5Sespie   if (method == NULL_TREE)
2099*c87b03e5Sespie     {
2100*c87b03e5Sespie       method_type = get_type_from_signature (method_signature);
2101*c87b03e5Sespie       pop_arguments (TYPE_ARG_TYPES (method_type));
2102*c87b03e5Sespie       if (opcode != OPCODE_invokestatic)
2103*c87b03e5Sespie 	pop_type (self_type);
2104*c87b03e5Sespie       method_type = promote_type (TREE_TYPE (method_type));
2105*c87b03e5Sespie       push_value (convert (method_type, integer_zero_node));
2106*c87b03e5Sespie       return;
2107*c87b03e5Sespie     }
2108*c87b03e5Sespie 
2109*c87b03e5Sespie   method_type = TREE_TYPE (method);
2110*c87b03e5Sespie   arg_list = pop_arguments (TYPE_ARG_TYPES (method_type));
2111*c87b03e5Sespie   flush_quick_stack ();
2112*c87b03e5Sespie 
2113*c87b03e5Sespie   func = NULL_TREE;
2114*c87b03e5Sespie   if (opcode == OPCODE_invokestatic)
2115*c87b03e5Sespie     func = build_known_method_ref (method, method_type, self_type,
2116*c87b03e5Sespie 				   method_signature, arg_list);
2117*c87b03e5Sespie   else if (opcode == OPCODE_invokespecial
2118*c87b03e5Sespie 	   || (opcode == OPCODE_invokevirtual
2119*c87b03e5Sespie 	       && (METHOD_PRIVATE (method)
2120*c87b03e5Sespie 		   || METHOD_FINAL (method)
2121*c87b03e5Sespie 		   || CLASS_FINAL (TYPE_NAME (self_type)))))
2122*c87b03e5Sespie     {
2123*c87b03e5Sespie       /* If the object for the method call is null, we throw an
2124*c87b03e5Sespie 	 exception.  We don't do this if the object is the current
2125*c87b03e5Sespie 	 method's `this'.  In other cases we just rely on an
2126*c87b03e5Sespie 	 optimization pass to eliminate redundant checks.  FIXME:
2127*c87b03e5Sespie 	 Unfortunately there doesn't seem to be a way to determine
2128*c87b03e5Sespie 	 what the current method is right now.
2129*c87b03e5Sespie 	 We do omit the check if we're calling <init>.  */
2130*c87b03e5Sespie       /* We use a SAVE_EXPR here to make sure we only evaluate
2131*c87b03e5Sespie 	 the new `self' expression once.  */
2132*c87b03e5Sespie       tree save_arg = save_expr (TREE_VALUE (arg_list));
2133*c87b03e5Sespie       TREE_VALUE (arg_list) = save_arg;
2134*c87b03e5Sespie       check = java_check_reference (save_arg, ! DECL_INIT_P (method));
2135*c87b03e5Sespie       func = build_known_method_ref (method, method_type, self_type,
2136*c87b03e5Sespie 				     method_signature, arg_list);
2137*c87b03e5Sespie     }
2138*c87b03e5Sespie   else
2139*c87b03e5Sespie     {
2140*c87b03e5Sespie       tree dtable = invoke_build_dtable (opcode == OPCODE_invokeinterface,
2141*c87b03e5Sespie 					 arg_list);
2142*c87b03e5Sespie       if (opcode == OPCODE_invokevirtual)
2143*c87b03e5Sespie 	func = build_invokevirtual (dtable, method);
2144*c87b03e5Sespie       else
2145*c87b03e5Sespie 	func = build_invokeinterface (dtable, method);
2146*c87b03e5Sespie     }
2147*c87b03e5Sespie   func = build1 (NOP_EXPR, build_pointer_type (method_type), func);
2148*c87b03e5Sespie 
2149*c87b03e5Sespie   call = build (CALL_EXPR, TREE_TYPE (method_type), func, arg_list, NULL_TREE);
2150*c87b03e5Sespie   TREE_SIDE_EFFECTS (call) = 1;
2151*c87b03e5Sespie   call = check_for_builtin (method, call);
2152*c87b03e5Sespie 
2153*c87b03e5Sespie   if (check != NULL_TREE)
2154*c87b03e5Sespie     {
2155*c87b03e5Sespie       call = build (COMPOUND_EXPR, TREE_TYPE (call), check, call);
2156*c87b03e5Sespie       TREE_SIDE_EFFECTS (call) = 1;
2157*c87b03e5Sespie     }
2158*c87b03e5Sespie 
2159*c87b03e5Sespie   if (TREE_CODE (TREE_TYPE (method_type)) == VOID_TYPE)
2160*c87b03e5Sespie     expand_expr_stmt (call);
2161*c87b03e5Sespie   else
2162*c87b03e5Sespie     {
2163*c87b03e5Sespie       push_value (call);
2164*c87b03e5Sespie       flush_quick_stack ();
2165*c87b03e5Sespie     }
2166*c87b03e5Sespie }
2167*c87b03e5Sespie 
2168*c87b03e5Sespie /* Create a stub which will be put into the vtable but which will call
2169*c87b03e5Sespie    a JNI function.  */
2170*c87b03e5Sespie 
2171*c87b03e5Sespie tree
build_jni_stub(method)2172*c87b03e5Sespie build_jni_stub (method)
2173*c87b03e5Sespie      tree method;
2174*c87b03e5Sespie {
2175*c87b03e5Sespie   tree jnifunc, call, args, body, lookup_arg, method_sig, arg_types;
2176*c87b03e5Sespie   tree jni_func_type, tem;
2177*c87b03e5Sespie   tree env_var, res_var = NULL_TREE, block;
2178*c87b03e5Sespie   tree method_args, res_type;
2179*c87b03e5Sespie   tree meth_var;
2180*c87b03e5Sespie 
2181*c87b03e5Sespie   int args_size = 0;
2182*c87b03e5Sespie 
2183*c87b03e5Sespie   tree klass = DECL_CONTEXT (method);
2184*c87b03e5Sespie   int from_class = ! CLASS_FROM_SOURCE_P (klass);
2185*c87b03e5Sespie   klass = build_class_ref (klass);
2186*c87b03e5Sespie 
2187*c87b03e5Sespie   if (! METHOD_NATIVE (method) || ! flag_jni)
2188*c87b03e5Sespie     abort ();
2189*c87b03e5Sespie 
2190*c87b03e5Sespie   DECL_ARTIFICIAL (method) = 1;
2191*c87b03e5Sespie   DECL_EXTERNAL (method) = 0;
2192*c87b03e5Sespie 
2193*c87b03e5Sespie   env_var = build_decl (VAR_DECL, get_identifier ("env"), ptr_type_node);
2194*c87b03e5Sespie   DECL_CONTEXT (env_var) = method;
2195*c87b03e5Sespie 
2196*c87b03e5Sespie   if (TREE_TYPE (TREE_TYPE (method)) != void_type_node)
2197*c87b03e5Sespie     {
2198*c87b03e5Sespie       res_var = build_decl (VAR_DECL, get_identifier ("res"),
2199*c87b03e5Sespie 			    TREE_TYPE (TREE_TYPE (method)));
2200*c87b03e5Sespie       DECL_CONTEXT (res_var) = method;
2201*c87b03e5Sespie       TREE_CHAIN (env_var) = res_var;
2202*c87b03e5Sespie     }
2203*c87b03e5Sespie 
2204*c87b03e5Sespie   meth_var = build_decl (VAR_DECL, get_identifier ("meth"), ptr_type_node);
2205*c87b03e5Sespie   TREE_STATIC (meth_var) = 1;
2206*c87b03e5Sespie   TREE_PUBLIC (meth_var) = 0;
2207*c87b03e5Sespie   DECL_EXTERNAL (meth_var) = 0;
2208*c87b03e5Sespie   DECL_CONTEXT (meth_var) = method;
2209*c87b03e5Sespie   DECL_ARTIFICIAL (meth_var) = 1;
2210*c87b03e5Sespie   DECL_INITIAL (meth_var) = null_pointer_node;
2211*c87b03e5Sespie   TREE_USED (meth_var) = 1;
2212*c87b03e5Sespie   chainon (env_var, meth_var);
2213*c87b03e5Sespie   layout_decl (meth_var, 0);
2214*c87b03e5Sespie   make_decl_rtl (meth_var, NULL);
2215*c87b03e5Sespie   rest_of_decl_compilation (meth_var, NULL, 0, 0);
2216*c87b03e5Sespie 
2217*c87b03e5Sespie   /* One strange way that the front ends are different is that they
2218*c87b03e5Sespie      store arguments differently.  */
2219*c87b03e5Sespie   if (from_class)
2220*c87b03e5Sespie     method_args = DECL_ARGUMENTS (method);
2221*c87b03e5Sespie   else
2222*c87b03e5Sespie     method_args = BLOCK_EXPR_DECLS (DECL_FUNCTION_BODY (method));
2223*c87b03e5Sespie   block = build_block (env_var, NULL_TREE, NULL_TREE,
2224*c87b03e5Sespie 		       method_args, NULL_TREE);
2225*c87b03e5Sespie   TREE_SIDE_EFFECTS (block) = 1;
2226*c87b03e5Sespie   /* When compiling from source we don't set the type of the block,
2227*c87b03e5Sespie      because that will prevent patch_return from ever being run.  */
2228*c87b03e5Sespie   if (from_class)
2229*c87b03e5Sespie     TREE_TYPE (block) = TREE_TYPE (TREE_TYPE (method));
2230*c87b03e5Sespie 
2231*c87b03e5Sespie   /* Compute the local `env' by calling _Jv_GetJNIEnvNewFrame.  */
2232*c87b03e5Sespie   body = build (MODIFY_EXPR, ptr_type_node, env_var,
2233*c87b03e5Sespie 		build (CALL_EXPR, ptr_type_node,
2234*c87b03e5Sespie 		       build_address_of (soft_getjnienvnewframe_node),
2235*c87b03e5Sespie 		       build_tree_list (NULL_TREE, klass),
2236*c87b03e5Sespie 		       NULL_TREE));
2237*c87b03e5Sespie   CAN_COMPLETE_NORMALLY (body) = 1;
2238*c87b03e5Sespie 
2239*c87b03e5Sespie   /* All the arguments to this method become arguments to the
2240*c87b03e5Sespie      underlying JNI function.  If we had to wrap object arguments in a
2241*c87b03e5Sespie      special way, we would do that here.  */
2242*c87b03e5Sespie   args = NULL_TREE;
2243*c87b03e5Sespie   for (tem = method_args; tem != NULL_TREE; tem = TREE_CHAIN (tem))
2244*c87b03e5Sespie     {
2245*c87b03e5Sespie       int arg_bits = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (tem)));
2246*c87b03e5Sespie #ifdef PARM_BOUNDARY
2247*c87b03e5Sespie       arg_bits = (((arg_bits + PARM_BOUNDARY - 1) / PARM_BOUNDARY)
2248*c87b03e5Sespie                   * PARM_BOUNDARY);
2249*c87b03e5Sespie #endif
2250*c87b03e5Sespie       args_size += (arg_bits / BITS_PER_UNIT);
2251*c87b03e5Sespie 
2252*c87b03e5Sespie       args = tree_cons (NULL_TREE, tem, args);
2253*c87b03e5Sespie     }
2254*c87b03e5Sespie   args = nreverse (args);
2255*c87b03e5Sespie   arg_types = TYPE_ARG_TYPES (TREE_TYPE (method));
2256*c87b03e5Sespie 
2257*c87b03e5Sespie   /* For a static method the second argument is the class.  For a
2258*c87b03e5Sespie      non-static method the second argument is `this'; that is already
2259*c87b03e5Sespie      available in the argument list.  */
2260*c87b03e5Sespie   if (METHOD_STATIC (method))
2261*c87b03e5Sespie     {
2262*c87b03e5Sespie       args_size += int_size_in_bytes (TREE_TYPE (klass));
2263*c87b03e5Sespie       args = tree_cons (NULL_TREE, klass, args);
2264*c87b03e5Sespie       arg_types = tree_cons (NULL_TREE, object_ptr_type_node, arg_types);
2265*c87b03e5Sespie     }
2266*c87b03e5Sespie 
2267*c87b03e5Sespie   /* The JNIEnv structure is the first argument to the JNI function.  */
2268*c87b03e5Sespie   args_size += int_size_in_bytes (TREE_TYPE (env_var));
2269*c87b03e5Sespie   args = tree_cons (NULL_TREE, env_var, args);
2270*c87b03e5Sespie   arg_types = tree_cons (NULL_TREE, ptr_type_node, arg_types);
2271*c87b03e5Sespie 
2272*c87b03e5Sespie   /* We call _Jv_LookupJNIMethod to find the actual underlying
2273*c87b03e5Sespie      function pointer.  _Jv_LookupJNIMethod will throw the appropriate
2274*c87b03e5Sespie      exception if this function is not found at runtime.  */
2275*c87b03e5Sespie   tem = build_tree_list (NULL_TREE, build_int_2 (args_size, 0));
2276*c87b03e5Sespie   method_sig = build_java_signature (TREE_TYPE (method));
2277*c87b03e5Sespie   lookup_arg = tree_cons (NULL_TREE,
2278*c87b03e5Sespie                           build_utf8_ref (unmangle_classname
2279*c87b03e5Sespie                                           (IDENTIFIER_POINTER (method_sig),
2280*c87b03e5Sespie                                            IDENTIFIER_LENGTH (method_sig))),
2281*c87b03e5Sespie                           tem);
2282*c87b03e5Sespie   tem = DECL_NAME (method);
2283*c87b03e5Sespie   lookup_arg
2284*c87b03e5Sespie     = tree_cons (NULL_TREE, klass,
2285*c87b03e5Sespie 		 tree_cons (NULL_TREE, build_utf8_ref (tem), lookup_arg));
2286*c87b03e5Sespie 
2287*c87b03e5Sespie   tem = build_function_type (TREE_TYPE (TREE_TYPE (method)), arg_types);
2288*c87b03e5Sespie 
2289*c87b03e5Sespie #ifdef MODIFY_JNI_METHOD_CALL
2290*c87b03e5Sespie   tem = MODIFY_JNI_METHOD_CALL (tem);
2291*c87b03e5Sespie #endif
2292*c87b03e5Sespie 
2293*c87b03e5Sespie   jni_func_type = build_pointer_type (tem);
2294*c87b03e5Sespie 
2295*c87b03e5Sespie   jnifunc = build (COND_EXPR, ptr_type_node,
2296*c87b03e5Sespie 		   meth_var, meth_var,
2297*c87b03e5Sespie 		   build (MODIFY_EXPR, ptr_type_node,
2298*c87b03e5Sespie 			  meth_var,
2299*c87b03e5Sespie 			  build (CALL_EXPR, ptr_type_node,
2300*c87b03e5Sespie 				 build_address_of (soft_lookupjnimethod_node),
2301*c87b03e5Sespie 				 lookup_arg, NULL_TREE)));
2302*c87b03e5Sespie 
2303*c87b03e5Sespie   /* Now we make the actual JNI call via the resulting function
2304*c87b03e5Sespie      pointer.    */
2305*c87b03e5Sespie   call = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (method)),
2306*c87b03e5Sespie 		build1 (NOP_EXPR, jni_func_type, jnifunc),
2307*c87b03e5Sespie 		args, NULL_TREE);
2308*c87b03e5Sespie 
2309*c87b03e5Sespie   /* If the JNI call returned a result, capture it here.  If we had to
2310*c87b03e5Sespie      unwrap JNI object results, we would do that here.  */
2311*c87b03e5Sespie   if (res_var != NULL_TREE)
2312*c87b03e5Sespie     call = build (MODIFY_EXPR, TREE_TYPE (TREE_TYPE (method)),
2313*c87b03e5Sespie 		  res_var, call);
2314*c87b03e5Sespie 
2315*c87b03e5Sespie   TREE_SIDE_EFFECTS (call) = 1;
2316*c87b03e5Sespie   CAN_COMPLETE_NORMALLY (call) = 1;
2317*c87b03e5Sespie 
2318*c87b03e5Sespie   body = build (COMPOUND_EXPR, void_type_node, body, call);
2319*c87b03e5Sespie   TREE_SIDE_EFFECTS (body) = 1;
2320*c87b03e5Sespie 
2321*c87b03e5Sespie   /* Now free the environment we allocated.  */
2322*c87b03e5Sespie   call = build (CALL_EXPR, ptr_type_node,
2323*c87b03e5Sespie 		build_address_of (soft_jnipopsystemframe_node),
2324*c87b03e5Sespie 		build_tree_list (NULL_TREE, env_var),
2325*c87b03e5Sespie 		NULL_TREE);
2326*c87b03e5Sespie   TREE_SIDE_EFFECTS (call) = 1;
2327*c87b03e5Sespie   CAN_COMPLETE_NORMALLY (call) = 1;
2328*c87b03e5Sespie   body = build (COMPOUND_EXPR, void_type_node, body, call);
2329*c87b03e5Sespie   TREE_SIDE_EFFECTS (body) = 1;
2330*c87b03e5Sespie 
2331*c87b03e5Sespie   /* Finally, do the return.  When compiling from source we rely on
2332*c87b03e5Sespie      patch_return to patch the return value -- because DECL_RESULT is
2333*c87b03e5Sespie      not set at the time this function is called.  */
2334*c87b03e5Sespie   if (from_class)
2335*c87b03e5Sespie     {
2336*c87b03e5Sespie       res_type = void_type_node;
2337*c87b03e5Sespie       if (res_var != NULL_TREE)
2338*c87b03e5Sespie 	{
2339*c87b03e5Sespie 	  tree drt;
2340*c87b03e5Sespie 	  if (! DECL_RESULT (method))
2341*c87b03e5Sespie 	    abort ();
2342*c87b03e5Sespie 	  /* Make sure we copy the result variable to the actual
2343*c87b03e5Sespie 	     result.  We use the type of the DECL_RESULT because it
2344*c87b03e5Sespie 	     might be different from the return type of the function:
2345*c87b03e5Sespie 	     it might be promoted.  */
2346*c87b03e5Sespie 	  drt = TREE_TYPE (DECL_RESULT (method));
2347*c87b03e5Sespie 	  if (drt != TREE_TYPE (res_var))
2348*c87b03e5Sespie 	    res_var = build1 (CONVERT_EXPR, drt, res_var);
2349*c87b03e5Sespie 	  res_var = build (MODIFY_EXPR, drt, DECL_RESULT (method), res_var);
2350*c87b03e5Sespie 	  TREE_SIDE_EFFECTS (res_var) = 1;
2351*c87b03e5Sespie 	}
2352*c87b03e5Sespie     }
2353*c87b03e5Sespie   else
2354*c87b03e5Sespie     {
2355*c87b03e5Sespie       /* This is necessary to get patch_return to run.  */
2356*c87b03e5Sespie       res_type = NULL_TREE;
2357*c87b03e5Sespie     }
2358*c87b03e5Sespie   body = build (COMPOUND_EXPR, void_type_node, body,
2359*c87b03e5Sespie 		build1 (RETURN_EXPR, res_type, res_var));
2360*c87b03e5Sespie   TREE_SIDE_EFFECTS (body) = 1;
2361*c87b03e5Sespie 
2362*c87b03e5Sespie   BLOCK_EXPR_BODY (block) = body;
2363*c87b03e5Sespie   return block;
2364*c87b03e5Sespie }
2365*c87b03e5Sespie 
2366*c87b03e5Sespie /* Expand an operation to extract from or store into a field.
2367*c87b03e5Sespie    IS_STATIC is 1 iff the field is static.
2368*c87b03e5Sespie    IS_PUTTING is 1 for putting into a field;  0 for getting from the field.
2369*c87b03e5Sespie    FIELD_REF_INDEX is an index into the constant pool.  */
2370*c87b03e5Sespie 
2371*c87b03e5Sespie static void
expand_java_field_op(is_static,is_putting,field_ref_index)2372*c87b03e5Sespie expand_java_field_op (is_static, is_putting, field_ref_index)
2373*c87b03e5Sespie      int is_static;
2374*c87b03e5Sespie      int is_putting;
2375*c87b03e5Sespie      int field_ref_index;
2376*c87b03e5Sespie {
2377*c87b03e5Sespie   tree self_type =
2378*c87b03e5Sespie       get_class_constant (current_jcf,
2379*c87b03e5Sespie 			  COMPONENT_REF_CLASS_INDEX (&current_jcf->cpool,
2380*c87b03e5Sespie 						     field_ref_index));
2381*c87b03e5Sespie   const char *self_name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (self_type)));
2382*c87b03e5Sespie   tree field_name = COMPONENT_REF_NAME (&current_jcf->cpool, field_ref_index);
2383*c87b03e5Sespie   tree field_signature = COMPONENT_REF_SIGNATURE (&current_jcf->cpool,
2384*c87b03e5Sespie 						  field_ref_index);
2385*c87b03e5Sespie   tree field_type = get_type_from_signature (field_signature);
2386*c87b03e5Sespie   tree new_value = is_putting ? pop_value (field_type) : NULL_TREE;
2387*c87b03e5Sespie   tree field_ref;
2388*c87b03e5Sespie   int is_error = 0;
2389*c87b03e5Sespie   tree field_decl = lookup_field (&self_type, field_name);
2390*c87b03e5Sespie   if (field_decl == error_mark_node)
2391*c87b03e5Sespie     {
2392*c87b03e5Sespie       is_error = 1;
2393*c87b03e5Sespie     }
2394*c87b03e5Sespie   else if (field_decl == NULL_TREE)
2395*c87b03e5Sespie     {
2396*c87b03e5Sespie       error ("missing field '%s' in '%s'",
2397*c87b03e5Sespie 	     IDENTIFIER_POINTER (field_name), self_name);
2398*c87b03e5Sespie       is_error = 1;
2399*c87b03e5Sespie     }
2400*c87b03e5Sespie   else if (build_java_signature (TREE_TYPE (field_decl)) != field_signature)
2401*c87b03e5Sespie     {
2402*c87b03e5Sespie       error ("mismatching signature for field '%s' in '%s'",
2403*c87b03e5Sespie 	     IDENTIFIER_POINTER (field_name), self_name);
2404*c87b03e5Sespie       is_error = 1;
2405*c87b03e5Sespie     }
2406*c87b03e5Sespie   field_ref = is_static ? NULL_TREE : pop_value (self_type);
2407*c87b03e5Sespie   if (is_error)
2408*c87b03e5Sespie     {
2409*c87b03e5Sespie       if (! is_putting)
2410*c87b03e5Sespie 	push_value (convert (field_type, integer_zero_node));
2411*c87b03e5Sespie       flush_quick_stack ();
2412*c87b03e5Sespie       return;
2413*c87b03e5Sespie     }
2414*c87b03e5Sespie 
2415*c87b03e5Sespie   field_ref = build_field_ref (field_ref, self_type, field_name);
2416*c87b03e5Sespie   if (is_static)
2417*c87b03e5Sespie     field_ref = build_class_init (self_type, field_ref);
2418*c87b03e5Sespie   if (is_putting)
2419*c87b03e5Sespie     {
2420*c87b03e5Sespie       flush_quick_stack ();
2421*c87b03e5Sespie       if (FIELD_FINAL (field_decl))
2422*c87b03e5Sespie 	{
2423*c87b03e5Sespie 	  if (DECL_CONTEXT (field_decl) != current_class)
2424*c87b03e5Sespie 	    error_with_decl (field_decl,
2425*c87b03e5Sespie 		     "assignment to final field `%s' not in field's class");
2426*c87b03e5Sespie 	  else if (FIELD_STATIC (field_decl))
2427*c87b03e5Sespie 	    {
2428*c87b03e5Sespie 	      if (!DECL_CLINIT_P (current_function_decl))
2429*c87b03e5Sespie 		warning_with_decl (field_decl,
2430*c87b03e5Sespie              "assignment to final static field `%s' not in class initializer");
2431*c87b03e5Sespie 	    }
2432*c87b03e5Sespie 	  else
2433*c87b03e5Sespie 	    {
2434*c87b03e5Sespie 	      tree cfndecl_name = DECL_NAME (current_function_decl);
2435*c87b03e5Sespie 	      if (! DECL_CONSTRUCTOR_P (current_function_decl)
2436*c87b03e5Sespie 		  && !ID_FINIT_P (cfndecl_name))
2437*c87b03e5Sespie 		warning_with_decl (field_decl, "assignment to final field `%s' not in constructor");
2438*c87b03e5Sespie 	    }
2439*c87b03e5Sespie 	}
2440*c87b03e5Sespie       expand_assignment (field_ref, new_value, 0, 0);
2441*c87b03e5Sespie     }
2442*c87b03e5Sespie   else
2443*c87b03e5Sespie     push_value (field_ref);
2444*c87b03e5Sespie }
2445*c87b03e5Sespie 
2446*c87b03e5Sespie void
load_type_state(label)2447*c87b03e5Sespie load_type_state (label)
2448*c87b03e5Sespie      tree label;
2449*c87b03e5Sespie {
2450*c87b03e5Sespie   int i;
2451*c87b03e5Sespie   tree vec = LABEL_TYPE_STATE (label);
2452*c87b03e5Sespie   int cur_length = TREE_VEC_LENGTH (vec);
2453*c87b03e5Sespie   stack_pointer = cur_length - DECL_MAX_LOCALS(current_function_decl);
2454*c87b03e5Sespie   for (i = 0; i < cur_length; i++)
2455*c87b03e5Sespie     type_map [i] = TREE_VEC_ELT (vec, i);
2456*c87b03e5Sespie }
2457*c87b03e5Sespie 
2458*c87b03e5Sespie /* Do the expansion of a Java switch. With Gcc, switches are front-end
2459*c87b03e5Sespie    dependent things, but they rely on gcc routines. This function is
2460*c87b03e5Sespie    placed here because it uses things defined locally in parse.y. */
2461*c87b03e5Sespie 
2462*c87b03e5Sespie static tree
case_identity(t,v)2463*c87b03e5Sespie case_identity (t, v)
2464*c87b03e5Sespie      tree t __attribute__ ((__unused__));
2465*c87b03e5Sespie      tree v;
2466*c87b03e5Sespie {
2467*c87b03e5Sespie   return v;
2468*c87b03e5Sespie }
2469*c87b03e5Sespie 
2470*c87b03e5Sespie /* Return the name of the vtable for an array of a given primitive
2471*c87b03e5Sespie    type.  */
2472*c87b03e5Sespie static tree
get_primitive_array_vtable(tree elt)2473*c87b03e5Sespie get_primitive_array_vtable (tree elt)
2474*c87b03e5Sespie {
2475*c87b03e5Sespie   tree r;
2476*c87b03e5Sespie   if (elt == boolean_type_node)
2477*c87b03e5Sespie     r = boolean_array_vtable;
2478*c87b03e5Sespie   else if (elt == byte_type_node)
2479*c87b03e5Sespie     r = byte_array_vtable;
2480*c87b03e5Sespie   else if (elt == char_type_node)
2481*c87b03e5Sespie     r = char_array_vtable;
2482*c87b03e5Sespie   else if (elt == short_type_node)
2483*c87b03e5Sespie     r = short_array_vtable;
2484*c87b03e5Sespie   else if (elt == int_type_node)
2485*c87b03e5Sespie     r = int_array_vtable;
2486*c87b03e5Sespie   else if (elt == long_type_node)
2487*c87b03e5Sespie     r = long_array_vtable;
2488*c87b03e5Sespie   else if (elt == float_type_node)
2489*c87b03e5Sespie     r = float_array_vtable;
2490*c87b03e5Sespie   else if (elt == double_type_node)
2491*c87b03e5Sespie     r = double_array_vtable;
2492*c87b03e5Sespie   else
2493*c87b03e5Sespie     abort ();
2494*c87b03e5Sespie   return build_address_of (r);
2495*c87b03e5Sespie }
2496*c87b03e5Sespie 
2497*c87b03e5Sespie struct rtx_def *
java_expand_expr(exp,target,tmode,modifier)2498*c87b03e5Sespie java_expand_expr (exp, target, tmode, modifier)
2499*c87b03e5Sespie      register tree exp;
2500*c87b03e5Sespie      rtx target;
2501*c87b03e5Sespie      enum machine_mode tmode;
2502*c87b03e5Sespie      int modifier; /* Actually an enum expand_modifier.  */
2503*c87b03e5Sespie {
2504*c87b03e5Sespie   tree current;
2505*c87b03e5Sespie 
2506*c87b03e5Sespie   switch (TREE_CODE (exp))
2507*c87b03e5Sespie     {
2508*c87b03e5Sespie     case NEW_ARRAY_INIT:
2509*c87b03e5Sespie       {
2510*c87b03e5Sespie 	rtx tmp;
2511*c87b03e5Sespie 	tree array_type = TREE_TYPE (TREE_TYPE (exp));
2512*c87b03e5Sespie 	tree element_type = TYPE_ARRAY_ELEMENT (array_type);
2513*c87b03e5Sespie 	tree data_fld = TREE_CHAIN (TREE_CHAIN (TYPE_FIELDS (array_type)));
2514*c87b03e5Sespie 	HOST_WIDE_INT ilength = java_array_type_length (array_type);
2515*c87b03e5Sespie 	tree length = build_int_2 (ilength, 0);
2516*c87b03e5Sespie 	tree init = TREE_OPERAND (exp, 0);
2517*c87b03e5Sespie 	tree array_decl;
2518*c87b03e5Sespie 
2519*c87b03e5Sespie 	/* See if we can generate the array statically.  */
2520*c87b03e5Sespie 	if (TREE_CONSTANT (init) && TREE_STATIC (exp)
2521*c87b03e5Sespie 	    && JPRIMITIVE_TYPE_P (element_type))
2522*c87b03e5Sespie 	  {
2523*c87b03e5Sespie 	    tree temp, value, init_decl;
2524*c87b03e5Sespie 	    struct rtx_def *r;
2525*c87b03e5Sespie 	    START_RECORD_CONSTRUCTOR (temp, object_type_node);
2526*c87b03e5Sespie 	    PUSH_FIELD_VALUE (temp, "vtable",
2527*c87b03e5Sespie 			      get_primitive_array_vtable (element_type));
2528*c87b03e5Sespie 	    if (! flag_hash_synchronization)
2529*c87b03e5Sespie 	      PUSH_FIELD_VALUE (temp, "sync_info", null_pointer_node);
2530*c87b03e5Sespie 	    FINISH_RECORD_CONSTRUCTOR (temp);
2531*c87b03e5Sespie 	    START_RECORD_CONSTRUCTOR (value, array_type);
2532*c87b03e5Sespie 	    PUSH_SUPER_VALUE (value, temp);
2533*c87b03e5Sespie 	    PUSH_FIELD_VALUE (value, "length", length);
2534*c87b03e5Sespie 	    PUSH_FIELD_VALUE (value, "data", init);
2535*c87b03e5Sespie 	    FINISH_RECORD_CONSTRUCTOR (value);
2536*c87b03e5Sespie 
2537*c87b03e5Sespie 	    init_decl = build_decl (VAR_DECL, generate_name (), array_type);
2538*c87b03e5Sespie 	    pushdecl_top_level (init_decl);
2539*c87b03e5Sespie 	    TREE_STATIC (init_decl) = 1;
2540*c87b03e5Sespie 	    DECL_INITIAL (init_decl) = value;
2541*c87b03e5Sespie 	    DECL_IGNORED_P (init_decl) = 1;
2542*c87b03e5Sespie 	    TREE_READONLY (init_decl) = 1;
2543*c87b03e5Sespie 	    /* Hash synchronization requires at least 64-bit alignment. */
2544*c87b03e5Sespie 	    if (flag_hash_synchronization && POINTER_SIZE < 64)
2545*c87b03e5Sespie 	      DECL_ALIGN (init_decl) = 64;
2546*c87b03e5Sespie 	    rest_of_decl_compilation (init_decl, NULL, 1, 0);
2547*c87b03e5Sespie 	    TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (init_decl)) = 1;
2548*c87b03e5Sespie 	    init = build1 (ADDR_EXPR, TREE_TYPE (exp), init_decl);
2549*c87b03e5Sespie 	    r = expand_expr (init, target, tmode, modifier);
2550*c87b03e5Sespie 	    return r;
2551*c87b03e5Sespie 	  }
2552*c87b03e5Sespie 
2553*c87b03e5Sespie 	array_decl = build_decl (VAR_DECL, NULL_TREE, TREE_TYPE (exp));
2554*c87b03e5Sespie 	expand_decl (array_decl);
2555*c87b03e5Sespie 	tmp = expand_assignment (array_decl,
2556*c87b03e5Sespie 				 build_new_array (element_type, length),
2557*c87b03e5Sespie 				 1, 0);
2558*c87b03e5Sespie 	if (TREE_CONSTANT (init)
2559*c87b03e5Sespie 	    && ilength >= 10 && JPRIMITIVE_TYPE_P (element_type))
2560*c87b03e5Sespie 	  {
2561*c87b03e5Sespie 	    tree init_decl;
2562*c87b03e5Sespie 	    init_decl = build_decl (VAR_DECL, generate_name (),
2563*c87b03e5Sespie 				    TREE_TYPE (init));
2564*c87b03e5Sespie 	    pushdecl_top_level (init_decl);
2565*c87b03e5Sespie 	    TREE_STATIC (init_decl) = 1;
2566*c87b03e5Sespie 	    DECL_INITIAL (init_decl) = init;
2567*c87b03e5Sespie 	    DECL_IGNORED_P (init_decl) = 1;
2568*c87b03e5Sespie 	    TREE_READONLY (init_decl) = 1;
2569*c87b03e5Sespie 	    rest_of_decl_compilation (init_decl, NULL, 1, 0);
2570*c87b03e5Sespie 	    TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (init_decl)) = 1;
2571*c87b03e5Sespie 	    init = init_decl;
2572*c87b03e5Sespie 	  }
2573*c87b03e5Sespie 	expand_assignment (build (COMPONENT_REF, TREE_TYPE (data_fld),
2574*c87b03e5Sespie 				  build_java_indirect_ref (array_type,
2575*c87b03e5Sespie 					  array_decl, flag_check_references),
2576*c87b03e5Sespie 				  data_fld), init, 0, 0);
2577*c87b03e5Sespie 	return tmp;
2578*c87b03e5Sespie       }
2579*c87b03e5Sespie     case BLOCK:
2580*c87b03e5Sespie       if (BLOCK_EXPR_BODY (exp))
2581*c87b03e5Sespie 	{
2582*c87b03e5Sespie 	  tree local;
2583*c87b03e5Sespie 	  rtx last;
2584*c87b03e5Sespie 	  tree body = BLOCK_EXPR_BODY (exp);
2585*c87b03e5Sespie 	  /* Set to 1 or more when we found a static class
2586*c87b03e5Sespie              initialization flag. */
2587*c87b03e5Sespie 	  int found_class_initialization_flag = 0;
2588*c87b03e5Sespie 
2589*c87b03e5Sespie 	  pushlevel (2);	/* 2 and above */
2590*c87b03e5Sespie 	  expand_start_bindings (0);
2591*c87b03e5Sespie 	  local = BLOCK_EXPR_DECLS (exp);
2592*c87b03e5Sespie 	  while (local)
2593*c87b03e5Sespie 	    {
2594*c87b03e5Sespie 	      tree next = TREE_CHAIN (local);
2595*c87b03e5Sespie 	      found_class_initialization_flag +=
2596*c87b03e5Sespie 		LOCAL_CLASS_INITIALIZATION_FLAG_P (local);
2597*c87b03e5Sespie 	      layout_decl (local, 0);
2598*c87b03e5Sespie 	      expand_decl (pushdecl (local));
2599*c87b03e5Sespie 	      local = next;
2600*c87b03e5Sespie 	    }
2601*c87b03e5Sespie 
2602*c87b03e5Sespie 	  /* Emit initialization code for test flags if we saw one. */
2603*c87b03e5Sespie 	  if (! always_initialize_class_p
2604*c87b03e5Sespie 	      && current_function_decl
2605*c87b03e5Sespie 	      && found_class_initialization_flag)
2606*c87b03e5Sespie 	    htab_traverse
2607*c87b03e5Sespie 	      (DECL_FUNCTION_INIT_TEST_TABLE (current_function_decl),
2608*c87b03e5Sespie 	       emit_init_test_initialization, NULL);
2609*c87b03e5Sespie 
2610*c87b03e5Sespie 	  /* Avoid deep recursion for long block.  */
2611*c87b03e5Sespie 	  while (TREE_CODE (body) == COMPOUND_EXPR)
2612*c87b03e5Sespie 	    {
2613*c87b03e5Sespie 	      expand_expr (TREE_OPERAND (body, 0), const0_rtx, VOIDmode, 0);
2614*c87b03e5Sespie 	      emit_queue ();
2615*c87b03e5Sespie 	      body = TREE_OPERAND (body, 1);
2616*c87b03e5Sespie 	    }
2617*c87b03e5Sespie   	  last = expand_expr (body, NULL_RTX, VOIDmode, 0);
2618*c87b03e5Sespie 	  emit_queue ();
2619*c87b03e5Sespie 	  expand_end_bindings (getdecls (), 1, 0);
2620*c87b03e5Sespie 	  poplevel (1, 1, 0);
2621*c87b03e5Sespie 	  return last;
2622*c87b03e5Sespie 	}
2623*c87b03e5Sespie       return const0_rtx;
2624*c87b03e5Sespie 
2625*c87b03e5Sespie     case CASE_EXPR:
2626*c87b03e5Sespie       {
2627*c87b03e5Sespie 	tree duplicate;
2628*c87b03e5Sespie 	if (pushcase (TREE_OPERAND (exp, 0), case_identity,
2629*c87b03e5Sespie 		      build_decl (LABEL_DECL, NULL_TREE, NULL_TREE),
2630*c87b03e5Sespie 		      &duplicate) == 2)
2631*c87b03e5Sespie 	  {
2632*c87b03e5Sespie 	    EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (exp);
2633*c87b03e5Sespie 	    parse_error_context
2634*c87b03e5Sespie 	      (wfl_operator, "Duplicate case label: `%s'",
2635*c87b03e5Sespie 	       print_int_node (TREE_OPERAND (exp, 0)));
2636*c87b03e5Sespie 	  }
2637*c87b03e5Sespie 	return const0_rtx;
2638*c87b03e5Sespie       }
2639*c87b03e5Sespie 
2640*c87b03e5Sespie     case DEFAULT_EXPR:
2641*c87b03e5Sespie       pushcase (NULL_TREE, 0,
2642*c87b03e5Sespie 		build_decl (LABEL_DECL, NULL_TREE, NULL_TREE), NULL);
2643*c87b03e5Sespie       return const0_rtx;
2644*c87b03e5Sespie 
2645*c87b03e5Sespie     case SWITCH_EXPR:
2646*c87b03e5Sespie       expand_start_case (0, TREE_OPERAND (exp, 0), int_type_node, "switch");
2647*c87b03e5Sespie       expand_expr_stmt (TREE_OPERAND (exp, 1));
2648*c87b03e5Sespie       expand_end_case (TREE_OPERAND (exp, 0));
2649*c87b03e5Sespie       return const0_rtx;
2650*c87b03e5Sespie 
2651*c87b03e5Sespie     case TRY_EXPR:
2652*c87b03e5Sespie       /* We expand a try[-catch] block */
2653*c87b03e5Sespie 
2654*c87b03e5Sespie       /* Expand the try block */
2655*c87b03e5Sespie       expand_eh_region_start ();
2656*c87b03e5Sespie       expand_expr_stmt (TREE_OPERAND (exp, 0));
2657*c87b03e5Sespie       expand_start_all_catch ();
2658*c87b03e5Sespie 
2659*c87b03e5Sespie       /* Expand all catch clauses (EH handlers) */
2660*c87b03e5Sespie       for (current = TREE_OPERAND (exp, 1); current;
2661*c87b03e5Sespie 	   current = TREE_CHAIN (current))
2662*c87b03e5Sespie 	{
2663*c87b03e5Sespie 	  tree catch = TREE_OPERAND (current, 0);
2664*c87b03e5Sespie 	  tree decl = BLOCK_EXPR_DECLS (catch);
2665*c87b03e5Sespie 	  tree type = (decl ? TREE_TYPE (TREE_TYPE (decl)) : NULL_TREE);
2666*c87b03e5Sespie 
2667*c87b03e5Sespie 	  expand_start_catch (type);
2668*c87b03e5Sespie 	  expand_expr_stmt (TREE_OPERAND (current, 0));
2669*c87b03e5Sespie 	  expand_end_catch ();
2670*c87b03e5Sespie 	}
2671*c87b03e5Sespie       expand_end_all_catch ();
2672*c87b03e5Sespie       return const0_rtx;
2673*c87b03e5Sespie 
2674*c87b03e5Sespie     case JAVA_EXC_OBJ_EXPR:
2675*c87b03e5Sespie       return expand_expr (build_exception_object_ref (TREE_TYPE (exp)),
2676*c87b03e5Sespie 			  target, tmode, modifier);
2677*c87b03e5Sespie 
2678*c87b03e5Sespie     case LABEL_EXPR:
2679*c87b03e5Sespie       /* Used only by expanded inline functions.  */
2680*c87b03e5Sespie       expand_label (TREE_OPERAND (exp, 0));
2681*c87b03e5Sespie       return const0_rtx;
2682*c87b03e5Sespie 
2683*c87b03e5Sespie     default:
2684*c87b03e5Sespie       internal_error ("can't expand %s", tree_code_name [TREE_CODE (exp)]);
2685*c87b03e5Sespie     }
2686*c87b03e5Sespie }
2687*c87b03e5Sespie 
2688*c87b03e5Sespie /* Go over METHOD's bytecode and note instruction starts in
2689*c87b03e5Sespie    instruction_bits[].  */
2690*c87b03e5Sespie 
2691*c87b03e5Sespie void
note_instructions(jcf,method)2692*c87b03e5Sespie note_instructions (jcf, method)
2693*c87b03e5Sespie      JCF *jcf;
2694*c87b03e5Sespie      tree method;
2695*c87b03e5Sespie {
2696*c87b03e5Sespie   int PC;
2697*c87b03e5Sespie   unsigned char* byte_ops;
2698*c87b03e5Sespie   long length = DECL_CODE_LENGTH (method);
2699*c87b03e5Sespie 
2700*c87b03e5Sespie   int saw_index;
2701*c87b03e5Sespie   jint INT_temp;
2702*c87b03e5Sespie 
2703*c87b03e5Sespie #undef RET /* Defined by config/i386/i386.h */
2704*c87b03e5Sespie #undef AND /* Causes problems with opcodes for iand and land. */
2705*c87b03e5Sespie #undef PTR
2706*c87b03e5Sespie #define BCODE byte_ops
2707*c87b03e5Sespie #define BYTE_type_node byte_type_node
2708*c87b03e5Sespie #define SHORT_type_node short_type_node
2709*c87b03e5Sespie #define INT_type_node int_type_node
2710*c87b03e5Sespie #define LONG_type_node long_type_node
2711*c87b03e5Sespie #define CHAR_type_node char_type_node
2712*c87b03e5Sespie #define PTR_type_node ptr_type_node
2713*c87b03e5Sespie #define FLOAT_type_node float_type_node
2714*c87b03e5Sespie #define DOUBLE_type_node double_type_node
2715*c87b03e5Sespie #define VOID_type_node void_type_node
2716*c87b03e5Sespie #define CONST_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
2717*c87b03e5Sespie #define CONST_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
2718*c87b03e5Sespie #define VAR_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
2719*c87b03e5Sespie #define VAR_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
2720*c87b03e5Sespie 
2721*c87b03e5Sespie #define CHECK_PC_IN_RANGE(PC) ((void)1) /* Already handled by verifier. */
2722*c87b03e5Sespie 
2723*c87b03e5Sespie   JCF_SEEK (jcf, DECL_CODE_OFFSET (method));
2724*c87b03e5Sespie   byte_ops = jcf->read_ptr;
2725*c87b03e5Sespie   instruction_bits = xrealloc (instruction_bits, length + 1);
2726*c87b03e5Sespie   memset (instruction_bits, 0, length + 1);
2727*c87b03e5Sespie 
2728*c87b03e5Sespie   /* This pass figures out which PC can be the targets of jumps. */
2729*c87b03e5Sespie   for (PC = 0; PC < length;)
2730*c87b03e5Sespie     {
2731*c87b03e5Sespie       int oldpc = PC; /* PC at instruction start. */
2732*c87b03e5Sespie       instruction_bits [PC] |=  BCODE_INSTRUCTION_START;
2733*c87b03e5Sespie       switch (byte_ops[PC++])
2734*c87b03e5Sespie 	{
2735*c87b03e5Sespie #define JAVAOP(OPNAME, OPCODE, OPKIND, OPERAND_TYPE, OPERAND_VALUE) \
2736*c87b03e5Sespie         case OPCODE: \
2737*c87b03e5Sespie 	  PRE_##OPKIND(OPERAND_TYPE, OPERAND_VALUE); \
2738*c87b03e5Sespie 	  break;
2739*c87b03e5Sespie 
2740*c87b03e5Sespie #define NOTE_LABEL(PC) note_label(oldpc, PC)
2741*c87b03e5Sespie 
2742*c87b03e5Sespie #define PRE_PUSHC(OPERAND_TYPE, OPERAND_VALUE) (void)(OPERAND_VALUE);
2743*c87b03e5Sespie #define PRE_LOAD(OPERAND_TYPE, OPERAND_VALUE) (void)(OPERAND_VALUE);
2744*c87b03e5Sespie #define PRE_STORE(OPERAND_TYPE, OPERAND_VALUE) (void)(OPERAND_VALUE);
2745*c87b03e5Sespie #define PRE_STACK(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
2746*c87b03e5Sespie #define PRE_UNOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
2747*c87b03e5Sespie #define PRE_BINOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
2748*c87b03e5Sespie #define PRE_CONVERT(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
2749*c87b03e5Sespie #define PRE_CONVERT2(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
2750*c87b03e5Sespie 
2751*c87b03e5Sespie #define PRE_SPECIAL(OPERAND_TYPE, INSTRUCTION) \
2752*c87b03e5Sespie   PRE_SPECIAL_##INSTRUCTION(OPERAND_TYPE)
2753*c87b03e5Sespie #define PRE_SPECIAL_IINC(OPERAND_TYPE) \
2754*c87b03e5Sespie   ((void) IMMEDIATE_u1, (void) IMMEDIATE_s1)
2755*c87b03e5Sespie #define PRE_SPECIAL_ENTER(IGNORE) /* nothing */
2756*c87b03e5Sespie #define PRE_SPECIAL_EXIT(IGNORE) /* nothing */
2757*c87b03e5Sespie #define PRE_SPECIAL_THROW(IGNORE) /* nothing */
2758*c87b03e5Sespie #define PRE_SPECIAL_BREAK(IGNORE) /* nothing */
2759*c87b03e5Sespie 
2760*c87b03e5Sespie /* two forms of wide instructions */
2761*c87b03e5Sespie #define PRE_SPECIAL_WIDE(IGNORE) \
2762*c87b03e5Sespie   { \
2763*c87b03e5Sespie     int modified_opcode = IMMEDIATE_u1; \
2764*c87b03e5Sespie     if (modified_opcode == OPCODE_iinc)	\
2765*c87b03e5Sespie       { \
2766*c87b03e5Sespie 	(void) IMMEDIATE_u2;	/* indexbyte1 and indexbyte2 */ \
2767*c87b03e5Sespie 	(void) IMMEDIATE_s2;	/* constbyte1 and constbyte2 */ \
2768*c87b03e5Sespie       } \
2769*c87b03e5Sespie     else \
2770*c87b03e5Sespie       { \
2771*c87b03e5Sespie 	(void) IMMEDIATE_u2;	/* indexbyte1 and indexbyte2 */ \
2772*c87b03e5Sespie       } \
2773*c87b03e5Sespie   }
2774*c87b03e5Sespie 
2775*c87b03e5Sespie #define PRE_IMPL(IGNORE1, IGNORE2) /* nothing */
2776*c87b03e5Sespie 
2777*c87b03e5Sespie #define PRE_MONITOR(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
2778*c87b03e5Sespie 
2779*c87b03e5Sespie #define PRE_RETURN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
2780*c87b03e5Sespie #define PRE_ARRAY(OPERAND_TYPE, SUBOP) \
2781*c87b03e5Sespie 	  PRE_ARRAY_##SUBOP(OPERAND_TYPE)
2782*c87b03e5Sespie #define PRE_ARRAY_LOAD(TYPE) /* nothing */
2783*c87b03e5Sespie #define PRE_ARRAY_STORE(TYPE) /* nothing */
2784*c87b03e5Sespie #define PRE_ARRAY_LENGTH(TYPE) /* nothing */
2785*c87b03e5Sespie #define PRE_ARRAY_NEW(TYPE) PRE_ARRAY_NEW_##TYPE
2786*c87b03e5Sespie #define PRE_ARRAY_NEW_NUM ((void) IMMEDIATE_u1)
2787*c87b03e5Sespie #define PRE_ARRAY_NEW_PTR ((void) IMMEDIATE_u2)
2788*c87b03e5Sespie #define PRE_ARRAY_NEW_MULTI ((void) IMMEDIATE_u2, (void) IMMEDIATE_u1)
2789*c87b03e5Sespie 
2790*c87b03e5Sespie #define PRE_TEST(OPERAND_TYPE, OPERAND_VALUE) NOTE_LABEL (oldpc+IMMEDIATE_s2)
2791*c87b03e5Sespie #define PRE_COND(OPERAND_TYPE, OPERAND_VALUE) NOTE_LABEL (oldpc+IMMEDIATE_s2)
2792*c87b03e5Sespie #define PRE_BRANCH(OPERAND_TYPE, OPERAND_VALUE) \
2793*c87b03e5Sespie   saw_index = 0;  INT_temp = (OPERAND_VALUE); \
2794*c87b03e5Sespie   if (!saw_index)  NOTE_LABEL(oldpc + INT_temp);
2795*c87b03e5Sespie #define PRE_JSR(OPERAND_TYPE, OPERAND_VALUE) \
2796*c87b03e5Sespie   saw_index = 0;  INT_temp = (OPERAND_VALUE); \
2797*c87b03e5Sespie   NOTE_LABEL (PC); \
2798*c87b03e5Sespie   if (!saw_index)  NOTE_LABEL(oldpc + INT_temp);
2799*c87b03e5Sespie 
2800*c87b03e5Sespie #define PRE_RET(OPERAND_TYPE, OPERAND_VALUE)  (void)(OPERAND_VALUE)
2801*c87b03e5Sespie 
2802*c87b03e5Sespie #define PRE_SWITCH(OPERAND_TYPE, TABLE_OR_LOOKUP) \
2803*c87b03e5Sespie   PC = (PC + 3) / 4 * 4; PRE_##TABLE_OR_LOOKUP##_SWITCH
2804*c87b03e5Sespie 
2805*c87b03e5Sespie #define PRE_LOOKUP_SWITCH						\
2806*c87b03e5Sespie   { jint default_offset = IMMEDIATE_s4;  jint npairs = IMMEDIATE_s4;	\
2807*c87b03e5Sespie     NOTE_LABEL (default_offset+oldpc);					\
2808*c87b03e5Sespie     if (npairs >= 0)							\
2809*c87b03e5Sespie       while (--npairs >= 0) {						\
2810*c87b03e5Sespie        jint match ATTRIBUTE_UNUSED = IMMEDIATE_s4;			\
2811*c87b03e5Sespie        jint offset = IMMEDIATE_s4;					\
2812*c87b03e5Sespie        NOTE_LABEL (offset+oldpc); }					\
2813*c87b03e5Sespie   }
2814*c87b03e5Sespie 
2815*c87b03e5Sespie #define PRE_TABLE_SWITCH				\
2816*c87b03e5Sespie   { jint default_offset = IMMEDIATE_s4;			\
2817*c87b03e5Sespie     jint low = IMMEDIATE_s4; jint high = IMMEDIATE_s4;	\
2818*c87b03e5Sespie     NOTE_LABEL (default_offset+oldpc);			\
2819*c87b03e5Sespie     if (low <= high)					\
2820*c87b03e5Sespie      while (low++ <= high) {				\
2821*c87b03e5Sespie        jint offset = IMMEDIATE_s4;			\
2822*c87b03e5Sespie        NOTE_LABEL (offset+oldpc); }			\
2823*c87b03e5Sespie   }
2824*c87b03e5Sespie 
2825*c87b03e5Sespie #define PRE_FIELD(MAYBE_STATIC, PUT_OR_GET) (void)(IMMEDIATE_u2);
2826*c87b03e5Sespie #define PRE_OBJECT(MAYBE_STATIC, PUT_OR_GET) (void)(IMMEDIATE_u2);
2827*c87b03e5Sespie #define PRE_INVOKE(MAYBE_STATIC, IS_INTERFACE) \
2828*c87b03e5Sespie   (void)(IMMEDIATE_u2); \
2829*c87b03e5Sespie   PC += 2 * IS_INTERFACE /* for invokeinterface */;
2830*c87b03e5Sespie 
2831*c87b03e5Sespie #include "javaop.def"
2832*c87b03e5Sespie #undef JAVAOP
2833*c87b03e5Sespie 	}
2834*c87b03e5Sespie     } /* for */
2835*c87b03e5Sespie }
2836*c87b03e5Sespie 
2837*c87b03e5Sespie void
expand_byte_code(jcf,method)2838*c87b03e5Sespie expand_byte_code (jcf, method)
2839*c87b03e5Sespie      JCF *jcf;
2840*c87b03e5Sespie      tree method;
2841*c87b03e5Sespie {
2842*c87b03e5Sespie   int PC;
2843*c87b03e5Sespie   int i;
2844*c87b03e5Sespie   const unsigned char *linenumber_pointer;
2845*c87b03e5Sespie   int dead_code_index = -1;
2846*c87b03e5Sespie   unsigned char* byte_ops;
2847*c87b03e5Sespie   long length = DECL_CODE_LENGTH (method);
2848*c87b03e5Sespie 
2849*c87b03e5Sespie   stack_pointer = 0;
2850*c87b03e5Sespie   JCF_SEEK (jcf, DECL_CODE_OFFSET (method));
2851*c87b03e5Sespie   byte_ops = jcf->read_ptr;
2852*c87b03e5Sespie 
2853*c87b03e5Sespie   /* We make an initial pass of the line number table, to note
2854*c87b03e5Sespie      which instructions have associated line number entries. */
2855*c87b03e5Sespie   linenumber_pointer = linenumber_table;
2856*c87b03e5Sespie   for (i = 0; i < linenumber_count; i++)
2857*c87b03e5Sespie     {
2858*c87b03e5Sespie       int pc = GET_u2 (linenumber_pointer);
2859*c87b03e5Sespie       linenumber_pointer += 4;
2860*c87b03e5Sespie       if (pc >= length)
2861*c87b03e5Sespie 	warning ("invalid PC in line number table");
2862*c87b03e5Sespie       else
2863*c87b03e5Sespie 	{
2864*c87b03e5Sespie 	  if ((instruction_bits[pc] & BCODE_HAS_LINENUMBER) != 0)
2865*c87b03e5Sespie 	    instruction_bits[pc] |= BCODE_HAS_MULTI_LINENUMBERS;
2866*c87b03e5Sespie 	  instruction_bits[pc] |= BCODE_HAS_LINENUMBER;
2867*c87b03e5Sespie 	}
2868*c87b03e5Sespie     }
2869*c87b03e5Sespie 
2870*c87b03e5Sespie   if (! verify_jvm_instructions (jcf, byte_ops, length))
2871*c87b03e5Sespie     return;
2872*c87b03e5Sespie 
2873*c87b03e5Sespie   /* Translate bytecodes to rtl instructions. */
2874*c87b03e5Sespie   linenumber_pointer = linenumber_table;
2875*c87b03e5Sespie   for (PC = 0; PC < length;)
2876*c87b03e5Sespie     {
2877*c87b03e5Sespie       if ((instruction_bits [PC] & BCODE_TARGET) != 0 || PC == 0)
2878*c87b03e5Sespie 	{
2879*c87b03e5Sespie 	  tree label = lookup_label (PC);
2880*c87b03e5Sespie           flush_quick_stack ();
2881*c87b03e5Sespie 	  if ((instruction_bits [PC] & BCODE_TARGET) != 0)
2882*c87b03e5Sespie 	    expand_label (label);
2883*c87b03e5Sespie 	  if (LABEL_VERIFIED (label) || PC == 0)
2884*c87b03e5Sespie 	    load_type_state (label);
2885*c87b03e5Sespie 	}
2886*c87b03e5Sespie 
2887*c87b03e5Sespie       if (! (instruction_bits [PC] & BCODE_VERIFIED))
2888*c87b03e5Sespie 	{
2889*c87b03e5Sespie 	  if (dead_code_index == -1)
2890*c87b03e5Sespie 	    {
2891*c87b03e5Sespie 	      /* This is the start of a region of unreachable bytecodes.
2892*c87b03e5Sespie                  They still need to be processed in order for EH ranges
2893*c87b03e5Sespie                  to get handled correctly.  However, we can simply
2894*c87b03e5Sespie                  replace these bytecodes with nops.  */
2895*c87b03e5Sespie 	      dead_code_index = PC;
2896*c87b03e5Sespie             }
2897*c87b03e5Sespie 
2898*c87b03e5Sespie           /* Turn this bytecode into a nop.  */
2899*c87b03e5Sespie           byte_ops[PC] = 0x0;
2900*c87b03e5Sespie         }
2901*c87b03e5Sespie        else
2902*c87b03e5Sespie         {
2903*c87b03e5Sespie 	  if (dead_code_index != -1)
2904*c87b03e5Sespie 	    {
2905*c87b03e5Sespie               /* We've just reached the end of a region of dead code.  */
2906*c87b03e5Sespie               warning ("unreachable bytecode from %d to before %d",
2907*c87b03e5Sespie                        dead_code_index, PC);
2908*c87b03e5Sespie               dead_code_index = -1;
2909*c87b03e5Sespie             }
2910*c87b03e5Sespie 	}
2911*c87b03e5Sespie 
2912*c87b03e5Sespie       /* Handle possible line number entry for this PC.
2913*c87b03e5Sespie 
2914*c87b03e5Sespie 	 This code handles out-of-order and multiple linenumbers per PC,
2915*c87b03e5Sespie 	 but is optimized for the case of line numbers increasing
2916*c87b03e5Sespie 	 monotonically with PC. */
2917*c87b03e5Sespie       if ((instruction_bits[PC] & BCODE_HAS_LINENUMBER) != 0)
2918*c87b03e5Sespie 	{
2919*c87b03e5Sespie 	  if ((instruction_bits[PC] & BCODE_HAS_MULTI_LINENUMBERS) != 0
2920*c87b03e5Sespie 	      || GET_u2 (linenumber_pointer) != PC)
2921*c87b03e5Sespie 	    linenumber_pointer = linenumber_table;
2922*c87b03e5Sespie 	  while (linenumber_pointer < linenumber_table + linenumber_count * 4)
2923*c87b03e5Sespie 	    {
2924*c87b03e5Sespie 	      int pc = GET_u2 (linenumber_pointer);
2925*c87b03e5Sespie 	      linenumber_pointer += 4;
2926*c87b03e5Sespie 	      if (pc == PC)
2927*c87b03e5Sespie 		{
2928*c87b03e5Sespie 		  lineno = GET_u2 (linenumber_pointer - 2);
2929*c87b03e5Sespie 		  emit_line_note (input_filename, lineno);
2930*c87b03e5Sespie 		  if (!(instruction_bits[PC] & BCODE_HAS_MULTI_LINENUMBERS))
2931*c87b03e5Sespie 		    break;
2932*c87b03e5Sespie 		}
2933*c87b03e5Sespie 	    }
2934*c87b03e5Sespie 	}
2935*c87b03e5Sespie       maybe_pushlevels (PC);
2936*c87b03e5Sespie       PC = process_jvm_instruction (PC, byte_ops, length);
2937*c87b03e5Sespie       maybe_poplevels (PC);
2938*c87b03e5Sespie     } /* for */
2939*c87b03e5Sespie 
2940*c87b03e5Sespie   if (dead_code_index != -1)
2941*c87b03e5Sespie     {
2942*c87b03e5Sespie       /* We've just reached the end of a region of dead code.  */
2943*c87b03e5Sespie       warning ("unreachable bytecode from %d to the end of the method",
2944*c87b03e5Sespie               dead_code_index);
2945*c87b03e5Sespie     }
2946*c87b03e5Sespie }
2947*c87b03e5Sespie 
2948*c87b03e5Sespie static void
java_push_constant_from_pool(jcf,index)2949*c87b03e5Sespie java_push_constant_from_pool (jcf, index)
2950*c87b03e5Sespie      JCF *jcf;
2951*c87b03e5Sespie      int index;
2952*c87b03e5Sespie {
2953*c87b03e5Sespie   tree c;
2954*c87b03e5Sespie   if (JPOOL_TAG (jcf, index) == CONSTANT_String)
2955*c87b03e5Sespie     {
2956*c87b03e5Sespie       tree name;
2957*c87b03e5Sespie       name = get_name_constant (jcf, JPOOL_USHORT1 (jcf, index));
2958*c87b03e5Sespie       index = alloc_name_constant (CONSTANT_String, name);
2959*c87b03e5Sespie       c = build_ref_from_constant_pool (index);
2960*c87b03e5Sespie       TREE_TYPE (c) = promote_type (string_type_node);
2961*c87b03e5Sespie     }
2962*c87b03e5Sespie   else
2963*c87b03e5Sespie     c = get_constant (jcf, index);
2964*c87b03e5Sespie   push_value (c);
2965*c87b03e5Sespie }
2966*c87b03e5Sespie 
2967*c87b03e5Sespie int
process_jvm_instruction(PC,byte_ops,length)2968*c87b03e5Sespie process_jvm_instruction (PC, byte_ops, length)
2969*c87b03e5Sespie      int PC;
2970*c87b03e5Sespie      const unsigned char* byte_ops;
2971*c87b03e5Sespie      long length ATTRIBUTE_UNUSED;
2972*c87b03e5Sespie {
2973*c87b03e5Sespie   const char *opname; /* Temporary ??? */
2974*c87b03e5Sespie   int oldpc = PC; /* PC at instruction start. */
2975*c87b03e5Sespie 
2976*c87b03e5Sespie   /* If the instruction is at the beginning of a exception handler,
2977*c87b03e5Sespie      replace the top of the stack with the thrown object reference */
2978*c87b03e5Sespie   if (instruction_bits [PC] & BCODE_EXCEPTION_TARGET)
2979*c87b03e5Sespie     {
2980*c87b03e5Sespie       tree type = pop_type (ptr_type_node);
2981*c87b03e5Sespie       push_value (build (JAVA_EXC_OBJ_EXPR, type));
2982*c87b03e5Sespie     }
2983*c87b03e5Sespie 
2984*c87b03e5Sespie   switch (byte_ops[PC++])
2985*c87b03e5Sespie     {
2986*c87b03e5Sespie #define JAVAOP(OPNAME, OPCODE, OPKIND, OPERAND_TYPE, OPERAND_VALUE) \
2987*c87b03e5Sespie     case OPCODE: \
2988*c87b03e5Sespie       opname = #OPNAME; \
2989*c87b03e5Sespie       OPKIND(OPERAND_TYPE, OPERAND_VALUE); \
2990*c87b03e5Sespie       break;
2991*c87b03e5Sespie 
2992*c87b03e5Sespie #define RET(OPERAND_TYPE, OPERAND_VALUE) 				\
2993*c87b03e5Sespie   {									\
2994*c87b03e5Sespie     int saw_index = 0;							\
2995*c87b03e5Sespie     int index     = OPERAND_VALUE;					\
2996*c87b03e5Sespie     build_java_ret (find_local_variable (index, ptr_type_node, oldpc));	\
2997*c87b03e5Sespie   }
2998*c87b03e5Sespie 
2999*c87b03e5Sespie #define JSR(OPERAND_TYPE, OPERAND_VALUE) \
3000*c87b03e5Sespie   {						    \
3001*c87b03e5Sespie     /* OPERAND_VALUE may have side-effects on PC */ \
3002*c87b03e5Sespie     int opvalue = OPERAND_VALUE;		    \
3003*c87b03e5Sespie     build_java_jsr (oldpc + opvalue, PC);	    \
3004*c87b03e5Sespie   }
3005*c87b03e5Sespie 
3006*c87b03e5Sespie /* Push a constant onto the stack. */
3007*c87b03e5Sespie #define PUSHC(OPERAND_TYPE, OPERAND_VALUE) \
3008*c87b03e5Sespie   { int saw_index = 0;  int ival = (OPERAND_VALUE); \
3009*c87b03e5Sespie     if (saw_index) java_push_constant_from_pool (current_jcf, ival); \
3010*c87b03e5Sespie     else expand_java_pushc (ival, OPERAND_TYPE##_type_node); }
3011*c87b03e5Sespie 
3012*c87b03e5Sespie /* internal macro added for use by the WIDE case */
3013*c87b03e5Sespie #define LOAD_INTERNAL(OPTYPE, OPVALUE) \
3014*c87b03e5Sespie   expand_load_internal (OPVALUE, type_map[OPVALUE], oldpc);
3015*c87b03e5Sespie 
3016*c87b03e5Sespie /* Push local variable onto the opcode stack. */
3017*c87b03e5Sespie #define LOAD(OPERAND_TYPE, OPERAND_VALUE) \
3018*c87b03e5Sespie   { \
3019*c87b03e5Sespie     /* have to do this since OPERAND_VALUE may have side-effects */ \
3020*c87b03e5Sespie     int opvalue = OPERAND_VALUE; \
3021*c87b03e5Sespie     LOAD_INTERNAL(OPERAND_TYPE##_type_node, opvalue); \
3022*c87b03e5Sespie   }
3023*c87b03e5Sespie 
3024*c87b03e5Sespie #define RETURN(OPERAND_TYPE, OPERAND_VALUE) \
3025*c87b03e5Sespie   expand_java_return (OPERAND_TYPE##_type_node)
3026*c87b03e5Sespie 
3027*c87b03e5Sespie #define REM_EXPR TRUNC_MOD_EXPR
3028*c87b03e5Sespie #define BINOP(OPERAND_TYPE, OPERAND_VALUE) \
3029*c87b03e5Sespie   expand_java_binop (OPERAND_TYPE##_type_node, OPERAND_VALUE##_EXPR)
3030*c87b03e5Sespie 
3031*c87b03e5Sespie #define FIELD(IS_STATIC, IS_PUT) \
3032*c87b03e5Sespie   expand_java_field_op (IS_STATIC, IS_PUT, IMMEDIATE_u2)
3033*c87b03e5Sespie 
3034*c87b03e5Sespie #define TEST(OPERAND_TYPE, CONDITION) \
3035*c87b03e5Sespie   expand_test (CONDITION##_EXPR, OPERAND_TYPE##_type_node, oldpc+IMMEDIATE_s2)
3036*c87b03e5Sespie 
3037*c87b03e5Sespie #define COND(OPERAND_TYPE, CONDITION) \
3038*c87b03e5Sespie   expand_cond (CONDITION##_EXPR, OPERAND_TYPE##_type_node, oldpc+IMMEDIATE_s2)
3039*c87b03e5Sespie 
3040*c87b03e5Sespie #define BRANCH(OPERAND_TYPE, OPERAND_VALUE) \
3041*c87b03e5Sespie   BRANCH_##OPERAND_TYPE (OPERAND_VALUE)
3042*c87b03e5Sespie 
3043*c87b03e5Sespie #define BRANCH_GOTO(OPERAND_VALUE) \
3044*c87b03e5Sespie   expand_java_goto (oldpc + OPERAND_VALUE)
3045*c87b03e5Sespie 
3046*c87b03e5Sespie #define BRANCH_CALL(OPERAND_VALUE) \
3047*c87b03e5Sespie   expand_java_call (oldpc + OPERAND_VALUE, oldpc)
3048*c87b03e5Sespie 
3049*c87b03e5Sespie #if 0
3050*c87b03e5Sespie #define BRANCH_RETURN(OPERAND_VALUE) \
3051*c87b03e5Sespie   { \
3052*c87b03e5Sespie     tree type = OPERAND_TYPE##_type_node; \
3053*c87b03e5Sespie     tree value = find_local_variable (OPERAND_VALUE, type, oldpc); \
3054*c87b03e5Sespie     expand_java_ret (value); \
3055*c87b03e5Sespie   }
3056*c87b03e5Sespie #endif
3057*c87b03e5Sespie 
3058*c87b03e5Sespie #define NOT_IMPL(OPERAND_TYPE, OPERAND_VALUE) \
3059*c87b03e5Sespie 	  fprintf (stderr, "%3d: %s ", oldpc, opname); \
3060*c87b03e5Sespie 	  fprintf (stderr, "(not implemented)\n")
3061*c87b03e5Sespie #define NOT_IMPL1(OPERAND_VALUE) \
3062*c87b03e5Sespie 	  fprintf (stderr, "%3d: %s ", oldpc, opname); \
3063*c87b03e5Sespie 	  fprintf (stderr, "(not implemented)\n")
3064*c87b03e5Sespie 
3065*c87b03e5Sespie #define BRANCH_RETURN(OPERAND_VALUE) NOT_IMPL1(OPERAND_VALUE)
3066*c87b03e5Sespie 
3067*c87b03e5Sespie #define STACK(SUBOP, COUNT) STACK_##SUBOP (COUNT)
3068*c87b03e5Sespie 
3069*c87b03e5Sespie #define STACK_POP(COUNT) java_stack_pop (COUNT)
3070*c87b03e5Sespie 
3071*c87b03e5Sespie #define STACK_SWAP(COUNT) java_stack_swap()
3072*c87b03e5Sespie 
3073*c87b03e5Sespie #define STACK_DUP(COUNT) java_stack_dup (COUNT, 0)
3074*c87b03e5Sespie #define STACK_DUPx1(COUNT) java_stack_dup (COUNT, 1)
3075*c87b03e5Sespie #define STACK_DUPx2(COUNT) java_stack_dup (COUNT, 2)
3076*c87b03e5Sespie 
3077*c87b03e5Sespie #define SWITCH(OPERAND_TYPE, TABLE_OR_LOOKUP) \
3078*c87b03e5Sespie   PC = (PC + 3) / 4 * 4; TABLE_OR_LOOKUP##_SWITCH
3079*c87b03e5Sespie 
3080*c87b03e5Sespie #define LOOKUP_SWITCH \
3081*c87b03e5Sespie   { jint default_offset = IMMEDIATE_s4;  jint npairs = IMMEDIATE_s4; \
3082*c87b03e5Sespie     tree selector = pop_value (INT_type_node); \
3083*c87b03e5Sespie     tree duplicate, label; \
3084*c87b03e5Sespie     tree type = TREE_TYPE (selector); \
3085*c87b03e5Sespie     flush_quick_stack (); \
3086*c87b03e5Sespie     expand_start_case (0, selector, type, "switch statement");\
3087*c87b03e5Sespie     while (--npairs >= 0) \
3088*c87b03e5Sespie       { \
3089*c87b03e5Sespie 	jint match = IMMEDIATE_s4; jint offset = IMMEDIATE_s4; \
3090*c87b03e5Sespie 	tree value = build_int_2 (match, match < 0 ? -1 : 0); \
3091*c87b03e5Sespie 	TREE_TYPE (value) = type; \
3092*c87b03e5Sespie 	label =  build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); \
3093*c87b03e5Sespie 	pushcase (value, convert, label, &duplicate); \
3094*c87b03e5Sespie 	expand_java_goto (oldpc + offset); \
3095*c87b03e5Sespie       } \
3096*c87b03e5Sespie     label =  build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); \
3097*c87b03e5Sespie     pushcase (NULL_TREE, 0, label, &duplicate); \
3098*c87b03e5Sespie     expand_java_goto (oldpc + default_offset); \
3099*c87b03e5Sespie     expand_end_case (selector); \
3100*c87b03e5Sespie   }
3101*c87b03e5Sespie 
3102*c87b03e5Sespie #define TABLE_SWITCH \
3103*c87b03e5Sespie   { jint default_offset = IMMEDIATE_s4; \
3104*c87b03e5Sespie     jint low = IMMEDIATE_s4; jint high = IMMEDIATE_s4; \
3105*c87b03e5Sespie     tree selector = pop_value (INT_type_node); \
3106*c87b03e5Sespie     tree duplicate, label; \
3107*c87b03e5Sespie     tree type = TREE_TYPE (selector); \
3108*c87b03e5Sespie     flush_quick_stack (); \
3109*c87b03e5Sespie     expand_start_case (0, selector, type, "switch statement");\
3110*c87b03e5Sespie     for (; low <= high; low++) \
3111*c87b03e5Sespie       { \
3112*c87b03e5Sespie         jint offset = IMMEDIATE_s4; \
3113*c87b03e5Sespie         tree value = build_int_2 (low, low < 0 ? -1 : 0); \
3114*c87b03e5Sespie         TREE_TYPE (value) = type; \
3115*c87b03e5Sespie         label =  build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); \
3116*c87b03e5Sespie         pushcase (value, convert, label, &duplicate); \
3117*c87b03e5Sespie         expand_java_goto (oldpc + offset); \
3118*c87b03e5Sespie       } \
3119*c87b03e5Sespie     label =  build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); \
3120*c87b03e5Sespie     pushcase (NULL_TREE, 0, label, &duplicate); \
3121*c87b03e5Sespie     expand_java_goto (oldpc + default_offset); \
3122*c87b03e5Sespie     expand_end_case (selector); \
3123*c87b03e5Sespie   }
3124*c87b03e5Sespie 
3125*c87b03e5Sespie #define INVOKE(MAYBE_STATIC, IS_INTERFACE) \
3126*c87b03e5Sespie   { int opcode = byte_ops[PC-1]; \
3127*c87b03e5Sespie     int method_ref_index = IMMEDIATE_u2; \
3128*c87b03e5Sespie     int nargs; \
3129*c87b03e5Sespie     if (IS_INTERFACE) { nargs = IMMEDIATE_u1;  (void) IMMEDIATE_u1; } \
3130*c87b03e5Sespie     else nargs = -1; \
3131*c87b03e5Sespie     expand_invoke (opcode, method_ref_index, nargs); \
3132*c87b03e5Sespie   }
3133*c87b03e5Sespie 
3134*c87b03e5Sespie /* Handle new, checkcast, instanceof */
3135*c87b03e5Sespie #define OBJECT(TYPE, OP) \
3136*c87b03e5Sespie   expand_java_##OP (get_class_constant (current_jcf, IMMEDIATE_u2))
3137*c87b03e5Sespie 
3138*c87b03e5Sespie #define ARRAY(OPERAND_TYPE, SUBOP) ARRAY_##SUBOP(OPERAND_TYPE)
3139*c87b03e5Sespie 
3140*c87b03e5Sespie #define ARRAY_LOAD(OPERAND_TYPE) 			\
3141*c87b03e5Sespie   {							\
3142*c87b03e5Sespie     expand_java_arrayload( OPERAND_TYPE##_type_node );	\
3143*c87b03e5Sespie   }
3144*c87b03e5Sespie 
3145*c87b03e5Sespie #define ARRAY_STORE(OPERAND_TYPE)			\
3146*c87b03e5Sespie   {							\
3147*c87b03e5Sespie     expand_java_arraystore( OPERAND_TYPE##_type_node );	\
3148*c87b03e5Sespie   }
3149*c87b03e5Sespie 
3150*c87b03e5Sespie #define ARRAY_LENGTH(OPERAND_TYPE) expand_java_array_length();
3151*c87b03e5Sespie #define ARRAY_NEW(OPERAND_TYPE) ARRAY_NEW_##OPERAND_TYPE()
3152*c87b03e5Sespie #define ARRAY_NEW_PTR()							\
3153*c87b03e5Sespie     push_value (build_anewarray (get_class_constant (current_jcf,	\
3154*c87b03e5Sespie 						     IMMEDIATE_u2),	\
3155*c87b03e5Sespie 				 pop_value (int_type_node)));
3156*c87b03e5Sespie #define ARRAY_NEW_NUM()				\
3157*c87b03e5Sespie   {						\
3158*c87b03e5Sespie     int atype = IMMEDIATE_u1;			\
3159*c87b03e5Sespie     push_value (build_newarray (atype, pop_value (int_type_node)));\
3160*c87b03e5Sespie   }
3161*c87b03e5Sespie #define ARRAY_NEW_MULTI()					\
3162*c87b03e5Sespie   {								\
3163*c87b03e5Sespie     tree class = get_class_constant (current_jcf, IMMEDIATE_u2 );	\
3164*c87b03e5Sespie     int  ndims = IMMEDIATE_u1;					\
3165*c87b03e5Sespie     expand_java_multianewarray( class, ndims );			\
3166*c87b03e5Sespie   }
3167*c87b03e5Sespie 
3168*c87b03e5Sespie #define UNOP(OPERAND_TYPE, OPERAND_VALUE) \
3169*c87b03e5Sespie   push_value (fold (build1 (NEGATE_EXPR, OPERAND_TYPE##_type_node, \
3170*c87b03e5Sespie 			    pop_value (OPERAND_TYPE##_type_node))));
3171*c87b03e5Sespie 
3172*c87b03e5Sespie #define CONVERT2(FROM_TYPE, TO_TYPE)					 \
3173*c87b03e5Sespie   {									 \
3174*c87b03e5Sespie     push_value (build1 (NOP_EXPR, int_type_node,			 \
3175*c87b03e5Sespie 			(convert (TO_TYPE##_type_node,			 \
3176*c87b03e5Sespie 				  pop_value (FROM_TYPE##_type_node))))); \
3177*c87b03e5Sespie   }
3178*c87b03e5Sespie 
3179*c87b03e5Sespie #define CONVERT(FROM_TYPE, TO_TYPE)				\
3180*c87b03e5Sespie   {								\
3181*c87b03e5Sespie     push_value (convert (TO_TYPE##_type_node,	                \
3182*c87b03e5Sespie 			 pop_value (FROM_TYPE##_type_node)));	\
3183*c87b03e5Sespie   }
3184*c87b03e5Sespie 
3185*c87b03e5Sespie /* internal macro added for use by the WIDE case
3186*c87b03e5Sespie    Added TREE_TYPE (decl) assignment, apbianco  */
3187*c87b03e5Sespie #define STORE_INTERNAL(OPTYPE, OPVALUE)			\
3188*c87b03e5Sespie   {							\
3189*c87b03e5Sespie     tree decl, value;					\
3190*c87b03e5Sespie     int var = OPVALUE;					\
3191*c87b03e5Sespie     tree type = OPTYPE;					\
3192*c87b03e5Sespie     value = pop_value (type);				\
3193*c87b03e5Sespie     type = TREE_TYPE (value);				\
3194*c87b03e5Sespie     decl = find_local_variable (var, type, oldpc);	\
3195*c87b03e5Sespie     set_local_type (var, type );			\
3196*c87b03e5Sespie     expand_assignment (decl, value, 0, 0);		\
3197*c87b03e5Sespie   }
3198*c87b03e5Sespie 
3199*c87b03e5Sespie #define STORE(OPERAND_TYPE, OPERAND_VALUE) \
3200*c87b03e5Sespie   { \
3201*c87b03e5Sespie     /* have to do this since OPERAND_VALUE may have side-effects */ \
3202*c87b03e5Sespie     int opvalue = OPERAND_VALUE; \
3203*c87b03e5Sespie     STORE_INTERNAL(OPERAND_TYPE##_type_node, opvalue); \
3204*c87b03e5Sespie   }
3205*c87b03e5Sespie 
3206*c87b03e5Sespie #define SPECIAL(OPERAND_TYPE, INSTRUCTION) \
3207*c87b03e5Sespie   SPECIAL_##INSTRUCTION(OPERAND_TYPE)
3208*c87b03e5Sespie 
3209*c87b03e5Sespie #define SPECIAL_ENTER(IGNORED) MONITOR_OPERATION (soft_monitorenter_node)
3210*c87b03e5Sespie #define SPECIAL_EXIT(IGNORED)  MONITOR_OPERATION (soft_monitorexit_node)
3211*c87b03e5Sespie 
3212*c87b03e5Sespie #define MONITOR_OPERATION(call)			\
3213*c87b03e5Sespie   {						\
3214*c87b03e5Sespie     tree o = pop_value (ptr_type_node);		\
3215*c87b03e5Sespie     tree c;					\
3216*c87b03e5Sespie     flush_quick_stack ();			\
3217*c87b03e5Sespie     c = build_java_monitor (call, o);		\
3218*c87b03e5Sespie     TREE_SIDE_EFFECTS (c) = 1;			\
3219*c87b03e5Sespie     expand_expr_stmt (c);			\
3220*c87b03e5Sespie   }
3221*c87b03e5Sespie 
3222*c87b03e5Sespie #define SPECIAL_IINC(IGNORED) \
3223*c87b03e5Sespie   { \
3224*c87b03e5Sespie     unsigned int local_var_index = IMMEDIATE_u1; \
3225*c87b03e5Sespie     int ival = IMMEDIATE_s1; \
3226*c87b03e5Sespie     expand_iinc(local_var_index, ival, oldpc); \
3227*c87b03e5Sespie   }
3228*c87b03e5Sespie 
3229*c87b03e5Sespie #define SPECIAL_WIDE(IGNORED) \
3230*c87b03e5Sespie   { \
3231*c87b03e5Sespie     int modified_opcode = IMMEDIATE_u1; \
3232*c87b03e5Sespie     unsigned int local_var_index = IMMEDIATE_u2; \
3233*c87b03e5Sespie     switch (modified_opcode) \
3234*c87b03e5Sespie       { \
3235*c87b03e5Sespie       case OPCODE_iinc: \
3236*c87b03e5Sespie 	{ \
3237*c87b03e5Sespie 	  int ival = IMMEDIATE_s2; \
3238*c87b03e5Sespie 	  expand_iinc (local_var_index, ival, oldpc); \
3239*c87b03e5Sespie 	  break; \
3240*c87b03e5Sespie 	} \
3241*c87b03e5Sespie       case OPCODE_iload: \
3242*c87b03e5Sespie       case OPCODE_lload: \
3243*c87b03e5Sespie       case OPCODE_fload: \
3244*c87b03e5Sespie       case OPCODE_dload: \
3245*c87b03e5Sespie       case OPCODE_aload: \
3246*c87b03e5Sespie 	{ \
3247*c87b03e5Sespie 	  /* duplicate code from LOAD macro */ \
3248*c87b03e5Sespie 	  LOAD_INTERNAL(operand_type[modified_opcode], local_var_index); \
3249*c87b03e5Sespie 	  break; \
3250*c87b03e5Sespie 	} \
3251*c87b03e5Sespie       case OPCODE_istore: \
3252*c87b03e5Sespie       case OPCODE_lstore: \
3253*c87b03e5Sespie       case OPCODE_fstore: \
3254*c87b03e5Sespie       case OPCODE_dstore: \
3255*c87b03e5Sespie       case OPCODE_astore: \
3256*c87b03e5Sespie 	{ \
3257*c87b03e5Sespie 	  STORE_INTERNAL(operand_type[modified_opcode], local_var_index); \
3258*c87b03e5Sespie 	  break; \
3259*c87b03e5Sespie 	} \
3260*c87b03e5Sespie       default: \
3261*c87b03e5Sespie         error ("unrecogized wide sub-instruction"); \
3262*c87b03e5Sespie       } \
3263*c87b03e5Sespie   }
3264*c87b03e5Sespie 
3265*c87b03e5Sespie #define SPECIAL_THROW(IGNORED) \
3266*c87b03e5Sespie   build_java_athrow (pop_value (throwable_type_node))
3267*c87b03e5Sespie 
3268*c87b03e5Sespie #define SPECIAL_BREAK NOT_IMPL1
3269*c87b03e5Sespie #define IMPL          NOT_IMPL
3270*c87b03e5Sespie 
3271*c87b03e5Sespie #include "javaop.def"
3272*c87b03e5Sespie #undef JAVAOP
3273*c87b03e5Sespie    default:
3274*c87b03e5Sespie     fprintf (stderr, "%3d: unknown(%3d)\n", oldpc, byte_ops[PC]);
3275*c87b03e5Sespie   }
3276*c87b03e5Sespie   return PC;
3277*c87b03e5Sespie }
3278*c87b03e5Sespie 
3279*c87b03e5Sespie /* Return the opcode at PC in the code section pointed to by
3280*c87b03e5Sespie    CODE_OFFSET.  */
3281*c87b03e5Sespie 
3282*c87b03e5Sespie static unsigned char
peek_opcode_at_pc(jcf,code_offset,pc)3283*c87b03e5Sespie peek_opcode_at_pc (jcf, code_offset, pc)
3284*c87b03e5Sespie     JCF *jcf;
3285*c87b03e5Sespie     int code_offset, pc;
3286*c87b03e5Sespie {
3287*c87b03e5Sespie   unsigned char opcode;
3288*c87b03e5Sespie   long absolute_offset = (long)JCF_TELL (jcf);
3289*c87b03e5Sespie 
3290*c87b03e5Sespie   JCF_SEEK (jcf, code_offset);
3291*c87b03e5Sespie   opcode = jcf->read_ptr [pc];
3292*c87b03e5Sespie   JCF_SEEK (jcf, absolute_offset);
3293*c87b03e5Sespie   return opcode;
3294*c87b03e5Sespie }
3295*c87b03e5Sespie 
3296*c87b03e5Sespie /* Some bytecode compilers are emitting accurate LocalVariableTable
3297*c87b03e5Sespie    attributes. Here's an example:
3298*c87b03e5Sespie 
3299*c87b03e5Sespie      PC   <t>store_<n>
3300*c87b03e5Sespie      PC+1 ...
3301*c87b03e5Sespie 
3302*c87b03e5Sespie      Attribute "LocalVariableTable"
3303*c87b03e5Sespie      slot #<n>: ... (PC: PC+1 length: L)
3304*c87b03e5Sespie 
3305*c87b03e5Sespie    This is accurate because the local in slot <n> really exists after
3306*c87b03e5Sespie    the opcode at PC is executed, hence from PC+1 to PC+1+L.
3307*c87b03e5Sespie 
3308*c87b03e5Sespie    This procedure recognizes this situation and extends the live range
3309*c87b03e5Sespie    of the local in SLOT to START_PC-1 or START_PC-2 (depending on the
3310*c87b03e5Sespie    length of the store instruction.)
3311*c87b03e5Sespie 
3312*c87b03e5Sespie    This function is used by `give_name_to_locals' so that a local's
3313*c87b03e5Sespie    DECL features a DECL_LOCAL_START_PC such that the first related
3314*c87b03e5Sespie    store operation will use DECL as a destination, not a unrelated
3315*c87b03e5Sespie    temporary created for the occasion.
3316*c87b03e5Sespie 
3317*c87b03e5Sespie    This function uses a global (instruction_bits) `note_instructions' should
3318*c87b03e5Sespie    have allocated and filled properly.  */
3319*c87b03e5Sespie 
3320*c87b03e5Sespie int
maybe_adjust_start_pc(jcf,code_offset,start_pc,slot)3321*c87b03e5Sespie maybe_adjust_start_pc (jcf, code_offset, start_pc, slot)
3322*c87b03e5Sespie      struct JCF *jcf;
3323*c87b03e5Sespie      int code_offset, start_pc, slot;
3324*c87b03e5Sespie {
3325*c87b03e5Sespie   int first, index, opcode;
3326*c87b03e5Sespie   int pc, insn_pc;
3327*c87b03e5Sespie   int wide_found = 0;
3328*c87b03e5Sespie 
3329*c87b03e5Sespie   if (!start_pc)
3330*c87b03e5Sespie     return start_pc;
3331*c87b03e5Sespie 
3332*c87b03e5Sespie   first = index = -1;
3333*c87b03e5Sespie 
3334*c87b03e5Sespie   /* Find last previous instruction and remember it */
3335*c87b03e5Sespie   for (pc = start_pc-1; pc; pc--)
3336*c87b03e5Sespie     if (instruction_bits [pc] & BCODE_INSTRUCTION_START)
3337*c87b03e5Sespie       break;
3338*c87b03e5Sespie   insn_pc = pc;
3339*c87b03e5Sespie 
3340*c87b03e5Sespie   /* Retrieve the instruction, handle `wide'. */
3341*c87b03e5Sespie   opcode = (int) peek_opcode_at_pc (jcf, code_offset, pc++);
3342*c87b03e5Sespie   if (opcode == OPCODE_wide)
3343*c87b03e5Sespie     {
3344*c87b03e5Sespie       wide_found = 1;
3345*c87b03e5Sespie       opcode = (int) peek_opcode_at_pc (jcf, code_offset, pc++);
3346*c87b03e5Sespie     }
3347*c87b03e5Sespie 
3348*c87b03e5Sespie   switch (opcode)
3349*c87b03e5Sespie     {
3350*c87b03e5Sespie     case OPCODE_astore_0:
3351*c87b03e5Sespie     case OPCODE_astore_1:
3352*c87b03e5Sespie     case OPCODE_astore_2:
3353*c87b03e5Sespie     case OPCODE_astore_3:
3354*c87b03e5Sespie       first = OPCODE_astore_0;
3355*c87b03e5Sespie       break;
3356*c87b03e5Sespie 
3357*c87b03e5Sespie     case OPCODE_istore_0:
3358*c87b03e5Sespie     case OPCODE_istore_1:
3359*c87b03e5Sespie     case OPCODE_istore_2:
3360*c87b03e5Sespie     case OPCODE_istore_3:
3361*c87b03e5Sespie       first = OPCODE_istore_0;
3362*c87b03e5Sespie       break;
3363*c87b03e5Sespie 
3364*c87b03e5Sespie     case OPCODE_lstore_0:
3365*c87b03e5Sespie     case OPCODE_lstore_1:
3366*c87b03e5Sespie     case OPCODE_lstore_2:
3367*c87b03e5Sespie     case OPCODE_lstore_3:
3368*c87b03e5Sespie       first = OPCODE_lstore_0;
3369*c87b03e5Sespie       break;
3370*c87b03e5Sespie 
3371*c87b03e5Sespie     case OPCODE_fstore_0:
3372*c87b03e5Sespie     case OPCODE_fstore_1:
3373*c87b03e5Sespie     case OPCODE_fstore_2:
3374*c87b03e5Sespie     case OPCODE_fstore_3:
3375*c87b03e5Sespie       first = OPCODE_fstore_0;
3376*c87b03e5Sespie       break;
3377*c87b03e5Sespie 
3378*c87b03e5Sespie     case OPCODE_dstore_0:
3379*c87b03e5Sespie     case OPCODE_dstore_1:
3380*c87b03e5Sespie     case OPCODE_dstore_2:
3381*c87b03e5Sespie     case OPCODE_dstore_3:
3382*c87b03e5Sespie       first = OPCODE_dstore_0;
3383*c87b03e5Sespie       break;
3384*c87b03e5Sespie 
3385*c87b03e5Sespie     case OPCODE_astore:
3386*c87b03e5Sespie     case OPCODE_istore:
3387*c87b03e5Sespie     case OPCODE_lstore:
3388*c87b03e5Sespie     case OPCODE_fstore:
3389*c87b03e5Sespie     case OPCODE_dstore:
3390*c87b03e5Sespie       index = peek_opcode_at_pc (jcf, code_offset, pc);
3391*c87b03e5Sespie       if (wide_found)
3392*c87b03e5Sespie 	{
3393*c87b03e5Sespie 	  int other = peek_opcode_at_pc (jcf, code_offset, ++pc);
3394*c87b03e5Sespie 	  index = (other << 8) + index;
3395*c87b03e5Sespie 	}
3396*c87b03e5Sespie       break;
3397*c87b03e5Sespie     }
3398*c87b03e5Sespie 
3399*c87b03e5Sespie   /* Now we decide: first >0 means we have a <t>store_<n>, index >0
3400*c87b03e5Sespie      means we have a <t>store. */
3401*c87b03e5Sespie   if ((first > 0 && opcode - first == slot) || (index > 0 && index == slot))
3402*c87b03e5Sespie     start_pc = insn_pc;
3403*c87b03e5Sespie 
3404*c87b03e5Sespie   return start_pc;
3405*c87b03e5Sespie }
3406*c87b03e5Sespie 
3407*c87b03e5Sespie /* Force the (direct) sub-operands of NODE to be evaluated in left-to-right
3408*c87b03e5Sespie    order, as specified by Java Language Specification.
3409*c87b03e5Sespie 
3410*c87b03e5Sespie    The problem is that while expand_expr will evaluate its sub-operands in
3411*c87b03e5Sespie    left-to-right order, for variables it will just return an rtx (i.e.
3412*c87b03e5Sespie    an lvalue) for the variable (rather than an rvalue).  So it is possible
3413*c87b03e5Sespie    that a later sub-operand will change the register, and when the
3414*c87b03e5Sespie    actual operation is done, it will use the new value, when it should
3415*c87b03e5Sespie    have used the original value.
3416*c87b03e5Sespie 
3417*c87b03e5Sespie    We fix this by using save_expr.  This forces the sub-operand to be
3418*c87b03e5Sespie    copied into a fresh virtual register,
3419*c87b03e5Sespie 
3420*c87b03e5Sespie    For method invocation, we modify the arguments so that a
3421*c87b03e5Sespie    left-to-right order evaluation is performed. Saved expressions
3422*c87b03e5Sespie    will, in CALL_EXPR order, be reused when the call will be expanded.
3423*c87b03e5Sespie */
3424*c87b03e5Sespie 
3425*c87b03e5Sespie tree
force_evaluation_order(node)3426*c87b03e5Sespie force_evaluation_order (node)
3427*c87b03e5Sespie      tree  node;
3428*c87b03e5Sespie {
3429*c87b03e5Sespie   if (flag_syntax_only)
3430*c87b03e5Sespie     return node;
3431*c87b03e5Sespie   if (TREE_CODE_CLASS (TREE_CODE (node)) == '2')
3432*c87b03e5Sespie     {
3433*c87b03e5Sespie       if (TREE_SIDE_EFFECTS (TREE_OPERAND (node, 1)))
3434*c87b03e5Sespie 	TREE_OPERAND (node, 0) = save_expr (TREE_OPERAND (node, 0));
3435*c87b03e5Sespie     }
3436*c87b03e5Sespie   else if (TREE_CODE (node) == CALL_EXPR
3437*c87b03e5Sespie            || TREE_CODE (node) == NEW_CLASS_EXPR
3438*c87b03e5Sespie            || (TREE_CODE (node) == COMPOUND_EXPR
3439*c87b03e5Sespie                && TREE_CODE (TREE_OPERAND (node, 0)) == CALL_EXPR
3440*c87b03e5Sespie                && TREE_CODE (TREE_OPERAND (node, 1)) == SAVE_EXPR))
3441*c87b03e5Sespie     {
3442*c87b03e5Sespie       tree arg, cmp;
3443*c87b03e5Sespie 
3444*c87b03e5Sespie       if (!TREE_OPERAND (node, 1))
3445*c87b03e5Sespie 	return node;
3446*c87b03e5Sespie 
3447*c87b03e5Sespie       arg = node;
3448*c87b03e5Sespie 
3449*c87b03e5Sespie       /* Position arg properly, account for wrapped around ctors. */
3450*c87b03e5Sespie       if (TREE_CODE (node) == COMPOUND_EXPR)
3451*c87b03e5Sespie         arg = TREE_OPERAND (node, 0);
3452*c87b03e5Sespie 
3453*c87b03e5Sespie       arg = TREE_OPERAND (arg, 1);
3454*c87b03e5Sespie 
3455*c87b03e5Sespie       /* Not having a list of argument here is an error. */
3456*c87b03e5Sespie       if (TREE_CODE (arg) != TREE_LIST)
3457*c87b03e5Sespie         abort ();
3458*c87b03e5Sespie 
3459*c87b03e5Sespie       /* This reverses the evaluation order. This is a desired effect. */
3460*c87b03e5Sespie       for (cmp = NULL_TREE; arg; arg = TREE_CHAIN (arg))
3461*c87b03e5Sespie 	{
3462*c87b03e5Sespie 	  tree saved = save_expr (force_evaluation_order (TREE_VALUE (arg)));
3463*c87b03e5Sespie 	  cmp = (cmp == NULL_TREE ? saved :
3464*c87b03e5Sespie 		 build (COMPOUND_EXPR, void_type_node, cmp, saved));
3465*c87b03e5Sespie 	  TREE_VALUE (arg) = saved;
3466*c87b03e5Sespie 	}
3467*c87b03e5Sespie 
3468*c87b03e5Sespie       if (cmp && TREE_CODE (cmp) == COMPOUND_EXPR)
3469*c87b03e5Sespie 	TREE_SIDE_EFFECTS (cmp) = 1;
3470*c87b03e5Sespie 
3471*c87b03e5Sespie       if (cmp)
3472*c87b03e5Sespie 	{
3473*c87b03e5Sespie 	  cmp = save_expr (build (COMPOUND_EXPR, TREE_TYPE (node), cmp, node));
3474*c87b03e5Sespie 	  CAN_COMPLETE_NORMALLY (cmp) = CAN_COMPLETE_NORMALLY (node);
3475*c87b03e5Sespie 	  TREE_SIDE_EFFECTS (cmp) = 1;
3476*c87b03e5Sespie 	  node = cmp;
3477*c87b03e5Sespie 	}
3478*c87b03e5Sespie     }
3479*c87b03e5Sespie   return node;
3480*c87b03e5Sespie }
3481*c87b03e5Sespie 
3482*c87b03e5Sespie /* Called for every element in DECL_FUNCTION_INIT_TEST_TABLE of a
3483*c87b03e5Sespie    method in order to emit initialization code for each test flag.  */
3484*c87b03e5Sespie 
3485*c87b03e5Sespie static int
emit_init_test_initialization(entry,x)3486*c87b03e5Sespie emit_init_test_initialization (entry, x)
3487*c87b03e5Sespie      void * * entry;
3488*c87b03e5Sespie      void * x ATTRIBUTE_UNUSED;
3489*c87b03e5Sespie {
3490*c87b03e5Sespie   struct treetreehash_entry *ite = (struct treetreehash_entry *) *entry;
3491*c87b03e5Sespie   tree klass = build_class_ref (ite->key);
3492*c87b03e5Sespie   tree rhs;
3493*c87b03e5Sespie 
3494*c87b03e5Sespie   /* If the DECL_INITIAL of the test flag is set to true, it
3495*c87b03e5Sespie      means that the class is already initialized the time it
3496*c87b03e5Sespie      is in use. */
3497*c87b03e5Sespie   if (DECL_INITIAL (ite->value) == boolean_true_node)
3498*c87b03e5Sespie     rhs = boolean_true_node;
3499*c87b03e5Sespie   /* Otherwise, we initialize the class init check variable by looking
3500*c87b03e5Sespie      at the `state' field of the class to see if it is already
3501*c87b03e5Sespie      initialized.  This makes things a bit faster if the class is
3502*c87b03e5Sespie      already initialized, which should be the common case.  */
3503*c87b03e5Sespie   else
3504*c87b03e5Sespie     rhs = build (GE_EXPR, boolean_type_node,
3505*c87b03e5Sespie 		 build (COMPONENT_REF, byte_type_node,
3506*c87b03e5Sespie 			build1 (INDIRECT_REF, class_type_node, klass),
3507*c87b03e5Sespie 			lookup_field (&class_type_node,
3508*c87b03e5Sespie 				      get_identifier ("state"))),
3509*c87b03e5Sespie 		 build_int_2 (JV_STATE_DONE, 0));
3510*c87b03e5Sespie 
3511*c87b03e5Sespie   expand_expr_stmt (build (MODIFY_EXPR, boolean_type_node,
3512*c87b03e5Sespie 			   ite->value, rhs));
3513*c87b03e5Sespie   return true;
3514*c87b03e5Sespie }
3515*c87b03e5Sespie 
3516*c87b03e5Sespie #include "gt-java-expr.h"
3517*c87b03e5Sespie 
3518