]> gcc.gnu.org Git - gcc.git/blame - gcc/java/expr.c
Extensive changes.
[gcc.git] / gcc / java / expr.c
CommitLineData
e04a16fb
AG
1/* Process expressions for the GNU compiler for the Java(TM) language.
2 Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING. If not, write to
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA.
20
21Java and all Java-based marks are trademarks or registered trademarks
22of Sun Microsystems, Inc. in the United States and other countries.
23The Free Software Foundation is independent of Sun Microsystems, Inc. */
24
25/* Hacked by Per Bothner <bothner@cygnus.com> February 1996. */
26
e04a16fb 27#include "config.h"
1f43f4b4 28#include "system.h"
e04a16fb
AG
29#include "tree.h"
30#include "real.h"
31#include "rtl.h"
32#include "expr.h"
33#include "java-tree.h"
34#include "javaop.h"
35#include "java-opcodes.h"
36#include "jcf.h"
37#include "java-except.h"
38#include "parse.h"
1f43f4b4 39#include "toplev.h"
e04a16fb
AG
40
41static tree operand_type[59];
42extern struct obstack permanent_obstack;
43
44void
45init_expr_processing()
46{
47 operand_type[21] = operand_type[54] = int_type_node;
48 operand_type[22] = operand_type[55] = long_type_node;
49 operand_type[23] = operand_type[56] = float_type_node;
50 operand_type[24] = operand_type[57] = double_type_node;
51 operand_type[25] = operand_type[58] = ptr_type_node;
52}
53
54/* We store the stack state in two places:
55 Within a basic block, we use the quick_stack, which is a
56 pushdown list (TREE_LISTs) of expression nodes.
57 This is the top part of the stack; below that we use find_stack_slot.
58 At the end of a basic block, the quick_stack must be flushed
59 to the stack slot array (as handled by find_stack_slot).
60 Using quick_stack generates better code (especially when
61 compiled without optimization), because we do not have to
62 explicitly store and load trees to temporary variables.
63
64 If a variable is on the quick stack, it means the value of variable
65 when the quick stack was last flushed. Conceptually, flush_quick_stack
66 saves all the the quick_stack elements in parellel. However, that is
67 complicated, so it actually saves them (i.e. copies each stack value
68 to is home virtual register) from low indexes. This allows a quick_stack
69 element at index i (counting from the bottom of stack the) to references
70 slot virtuals for register that are >= i, but not those that are deeper.
71 This convention makes most operations easier. For example iadd works
72 even when the stack contains (reg[0], reg[1]): It results in the
73 stack containing (reg[0]+reg[1]), which is OK. However, some stack
74 operations are more complicated. For example dup given a stack
75 containing (reg[0]) would yield (reg[0], reg[0]), which would violate
76 the convention, since stack value 1 would refer to a register with
77 lower index (reg[0]), which flush_quick_stack does not safely handle.
78 So dup cannot just add an extra element to the quick_stack, but iadd can.
79*/
80
81tree quick_stack = NULL_TREE;
82
83/* A free-list of unused permamnet TREE_LIST nodes. */
84tree tree_list_free_list = NULL_TREE;
85
86/* The stack pointer of the Java virtual machine.
87 This does include the size of the quick_stack. */
88
89int stack_pointer;
90
91unsigned char *linenumber_table;
92int linenumber_count;
93
94tree
95truthvalue_conversion (expr)
96 tree expr;
97{
98 /* It is simpler and generates better code to have only TRUTH_*_EXPR
99 or comparison expressions as truth values at this level.
100
101 This function should normally be identity for Java. */
102
103 switch (TREE_CODE (expr))
104 {
105 case EQ_EXPR:
106 case NE_EXPR: case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
107 case TRUTH_ANDIF_EXPR:
108 case TRUTH_ORIF_EXPR:
109 case TRUTH_AND_EXPR:
110 case TRUTH_OR_EXPR:
111 case ERROR_MARK:
112 return expr;
113
114 case INTEGER_CST:
115 return integer_zerop (expr) ? boolean_false_node : boolean_true_node;
116
117 case REAL_CST:
118 return real_zerop (expr) ? boolean_false_node : boolean_true_node;
119
120 /* are these legal? XXX JH */
121 case NEGATE_EXPR:
122 case ABS_EXPR:
123 case FLOAT_EXPR:
124 case FFS_EXPR:
125 /* These don't change whether an object is non-zero or zero. */
126 return truthvalue_conversion (TREE_OPERAND (expr, 0));
127
128 case COND_EXPR:
129 /* Distribute the conversion into the arms of a COND_EXPR. */
130 return fold (build (COND_EXPR, boolean_type_node, TREE_OPERAND (expr, 0),
131 truthvalue_conversion (TREE_OPERAND (expr, 1)),
132 truthvalue_conversion (TREE_OPERAND (expr, 2))));
133
134 case NOP_EXPR:
135 /* If this is widening the argument, we can ignore it. */
136 if (TYPE_PRECISION (TREE_TYPE (expr))
137 >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
138 return truthvalue_conversion (TREE_OPERAND (expr, 0));
139 /* fall through to default */
140
141 default:
142 return fold (build (NE_EXPR, boolean_type_node, expr, boolean_false_node));
143 }
144}
145
146#ifdef JAVA_USE_HANDLES
147/* Given a pointer to a handle, get a pointer to an object. */
148
149tree
150unhand_expr (expr)
151 tree expr;
152{
153 tree field, handle_type;
154 expr = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (expr)), expr);
155 handle_type = TREE_TYPE (expr);
156 field = TYPE_FIELDS (handle_type);
157 expr = build (COMPONENT_REF, TREE_TYPE (field), expr, field);
158 return expr;
159}
160#endif
161
162/* Save any stack slots that happen to be in the quick_stack into their
163 home virtual register slots.
164
165 The copy order is from low stack index to high, to support the invariant
166 that the expression for a slot may contain decls for stack slots with
167 higher (or the same) index, but not lower. */
168
169void
170flush_quick_stack ()
171{
172 int stack_index = stack_pointer;
173 register tree prev, cur, next;
174
175 /* First reverse the quick_stack, and count the number of slots it has. */
176 for (cur = quick_stack, prev = NULL_TREE; cur != NULL_TREE; cur = next)
177 {
178 next = TREE_CHAIN (cur);
179 TREE_CHAIN (cur) = prev;
180 prev = cur;
181 stack_index -= 1 + TYPE_IS_WIDE (TREE_TYPE (TREE_VALUE (cur)));
182 }
183 quick_stack = prev;
184
185 while (quick_stack != NULL_TREE)
186 {
187 tree decl;
188 tree node = quick_stack, type;
189 quick_stack = TREE_CHAIN (node);
190 TREE_CHAIN (node) = tree_list_free_list;
191 tree_list_free_list = node;
192 node = TREE_VALUE (node);
193 type = TREE_TYPE (node);
194
195 decl = find_stack_slot (stack_index, type);
196 if (decl != node)
197 expand_assignment (decl, node, 0, 0);
198 stack_index += 1 + TYPE_IS_WIDE (type);
199 }
200}
201
202void
203push_type (type)
204 tree type;
205{
206 int n_words;
207 type = promote_type (type);
208 n_words = 1 + TYPE_IS_WIDE (type);
209 if (stack_pointer + n_words > DECL_MAX_STACK (current_function_decl))
210 fatal ("stack overflow");
211 stack_type_map[stack_pointer++] = type;
212 n_words--;
213 while (--n_words >= 0)
214 stack_type_map[stack_pointer++] = TYPE_SECOND;
215}
216
217void
218push_value (value)
219 tree value;
220{
221 tree type = TREE_TYPE (value);
222 if (TYPE_PRECISION (type) < 32 && INTEGRAL_TYPE_P (type))
223 {
224 type = promote_type (type);
225 value = convert (type, value);
226 }
227 push_type (type);
228 if (tree_list_free_list == NULL_TREE)
229 quick_stack = perm_tree_cons (NULL_TREE, value, quick_stack);
230 else
231 {
232 tree node = tree_list_free_list;
233 tree_list_free_list = TREE_CHAIN (tree_list_free_list);
234 TREE_VALUE (node) = value;
235 TREE_CHAIN (node) = quick_stack;
236 quick_stack = node;
237 }
238}
239
240tree
241pop_type (type)
242 tree type;
243{
244 int n_words;
245 int i;
246 tree t;
247 if (TREE_CODE (type) == RECORD_TYPE)
248 type = promote_type (type);
249 n_words = 1 + TYPE_IS_WIDE (type);
250 if (stack_pointer < n_words)
251 fatal ("stack underflow");
252 while (--n_words > 0)
253 {
254 if (stack_type_map[--stack_pointer] != void_type_node)
255 fatal ("Invalid multi-word value on type stack");
256 }
257 t = stack_type_map[--stack_pointer];
258 if (type == NULL_TREE || t == type)
259 return t;
260 if (INTEGRAL_TYPE_P (type) && INTEGRAL_TYPE_P (t)
261 && TYPE_PRECISION (type) <= 32 && TYPE_PRECISION (t) <= 32)
262 return t;
263 if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (t) == POINTER_TYPE)
264 {
265 if (type == ptr_type_node || type == object_ptr_type_node)
266 return t;
267 else if (t == ptr_type_node) /* Special case for null reference. */
268 return type;
269 else if (can_widen_reference_to (t, type))
270 return t;
271 }
272 error ("unexpected type on stack");
273 return t;
274}
275
276/* Return 1f if SOURCE_TYPE can be safely widened to TARGET_TYPE.
277 Handles array types and interfaces. */
278
279int
280can_widen_reference_to (source_type, target_type)
281 tree source_type, target_type;
282{
283 if (source_type == ptr_type_node || target_type == object_ptr_type_node)
284 return 1;
285
286 /* Get rid of pointers */
287 if (TREE_CODE (source_type) == POINTER_TYPE)
288 source_type = TREE_TYPE (source_type);
289 if (TREE_CODE (target_type) == POINTER_TYPE)
290 target_type = TREE_TYPE (target_type);
291
292 if (source_type == target_type)
293 return 1;
294 else
295 {
296 source_type = HANDLE_TO_CLASS_TYPE (source_type);
297 target_type = HANDLE_TO_CLASS_TYPE (target_type);
298 if (TYPE_ARRAY_P (source_type) || TYPE_ARRAY_P (target_type))
299 {
300 HOST_WIDE_INT source_length, target_length;
301 if (TYPE_ARRAY_P (source_type) != TYPE_ARRAY_P (target_type))
302 return 0;
303 target_length = java_array_type_length (target_type);
304 if (target_length >= 0)
305 {
306 source_length = java_array_type_length (source_type);
307 if (source_length != target_length)
308 return 0;
309 }
310 source_type = TYPE_ARRAY_ELEMENT (source_type);
311 target_type = TYPE_ARRAY_ELEMENT (target_type);
312 if (source_type == target_type)
313 return 1;
314 if (TREE_CODE (source_type) != POINTER_TYPE
315 || TREE_CODE (target_type) != POINTER_TYPE)
316 return 0;
317 return can_widen_reference_to (source_type, target_type);
318 }
319 else
320 {
321 int source_depth = class_depth (source_type);
322 int target_depth = class_depth (target_type);
323
324 if (CLASS_INTERFACE (TYPE_NAME (target_type)))
325 {
326 /* target_type is OK if source_type or source_type ancestors
327 implement target_type. We handle multiple sub-interfaces */
328
329 tree basetype_vec = TYPE_BINFO_BASETYPES (source_type);
330 int n = TREE_VEC_LENGTH (basetype_vec), i;
331 for (i=0 ; i < n; i++)
332 if (can_widen_reference_to
333 (TREE_TYPE (TREE_VEC_ELT (basetype_vec, i)),
334 target_type))
335 return 1;
336 if (n == 0)
337 return 0;
338 }
339
340 for ( ; source_depth > target_depth; source_depth--)
341 {
342 source_type = TYPE_BINFO_BASETYPE (source_type, 0);
343 }
344 return source_type == target_type;
345 }
346 }
347}
348
349tree
350pop_value (type)
351 tree type;
352{
353 int n_words = 1 + TYPE_IS_WIDE (type);
354 int i;
355 type = pop_type (type);
356 if (quick_stack)
357 {
358 tree node = quick_stack;
359 quick_stack = TREE_CHAIN (quick_stack);
360 TREE_CHAIN (node) = tree_list_free_list;
361 tree_list_free_list = node;
362 node = TREE_VALUE (node);
363 return node;
364 }
365 else
366 return find_stack_slot (stack_pointer, promote_type (type));
367}
368
369
370/* Pop and discrad the top COUNT stack slots. */
371
372void
373java_stack_pop (count)
374 int count;
375{
376 while (count > 0)
377 {
378 tree type, val;
379 if (stack_pointer == 0)
380 fatal ("stack underflow");
381 type = stack_type_map[stack_pointer - 1];
382 if (type == TYPE_SECOND)
383 {
384 count--;
385 if (stack_pointer == 1 || count <= 0)
386 fatal ("stack underflow");
387 type = stack_type_map[stack_pointer - 2];
388 }
389 val = pop_value (type);
390 count--;
391 }
392}
393
394/* Implement the 'swap' operator (to swap two top stack slots). */
395
396void
397java_stack_swap ()
398{
399 tree type1, type2;
400 rtx temp;
401 tree decl1, decl2;
402
403 if (stack_pointer < 2
404 || (type1 = stack_type_map[stack_pointer - 1]) == TYPE_UNKNOWN
405 || (type2 = stack_type_map[stack_pointer - 2]) == TYPE_UNKNOWN
406 || type1 == TYPE_SECOND || type2 == TYPE_SECOND
407 || TYPE_IS_WIDE (type1) || TYPE_IS_WIDE (type2))
408 fatal ("bad stack swap");
409
410 flush_quick_stack ();
411 decl1 = find_stack_slot (stack_pointer - 1, type1);
412 decl2 = find_stack_slot (stack_pointer - 2, type2);
413 temp = copy_to_reg (DECL_RTL (decl1));
414 emit_move_insn (DECL_RTL (decl1), DECL_RTL (decl2));
415 emit_move_insn (DECL_RTL (decl2), temp);
416 stack_type_map[stack_pointer - 1] = type2;
417 stack_type_map[stack_pointer - 2] = type1;
418}
419
420void
421java_stack_dup (size, offset)
422 int size, offset;
423{
424 int low_index = stack_pointer - size - offset;
425 int dst_index;
426 if (low_index < 0)
427 error ("stack underflow - dup* operation");
428
429 flush_quick_stack ();
430
431 stack_pointer += size;
432 dst_index = stack_pointer;
433
434 for (dst_index = stack_pointer; --dst_index >= low_index; )
435 {
436 tree type;
437 int src_index = dst_index - size;
438 if (src_index < low_index)
439 src_index = dst_index + size + offset;
440 type = stack_type_map [src_index];
441 if (type == TYPE_SECOND)
442 {
443 if (src_index <= low_index)
444 fatal ("dup operation splits 64-bit number");
445 stack_type_map[dst_index] = type;
446 src_index--; dst_index--;
447 type = stack_type_map[src_index];
448 if (! TYPE_IS_WIDE (type))
449 fatal ("internal error - dup operation");
450 }
451 else if (TYPE_IS_WIDE (type))
452 fatal ("internal error - dup operation");
453 if (src_index != dst_index)
454 {
455 tree src_decl = find_stack_slot (src_index, type);
456 tree dst_decl = find_stack_slot (dst_index, type);
457 emit_move_insn (DECL_RTL (dst_decl), DECL_RTL (src_decl));
458 stack_type_map[dst_index] = type;
459 }
460 }
461}
462
e4de5a10 463/* Calls _Jv_Throw. Discard the contents of the value stack. */
e04a16fb
AG
464
465tree
466build_java_athrow (node)
467 tree node;
468{
469 tree call;
470
471 call = build (CALL_EXPR,
472 void_type_node,
473 build_address_of (throw_node),
474 build_tree_list (NULL_TREE, node),
475 NULL_TREE);
476 TREE_SIDE_EFFECTS (call) = 1;
477 expand_expr_stmt (call);
478 java_stack_pop (stack_pointer);
479}
480
481/* Implementation for jsr/ret */
482
483void
484build_java_jsr (where, ret)
485 tree where;
486 tree ret;
487{
488 tree ret_label = fold (build1 (ADDR_EXPR, return_address_type_node, ret));
489 push_value (ret_label);
490 flush_quick_stack ();
491 expand_goto (where);
492 expand_label (ret);
493}
494
495void
496build_java_ret (location)
497 tree location;
498{
499 expand_computed_goto (location);
500}
501
502/* Implementation of operations on array: new, load, store, length */
503
504/* Array core info access macros */
505
506#define JAVA_ARRAY_LENGTH_OFFSET(A) \
507 size_binop (CEIL_DIV_EXPR, \
508 (DECL_FIELD_BITPOS \
509 (TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (TREE_TYPE (A)))))), \
510 size_int (BITS_PER_UNIT))
511
512tree
513decode_newarray_type (int atype)
514{
515 switch (atype)
516 {
517 case 4: return boolean_type_node;
518 case 5: return char_type_node;
519 case 6: return float_type_node;
520 case 7: return double_type_node;
521 case 8: return byte_type_node;
522 case 9: return short_type_node;
523 case 10: return int_type_node;
524 case 11: return long_type_node;
525 default: return NULL_TREE;
526 }
527}
528
e4de5a10
PB
529/* Build a call to _Jv_ThrowBadArrayIndex(), the
530 ArrayIndexOfBoundsException exception handler. */
e04a16fb
AG
531
532static tree
e4de5a10
PB
533build_java_throw_out_of_bounds_exception (index)
534 tree index;
e04a16fb
AG
535{
536 tree node = build (CALL_EXPR, int_type_node,
537 build_address_of (soft_badarrayindex_node),
e4de5a10 538 build_tree_list (NULL_TREE, index), NULL_TREE);
e04a16fb
AG
539 TREE_SIDE_EFFECTS (node) = 1; /* Allows expansion within ANDIF */
540 return (node);
541}
542
543/* Return the length of an array. Doesn't perform any checking on the nature
544 or value of the array NODE. May be used to implement some bytecodes. */
545
546tree
547build_java_array_length_access (node)
548 tree node;
549{
550 tree type = TREE_TYPE (node);
551 HOST_WIDE_INT length;
552 if (!is_array_type_p (type))
553 fatal ("array length on a non-array reference");
554 length = java_array_type_length (type);
555 if (length >= 0)
556 return build_int_2 (length, 0);
557 return fold (build1 (INDIRECT_REF,
558 int_type_node,
559 fold (build (PLUS_EXPR, ptr_type_node,
560 node,
561 JAVA_ARRAY_LENGTH_OFFSET(node)))));
562}
563
564/* Optionally checks an array against the NULL pointer, eventually throwing a
565 NullPointerException. It could replace signal handling, but tied to NULL.
566 ARG1: the pointer to check, ARG2: the expression to use if
567 the pointer is non-null and ARG3 the type that should be returned. */
568
569tree
570build_java_arraynull_check (node, expr, type)
571 tree node;
572 tree expr;
573 tree type;
574{
575#if 0
576 static int java_array_access_throws_null_exception = 0;
577 node = ???;
578 if (java_array_access_throws_null_exception)
579 return (build (COND_EXPR,
580 type,
581 build (EQ_EXPR, int_type_node, node, null_pointer_node),
582 build_java_athrow (node), expr ));
583 else
584#endif
585 return (expr);
586}
587
588static tree
589java_array_data_offset (array)
590 tree array;
591{
592 tree array_type = TREE_TYPE (TREE_TYPE (array));
593 tree data_fld = TREE_CHAIN (TREE_CHAIN (TYPE_FIELDS (array_type)));
594 if (data_fld == NULL_TREE)
595 return size_in_bytes (array_type);
596 else
597 return build_int_2 (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (data_fld))
598 / BITS_PER_UNIT, 0);
599}
600
601/* Implement array indexing (either as l-value or r-value).
602 Returns a tree for ARRAY[INDEX], assume TYPE is the element type.
603 Optionally performs bounds checking and/or test to NULL.
604 At this point, ARRAY should have been verified as an array. */
605
606tree
607build_java_arrayaccess (array, type, index)
608 tree array, type, index;
609{
610 tree arith, node, throw = NULL_TREE;
611
612 arith = fold (build (PLUS_EXPR, int_type_node,
613 java_array_data_offset (array),
614 fold (build (MULT_EXPR, int_type_node,
615 index, size_in_bytes(type)))));
616
617 if (flag_bounds_check)
618 {
619 /* Generate:
620 * (unsigned jint) INDEX >= (unsigned jint) LEN
621 * && throw ArrayIndexOutOfBoundsException.
622 * Note this is equivalent to and more efficient than:
623 * INDEX < 0 || INDEX >= LEN && throw ... */
624 tree test;
625 tree len = build_java_array_length_access (array);
626 TREE_TYPE (len) = unsigned_int_type_node;
627 test = fold (build (GE_EXPR, boolean_type_node,
628 convert (unsigned_int_type_node, index),
629 len));
630 if (! integer_zerop (test))
631 {
632 throw = build (TRUTH_ANDIF_EXPR, int_type_node, test,
e4de5a10 633 build_java_throw_out_of_bounds_exception (index));
e04a16fb
AG
634 /* allows expansion within COMPOUND */
635 TREE_SIDE_EFFECTS( throw ) = 1;
636 }
637 }
638
639 node = build1 (INDIRECT_REF, type,
640 fold (build (PLUS_EXPR, ptr_type_node,
641 array,
642 (throw ? build (COMPOUND_EXPR, int_type_node,
643 throw, arith )
644 : arith))));
645
646 return (fold (build_java_arraynull_check (array, node, type)));
647}
648
649/* Makes sure that INDEXED_TYPE is appropriate. If not, make it from
650 ARRAY_NODE. This function is used to retrieve something less vague than
651 a pointer type when indexing the first dimension of something like [[<t>.
652 May return a corrected type, if necessary, otherwise INDEXED_TYPE is
653 return unchanged.
654 As a side effect, it also makes sure that ARRAY_NODE is an array. */
655
656static tree
657build_java_check_indexed_type (array_node, indexed_type)
658 tree array_node;
659 tree indexed_type;
660{
661 tree elt_type;
662
663 if (!is_array_type_p (TREE_TYPE (array_node)))
664 fatal ("array indexing on a non-array reference");
665
666 elt_type = (TYPE_ARRAY_ELEMENT (TREE_TYPE (TREE_TYPE (array_node))));
667
668 if (indexed_type == ptr_type_node )
669 return promote_type (elt_type);
670
671 /* BYTE/BOOLEAN store and load are used for both type */
672 if (indexed_type == byte_type_node && elt_type == boolean_type_node )
673 return boolean_type_node;
674
675 if (indexed_type != elt_type )
676 fatal ("type array element mismatch");
677 else
678 return indexed_type;
679}
680
e4de5a10 681/* newarray triggers a call to _Jv_NewArray. This function should be called
e04a16fb
AG
682 with an integer code (the type of array to create) and get from the stack
683 the size of the dimmension. */
684
685tree
686build_newarray (atype_value, length)
687 int atype_value;
688 tree length;
689{
690 tree type = build_java_array_type (decode_newarray_type (atype_value),
691 TREE_CODE (length) == INTEGER_CST
692 ? TREE_INT_CST_LOW (length)
693 : -1);
694 return build (CALL_EXPR, promote_type (type),
695 build_address_of (soft_newarray_node),
696 tree_cons (NULL_TREE,
697 build_int_2 (atype_value, 0),
698 build_tree_list (NULL_TREE, length)),
699 NULL_TREE);
700}
701
702/* Generates anewarray from a given CLASS_TYPE. Gets from the stack the size
703 of the dimension. */
704/* Merge with build_newarray. FIXME. */
705tree
706build_anewarray (class_type, length)
707 tree class_type;
708 tree length;
709{
e4de5a10 710 tree type = build_java_array_type (class_type,
e04a16fb
AG
711 TREE_CODE (length) == INTEGER_CST
712 ? TREE_INT_CST_LOW (length)
713 : -1);
714 return build (CALL_EXPR, promote_type (type),
715 build_address_of (soft_anewarray_node),
716 tree_cons (NULL_TREE, length,
717 tree_cons (NULL_TREE, build_class_ref (class_type),
718 build_tree_list (NULL_TREE,
719 null_pointer_node))),
720 NULL_TREE);
721}
722
e4de5a10
PB
723/* Generates a call to _Jv_NewMultiArray. multianewarray expects a
724 class pointer, a number of dimensions and the matching number of
725 dimensions. The argument list is NULL terminated. */
e04a16fb
AG
726
727void
728expand_java_multianewarray (class_type, ndim)
729 tree class_type;
730 int ndim;
731{
732 int i;
733 tree args = build_tree_list( NULL_TREE, null_pointer_node );
734
735 for( i = 0; i < ndim; i++ )
736 args = tree_cons (NULL_TREE, pop_value (int_type_node), args);
737
738 push_value (build (CALL_EXPR,
739 promote_type (class_type),
740 build_address_of (soft_multianewarray_node),
741 tree_cons (NULL_TREE, build_class_ref (class_type),
742 tree_cons (NULL_TREE,
743 build_int_2 (ndim, 0), args )),
744 NULL_TREE));
745}
746
747/* ARRAY[INDEX] <- RHS. build_java_check_indexed_type makes sure that
748 ARRAY is an array type. May expand some bound checking and NULL
749 pointer checking. RHS_TYPE_NODE we are going to store. In the case
750 of the CHAR/BYTE/BOOLEAN SHORT, the type popped of the stack is an
751 INT. In those cases, we make the convertion.
752
753 if ARRAy is a reference type, the assignment is checked at run-time
754 to make sure that the RHS can be assigned to the array element
755 type. It is not necessary to generate this code if ARRAY is final. */
756
757void
758expand_java_arraystore (rhs_type_node)
759 tree rhs_type_node;
760{
761 tree rhs_node = pop_value ((INTEGRAL_TYPE_P (rhs_type_node)
762 && TYPE_PRECISION (rhs_type_node) <= 32) ?
763 int_type_node : rhs_type_node);
764 tree index = pop_value (int_type_node);
765 tree array = pop_value (ptr_type_node);
766
767 rhs_type_node = build_java_check_indexed_type (array, rhs_type_node);
768
769 flush_quick_stack ();
770
771 index = save_expr (index);
772 array = save_expr (array);
773
774 if (TREE_CODE (rhs_type_node) == POINTER_TYPE
775 && !CLASS_FINAL (TYPE_NAME (TREE_TYPE (rhs_type_node))))
776 {
777 tree check = build (CALL_EXPR, void_type_node,
778 build_address_of (soft_checkarraystore_node),
779 tree_cons (NULL_TREE, array,
780 build_tree_list (NULL_TREE, rhs_node)),
781 NULL_TREE);
782 TREE_SIDE_EFFECTS (check) = 1;
783 expand_expr_stmt (check);
784 }
785
786 expand_assignment (build_java_arrayaccess (array,
787 rhs_type_node,
788 index),
789 rhs_node, 0, 0);
790}
791
792/* Expand the evaluation of ARRAY[INDEX]. build_java_check_indexed_type makes
793 sure that LHS is an array type. May expand some bound checking and NULL
794 pointer checking.
795 LHS_TYPE_NODE is the type of ARRAY[INDEX]. But in the case of CHAR/BYTE/
796 BOOLEAN/SHORT, we push a promoted type back to the stack.
797*/
798
799void
800expand_java_arrayload (lhs_type_node )
801 tree lhs_type_node;
802{
803 tree load_node;
804 int convert;
805 tree index_node = pop_value (int_type_node);
806 tree array_node = pop_value (ptr_type_node);
807
808 index_node = save_expr (index_node);
809 array_node = save_expr (array_node);
810 lhs_type_node = build_java_check_indexed_type (array_node, lhs_type_node);
811
812 load_node = build_java_arrayaccess (array_node,
813 lhs_type_node,
814 index_node);
815
816 if (INTEGRAL_TYPE_P (lhs_type_node) && TYPE_PRECISION (lhs_type_node) <= 32)
817 load_node = fold (build1 (NOP_EXPR, int_type_node, load_node));
818 push_value (load_node);
819}
820
821/* Expands .length. Makes sure that we deal with and array and may expand
822 a NULL check on the array object. */
823
824void
825expand_java_array_length ()
826{
827 tree array = pop_value (ptr_type_node);
828 tree length = build_java_array_length_access (array);
829
830 push_value (build_java_arraynull_check (array, length, int_type_node));
831}
832
e4de5a10
PB
833/* Emit code for the call to _Jv_Monitor{Enter,Exit}. CALL can be
834 either soft_monitorenter_node or soft_monitorexit_node. */
e04a16fb
AG
835
836tree
837build_java_monitor (call, object)
838 tree call;
839 tree object;
840{
841 return (build (CALL_EXPR,
842 void_type_node,
843 build_address_of (call),
844 build_tree_list (NULL_TREE, object),
845 NULL_TREE));
846}
847
848/* Emit code for one of the PUSHC instructions. */
849
850void
851expand_java_pushc (ival, type)
852 int ival;
853 tree type;
854{
855 tree value;
856 if (type == ptr_type_node && ival == 0)
857 value = null_pointer_node;
858 else if (type == int_type_node || type == long_type_node)
859 {
860 value = build_int_2 (ival, ival < 0 ? -1 : 0);
861 TREE_TYPE (value) = type;
862 }
863 else if (type == float_type_node || type == double_type_node)
864 {
865 REAL_VALUE_TYPE x;
866#ifdef REAL_ARITHMETIC
867 REAL_VALUE_FROM_INT (x, ival, 0, TYPE_MODE (type));
868#else
869 x = ival;
870#endif
871 value = build_real (type, x);
872 }
873 else
874 fatal ("internal error in expand_java_pushc");
875 push_value (value);
876}
877
878void
879expand_java_return (type)
880 tree type;
881{
882 if (type == void_type_node)
883 expand_null_return ();
884 else
885 {
886 tree retval = pop_value (type);
887 tree res = DECL_RESULT (current_function_decl);
888 retval = build (MODIFY_EXPR, TREE_TYPE (res), res, retval);
889 TREE_SIDE_EFFECTS (retval) = 1;
890 expand_return (retval);
891 }
892}
893
894tree
895build_address_of (value)
896 tree value;
897{
898 return build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (value)), value);
899}
900
901void
902expand_java_NEW (type)
903 tree type;
904{
905 if (! CLASS_LOADED_P (type))
906 load_class (type, 1);
907 push_value (build (CALL_EXPR, promote_type (type),
908 build_address_of (alloc_object_node),
909 tree_cons (NULL_TREE, build_class_ref (type),
910 build_tree_list (NULL_TREE,
911 size_in_bytes (type))),
912 NULL_TREE));
913}
914
915void
916expand_java_INSTANCEOF (type)
917 tree type;
918{
919 tree value = pop_value (object_ptr_type_node);
920 value = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (soft_instanceof_node)),
921 build_address_of (soft_instanceof_node),
922 tree_cons (NULL_TREE, value,
923 build_tree_list (NULL_TREE,
924 build_class_ref (type))),
925 NULL_TREE);
926 push_value (value);
927}
928
929void
930expand_java_CHECKCAST (type)
931 tree type;
932{
933 tree value = pop_value (ptr_type_node);
934 value = build (CALL_EXPR, promote_type (type),
935 build_address_of (soft_checkcast_node),
936 tree_cons (NULL_TREE, build_class_ref (type),
937 build_tree_list (NULL_TREE, value)),
938 NULL_TREE);
939 push_value (value);
940}
941
942void
943expand_iinc (unsigned int local_var_index, int ival, int pc)
944{
945 tree local_var, res;
946 tree constant_value;
947
948 flush_quick_stack ();
949 local_var = find_local_variable (local_var_index, int_type_node, pc);
950 constant_value = build_int_2 (ival, ival < 0 ? -1 : 0);
951 res = fold (build (PLUS_EXPR, int_type_node, local_var, constant_value));
952 expand_assignment (local_var, res, 0, 0);
953}
954
955tree
956build_java_binop (op, type, arg1, arg2)
957 enum tree_code op;
958 tree type, arg1, arg2;
959{
960 tree mask;
961 switch (op)
962 {
963 case URSHIFT_EXPR:
964 {
965 tree u_type = unsigned_type (type);
966 arg1 = convert (u_type, arg1);
967 arg1 = build_java_binop (RSHIFT_EXPR, u_type, arg1, arg2);
968 return convert (type, arg1);
969 }
970 case LSHIFT_EXPR:
971 case RSHIFT_EXPR:
972 mask = build_int_2 (TYPE_PRECISION (TREE_TYPE (arg1)) - 1, 0);
973 arg2 = fold (build (BIT_AND_EXPR, int_type_node, arg2, mask));
974 break;
975
976 case COMPARE_L_EXPR: /* arg1 > arg2 ? 1 : arg1 == arg2 ? 0 : -1 */
977 case COMPARE_G_EXPR: /* arg1 < arg2 ? -1 : arg1 == arg2 ? 0 : 1 */
978 arg1 = save_expr (arg1); arg2 = save_expr (arg2);
979 {
980 tree ifexp1 = fold ( build (op == COMPARE_L_EXPR ? GT_EXPR : LT_EXPR,
981 boolean_type_node, arg1, arg2));
982 tree ifexp2 = fold ( build (EQ_EXPR, boolean_type_node, arg1, arg2));
983 tree second_compare = fold (build (COND_EXPR, int_type_node,
984 ifexp2, integer_zero_node,
985 op == COMPARE_L_EXPR
986 ? integer_negative_one_node
987 : integer_one_node));
988 return fold (build (COND_EXPR, int_type_node, ifexp1,
989 op == COMPARE_L_EXPR ? integer_one_node
990 : integer_negative_one_node,
991 second_compare));
992 }
993 case COMPARE_EXPR:
994 arg1 = save_expr (arg1); arg2 = save_expr (arg2);
995 {
996 tree ifexp1 = fold ( build (LT_EXPR, boolean_type_node, arg1, arg2));
997 tree ifexp2 = fold ( build (GT_EXPR, boolean_type_node, arg1, arg2));
998 tree second_compare = fold ( build (COND_EXPR, int_type_node,
999 ifexp2, integer_one_node,
1000 integer_zero_node));
1001 return fold (build (COND_EXPR, int_type_node,
1002 ifexp1, integer_negative_one_node, second_compare));
1003 }
1004
1005 case TRUNC_MOD_EXPR:
1006 if (TREE_CODE (type) == REAL_TYPE)
1007 {
1008 tree call;
1009 if (type != double_type_node)
1010 {
1011 arg1 = convert (double_type_node, arg1);
1012 arg2 = convert (double_type_node, arg2);
1013 }
1014 call = build (CALL_EXPR, double_type_node,
1015 build_address_of (soft_fmod_node),
1016 tree_cons (NULL_TREE, arg1,
1017 build_tree_list (NULL_TREE, arg2)),
1018 NULL_TREE);
1019 if (type != double_type_node)
1020 call = convert (type, call);
1021 return call;
1022 }
1023 break;
1024
1025#if 0 /* not required */
1026 case PLUS_EXPR:
1027 case MULT_EXPR:
1028 case MINUS_EXPR:
1029 case TRUNC_DIV_EXPR:
1030 case RDIV_EXPR:
1031/* case REM_EXPR: */
1032 case BIT_AND_EXPR:
1033 case BIT_IOR_EXPR:
1034 case BIT_XOR_EXPR:
1035 break;
1036 default:
1037 error ("unknown opcode");
1038 return error_mark_node;
1039#endif
1040
1041 }
1042 return fold (build (op, type, arg1, arg2));
1043}
1044
1045void
1046expand_java_binop (type, op)
1047 tree type; enum tree_code op;
1048{
1049 tree larg, rarg;
1050 tree ltype = type;
1051 tree rtype = type;
1052 switch (op)
1053 {
1054 case LSHIFT_EXPR:
1055 case RSHIFT_EXPR:
1056 case URSHIFT_EXPR:
1057 rtype = int_type_node;
1058 rarg = pop_value (rtype);
1059 break;
1060 default:
1061 rarg = pop_value (rtype);
1062 }
1063 larg = pop_value (ltype);
1064 push_value (build_java_binop (op, type, larg, rarg));
1065}
1066
1067/* Lookup the field named NAME in *TYPEP or its super classes.
1068 If not found, return NULL_TREE.
1069 (If the *TYPEP is not found, return error_mark_node.)
1070 If found, return the FIELD_DECL, and set *TYPEP to the
1071 class containing the field. */
1072
1073tree
1074lookup_field (typep, name)
1075 tree *typep;
1076 tree name;
1077{
1078 if (CLASS_P (*typep) && !CLASS_LOADED_P (*typep))
1079 {
1080 load_class (*typep, 1);
1081 if (TREE_CODE (TYPE_SIZE (*typep)) == ERROR_MARK)
1082 return error_mark_node;
1083 }
1084 do
1085 {
1086 tree field;
1087 for (field = TYPE_FIELDS (*typep); field; field = TREE_CHAIN (field))
1088 {
1089 if (DECL_NAME (field) == name)
1090 return field;
1091 }
1092 *typep = CLASSTYPE_SUPER (*typep);
1093 } while (*typep);
1094 return NULL_TREE;
1095}
1096
1097/* Look up the field named NAME in object SELF_VALUE,
1098 which has class SELF_CLASS (a non-handle RECORD_TYPE).
1099 SELF_VALUE is NULL_TREE if looking for a static field. */
1100
1101tree
1102build_field_ref (self_value, self_class, name)
1103 tree self_value, self_class, name;
1104{
1105 tree base_class = self_class;
1106 tree field_decl = lookup_field (&base_class, name);
1107 if (field_decl == NULL_TREE)
1108 {
1109 error ("field `%s' not found", IDENTIFIER_POINTER (name));
1110 return error_mark_node;
1111 }
1112 if (self_value == NULL_TREE)
1113 {
1114 return build_static_field_ref (field_decl);
1115 }
1116 else
1117 {
1118 tree base_handle_type = promote_type (base_class);
1119 if (base_handle_type != TREE_TYPE (self_value))
1120 self_value = fold (build1 (NOP_EXPR, base_handle_type, self_value));
1121#ifdef JAVA_USE_HANDLES
1122 self_value = unhand_expr (self_value);
1123#endif
1124 self_value = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (self_value)),
1125 self_value);
1126 return fold (build (COMPONENT_REF, TREE_TYPE (field_decl),
1127 self_value, field_decl));
1128 }
1129}
1130
1131tree
1132lookup_label (pc)
1133 int pc;
1134{
1135 tree name;
1136 char buf[20];
1137 sprintf (buf, "LJpc=%d", pc);
1138 name = get_identifier (buf);
1139 if (IDENTIFIER_LOCAL_VALUE (name))
1140 return IDENTIFIER_LOCAL_VALUE (name);
1141 else
1142 {
1143 /* The type of the address of a label is return_address_type_node. */
1144 tree decl = create_label_decl (name);
1145 LABEL_PC (decl) = pc;
1146 label_rtx (decl);
1147 return pushdecl (decl);
1148 }
1149}
1150
e4de5a10
PB
1151/* Generate a unique name for the purpose of loops and switches
1152 labels, and try-catch-finally blocks label or temporary variables. */
1153
1154tree
1155generate_name ()
1156{
1157 static int l_number = 0;
1158 char buff [20];
1159 sprintf (buff, "$L%d", l_number++);
1160 return get_identifier (buff);
1161}
1162
e04a16fb
AG
1163tree
1164create_label_decl (name)
1165 tree name;
1166{
1167 tree decl;
1168 push_obstacks (&permanent_obstack, &permanent_obstack);
1169 decl = build_decl (LABEL_DECL, name,
1170 TREE_TYPE (return_address_type_node));
1171 pop_obstacks ();
1172 DECL_CONTEXT (decl) = current_function_decl;
1173 DECL_IGNORED_P (decl) = 1;
1174 return decl;
1175}
1176
1177/* This maps a bytecode offset (PC) to various flags. */
1178char *instruction_bits;
1179
1180void
1181note_label (current_pc, target_pc)
1182 int current_pc, target_pc;
1183{
1184 lookup_label (target_pc);
1185 instruction_bits [target_pc] |= BCODE_JUMP_TARGET;
1186}
1187
1188/* Emit code to jump to TARGET_PC if VALUE1 CONDITION VALUE2,
1189 where CONDITION is one of one the compare operators. */
1190
e04a16fb
AG
1191void
1192expand_compare (condition, value1, value2, target_pc)
1193 enum tree_code condition;
1194 tree value1, value2;
1195 int target_pc;
1196{
1197 tree target = lookup_label (target_pc);
1198 tree cond = fold (build (condition, boolean_type_node, value1, value2));
1199 expand_start_cond (truthvalue_conversion (cond), 0);
1200 expand_goto (target);
1201 expand_end_cond ();
1202}
1203
1204/* Emit code for a TEST-type opcode. */
1205
1206void
1207expand_test (condition, type, target_pc)
1208 enum tree_code condition;
1209 tree type;
1210 int target_pc;
1211{
1212 tree value1, value2;
1213 flush_quick_stack ();
1214 value1 = pop_value (type);
1215 value2 = (type == ptr_type_node) ? null_pointer_node : integer_zero_node;
1216 expand_compare (condition, value1, value2, target_pc);
1217}
1218
1219/* Emit code for a COND-type opcode. */
1220
1221void
1222expand_cond (condition, type, target_pc)
1223 enum tree_code condition;
1224 tree type;
1225 int target_pc;
1226{
1227 tree value1, value2;
1228 flush_quick_stack ();
1229 /* note: pop values in opposite order */
1230 value2 = pop_value (type);
1231 value1 = pop_value (type);
1232 /* Maybe should check value1 and value2 for type compatibility ??? */
1233 expand_compare (condition, value1, value2, target_pc);
1234}
1235
1236void
1237expand_java_goto (target_pc)
1238 int target_pc;
1239{
1240 tree target_label = lookup_label (target_pc);
1241 flush_quick_stack ();
1242 expand_goto (target_label);
1243}
1244
1245void
1246expand_java_call (target_pc, return_address)
1247 int target_pc, return_address;
1248{
1249 tree target_label = lookup_label (target_pc);
1250 tree value = build_int_2 (return_address, return_address < 0 ? -1 : 0);
1251 push_value (value);
1252 flush_quick_stack ();
1253 expand_goto (target_label);
1254}
1255
1256void
1257expand_java_ret (return_address)
1258 tree return_address;
1259{
1260 warning ("ret instruction not implemented");
1261#if 0
1262 tree target_label = lookup_label (target_pc);
1263 flush_quick_stack ();
1264 expand_goto (target_label);
1265#endif
1266}
1267
1268/* Recursive helper function to pop argument types during verifiation. */
1269
1270void
1271pop_argument_types (arg_types)
1272 tree arg_types;
1273{
1274 if (arg_types == NULL_TREE)
1275 return;
1276 if (TREE_CODE (arg_types) == TREE_LIST)
1277 {
1278 pop_argument_types (TREE_CHAIN (arg_types));
1279 pop_type (TREE_VALUE (arg_types));
1280 return;
1281 }
1282 abort ();
1283}
1284
1285tree
1286pop_arguments (arg_types)
1287 tree arg_types;
1288{
1289 if (arg_types == NULL_TREE)
1290 return NULL_TREE;
1291 if (TREE_CODE (arg_types) == TREE_LIST)
1292 {
1293 tree tail = pop_arguments (TREE_CHAIN (arg_types));
e4de5a10
PB
1294 tree type = TREE_VALUE (arg_types);
1295 tree arg = pop_value (type);
1296#ifdef PROMOTE_PROTOTYPES
1297 if (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)
1298 && INTEGRAL_TYPE_P (type))
1299 arg = convert (integer_type_node, arg);
1300#endif
1301 return tree_cons (NULL_TREE, arg, tail);
e04a16fb
AG
1302 }
1303 abort ();
1304}
1305
1306/* Build an expression to initialize the class CLAS.
1307 if EXPR is non-NULL, returns an expression to first call the initializer
1308 (if it is needed) and then calls EXPR. */
1309
1310tree
1311build_class_init (clas, expr)
1312 tree clas, expr;
1313{
1314 tree init;
1315 if (inherits_from_p (current_class, clas))
1316 return expr;
1317 init = build (CALL_EXPR, void_type_node,
1318 build_address_of (soft_initclass_node),
1319 build_tree_list (NULL_TREE, build_class_ref (clas)),
1320 NULL_TREE);
1321 TREE_SIDE_EFFECTS (init) = 1;
1322 if (expr != NULL_TREE)
1323 {
1324 expr = build (COMPOUND_EXPR, TREE_TYPE (expr), init, expr);
1325 TREE_SIDE_EFFECTS (expr) = 1;
1326 return expr;
1327 }
1328 return init;
1329}
1330
1331static tree methods_ident = NULL_TREE;
1332static tree ncode_ident = NULL_TREE;
1333tree dtable_ident = NULL_TREE;
1334
1335tree
1336build_known_method_ref (method, method_type, self_type, method_signature, arg_list)
1337 tree method, method_type, self_type, method_signature, arg_list;
1338{
1339 tree func;
15fdcfe9 1340 if (is_compiled_class (self_type))
e04a16fb
AG
1341 {
1342 make_decl_rtl (method, NULL, 1);
1343 func = build1 (ADDR_EXPR, method_ptr_type_node, method);
1344 }
1345 else
1346 {
1347 /* We don't know whether the method has been (statically) compiled.
1348 Compile this code to get a reference to the method's code:
1349
1350 SELF_TYPE->methods[METHOD_INDEX].ncode
1351
1352 This is guaranteed to work (assuming SELF_TYPE has
1353 been initialized), since if the method is not compiled yet,
1354 its ncode points to a trampoline that forces compilation. */
1355
1356 int method_index = 0;
1357 tree meth;
1358 tree ref = build_class_ref (self_type);
1359 ref = build1 (INDIRECT_REF, class_type_node, ref);
1360 if (ncode_ident == NULL_TREE)
1361 ncode_ident = get_identifier ("ncode");
1362 if (methods_ident == NULL_TREE)
1363 methods_ident = get_identifier ("methods");
1364 ref = build (COMPONENT_REF, method_ptr_type_node, ref,
1365 lookup_field (&class_type_node, methods_ident));
1366 for (meth = TYPE_METHODS (CLASS_TO_HANDLE_TYPE (self_type));
1367 ; meth = TREE_CHAIN (meth))
1368 {
1369 if (method == meth)
1370 break;
1371 if (meth == NULL_TREE)
1372 fatal ("method '%s' not found in class",
1373 IDENTIFIER_POINTER (DECL_NAME (method)));
1374 method_index++;
1375 }
1376 method_index *= int_size_in_bytes (method_type_node);
1377 ref = fold (build (PLUS_EXPR, method_ptr_type_node,
1378 ref, build_int_2 (method_index, 0)));
1379 ref = build1 (INDIRECT_REF, method_type_node, ref);
1380 func = build (COMPONENT_REF, nativecode_ptr_type_node,
1381 ref,
1382 lookup_field (&method_type_node, ncode_ident));
1383 }
1384 return func;
1385}
1386
1387tree
1388invoke_build_dtable (is_invoke_interface, arg_list)
1389 int is_invoke_interface;
1390 tree arg_list;
1391{
1392 tree dtable, objectref;
1393
1394 TREE_VALUE (arg_list) = save_expr (TREE_VALUE (arg_list));
1395
1396 /* If we're dealing with interfaces and if the objectref
1397 argument is an array then get the dispatch table of the class
1398 Object rather than the one from the objectref. */
1399 objectref = (is_invoke_interface
1400 && is_array_type_p (TREE_TYPE (TREE_VALUE (arg_list))) ?
1401 object_type_node : TREE_VALUE (arg_list));
1402
1403 if (dtable_ident == NULL_TREE)
1404 dtable_ident = get_identifier ("dtable");
1405 dtable = build1 (INDIRECT_REF, object_type_node, objectref );
1406 dtable = build (COMPONENT_REF, dtable_ptr_type, dtable,
1407 lookup_field (&object_type_node, dtable_ident));
1408
1409 return dtable;
1410}
1411
1412tree
1413build_invokevirtual (dtable, method)
1414 tree dtable, method;
1415{
1416 tree func;
1417 tree nativecode_ptr_ptr_type_node
1418 = build_pointer_type (nativecode_ptr_type_node);
1419 int method_index = TREE_INT_CST_LOW (DECL_VINDEX (method));
1420 /* Add one to skip "class" field of dtable, and one to skip unused
1421 vtable entry (for C++ compatibility). */
1422 method_index += 2;
1423 method_index
1424 *= int_size_in_bytes (nativecode_ptr_ptr_type_node);
1425 func = fold (build (PLUS_EXPR, nativecode_ptr_ptr_type_node,
1426 dtable, build_int_2 (method_index, 0)));
1427 func = build1 (INDIRECT_REF, nativecode_ptr_type_node, func);
1428
1429 return func;
1430}
1431
5e942c50
APB
1432tree
1433build_invokeinterface (dtable, method_name, method_signature)
1434 tree dtable, method_name, method_signature;
1435{
1436 static tree class_ident = NULL_TREE;
1437 tree lookup_arg;
1438
1439 /* We expand invokeinterface here. _Jv_LookupInterfaceMethod() will
1440 ensure that the selected method exists, is public and not
1441 abstract nor static. */
1442
1443 if (class_ident == NULL_TREE)
1444 class_ident = get_identifier ("class");
1445
1446 dtable = build1 (INDIRECT_REF, dtable_type, dtable);
1447 dtable = build (COMPONENT_REF, class_ptr_type, dtable,
1448 lookup_field (&dtable_type, class_ident));
1449 lookup_arg = build_tree_list (NULL_TREE, build_utf8_ref (method_signature));
1450 lookup_arg = tree_cons (NULL_TREE, dtable,
1451 tree_cons (NULL_TREE, build_utf8_ref (method_name),
1452 lookup_arg));
1453 return build (CALL_EXPR, ptr_type_node,
1454 build_address_of (soft_lookupinterfacemethod_node),
1455 lookup_arg, NULL_TREE);
1456}
1457
e04a16fb
AG
1458/* Expand one of the invoke_* opcodes.
1459 OCPODE is the specific opcode.
1460 METHOD_REF_INDEX is an index into the constant pool.
1461 NARGS is the number of arguments, or -1 if not specified. */
1462
1463void
1464expand_invoke (opcode, method_ref_index, nargs)
1465 int opcode;
1466 int method_ref_index;
1467 int nargs;
1468{
1469 tree method_signature = COMPONENT_REF_SIGNATURE(&current_jcf->cpool, method_ref_index);
1470 tree method_name = COMPONENT_REF_NAME (&current_jcf->cpool, method_ref_index);
1471 tree self_type = get_class_constant
1472 (current_jcf, COMPONENT_REF_CLASS_INDEX(&current_jcf->cpool, method_ref_index));
1473 char *self_name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (self_type)));
1474 tree call, func, method, arg_list, method_type;
1475
e04a16fb
AG
1476 if (! CLASS_LOADED_P (self_type))
1477 {
1478 load_class (self_type, 1);
1479 if (TREE_CODE (TYPE_SIZE (self_type)) == ERROR_MARK)
1480 fatal ("failed to find class '%s'", self_name);
1481 }
1482
1483 if (method_name == init_identifier_node)
1484 method = lookup_java_constructor (CLASS_TO_HANDLE_TYPE (self_type),
1485 method_signature);
1486 else
1487 method = lookup_java_method (CLASS_TO_HANDLE_TYPE (self_type),
1488 method_name, method_signature);
1489 if (method == NULL_TREE)
1490 {
1491 error ("Class '%s' has no method named '%s' matching signature '%s'",
1492 self_name,
1493 IDENTIFIER_POINTER (method_name),
1494 IDENTIFIER_POINTER (method_signature));
1495 }
1496 /* Invoke static can't invoke static/abstract method */
1497 else if (opcode == OPCODE_invokestatic)
1498 {
1499 if (!METHOD_STATIC (method))
1500 {
1501 error ("invokestatic on non static method");
1502 method = NULL_TREE;
1503 }
1504 else if (METHOD_ABSTRACT (method))
1505 {
1506 error ("invokestatic on abstract method");
1507 method = NULL_TREE;
1508 }
1509 }
1510 else
1511 {
1512 if (METHOD_STATIC (method))
1513 {
1514 error ("invoke[non-static] on static method");
1515 method = NULL_TREE;
1516 }
1517 }
1518
1519 if (method == NULL_TREE)
1520 {
1521 method_type = get_type_from_signature (method_signature);
1522 pop_arguments (TYPE_ARG_TYPES (method_type));
1523 if (opcode != OPCODE_invokestatic)
1524 pop_type (self_type);
1525 method_type = promote_type (TREE_TYPE (method_type));
1526 push_value (convert (method_type, integer_zero_node));
1527 return;
1528 }
1529
1530 method_type = TREE_TYPE (method);
1531 arg_list = pop_arguments (TYPE_ARG_TYPES (method_type));
1532 flush_quick_stack ();
1533
e04a16fb
AG
1534 func = NULL_TREE;
1535 if (opcode == OPCODE_invokestatic || opcode == OPCODE_invokespecial
1536 || (opcode == OPCODE_invokevirtual
1537 && (METHOD_FINAL (method) || CLASS_FINAL (TYPE_NAME (self_type)))))
1538 func = build_known_method_ref (method, method_type, self_type,
1539 method_signature, arg_list);
1540 else
1541 {
1542 tree dtable = invoke_build_dtable (opcode == OPCODE_invokeinterface,
1543 arg_list);
1544 if (opcode == OPCODE_invokevirtual)
1545 func = build_invokevirtual (dtable, method);
1546 else
5e942c50 1547 func = build_invokeinterface (dtable, method_name, method_signature);
e04a16fb
AG
1548 }
1549 func = build1 (NOP_EXPR, build_pointer_type (method_type), func);
1550 call = build (CALL_EXPR, TREE_TYPE (method_type), func, arg_list, NULL_TREE);
1551 TREE_SIDE_EFFECTS (call) = 1;
1552
e04a16fb
AG
1553 if (TREE_CODE (TREE_TYPE (method_type)) == VOID_TYPE)
1554 expand_expr_stmt (call);
1555 else
1556 {
1557 push_value (call);
1558 flush_quick_stack ();
1559 }
1560}
1561
1562
1563/* Expand an operation to extract from or store into a field.
1564 IS_STATIC is 1 iff the field is static.
1565 IS_PUTTING is 1 for putting into a field; 0 for getting from the field.
1566 FIELD_REF_INDEX is an index into the constant pool. */
1567
1568void
1569expand_java_field_op (is_static, is_putting, field_ref_index)
1570 int is_static;
1571 int is_putting;
1572 int field_ref_index;
1573{
1574 tree self_type = get_class_constant
1575 (current_jcf, COMPONENT_REF_CLASS_INDEX (&current_jcf->cpool, field_ref_index));
1576 char *self_name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (self_type)));
1577 tree field_name = COMPONENT_REF_NAME (&current_jcf->cpool, field_ref_index);
1578 tree field_signature = COMPONENT_REF_SIGNATURE (&current_jcf->cpool, field_ref_index);
1579 tree field_type = get_type_from_signature (field_signature);
1580 tree new_value = is_putting ? pop_value (field_type) : NULL_TREE;
1581 tree field_ref;
1582 int is_error = 0;
1583 tree field_decl = lookup_field (&self_type, field_name);
1584 if (field_decl == error_mark_node)
1585 {
1586 is_error = 1;
1587 }
1588 else if (field_decl == NULL_TREE)
1589 {
1590 error ("Missing field '%s' in '%s'",
1591 IDENTIFIER_POINTER (field_name), self_name);
1592 is_error = 1;
1593 }
1594 else if (build_java_signature (TREE_TYPE (field_decl)) != field_signature)
1595 {
1596 error ("Mismatching signature for field '%s' in '%s'",
1597 IDENTIFIER_POINTER (field_name), self_name);
1598 is_error = 1;
1599 }
1600 field_ref = is_static ? NULL_TREE : pop_value (self_type);
1601 if (is_error)
1602 {
1603 if (! is_putting)
e4de5a10 1604 push_value (convert (field_type, integer_zero_node));
e04a16fb
AG
1605 flush_quick_stack ();
1606 return;
1607 }
1608
1609 /* Inline references to java.lang.PRIMTYPE.TYPE.
1610 In addition to being a useful (minor) optimization,
1611 this is also needed to avoid circularities in the implementation
1612 of these fields in libjava. */
1613 if (field_name == TYPE_identifier_node && ! is_putting
e4de5a10 1614 && field_type == class_ptr_type
e04a16fb
AG
1615 && strncmp (self_name, "java.lang.", 10) == 0)
1616 {
5e942c50
APB
1617 tree typ = build_primtype_type_ref (self_name);
1618 if (typ)
e04a16fb 1619 {
5e942c50 1620 push_value (typ);
e04a16fb
AG
1621 return;
1622 }
1623 }
1624
1625 field_ref = build_field_ref (field_ref, self_type, field_name);
1626 if (is_static)
1627 field_ref = build_class_init (self_type, field_ref);
1628 if (is_putting)
1629 {
1630 flush_quick_stack ();
1631 if (FIELD_FINAL (field_decl))
1632 {
1633 if (DECL_CONTEXT (field_decl) != current_class)
1634 error_with_decl (field_decl,
1635 "assignment to final field `%s' not in field's class");
1636 else if (FIELD_STATIC (field_decl))
1637 {
1638 if (DECL_NAME (current_function_decl) != clinit_identifier_node)
1639 error_with_decl (field_decl,
1640 "assignment to final static field `%s' not in class initializer");
1641 }
1642 else
1643 {
1644 if (! DECL_CONSTRUCTOR_P (current_function_decl))
1645 error_with_decl (field_decl,
1646 "assignment to final field `%s' not in constructor");
1647 }
1648 }
1649 expand_assignment (field_ref, new_value, 0, 0);
1650 }
1651 else
1652 push_value (field_ref);
1653}
1654
5e942c50
APB
1655tree
1656build_primtype_type_ref (self_name)
1657 char *self_name;
1658{
1659 char *class_name = self_name+10;
1660 tree typ;
1661 if (strncmp(class_name, "Byte", 4) == 0)
1662 typ = byte_type_node;
1663 else if (strncmp(class_name, "Short", 5) == 0)
1664 typ = short_type_node;
1665 else if (strncmp(class_name, "Integer", 7) == 0)
1666 typ = int_type_node;
1667 else if (strncmp(class_name, "Long", 4) == 0)
1668 typ = long_type_node;
1669 else if (strncmp(class_name, "Float", 5) == 0)
1670 typ = float_type_node;
1671 else if (strncmp(class_name, "Boolean", 7) == 0)
1672 typ = boolean_type_node;
1673 else if (strncmp(class_name, "Char", 4) == 0)
1674 typ = char_type_node;
1675 else if (strncmp(class_name, "Void", 4) == 0)
1676 typ = void_type_node;
1677 else
1678 typ = NULL_TREE;
1679 if (typ != NULL_TREE)
1680 return build_class_ref (typ);
1681 else
1682 return NULL_TREE;
1683}
1684
e04a16fb
AG
1685void
1686load_type_state (label)
1687 tree label;
1688{
1689 int i;
1690 tree vec = LABEL_TYPE_STATE (label);
1691 int cur_length = TREE_VEC_LENGTH (vec);
1692 stack_pointer = cur_length - DECL_MAX_LOCALS(current_function_decl);
1693 for (i = 0; i < cur_length; i++)
1694 type_map [i] = TREE_VEC_ELT (vec, i);
1695}
1696
15fdcfe9
PB
1697/* Do the expansion of a Java switch. With Gcc, switches are front-end
1698 dependant things, but they rely on gcc routines. This function is
1699 placed here because it uses things defined locally in parse.y. */
1700
1701static tree
1702case_identity (t, v)
1703 tree t __attribute__ ((__unused__));
1704 tree v;
1705{
1706 return v;
1707}
1708
e04a16fb
AG
1709struct rtx_def *
1710java_lang_expand_expr (exp, target, tmode, modifier)
1711 register tree exp;
1712 rtx target;
1713 enum machine_mode tmode;
1714 enum expand_modifier modifier;
1715{
1716 register rtx op0;
1717 tree type = TREE_TYPE (exp);
1718 register enum machine_mode mode = TYPE_MODE (type);
1719 int unsignedp = TREE_UNSIGNED (type);
e4de5a10
PB
1720 tree node, current;
1721 int has_finally_p;
e04a16fb
AG
1722
1723 switch (TREE_CODE (exp))
1724 {
1725 case BLOCK:
1726 if (BLOCK_EXPR_BODY (exp))
1727 {
1728 tree local;
15fdcfe9 1729 tree body = BLOCK_EXPR_BODY (exp);
e04a16fb
AG
1730 struct rtx_def *to_return;
1731 pushlevel (2); /* 2 and above */
1732 expand_start_bindings (0);
1733 local = BLOCK_EXPR_DECLS (exp);
1734 while (local)
1735 {
1736 tree next = TREE_CHAIN (local);
1737 layout_decl (local, 0);
1738 expand_decl (pushdecl (local));
1739 local = next;
1740 }
15fdcfe9
PB
1741 /* Avoid deep recursion for long block. */
1742 while (TREE_CODE (body) == COMPOUND_EXPR)
1743 {
1744 expand_expr (TREE_OPERAND (body, 0), const0_rtx, VOIDmode, 0);
1745 body = TREE_OPERAND (body, 1);
1746 }
1747 to_return = expand_expr (body, target, tmode, modifier);
e04a16fb
AG
1748 poplevel (1, 1, 0);
1749 expand_end_bindings (getdecls (), 1, 0);
1750 return to_return;
1751 }
1752 break;
1753
15fdcfe9
PB
1754 case CASE_EXPR:
1755 {
1756 tree duplicate;
1757 if (pushcase (TREE_OPERAND (exp, 0), case_identity,
1758 build_decl (LABEL_DECL, NULL_TREE, NULL_TREE), &duplicate) == 2)
1759 {
1760 EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (exp);
1761 parse_error_context
1762 (wfl_operator, "Duplicate case label: `%s'",
1763 print_int_node (TREE_OPERAND (exp, 0)));
1764 }
1765 return const0_rtx;
1766 }
1767
1768 case DEFAULT_EXPR:
1769 pushcase (NULL_TREE, 0, build_decl (LABEL_DECL, NULL_TREE, NULL_TREE), NULL);
1770 return const0_rtx;
1771
e4de5a10 1772 case SWITCH_EXPR:
15fdcfe9
PB
1773 expand_start_case (0, TREE_OPERAND (exp, 0), int_type_node, "switch");
1774 expand_expr_stmt (TREE_OPERAND (exp, 1));
1775 expand_end_case (TREE_OPERAND (exp, 0));
e4de5a10
PB
1776 return const0_rtx;
1777
1778 case TRY_EXPR:
1779 /* We expand a try[-catch][-finally] block */
1780
1781 /* Expand the try block */
1782 expand_eh_region_start ();
1783 expand_expr_stmt (TREE_OPERAND (exp, 0));
1784 expand_start_all_catch ();
1785 has_finally_p = (TREE_OPERAND (exp, 2) ? 1 : 0);
1786
1787 /* Expand all catch clauses (EH handlers) */
1788 for (current = TREE_OPERAND (exp, 1); current;
1789 current = TREE_CHAIN (current))
1790 {
1791 extern rtx return_label;
1792 tree type;
1793 /* If we have a finally, the last exception handler is the
1794 one that is supposed to catch everything. */
1795 if (has_finally_p && !TREE_CHAIN (current))
1796 type = NULL_TREE;
1797 else
1798 {
1799 tree catch = java_get_catch_block (current, has_finally_p);
1800 tree decl = BLOCK_EXPR_DECLS (catch);
b9f7e36c 1801 type = (decl ? TREE_TYPE (TREE_TYPE (decl)) : NULL_TREE);
e4de5a10
PB
1802 }
1803 start_catch_handler (prepare_eh_table_type (type));
1804 expand_expr_stmt (TREE_OPERAND (current, 0));
1805
1806 /* Need to expand a goto to the end of the function here,
1807 but not for the catch everything handler. */
1808 if (type)
1809 {
1810 if (return_label)
1811 emit_jump (return_label);
1812 else
1813 fatal ("No return_label for this function - "
1814 "java_lang_expand_expr");
1815 }
1816 end_catch_handler ();
1817 }
1818
1819 /* Expand the finally block, if any */
1820 if (has_finally_p)
1821 {
1822 tree finally = TREE_OPERAND (exp, 2);
b9f7e36c
APB
1823 if (FINALLY_EXPR_LABEL (finally))
1824 emit_label (label_rtx (FINALLY_EXPR_LABEL (finally)));
e4de5a10
PB
1825 expand_expr_stmt (FINALLY_EXPR_BLOCK (finally));
1826 }
1827 expand_end_all_catch ();
1828 break;
1829
e04a16fb
AG
1830 default:
1831 fatal ("Can't expand '%s' tree - java_lang_expand_expr",
1832 tree_code_name [TREE_CODE (exp)]);
1833 }
1834}
1835
1836void
1837expand_byte_code (jcf, method)
1838 JCF *jcf;
1839 tree method;
1840{
1841 int PC;
1842 int i;
1843 int saw_index;
1844 unsigned char *linenumber_pointer;
1845 struct eh_range *prev_eh_ranges = NULL_EH_RANGE;
1846 struct eh_range *eh_ranges;
1847
1848#undef RET /* Defined by config/i386/i386.h */
1849#undef AND /* Causes problems with opcodes for iand and land. */
1850#undef PTR
1851#define BCODE byte_ops
1852#define BYTE_type_node byte_type_node
1853#define SHORT_type_node short_type_node
1854#define INT_type_node int_type_node
1855#define LONG_type_node long_type_node
1856#define CHAR_type_node char_type_node
1857#define PTR_type_node ptr_type_node
1858#define FLOAT_type_node float_type_node
1859#define DOUBLE_type_node double_type_node
1860#define VOID_type_node void_type_node
1861 jint INT_temp;
1862 unsigned char* byte_ops;
1863 long length = DECL_CODE_LENGTH (method);
1864
1865 stack_pointer = 0;
1866 JCF_SEEK (jcf, DECL_CODE_OFFSET (method));
1867 byte_ops = jcf->read_ptr;
1868
1869#define CONST_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1870#define CONST_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1871#define VAR_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1872#define VAR_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1873
1874#define CHECK_PC_IN_RANGE(PC) 1 /* Already handled by verifier. */
1875
1876 instruction_bits = oballoc (length + 1);
1877 bzero (instruction_bits, length + 1);
1878
1879 /* We make an initial pass of the line number table, to note
1880 which instructions have associated line number entries. */
1881 linenumber_pointer = linenumber_table;
1882 for (i = 0; i < linenumber_count; i++)
1883 {
1884 int pc = GET_u2 (linenumber_pointer);
1885 linenumber_pointer += 4;
1886 if (pc >= length)
1887 warning ("invalid PC in line number table");
1888 else
1889 {
1890 if ((instruction_bits[pc] & BCODE_HAS_LINENUMBER) != 0)
1891 instruction_bits[pc] |= BCODE_HAS_MULTI_LINENUMBERS;
1892 instruction_bits[pc] |= BCODE_HAS_LINENUMBER;
1893 }
1894 }
1895
1896 /* Do a preliminary pass.
1897 * This figures out which PC can be the targets of jumps. */
1898 for (PC = 0; PC < length;)
1899 {
1900 int oldpc = PC; /* PC at instruction start. */
1901 instruction_bits [PC] |= BCODE_INSTRUCTION_START;
1902 switch (byte_ops[PC++])
1903 {
1904#define JAVAOP(OPNAME, OPCODE, OPKIND, OPERAND_TYPE, OPERAND_VALUE) \
1905 case OPCODE: \
1906 PRE_##OPKIND(OPERAND_TYPE, OPERAND_VALUE); \
1907 break;
1908
1909#define NOTE_LABEL(PC) note_label(oldpc, PC)
1910
1911#define PRE_PUSHC(OPERAND_TYPE, OPERAND_VALUE) (void)(OPERAND_VALUE);
1912#define PRE_LOAD(OPERAND_TYPE, OPERAND_VALUE) (void)(OPERAND_VALUE);
1913#define PRE_STORE(OPERAND_TYPE, OPERAND_VALUE) (void)(OPERAND_VALUE);
1914#define PRE_STACK(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1915#define PRE_UNOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1916#define PRE_BINOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1917#define PRE_CONVERT(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1918#define PRE_CONVERT2(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1919
1920#define PRE_SPECIAL(OPERAND_TYPE, INSTRUCTION) \
1921 PRE_SPECIAL_##INSTRUCTION(OPERAND_TYPE)
1922#define PRE_SPECIAL_IINC(OPERAND_TYPE) \
1923 ((void) IMMEDIATE_u1, (void) IMMEDIATE_s1)
1924#define PRE_SPECIAL_ENTER(IGNORE) /* nothing */
1925#define PRE_SPECIAL_EXIT(IGNORE) /* nothing */
1926#define PRE_SPECIAL_THROW(IGNORE) /* nothing */
1927#define PRE_SPECIAL_BREAK(IGNORE) /* nothing */
1928
1929/* two forms of wide instructions */
1930#define PRE_SPECIAL_WIDE(IGNORE) \
1931 { \
1932 int modified_opcode = IMMEDIATE_u1; \
1933 if (modified_opcode == OPCODE_iinc) \
1934 { \
1935 (void) IMMEDIATE_u2; /* indexbyte1 and indexbyte2 */ \
1936 (void) IMMEDIATE_s2; /* constbyte1 and constbyte2 */ \
1937 } \
1938 else \
1939 { \
1940 (void) IMMEDIATE_u2; /* indexbyte1 and indexbyte2 */ \
1941 } \
1942 }
1943
1944/* nothing */ /* XXX JH */
1945
1946#define PRE_IMPL(IGNORE1, IGNORE2) /* nothing */
1947
1948#define PRE_MONITOR(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1949
1950#define PRE_RETURN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1951#define PRE_ARRAY(OPERAND_TYPE, SUBOP) \
1952 PRE_ARRAY_##SUBOP(OPERAND_TYPE)
1953#define PRE_ARRAY_LOAD(TYPE) /* nothing */
1954#define PRE_ARRAY_STORE(TYPE) /* nothing */
1955#define PRE_ARRAY_LENGTH(TYPE) /* nothing */
1956#define PRE_ARRAY_NEW(TYPE) PRE_ARRAY_NEW_##TYPE
1957#define PRE_ARRAY_NEW_NUM ((void) IMMEDIATE_u1)
1958#define PRE_ARRAY_NEW_PTR ((void) IMMEDIATE_u2)
1959#define PRE_ARRAY_NEW_MULTI ((void) IMMEDIATE_u2, (void) IMMEDIATE_u1)
1960
1961#define PRE_TEST(OPERAND_TYPE, OPERAND_VALUE) NOTE_LABEL (oldpc+IMMEDIATE_s2)
1962#define PRE_COND(OPERAND_TYPE, OPERAND_VALUE) NOTE_LABEL (oldpc+IMMEDIATE_s2)
1963#define PRE_BRANCH(OPERAND_TYPE, OPERAND_VALUE) \
1964 saw_index = 0; INT_temp = (OPERAND_VALUE); \
1965 if (!saw_index) NOTE_LABEL(oldpc + INT_temp);
1966#define PRE_JSR(OPERAND_TYPE, OPERAND_VALUE) \
1967 saw_index = 0; INT_temp = (OPERAND_VALUE); \
1968 if (!saw_index) NOTE_LABEL(oldpc + INT_temp);
1969
1970#define PRE_RET(OPERAND_TYPE, OPERAND_VALUE) (void)(OPERAND_VALUE)
1971
1972#define PRE_SWITCH(OPERAND_TYPE, TABLE_OR_LOOKUP) \
1973 PC = (PC + 3) / 4 * 4; PRE_##TABLE_OR_LOOKUP##_SWITCH
1974
1975#define PRE_LOOKUP_SWITCH \
1976 { jint default_offset = IMMEDIATE_s4; jint npairs = IMMEDIATE_s4; \
1977 NOTE_LABEL (default_offset+oldpc); \
1978 if (npairs >= 0) \
1979 while (--npairs >= 0) { \
1980 jint match = IMMEDIATE_s4; jint offset = IMMEDIATE_s4; \
1981 NOTE_LABEL (offset+oldpc); } \
1982 }
1983
1984#define PRE_TABLE_SWITCH \
1985 { jint default_offset = IMMEDIATE_s4; \
1986 jint low = IMMEDIATE_s4; jint high = IMMEDIATE_s4; \
1987 NOTE_LABEL (default_offset+oldpc); \
1988 if (low <= high) \
1989 while (low++ <= high) { \
1990 jint offset = IMMEDIATE_s4; \
1991 NOTE_LABEL (offset+oldpc); } \
1992 }
1993
1994#define PRE_FIELD(MAYBE_STATIC, PUT_OR_GET) (void)(IMMEDIATE_u2);
1995#define PRE_OBJECT(MAYBE_STATIC, PUT_OR_GET) (void)(IMMEDIATE_u2);
1996#define PRE_INVOKE(MAYBE_STATIC, IS_INTERFACE) \
1997 (void)(IMMEDIATE_u2); \
1998 PC += 2 * IS_INTERFACE /* for invokeinterface */;
1999
2000#include "javaop.def"
2001#undef JAVAOP
2002 }
2003 } /* for */
2004
2005 if (! verify_jvm_instructions (jcf, byte_ops, length))
2006 return;
2007
2008 /* Translate bytecodes to rtl instructions. */
2009 linenumber_pointer = linenumber_table;
2010 for (PC = 0; PC < length;)
2011 {
2012 if ((instruction_bits [PC] & BCODE_TARGET) != 0 || PC == 0)
2013 {
2014 tree label = lookup_label (PC);
2015 flush_quick_stack ();
2016 if ((instruction_bits [PC] & BCODE_TARGET) != 0)
2017 expand_label (label);
2018 if (LABEL_VERIFIED (label) || PC == 0)
2019 load_type_state (label);
2020 }
2021
2022 if (! (instruction_bits [PC] & BCODE_VERIFIED))
2023 {
2024 /* never executed - skip */
2025 warning ("Some bytecode operations (starting at pc %d) can never be executed", PC);
2026 while (PC < length
2027 && ! (instruction_bits [PC] & BCODE_VERIFIED))
2028 PC++;
2029 continue;
2030 }
2031
2032
2033 /* Handle possible line number entry for this PC.
2034
2035 This code handles out-of-order and multiple linenumbers per PC,
2036 but is optimized for the case of line numbers increasing
2037 monotonically with PC. */
2038 if ((instruction_bits[PC] & BCODE_HAS_LINENUMBER) != 0)
2039 {
2040 if ((instruction_bits[PC] & BCODE_HAS_MULTI_LINENUMBERS) != 0
2041 || GET_u2 (linenumber_pointer) != PC)
2042 linenumber_pointer = linenumber_table;
2043 while (linenumber_pointer < linenumber_table + linenumber_count * 4)
2044 {
2045 int pc = GET_u2 (linenumber_pointer);
2046 linenumber_pointer += 4;
2047 if (pc == PC)
2048 {
2049 lineno = GET_u2 (linenumber_pointer - 2);
2050 emit_line_note (input_filename, lineno);
2051 if (!(instruction_bits[PC] & BCODE_HAS_MULTI_LINENUMBERS))
2052 break;
2053 }
2054 }
2055 }
2056 maybe_start_try (PC);
2057 maybe_pushlevels (PC);
2058
2059 PC = process_jvm_instruction (PC, byte_ops, length);
2060
2061 maybe_poplevels (PC);
2062 maybe_end_try (PC);
2063 } /* for */
2064}
2065
2066void
2067java_push_constant_from_pool (jcf, index)
2068 JCF *jcf;
2069 int index;
2070{
2071 tree c;
2072 if (JPOOL_TAG (jcf, index) == CONSTANT_String)
2073 {
2074 tree name;
2075 push_obstacks (&permanent_obstack, &permanent_obstack);
2076 name = get_name_constant (jcf, JPOOL_USHORT1 (jcf, index));
2077 index = alloc_name_constant (CONSTANT_String, name);
2078 c = build_ref_from_constant_pool (index);
2079 TREE_TYPE (c) = promote_type (string_type_node);
2080 pop_obstacks ();
2081 }
2082 else
2083 c = get_constant (jcf, index);
2084 push_value (c);
2085}
2086
2087int
2088process_jvm_instruction (PC, byte_ops, length)
2089 int PC;
2090 unsigned char* byte_ops;
2091 long length;
2092{
2093 char *opname; /* Temporary ??? */
2094 int oldpc = PC; /* PC at instruction start. */
e4de5a10
PB
2095
2096 /* If the instruction is at the beginning of a exception handler,
2097 replace the top of the stack with the thrown object reference */
2098 if (instruction_bits [PC] & BCODE_EXCEPTION_TARGET)
2099 {
2100 pop_value (ptr_type_node);
2101 push_value (soft_exceptioninfo_call_node);
2102 }
2103
e04a16fb
AG
2104 switch (byte_ops[PC++])
2105 {
2106#define JAVAOP(OPNAME, OPCODE, OPKIND, OPERAND_TYPE, OPERAND_VALUE) \
2107 case OPCODE: \
2108 opname = #OPNAME; \
2109 OPKIND(OPERAND_TYPE, OPERAND_VALUE); \
2110 break;
2111
2112#define RET(OPERAND_TYPE, OPERAND_VALUE) \
2113 { \
2114 int saw_index = 0; \
2115 int index = OPERAND_VALUE; \
2116 build_java_ret (find_local_variable (index, ptr_type_node, oldpc)); \
2117 }
2118
2119#define JSR(OPERAND_TYPE, OPERAND_VALUE) \
2120 { \
2121 tree where = lookup_label (oldpc+OPERAND_VALUE); \
2122 tree ret = lookup_label (PC); \
2123 build_java_jsr (where, ret); \
2124 }
2125
2126/* Push a constant onto the stack. */
2127#define PUSHC(OPERAND_TYPE, OPERAND_VALUE) \
2128 { int saw_index = 0; int ival = (OPERAND_VALUE); \
2129 if (saw_index) java_push_constant_from_pool (current_jcf, ival); \
2130 else expand_java_pushc (ival, OPERAND_TYPE##_type_node); }
2131
2132/* internal macro added for use by the WIDE case */
2133#define LOAD_INTERNAL(OPTYPE, OPVALUE) \
2134 push_value (find_local_variable (OPVALUE, type_map[OPVALUE], oldpc));
2135
2136/* Push local variable onto the opcode stack. */
2137#define LOAD(OPERAND_TYPE, OPERAND_VALUE) \
2138 { \
2139 /* have to do this since OPERAND_VALUE may have side-effects */ \
2140 int opvalue = OPERAND_VALUE; \
2141 LOAD_INTERNAL(OPERAND_TYPE##_type_node, opvalue); \
2142 }
2143
2144#define RETURN(OPERAND_TYPE, OPERAND_VALUE) \
2145 expand_java_return (OPERAND_TYPE##_type_node)
2146
2147#define REM_EXPR TRUNC_MOD_EXPR
2148#define BINOP(OPERAND_TYPE, OPERAND_VALUE) \
2149 expand_java_binop (OPERAND_TYPE##_type_node, OPERAND_VALUE##_EXPR)
2150
2151#define FIELD(IS_STATIC, IS_PUT) \
2152 expand_java_field_op (IS_STATIC, IS_PUT, IMMEDIATE_u2)
2153
2154#define TEST(OPERAND_TYPE, CONDITION) \
2155 expand_test (CONDITION##_EXPR, OPERAND_TYPE##_type_node, oldpc+IMMEDIATE_s2)
2156
2157#define COND(OPERAND_TYPE, CONDITION) \
2158 expand_cond (CONDITION##_EXPR, OPERAND_TYPE##_type_node, oldpc+IMMEDIATE_s2)
2159
2160#define BRANCH(OPERAND_TYPE, OPERAND_VALUE) \
2161 BRANCH_##OPERAND_TYPE (OPERAND_VALUE)
2162
2163#define BRANCH_GOTO(OPERAND_VALUE) \
2164 expand_java_goto (oldpc + OPERAND_VALUE)
2165
2166#define BRANCH_CALL(OPERAND_VALUE) \
2167 expand_java_call (oldpc + OPERAND_VALUE, oldpc)
2168
2169#if 0
2170#define BRANCH_RETURN(OPERAND_VALUE) \
2171 { \
2172 tree type = OPERAND_TYPE##_type_node; \
2173 tree value = find_local_variable (OPERAND_VALUE, type, oldpc); \
2174 expand_java_ret (value); \
2175 }
2176#endif
2177
2178#define NOT_IMPL(OPERAND_TYPE, OPERAND_VALUE) \
2179 fprintf (stderr, "%3d: %s ", oldpc, opname); \
2180 fprintf (stderr, "(not implemented)\n")
2181#define NOT_IMPL1(OPERAND_VALUE) \
2182 fprintf (stderr, "%3d: %s ", oldpc, opname); \
2183 fprintf (stderr, "(not implemented)\n")
2184
2185#define BRANCH_RETURN(OPERAND_VALUE) NOT_IMPL1(OPERAND_VALUE)
2186
2187#define STACK(SUBOP, COUNT) STACK_##SUBOP (COUNT)
2188
2189#define STACK_POP(COUNT) java_stack_pop (COUNT)
2190
2191#define STACK_SWAP(COUNT) java_stack_swap()
2192
2193#define STACK_DUP(COUNT) java_stack_dup (COUNT, 0)
2194#define STACK_DUPx1(COUNT) java_stack_dup (COUNT, 1)
2195#define STACK_DUPx2(COUNT) java_stack_dup (COUNT, 2)
2196
2197#define SWITCH(OPERAND_TYPE, TABLE_OR_LOOKUP) \
2198 PC = (PC + 3) / 4 * 4; TABLE_OR_LOOKUP##_SWITCH
2199
2200#define LOOKUP_SWITCH \
2201 { jint default_offset = IMMEDIATE_s4; jint npairs = IMMEDIATE_s4; \
2202 tree selector = pop_value (INT_type_node); \
2203 tree duplicate, label; \
2204 tree type = TREE_TYPE (selector); \
2205 flush_quick_stack (); \
2206 expand_start_case (0, selector, type, "switch statement");\
2207 push_momentary (); \
2208 while (--npairs >= 0) \
2209 { \
2210 jint match = IMMEDIATE_s4; jint offset = IMMEDIATE_s4; \
2211 tree value = build_int_2 (match, match < 0 ? -1 : 0); \
2212 TREE_TYPE (value) = type; \
2213 label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); \
2214 pushcase (value, convert, label, &duplicate); \
2215 expand_java_goto (oldpc + offset); \
2216 } \
2217 label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); \
2218 pushcase (NULL_TREE, 0, label, &duplicate); \
2219 expand_java_goto (oldpc + default_offset); \
2220 pop_momentary (); \
2221 expand_end_case (selector); \
2222 }
2223
2224#define TABLE_SWITCH \
2225 { jint default_offset = IMMEDIATE_s4; \
2226 jint low = IMMEDIATE_s4; jint high = IMMEDIATE_s4; \
2227 tree selector = pop_value (INT_type_node); \
2228 tree duplicate, label; \
2229 tree type = TREE_TYPE (selector); \
2230 flush_quick_stack (); \
2231 expand_start_case (0, selector, type, "switch statement");\
2232 push_momentary (); \
2233 for (; low <= high; low++) \
2234 { \
2235 jint offset = IMMEDIATE_s4; \
2236 tree value = build_int_2 (low, low < 0 ? -1 : 0); \
2237 TREE_TYPE (value) = type; \
2238 label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); \
2239 pushcase (value, convert, label, &duplicate); \
2240 expand_java_goto (oldpc + offset); \
2241 } \
2242 label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); \
2243 pushcase (NULL_TREE, 0, label, &duplicate); \
2244 expand_java_goto (oldpc + default_offset); \
2245 pop_momentary (); \
2246 expand_end_case (selector); \
2247 }
2248
2249#define INVOKE(MAYBE_STATIC, IS_INTERFACE) \
2250 { int opcode = byte_ops[PC-1]; \
2251 int method_ref_index = IMMEDIATE_u2; \
2252 int nargs; \
2253 if (IS_INTERFACE) { nargs = IMMEDIATE_u1; (void) IMMEDIATE_u1; } \
2254 else nargs = -1; \
2255 expand_invoke (opcode, method_ref_index, nargs); \
2256 }
2257
2258/* Handle new, checkcast, instanceof */
2259#define OBJECT(TYPE, OP) \
2260 expand_java_##OP (get_class_constant (current_jcf, IMMEDIATE_u2))
2261
2262#define ARRAY(OPERAND_TYPE, SUBOP) ARRAY_##SUBOP(OPERAND_TYPE)
2263
2264#define ARRAY_LOAD(OPERAND_TYPE) \
2265 { \
2266 expand_java_arrayload( OPERAND_TYPE##_type_node ); \
2267 }
2268
2269#define ARRAY_STORE(OPERAND_TYPE) \
2270 { \
2271 expand_java_arraystore( OPERAND_TYPE##_type_node ); \
2272 }
2273
2274#define ARRAY_LENGTH(OPERAND_TYPE) expand_java_array_length();
2275#define ARRAY_NEW(OPERAND_TYPE) ARRAY_NEW_##OPERAND_TYPE()
2276#define ARRAY_NEW_PTR() \
2277 push_value (build_anewarray (get_class_constant (current_jcf, \
2278 IMMEDIATE_u2), \
2279 pop_value (int_type_node)));
2280#define ARRAY_NEW_NUM() \
2281 { \
2282 int atype = IMMEDIATE_u1; \
2283 push_value (build_newarray (atype, pop_value (int_type_node)));\
2284 }
2285#define ARRAY_NEW_MULTI() \
2286 { \
2287 tree class = get_class_constant (current_jcf, IMMEDIATE_u2 ); \
2288 int ndims = IMMEDIATE_u1; \
2289 expand_java_multianewarray( class, ndims ); \
2290 }
2291
2292#define UNOP(OPERAND_TYPE, OPERAND_VALUE) \
2293 push_value (fold (build1 (NEGATE_EXPR, OPERAND_TYPE##_type_node, \
2294 pop_value (OPERAND_TYPE##_type_node))));
2295
2296#define CONVERT2(FROM_TYPE, TO_TYPE) \
2297 { \
2298 push_value (build1 (NOP_EXPR, int_type_node, \
2299 (convert (TO_TYPE##_type_node, \
2300 pop_value (FROM_TYPE##_type_node))))); \
2301 }
2302
2303#define CONVERT(FROM_TYPE, TO_TYPE) \
2304 { \
2305 push_value (convert (TO_TYPE##_type_node, \
2306 pop_value (FROM_TYPE##_type_node))); \
2307 }
2308
2309/* internal macro added for use by the WIDE case
2310 Added TREE_TYPE (decl) assignment, apbianco */
2311#define STORE_INTERNAL(OPTYPE, OPVALUE) \
2312 { \
2313 tree decl, value; \
2314 int var = OPVALUE; \
2315 tree type = OPTYPE; \
2316 value = pop_value (type); \
2317 type = TREE_TYPE (value); \
2318 decl = find_local_variable (var, type, oldpc); \
2319 set_local_type (var, type ); \
2320 expand_assignment (decl, value, 0, 0); \
2321 }
2322
2323#define STORE(OPERAND_TYPE, OPERAND_VALUE) \
2324 { \
2325 /* have to do this since OPERAND_VALUE may have side-effects */ \
2326 int opvalue = OPERAND_VALUE; \
2327 STORE_INTERNAL(OPERAND_TYPE##_type_node, opvalue); \
2328 }
2329
2330#define SPECIAL(OPERAND_TYPE, INSTRUCTION) \
2331 SPECIAL_##INSTRUCTION(OPERAND_TYPE)
2332
2333#define SPECIAL_ENTER(IGNORED) MONITOR_OPERATION (soft_monitorenter_node)
2334#define SPECIAL_EXIT(IGNORED) MONITOR_OPERATION (soft_monitorexit_node)
2335
2336#define MONITOR_OPERATION(call) \
2337 { \
2338 tree o = pop_value (ptr_type_node); \
2339 tree c; \
2340 flush_quick_stack (); \
2341 c = build_java_monitor (call, o); \
2342 TREE_SIDE_EFFECTS (c) = 1; \
2343 expand_expr_stmt (c); \
2344 }
2345
2346#define SPECIAL_IINC(IGNORED) \
2347 { \
2348 unsigned int local_var_index = IMMEDIATE_u1; \
2349 int ival = IMMEDIATE_s1; \
2350 expand_iinc(local_var_index, ival, oldpc); \
2351 }
2352
2353#define SPECIAL_WIDE(IGNORED) \
2354 { \
2355 int modified_opcode = IMMEDIATE_u1; \
2356 unsigned int local_var_index = IMMEDIATE_u2; \
2357 switch (modified_opcode) \
2358 { \
2359 case OPCODE_iinc: \
2360 { \
2361 int ival = IMMEDIATE_s2; \
2362 expand_iinc (local_var_index, ival, oldpc); \
2363 break; \
2364 } \
2365 case OPCODE_iload: \
2366 case OPCODE_lload: \
2367 case OPCODE_fload: \
2368 case OPCODE_dload: \
2369 case OPCODE_aload: \
2370 { \
2371 /* duplicate code from LOAD macro */ \
2372 LOAD_INTERNAL(operand_type[modified_opcode], local_var_index); \
2373 break; \
2374 } \
2375 case OPCODE_istore: \
2376 case OPCODE_lstore: \
2377 case OPCODE_fstore: \
2378 case OPCODE_dstore: \
2379 case OPCODE_astore: \
2380 { \
2381 STORE_INTERNAL(operand_type[modified_opcode], local_var_index); \
2382 break; \
2383 } \
2384 default: \
2385 error ("unrecogized wide sub-instruction"); \
2386 } \
2387 }
2388
2389#define SPECIAL_THROW(IGNORED) \
2390 build_java_athrow (pop_value (throwable_type_node))
2391
2392#define SPECIAL_BREAK NOT_IMPL1
2393#define IMPL NOT_IMPL
2394
2395#include "javaop.def"
2396#undef JAVAOP
2397 default:
2398 fprintf (stderr, "%3d: unknown(%3d)\n", oldpc, byte_ops[PC]);
2399 }
2400 return PC;
2401}
This page took 0.309345 seconds and 5 git commands to generate.