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(¤t_jcf->cpool, method_ref_index);
2047*c87b03e5Sespie tree method_name = COMPONENT_REF_NAME (¤t_jcf->cpool, method_ref_index);
2048*c87b03e5Sespie tree self_type = get_class_constant
2049*c87b03e5Sespie (current_jcf, COMPONENT_REF_CLASS_INDEX(¤t_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 (¤t_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 (¤t_jcf->cpool, field_ref_index);
2383*c87b03e5Sespie tree field_signature = COMPONENT_REF_SIGNATURE (¤t_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