1 /* Process expressions for the GNU compiler for the Java(TM) language.
2 Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
4 This file is part of GNU CC.
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
21 Java and all Java-based marks are trademarks or registered trademarks
22 of Sun Microsystems, Inc. in the United States and other countries.
23 The Free Software Foundation is independent of Sun Microsystems, Inc. */
25 /* Hacked by Per Bothner <bothner@cygnus.com> February 1996. */
33 #include "java-tree.h"
35 #include "java-opcodes.h"
37 #include "java-except.h"
41 static tree operand_type[59];
42 extern struct obstack permanent_obstack;
45 init_expr_processing()
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;
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.
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.
81 tree quick_stack = NULL_TREE;
83 /* A free-list of unused permamnet TREE_LIST nodes. */
84 tree tree_list_free_list = NULL_TREE;
86 /* The stack pointer of the Java virtual machine.
87 This does include the size of the quick_stack. */
91 unsigned char *linenumber_table;
95 truthvalue_conversion (expr)
98 /* It is simpler and generates better code to have only TRUTH_*_EXPR
99 or comparison expressions as truth values at this level.
101 This function should normally be identity for Java. */
103 switch (TREE_CODE (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:
115 return integer_zerop (expr) ? boolean_false_node : boolean_true_node;
118 return real_zerop (expr) ? boolean_false_node : boolean_true_node;
120 /* are these legal? XXX JH */
125 /* These don't change whether an object is non-zero or zero. */
126 return truthvalue_conversion (TREE_OPERAND (expr, 0));
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))));
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 */
142 return fold (build (NE_EXPR, boolean_type_node, expr, boolean_false_node));
146 #ifdef JAVA_USE_HANDLES
147 /* Given a pointer to a handle, get a pointer to an object. */
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);
162 /* Save any stack slots that happen to be in the quick_stack into their
163 home virtual register slots.
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. */
172 int stack_index = stack_pointer;
173 register tree prev, cur, next;
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)
178 next = TREE_CHAIN (cur);
179 TREE_CHAIN (cur) = prev;
181 stack_index -= 1 + TYPE_IS_WIDE (TREE_TYPE (TREE_VALUE (cur)));
185 while (quick_stack != NULL_TREE)
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);
195 decl = find_stack_slot (stack_index, type);
197 expand_assignment (decl, node, 0, 0);
198 stack_index += 1 + TYPE_IS_WIDE (type);
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;
213 while (--n_words >= 0)
214 stack_type_map[stack_pointer++] = TYPE_SECOND;
221 tree type = TREE_TYPE (value);
222 if (TYPE_PRECISION (type) < 32 && INTEGRAL_TYPE_P (type))
224 type = promote_type (type);
225 value = convert (type, value);
228 if (tree_list_free_list == NULL_TREE)
229 quick_stack = perm_tree_cons (NULL_TREE, value, quick_stack);
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;
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)
254 if (stack_type_map[--stack_pointer] != void_type_node)
255 fatal ("Invalid multi-word value on type stack");
257 t = stack_type_map[--stack_pointer];
258 if (type == NULL_TREE || t == type)
260 if (INTEGRAL_TYPE_P (type) && INTEGRAL_TYPE_P (t)
261 && TYPE_PRECISION (type) <= 32 && TYPE_PRECISION (t) <= 32)
263 if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (t) == POINTER_TYPE)
265 if (type == ptr_type_node || type == object_ptr_type_node)
267 else if (t == ptr_type_node) /* Special case for null reference. */
269 else if (can_widen_reference_to (t, type))
271 /* This is a kludge, but matches what Sun's verifier does.
272 It can be tricked, but is safe as long as type errors
273 (i.e. interface method calls) are caught at run-time. */
274 else if (CLASS_INTERFACE (TYPE_NAME (TREE_TYPE (type)))
275 && t == object_ptr_type_node)
278 error ("unexpected type on stack");
282 /* Return 1f if SOURCE_TYPE can be safely widened to TARGET_TYPE.
283 Handles array types and interfaces. */
286 can_widen_reference_to (source_type, target_type)
287 tree source_type, target_type;
289 if (source_type == ptr_type_node || target_type == object_ptr_type_node)
292 /* Get rid of pointers */
293 if (TREE_CODE (source_type) == POINTER_TYPE)
294 source_type = TREE_TYPE (source_type);
295 if (TREE_CODE (target_type) == POINTER_TYPE)
296 target_type = TREE_TYPE (target_type);
298 if (source_type == target_type)
302 source_type = HANDLE_TO_CLASS_TYPE (source_type);
303 target_type = HANDLE_TO_CLASS_TYPE (target_type);
304 if (TYPE_ARRAY_P (source_type) || TYPE_ARRAY_P (target_type))
306 HOST_WIDE_INT source_length, target_length;
307 if (TYPE_ARRAY_P (source_type) != TYPE_ARRAY_P (target_type))
309 target_length = java_array_type_length (target_type);
310 if (target_length >= 0)
312 source_length = java_array_type_length (source_type);
313 if (source_length != target_length)
316 source_type = TYPE_ARRAY_ELEMENT (source_type);
317 target_type = TYPE_ARRAY_ELEMENT (target_type);
318 if (source_type == target_type)
320 if (TREE_CODE (source_type) != POINTER_TYPE
321 || TREE_CODE (target_type) != POINTER_TYPE)
323 return can_widen_reference_to (source_type, target_type);
327 int source_depth = class_depth (source_type);
328 int target_depth = class_depth (target_type);
330 if (CLASS_INTERFACE (TYPE_NAME (target_type)))
332 /* target_type is OK if source_type or source_type ancestors
333 implement target_type. We handle multiple sub-interfaces */
335 tree basetype_vec = TYPE_BINFO_BASETYPES (source_type);
336 int n = TREE_VEC_LENGTH (basetype_vec), i;
337 for (i=0 ; i < n; i++)
338 if (can_widen_reference_to
339 (TREE_TYPE (TREE_VEC_ELT (basetype_vec, i)),
346 for ( ; source_depth > target_depth; source_depth--)
348 source_type = TYPE_BINFO_BASETYPE (source_type, 0);
350 return source_type == target_type;
359 int n_words = 1 + TYPE_IS_WIDE (type);
361 type = pop_type (type);
364 tree node = quick_stack;
365 quick_stack = TREE_CHAIN (quick_stack);
366 TREE_CHAIN (node) = tree_list_free_list;
367 tree_list_free_list = node;
368 node = TREE_VALUE (node);
372 return find_stack_slot (stack_pointer, promote_type (type));
376 /* Pop and discrad the top COUNT stack slots. */
379 java_stack_pop (count)
385 if (stack_pointer == 0)
386 fatal ("stack underflow");
387 type = stack_type_map[stack_pointer - 1];
388 if (type == TYPE_SECOND)
391 if (stack_pointer == 1 || count <= 0)
392 fatal ("stack underflow");
393 type = stack_type_map[stack_pointer - 2];
395 val = pop_value (type);
400 /* Implement the 'swap' operator (to swap two top stack slots). */
409 if (stack_pointer < 2
410 || (type1 = stack_type_map[stack_pointer - 1]) == TYPE_UNKNOWN
411 || (type2 = stack_type_map[stack_pointer - 2]) == TYPE_UNKNOWN
412 || type1 == TYPE_SECOND || type2 == TYPE_SECOND
413 || TYPE_IS_WIDE (type1) || TYPE_IS_WIDE (type2))
414 fatal ("bad stack swap");
416 flush_quick_stack ();
417 decl1 = find_stack_slot (stack_pointer - 1, type1);
418 decl2 = find_stack_slot (stack_pointer - 2, type2);
419 temp = copy_to_reg (DECL_RTL (decl1));
420 emit_move_insn (DECL_RTL (decl1), DECL_RTL (decl2));
421 emit_move_insn (DECL_RTL (decl2), temp);
422 stack_type_map[stack_pointer - 1] = type2;
423 stack_type_map[stack_pointer - 2] = type1;
427 java_stack_dup (size, offset)
430 int low_index = stack_pointer - size - offset;
433 error ("stack underflow - dup* operation");
435 flush_quick_stack ();
437 stack_pointer += size;
438 dst_index = stack_pointer;
440 for (dst_index = stack_pointer; --dst_index >= low_index; )
443 int src_index = dst_index - size;
444 if (src_index < low_index)
445 src_index = dst_index + size + offset;
446 type = stack_type_map [src_index];
447 if (type == TYPE_SECOND)
449 if (src_index <= low_index)
450 fatal ("dup operation splits 64-bit number");
451 stack_type_map[dst_index] = type;
452 src_index--; dst_index--;
453 type = stack_type_map[src_index];
454 if (! TYPE_IS_WIDE (type))
455 fatal ("internal error - dup operation");
457 else if (TYPE_IS_WIDE (type))
458 fatal ("internal error - dup operation");
459 if (src_index != dst_index)
461 tree src_decl = find_stack_slot (src_index, type);
462 tree dst_decl = find_stack_slot (dst_index, type);
463 emit_move_insn (DECL_RTL (dst_decl), DECL_RTL (src_decl));
464 stack_type_map[dst_index] = type;
469 /* Calls _Jv_Throw. Discard the contents of the value stack. */
472 build_java_athrow (node)
477 call = build (CALL_EXPR,
479 build_address_of (throw_node),
480 build_tree_list (NULL_TREE, node),
482 TREE_SIDE_EFFECTS (call) = 1;
483 expand_expr_stmt (call);
484 java_stack_pop (stack_pointer);
487 /* Implementation for jsr/ret */
490 build_java_jsr (where, ret)
494 tree ret_label = fold (build1 (ADDR_EXPR, return_address_type_node, ret));
495 push_value (ret_label);
496 flush_quick_stack ();
502 build_java_ret (location)
505 expand_computed_goto (location);
508 /* Implementation of operations on array: new, load, store, length */
510 /* Array core info access macros */
512 #define JAVA_ARRAY_LENGTH_OFFSET(A) \
513 size_binop (CEIL_DIV_EXPR, \
515 (TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (TREE_TYPE (A)))))), \
516 size_int (BITS_PER_UNIT))
519 decode_newarray_type (int atype)
523 case 4: return boolean_type_node;
524 case 5: return char_type_node;
525 case 6: return float_type_node;
526 case 7: return double_type_node;
527 case 8: return byte_type_node;
528 case 9: return short_type_node;
529 case 10: return int_type_node;
530 case 11: return long_type_node;
531 default: return NULL_TREE;
535 /* Build a call to _Jv_ThrowBadArrayIndex(), the
536 ArrayIndexOfBoundsException exception handler. */
539 build_java_throw_out_of_bounds_exception (index)
542 tree node = build (CALL_EXPR, int_type_node,
543 build_address_of (soft_badarrayindex_node),
544 build_tree_list (NULL_TREE, index), NULL_TREE);
545 TREE_SIDE_EFFECTS (node) = 1; /* Allows expansion within ANDIF */
549 /* Return the length of an array. Doesn't perform any checking on the nature
550 or value of the array NODE. May be used to implement some bytecodes. */
553 build_java_array_length_access (node)
556 tree type = TREE_TYPE (node);
557 HOST_WIDE_INT length;
558 if (!is_array_type_p (type))
559 fatal ("array length on a non-array reference");
560 length = java_array_type_length (type);
562 return build_int_2 (length, 0);
563 return fold (build1 (INDIRECT_REF,
565 fold (build (PLUS_EXPR, ptr_type_node,
567 JAVA_ARRAY_LENGTH_OFFSET(node)))));
570 /* Optionally checks an array against the NULL pointer, eventually throwing a
571 NullPointerException. It could replace signal handling, but tied to NULL.
572 ARG1: the pointer to check, ARG2: the expression to use if
573 the pointer is non-null and ARG3 the type that should be returned. */
576 build_java_arraynull_check (node, expr, type)
582 static int java_array_access_throws_null_exception = 0;
584 if (java_array_access_throws_null_exception)
585 return (build (COND_EXPR,
587 build (EQ_EXPR, int_type_node, node, null_pointer_node),
588 build_java_athrow (node), expr ));
595 java_array_data_offset (array)
598 tree array_type = TREE_TYPE (TREE_TYPE (array));
599 tree data_fld = TREE_CHAIN (TREE_CHAIN (TYPE_FIELDS (array_type)));
600 if (data_fld == NULL_TREE)
601 return size_in_bytes (array_type);
603 return build_int_2 (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (data_fld))
607 /* Implement array indexing (either as l-value or r-value).
608 Returns a tree for ARRAY[INDEX], assume TYPE is the element type.
609 Optionally performs bounds checking and/or test to NULL.
610 At this point, ARRAY should have been verified as an array. */
613 build_java_arrayaccess (array, type, index)
614 tree array, type, index;
616 tree arith, node, throw = NULL_TREE;
618 arith = fold (build (PLUS_EXPR, int_type_node,
619 java_array_data_offset (array),
620 fold (build (MULT_EXPR, int_type_node,
621 index, size_in_bytes(type)))));
623 if (flag_bounds_check)
626 * (unsigned jint) INDEX >= (unsigned jint) LEN
627 * && throw ArrayIndexOutOfBoundsException.
628 * Note this is equivalent to and more efficient than:
629 * INDEX < 0 || INDEX >= LEN && throw ... */
631 tree len = build_java_array_length_access (array);
632 TREE_TYPE (len) = unsigned_int_type_node;
633 test = fold (build (GE_EXPR, boolean_type_node,
634 convert (unsigned_int_type_node, index),
636 if (! integer_zerop (test))
638 throw = build (TRUTH_ANDIF_EXPR, int_type_node, test,
639 build_java_throw_out_of_bounds_exception (index));
640 /* allows expansion within COMPOUND */
641 TREE_SIDE_EFFECTS( throw ) = 1;
645 node = build1 (INDIRECT_REF, type,
646 fold (build (PLUS_EXPR, ptr_type_node,
648 (throw ? build (COMPOUND_EXPR, int_type_node,
652 return (fold (build_java_arraynull_check (array, node, type)));
655 /* Makes sure that INDEXED_TYPE is appropriate. If not, make it from
656 ARRAY_NODE. This function is used to retrieve something less vague than
657 a pointer type when indexing the first dimension of something like [[<t>.
658 May return a corrected type, if necessary, otherwise INDEXED_TYPE is
660 As a side effect, it also makes sure that ARRAY_NODE is an array. */
663 build_java_check_indexed_type (array_node, indexed_type)
669 if (!is_array_type_p (TREE_TYPE (array_node)))
670 fatal ("array indexing on a non-array reference");
672 elt_type = (TYPE_ARRAY_ELEMENT (TREE_TYPE (TREE_TYPE (array_node))));
674 if (indexed_type == ptr_type_node )
675 return promote_type (elt_type);
677 /* BYTE/BOOLEAN store and load are used for both type */
678 if (indexed_type == byte_type_node && elt_type == boolean_type_node )
679 return boolean_type_node;
681 if (indexed_type != elt_type )
682 fatal ("type array element mismatch");
687 /* newarray triggers a call to _Jv_NewArray. This function should be called
688 with an integer code (the type of array to create) and get from the stack
689 the size of the dimmension. */
692 build_newarray (atype_value, length)
696 tree type = build_java_array_type (decode_newarray_type (atype_value),
697 TREE_CODE (length) == INTEGER_CST
698 ? TREE_INT_CST_LOW (length)
700 return build (CALL_EXPR, promote_type (type),
701 build_address_of (soft_newarray_node),
702 tree_cons (NULL_TREE,
703 build_int_2 (atype_value, 0),
704 build_tree_list (NULL_TREE, length)),
708 /* Generates anewarray from a given CLASS_TYPE. Gets from the stack the size
710 /* Merge with build_newarray. FIXME. */
712 build_anewarray (class_type, length)
716 tree type = build_java_array_type (class_type,
717 TREE_CODE (length) == INTEGER_CST
718 ? TREE_INT_CST_LOW (length)
720 return build (CALL_EXPR, promote_type (type),
721 build_address_of (soft_anewarray_node),
722 tree_cons (NULL_TREE, length,
723 tree_cons (NULL_TREE, build_class_ref (class_type),
724 build_tree_list (NULL_TREE,
725 null_pointer_node))),
729 /* Generates a call to _Jv_NewMultiArray. multianewarray expects a
730 class pointer, a number of dimensions and the matching number of
731 dimensions. The argument list is NULL terminated. */
734 expand_java_multianewarray (class_type, ndim)
739 tree args = build_tree_list( NULL_TREE, null_pointer_node );
741 for( i = 0; i < ndim; i++ )
742 args = tree_cons (NULL_TREE, pop_value (int_type_node), args);
744 push_value (build (CALL_EXPR,
745 promote_type (class_type),
746 build_address_of (soft_multianewarray_node),
747 tree_cons (NULL_TREE, build_class_ref (class_type),
748 tree_cons (NULL_TREE,
749 build_int_2 (ndim, 0), args )),
753 /* ARRAY[INDEX] <- RHS. build_java_check_indexed_type makes sure that
754 ARRAY is an array type. May expand some bound checking and NULL
755 pointer checking. RHS_TYPE_NODE we are going to store. In the case
756 of the CHAR/BYTE/BOOLEAN SHORT, the type popped of the stack is an
757 INT. In those cases, we make the convertion.
759 if ARRAy is a reference type, the assignment is checked at run-time
760 to make sure that the RHS can be assigned to the array element
761 type. It is not necessary to generate this code if ARRAY is final. */
764 expand_java_arraystore (rhs_type_node)
767 tree rhs_node = pop_value ((INTEGRAL_TYPE_P (rhs_type_node)
768 && TYPE_PRECISION (rhs_type_node) <= 32) ?
769 int_type_node : rhs_type_node);
770 tree index = pop_value (int_type_node);
771 tree array = pop_value (ptr_type_node);
773 rhs_type_node = build_java_check_indexed_type (array, rhs_type_node);
775 flush_quick_stack ();
777 index = save_expr (index);
778 array = save_expr (array);
780 if (TREE_CODE (rhs_type_node) == POINTER_TYPE
781 && !CLASS_FINAL (TYPE_NAME (TREE_TYPE (rhs_type_node))))
783 tree check = build (CALL_EXPR, void_type_node,
784 build_address_of (soft_checkarraystore_node),
785 tree_cons (NULL_TREE, array,
786 build_tree_list (NULL_TREE, rhs_node)),
788 TREE_SIDE_EFFECTS (check) = 1;
789 expand_expr_stmt (check);
792 expand_assignment (build_java_arrayaccess (array,
798 /* Expand the evaluation of ARRAY[INDEX]. build_java_check_indexed_type makes
799 sure that LHS is an array type. May expand some bound checking and NULL
801 LHS_TYPE_NODE is the type of ARRAY[INDEX]. But in the case of CHAR/BYTE/
802 BOOLEAN/SHORT, we push a promoted type back to the stack.
806 expand_java_arrayload (lhs_type_node )
811 tree index_node = pop_value (int_type_node);
812 tree array_node = pop_value (ptr_type_node);
814 index_node = save_expr (index_node);
815 array_node = save_expr (array_node);
816 lhs_type_node = build_java_check_indexed_type (array_node, lhs_type_node);
818 load_node = build_java_arrayaccess (array_node,
822 if (INTEGRAL_TYPE_P (lhs_type_node) && TYPE_PRECISION (lhs_type_node) <= 32)
823 load_node = fold (build1 (NOP_EXPR, int_type_node, load_node));
824 push_value (load_node);
827 /* Expands .length. Makes sure that we deal with and array and may expand
828 a NULL check on the array object. */
831 expand_java_array_length ()
833 tree array = pop_value (ptr_type_node);
834 tree length = build_java_array_length_access (array);
836 push_value (build_java_arraynull_check (array, length, int_type_node));
839 /* Emit code for the call to _Jv_Monitor{Enter,Exit}. CALL can be
840 either soft_monitorenter_node or soft_monitorexit_node. */
843 build_java_monitor (call, object)
847 return (build (CALL_EXPR,
849 build_address_of (call),
850 build_tree_list (NULL_TREE, object),
854 /* Emit code for one of the PUSHC instructions. */
857 expand_java_pushc (ival, type)
862 if (type == ptr_type_node && ival == 0)
863 value = null_pointer_node;
864 else if (type == int_type_node || type == long_type_node)
866 value = build_int_2 (ival, ival < 0 ? -1 : 0);
867 TREE_TYPE (value) = type;
869 else if (type == float_type_node || type == double_type_node)
872 #ifdef REAL_ARITHMETIC
873 REAL_VALUE_FROM_INT (x, ival, 0, TYPE_MODE (type));
877 value = build_real (type, x);
880 fatal ("internal error in expand_java_pushc");
885 expand_java_return (type)
888 if (type == void_type_node)
889 expand_null_return ();
892 tree retval = pop_value (type);
893 tree res = DECL_RESULT (current_function_decl);
894 retval = build (MODIFY_EXPR, TREE_TYPE (res), res, retval);
895 TREE_SIDE_EFFECTS (retval) = 1;
896 expand_return (retval);
901 build_address_of (value)
904 return build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (value)), value);
908 expand_java_NEW (type)
911 if (! CLASS_LOADED_P (type))
912 load_class (type, 1);
913 push_value (build (CALL_EXPR, promote_type (type),
914 build_address_of (alloc_object_node),
915 tree_cons (NULL_TREE, build_class_ref (type),
916 build_tree_list (NULL_TREE,
917 size_in_bytes (type))),
922 expand_java_INSTANCEOF (type)
925 tree value = pop_value (object_ptr_type_node);
926 value = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (soft_instanceof_node)),
927 build_address_of (soft_instanceof_node),
928 tree_cons (NULL_TREE, value,
929 build_tree_list (NULL_TREE,
930 build_class_ref (type))),
936 expand_java_CHECKCAST (type)
939 tree value = pop_value (ptr_type_node);
940 value = build (CALL_EXPR, promote_type (type),
941 build_address_of (soft_checkcast_node),
942 tree_cons (NULL_TREE, build_class_ref (type),
943 build_tree_list (NULL_TREE, value)),
949 expand_iinc (unsigned int local_var_index, int ival, int pc)
954 flush_quick_stack ();
955 local_var = find_local_variable (local_var_index, int_type_node, pc);
956 constant_value = build_int_2 (ival, ival < 0 ? -1 : 0);
957 res = fold (build (PLUS_EXPR, int_type_node, local_var, constant_value));
958 expand_assignment (local_var, res, 0, 0);
962 build_java_binop (op, type, arg1, arg2)
964 tree type, arg1, arg2;
971 tree u_type = unsigned_type (type);
972 arg1 = convert (u_type, arg1);
973 arg1 = build_java_binop (RSHIFT_EXPR, u_type, arg1, arg2);
974 return convert (type, arg1);
978 mask = build_int_2 (TYPE_PRECISION (TREE_TYPE (arg1)) - 1, 0);
979 arg2 = fold (build (BIT_AND_EXPR, int_type_node, arg2, mask));
982 case COMPARE_L_EXPR: /* arg1 > arg2 ? 1 : arg1 == arg2 ? 0 : -1 */
983 case COMPARE_G_EXPR: /* arg1 < arg2 ? -1 : arg1 == arg2 ? 0 : 1 */
984 arg1 = save_expr (arg1); arg2 = save_expr (arg2);
986 tree ifexp1 = fold ( build (op == COMPARE_L_EXPR ? GT_EXPR : LT_EXPR,
987 boolean_type_node, arg1, arg2));
988 tree ifexp2 = fold ( build (EQ_EXPR, boolean_type_node, arg1, arg2));
989 tree second_compare = fold (build (COND_EXPR, int_type_node,
990 ifexp2, integer_zero_node,
992 ? integer_negative_one_node
993 : integer_one_node));
994 return fold (build (COND_EXPR, int_type_node, ifexp1,
995 op == COMPARE_L_EXPR ? integer_one_node
996 : integer_negative_one_node,
1000 arg1 = save_expr (arg1); arg2 = save_expr (arg2);
1002 tree ifexp1 = fold ( build (LT_EXPR, boolean_type_node, arg1, arg2));
1003 tree ifexp2 = fold ( build (GT_EXPR, boolean_type_node, arg1, arg2));
1004 tree second_compare = fold ( build (COND_EXPR, int_type_node,
1005 ifexp2, integer_one_node,
1006 integer_zero_node));
1007 return fold (build (COND_EXPR, int_type_node,
1008 ifexp1, integer_negative_one_node, second_compare));
1011 case TRUNC_MOD_EXPR:
1012 if (TREE_CODE (type) == REAL_TYPE)
1015 if (type != double_type_node)
1017 arg1 = convert (double_type_node, arg1);
1018 arg2 = convert (double_type_node, arg2);
1020 call = build (CALL_EXPR, double_type_node,
1021 build_address_of (soft_fmod_node),
1022 tree_cons (NULL_TREE, arg1,
1023 build_tree_list (NULL_TREE, arg2)),
1025 if (type != double_type_node)
1026 call = convert (type, call);
1031 #if 0 /* not required */
1035 case TRUNC_DIV_EXPR:
1037 /* case REM_EXPR: */
1043 error ("unknown opcode");
1044 return error_mark_node;
1048 return fold (build (op, type, arg1, arg2));
1052 expand_java_binop (type, op)
1053 tree type; enum tree_code op;
1063 rtype = int_type_node;
1064 rarg = pop_value (rtype);
1067 rarg = pop_value (rtype);
1069 larg = pop_value (ltype);
1070 push_value (build_java_binop (op, type, larg, rarg));
1073 /* Lookup the field named NAME in *TYPEP or its super classes.
1074 If not found, return NULL_TREE.
1075 (If the *TYPEP is not found, return error_mark_node.)
1076 If found, return the FIELD_DECL, and set *TYPEP to the
1077 class containing the field. */
1080 lookup_field (typep, name)
1084 if (CLASS_P (*typep) && !CLASS_LOADED_P (*typep))
1086 load_class (*typep, 1);
1087 if (TREE_CODE (TYPE_SIZE (*typep)) == ERROR_MARK)
1088 return error_mark_node;
1093 for (field = TYPE_FIELDS (*typep); field; field = TREE_CHAIN (field))
1095 if (DECL_NAME (field) == name)
1098 *typep = CLASSTYPE_SUPER (*typep);
1103 /* Look up the field named NAME in object SELF_VALUE,
1104 which has class SELF_CLASS (a non-handle RECORD_TYPE).
1105 SELF_VALUE is NULL_TREE if looking for a static field. */
1108 build_field_ref (self_value, self_class, name)
1109 tree self_value, self_class, name;
1111 tree base_class = self_class;
1112 tree field_decl = lookup_field (&base_class, name);
1113 if (field_decl == NULL_TREE)
1115 error ("field `%s' not found", IDENTIFIER_POINTER (name));
1116 return error_mark_node;
1118 if (self_value == NULL_TREE)
1120 return build_static_field_ref (field_decl);
1124 tree base_handle_type = promote_type (base_class);
1125 if (base_handle_type != TREE_TYPE (self_value))
1126 self_value = fold (build1 (NOP_EXPR, base_handle_type, self_value));
1127 #ifdef JAVA_USE_HANDLES
1128 self_value = unhand_expr (self_value);
1130 self_value = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (self_value)),
1132 return fold (build (COMPONENT_REF, TREE_TYPE (field_decl),
1133 self_value, field_decl));
1143 sprintf (buf, "LJpc=%d", pc);
1144 name = get_identifier (buf);
1145 if (IDENTIFIER_LOCAL_VALUE (name))
1146 return IDENTIFIER_LOCAL_VALUE (name);
1149 /* The type of the address of a label is return_address_type_node. */
1150 tree decl = create_label_decl (name);
1151 LABEL_PC (decl) = pc;
1153 return pushdecl (decl);
1157 /* Generate a unique name for the purpose of loops and switches
1158 labels, and try-catch-finally blocks label or temporary variables. */
1163 static int l_number = 0;
1165 sprintf (buff, "$L%d", l_number++);
1166 return get_identifier (buff);
1170 create_label_decl (name)
1174 push_obstacks (&permanent_obstack, &permanent_obstack);
1175 decl = build_decl (LABEL_DECL, name,
1176 TREE_TYPE (return_address_type_node));
1178 DECL_CONTEXT (decl) = current_function_decl;
1179 DECL_IGNORED_P (decl) = 1;
1183 /* This maps a bytecode offset (PC) to various flags. */
1184 char *instruction_bits;
1187 note_label (current_pc, target_pc)
1188 int current_pc, target_pc;
1190 lookup_label (target_pc);
1191 instruction_bits [target_pc] |= BCODE_JUMP_TARGET;
1194 /* Emit code to jump to TARGET_PC if VALUE1 CONDITION VALUE2,
1195 where CONDITION is one of one the compare operators. */
1198 expand_compare (condition, value1, value2, target_pc)
1199 enum tree_code condition;
1200 tree value1, value2;
1203 tree target = lookup_label (target_pc);
1204 tree cond = fold (build (condition, boolean_type_node, value1, value2));
1205 expand_start_cond (truthvalue_conversion (cond), 0);
1206 expand_goto (target);
1210 /* Emit code for a TEST-type opcode. */
1213 expand_test (condition, type, target_pc)
1214 enum tree_code condition;
1218 tree value1, value2;
1219 flush_quick_stack ();
1220 value1 = pop_value (type);
1221 value2 = (type == ptr_type_node) ? null_pointer_node : integer_zero_node;
1222 expand_compare (condition, value1, value2, target_pc);
1225 /* Emit code for a COND-type opcode. */
1228 expand_cond (condition, type, target_pc)
1229 enum tree_code condition;
1233 tree value1, value2;
1234 flush_quick_stack ();
1235 /* note: pop values in opposite order */
1236 value2 = pop_value (type);
1237 value1 = pop_value (type);
1238 /* Maybe should check value1 and value2 for type compatibility ??? */
1239 expand_compare (condition, value1, value2, target_pc);
1243 expand_java_goto (target_pc)
1246 tree target_label = lookup_label (target_pc);
1247 flush_quick_stack ();
1248 expand_goto (target_label);
1252 expand_java_call (target_pc, return_address)
1253 int target_pc, return_address;
1255 tree target_label = lookup_label (target_pc);
1256 tree value = build_int_2 (return_address, return_address < 0 ? -1 : 0);
1258 flush_quick_stack ();
1259 expand_goto (target_label);
1263 expand_java_ret (return_address)
1264 tree return_address;
1266 warning ("ret instruction not implemented");
1268 tree target_label = lookup_label (target_pc);
1269 flush_quick_stack ();
1270 expand_goto (target_label);
1274 /* Recursive helper function to pop argument types during verifiation. */
1277 pop_argument_types (arg_types)
1280 if (arg_types == NULL_TREE)
1282 if (TREE_CODE (arg_types) == TREE_LIST)
1284 pop_argument_types (TREE_CHAIN (arg_types));
1285 pop_type (TREE_VALUE (arg_types));
1292 pop_arguments (arg_types)
1295 if (arg_types == NULL_TREE)
1297 if (TREE_CODE (arg_types) == TREE_LIST)
1299 tree tail = pop_arguments (TREE_CHAIN (arg_types));
1300 tree type = TREE_VALUE (arg_types);
1301 tree arg = pop_value (type);
1302 #ifdef PROMOTE_PROTOTYPES
1303 if (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)
1304 && INTEGRAL_TYPE_P (type))
1305 arg = convert (integer_type_node, arg);
1307 return tree_cons (NULL_TREE, arg, tail);
1312 /* Build an expression to initialize the class CLAS.
1313 if EXPR is non-NULL, returns an expression to first call the initializer
1314 (if it is needed) and then calls EXPR. */
1317 build_class_init (clas, expr)
1321 if (inherits_from_p (current_class, clas))
1323 init = build (CALL_EXPR, void_type_node,
1324 build_address_of (soft_initclass_node),
1325 build_tree_list (NULL_TREE, build_class_ref (clas)),
1327 TREE_SIDE_EFFECTS (init) = 1;
1328 if (expr != NULL_TREE)
1330 expr = build (COMPOUND_EXPR, TREE_TYPE (expr), init, expr);
1331 TREE_SIDE_EFFECTS (expr) = 1;
1337 static tree methods_ident = NULL_TREE;
1338 static tree ncode_ident = NULL_TREE;
1339 tree dtable_ident = NULL_TREE;
1342 build_known_method_ref (method, method_type, self_type, method_signature, arg_list)
1343 tree method, method_type, self_type, method_signature, arg_list;
1346 if (is_compiled_class (self_type))
1348 make_decl_rtl (method, NULL, 1);
1349 func = build1 (ADDR_EXPR, method_ptr_type_node, method);
1353 /* We don't know whether the method has been (statically) compiled.
1354 Compile this code to get a reference to the method's code:
1356 SELF_TYPE->methods[METHOD_INDEX].ncode
1358 This is guaranteed to work (assuming SELF_TYPE has
1359 been initialized), since if the method is not compiled yet,
1360 its ncode points to a trampoline that forces compilation. */
1362 int method_index = 0;
1364 tree ref = build_class_ref (self_type);
1365 ref = build1 (INDIRECT_REF, class_type_node, ref);
1366 if (ncode_ident == NULL_TREE)
1367 ncode_ident = get_identifier ("ncode");
1368 if (methods_ident == NULL_TREE)
1369 methods_ident = get_identifier ("methods");
1370 ref = build (COMPONENT_REF, method_ptr_type_node, ref,
1371 lookup_field (&class_type_node, methods_ident));
1372 for (meth = TYPE_METHODS (CLASS_TO_HANDLE_TYPE (self_type));
1373 ; meth = TREE_CHAIN (meth))
1377 if (meth == NULL_TREE)
1378 fatal ("method '%s' not found in class",
1379 IDENTIFIER_POINTER (DECL_NAME (method)));
1382 method_index *= int_size_in_bytes (method_type_node);
1383 ref = fold (build (PLUS_EXPR, method_ptr_type_node,
1384 ref, build_int_2 (method_index, 0)));
1385 ref = build1 (INDIRECT_REF, method_type_node, ref);
1386 func = build (COMPONENT_REF, nativecode_ptr_type_node,
1388 lookup_field (&method_type_node, ncode_ident));
1394 invoke_build_dtable (is_invoke_interface, arg_list)
1395 int is_invoke_interface;
1398 tree dtable, objectref;
1400 TREE_VALUE (arg_list) = save_expr (TREE_VALUE (arg_list));
1402 /* If we're dealing with interfaces and if the objectref
1403 argument is an array then get the dispatch table of the class
1404 Object rather than the one from the objectref. */
1405 objectref = (is_invoke_interface
1406 && is_array_type_p (TREE_TYPE (TREE_VALUE (arg_list))) ?
1407 object_type_node : TREE_VALUE (arg_list));
1409 if (dtable_ident == NULL_TREE)
1410 dtable_ident = get_identifier ("dtable");
1411 dtable = build1 (INDIRECT_REF, object_type_node, objectref );
1412 dtable = build (COMPONENT_REF, dtable_ptr_type, dtable,
1413 lookup_field (&object_type_node, dtable_ident));
1419 build_invokevirtual (dtable, method)
1420 tree dtable, method;
1423 tree nativecode_ptr_ptr_type_node
1424 = build_pointer_type (nativecode_ptr_type_node);
1425 int method_index = TREE_INT_CST_LOW (DECL_VINDEX (method));
1426 /* Add one to skip "class" field of dtable, and one to skip unused
1427 vtable entry (for C++ compatibility). */
1430 *= int_size_in_bytes (nativecode_ptr_ptr_type_node);
1431 func = fold (build (PLUS_EXPR, nativecode_ptr_ptr_type_node,
1432 dtable, build_int_2 (method_index, 0)));
1433 func = build1 (INDIRECT_REF, nativecode_ptr_type_node, func);
1439 build_invokeinterface (dtable, method_name, method_signature)
1440 tree dtable, method_name, method_signature;
1442 static tree class_ident = NULL_TREE;
1445 /* We expand invokeinterface here. _Jv_LookupInterfaceMethod() will
1446 ensure that the selected method exists, is public and not
1447 abstract nor static. */
1449 if (class_ident == NULL_TREE)
1450 class_ident = get_identifier ("class");
1452 dtable = build1 (INDIRECT_REF, dtable_type, dtable);
1453 dtable = build (COMPONENT_REF, class_ptr_type, dtable,
1454 lookup_field (&dtable_type, class_ident));
1455 lookup_arg = build_tree_list (NULL_TREE, build_utf8_ref (method_signature));
1456 lookup_arg = tree_cons (NULL_TREE, dtable,
1457 tree_cons (NULL_TREE, build_utf8_ref (method_name),
1459 return build (CALL_EXPR, ptr_type_node,
1460 build_address_of (soft_lookupinterfacemethod_node),
1461 lookup_arg, NULL_TREE);
1464 /* Expand one of the invoke_* opcodes.
1465 OCPODE is the specific opcode.
1466 METHOD_REF_INDEX is an index into the constant pool.
1467 NARGS is the number of arguments, or -1 if not specified. */
1470 expand_invoke (opcode, method_ref_index, nargs)
1472 int method_ref_index;
1475 tree method_signature = COMPONENT_REF_SIGNATURE(¤t_jcf->cpool, method_ref_index);
1476 tree method_name = COMPONENT_REF_NAME (¤t_jcf->cpool, method_ref_index);
1477 tree self_type = get_class_constant
1478 (current_jcf, COMPONENT_REF_CLASS_INDEX(¤t_jcf->cpool, method_ref_index));
1479 char *self_name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (self_type)));
1480 tree call, func, method, arg_list, method_type;
1482 if (! CLASS_LOADED_P (self_type))
1484 load_class (self_type, 1);
1485 if (TREE_CODE (TYPE_SIZE (self_type)) == ERROR_MARK)
1486 fatal ("failed to find class '%s'", self_name);
1489 if (method_name == init_identifier_node)
1490 method = lookup_java_constructor (CLASS_TO_HANDLE_TYPE (self_type),
1493 method = lookup_java_method (CLASS_TO_HANDLE_TYPE (self_type),
1494 method_name, method_signature);
1495 if (method == NULL_TREE)
1497 error ("Class '%s' has no method named '%s' matching signature '%s'",
1499 IDENTIFIER_POINTER (method_name),
1500 IDENTIFIER_POINTER (method_signature));
1502 /* Invoke static can't invoke static/abstract method */
1503 else if (opcode == OPCODE_invokestatic)
1505 if (!METHOD_STATIC (method))
1507 error ("invokestatic on non static method");
1510 else if (METHOD_ABSTRACT (method))
1512 error ("invokestatic on abstract method");
1518 if (METHOD_STATIC (method))
1520 error ("invoke[non-static] on static method");
1525 if (method == NULL_TREE)
1527 method_type = get_type_from_signature (method_signature);
1528 pop_arguments (TYPE_ARG_TYPES (method_type));
1529 if (opcode != OPCODE_invokestatic)
1530 pop_type (self_type);
1531 method_type = promote_type (TREE_TYPE (method_type));
1532 push_value (convert (method_type, integer_zero_node));
1536 method_type = TREE_TYPE (method);
1537 arg_list = pop_arguments (TYPE_ARG_TYPES (method_type));
1538 flush_quick_stack ();
1541 if (opcode == OPCODE_invokestatic || opcode == OPCODE_invokespecial
1542 || (opcode == OPCODE_invokevirtual
1543 && (METHOD_FINAL (method) || CLASS_FINAL (TYPE_NAME (self_type)))))
1544 func = build_known_method_ref (method, method_type, self_type,
1545 method_signature, arg_list);
1548 tree dtable = invoke_build_dtable (opcode == OPCODE_invokeinterface,
1550 if (opcode == OPCODE_invokevirtual)
1551 func = build_invokevirtual (dtable, method);
1553 func = build_invokeinterface (dtable, method_name, method_signature);
1555 func = build1 (NOP_EXPR, build_pointer_type (method_type), func);
1556 call = build (CALL_EXPR, TREE_TYPE (method_type), func, arg_list, NULL_TREE);
1557 TREE_SIDE_EFFECTS (call) = 1;
1559 if (TREE_CODE (TREE_TYPE (method_type)) == VOID_TYPE)
1560 expand_expr_stmt (call);
1564 flush_quick_stack ();
1569 /* Expand an operation to extract from or store into a field.
1570 IS_STATIC is 1 iff the field is static.
1571 IS_PUTTING is 1 for putting into a field; 0 for getting from the field.
1572 FIELD_REF_INDEX is an index into the constant pool. */
1575 expand_java_field_op (is_static, is_putting, field_ref_index)
1578 int field_ref_index;
1580 tree self_type = get_class_constant
1581 (current_jcf, COMPONENT_REF_CLASS_INDEX (¤t_jcf->cpool, field_ref_index));
1582 char *self_name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (self_type)));
1583 tree field_name = COMPONENT_REF_NAME (¤t_jcf->cpool, field_ref_index);
1584 tree field_signature = COMPONENT_REF_SIGNATURE (¤t_jcf->cpool, field_ref_index);
1585 tree field_type = get_type_from_signature (field_signature);
1586 tree new_value = is_putting ? pop_value (field_type) : NULL_TREE;
1589 tree field_decl = lookup_field (&self_type, field_name);
1590 if (field_decl == error_mark_node)
1594 else if (field_decl == NULL_TREE)
1596 error ("Missing field '%s' in '%s'",
1597 IDENTIFIER_POINTER (field_name), self_name);
1600 else if (build_java_signature (TREE_TYPE (field_decl)) != field_signature)
1602 error ("Mismatching signature for field '%s' in '%s'",
1603 IDENTIFIER_POINTER (field_name), self_name);
1606 field_ref = is_static ? NULL_TREE : pop_value (self_type);
1610 push_value (convert (field_type, integer_zero_node));
1611 flush_quick_stack ();
1615 /* Inline references to java.lang.PRIMTYPE.TYPE.
1616 In addition to being a useful (minor) optimization,
1617 this is also needed to avoid circularities in the implementation
1618 of these fields in libjava. */
1619 if (field_name == TYPE_identifier_node && ! is_putting
1620 && field_type == class_ptr_type
1621 && strncmp (self_name, "java.lang.", 10) == 0)
1623 tree typ = build_primtype_type_ref (self_name);
1631 field_ref = build_field_ref (field_ref, self_type, field_name);
1633 field_ref = build_class_init (self_type, field_ref);
1636 flush_quick_stack ();
1637 if (FIELD_FINAL (field_decl))
1639 if (DECL_CONTEXT (field_decl) != current_class)
1640 error_with_decl (field_decl,
1641 "assignment to final field `%s' not in field's class");
1642 else if (FIELD_STATIC (field_decl))
1644 if (DECL_NAME (current_function_decl) != clinit_identifier_node)
1645 error_with_decl (field_decl,
1646 "assignment to final static field `%s' not in class initializer");
1650 if (! DECL_CONSTRUCTOR_P (current_function_decl))
1651 error_with_decl (field_decl,
1652 "assignment to final field `%s' not in constructor");
1655 expand_assignment (field_ref, new_value, 0, 0);
1658 push_value (field_ref);
1662 build_primtype_type_ref (self_name)
1665 char *class_name = self_name+10;
1667 if (strncmp(class_name, "Byte", 4) == 0)
1668 typ = byte_type_node;
1669 else if (strncmp(class_name, "Short", 5) == 0)
1670 typ = short_type_node;
1671 else if (strncmp(class_name, "Integer", 7) == 0)
1672 typ = int_type_node;
1673 else if (strncmp(class_name, "Long", 4) == 0)
1674 typ = long_type_node;
1675 else if (strncmp(class_name, "Float", 5) == 0)
1676 typ = float_type_node;
1677 else if (strncmp(class_name, "Boolean", 7) == 0)
1678 typ = boolean_type_node;
1679 else if (strncmp(class_name, "Char", 4) == 0)
1680 typ = char_type_node;
1681 else if (strncmp(class_name, "Void", 4) == 0)
1682 typ = void_type_node;
1685 if (typ != NULL_TREE)
1686 return build_class_ref (typ);
1692 load_type_state (label)
1696 tree vec = LABEL_TYPE_STATE (label);
1697 int cur_length = TREE_VEC_LENGTH (vec);
1698 stack_pointer = cur_length - DECL_MAX_LOCALS(current_function_decl);
1699 for (i = 0; i < cur_length; i++)
1700 type_map [i] = TREE_VEC_ELT (vec, i);
1703 /* Do the expansion of a Java switch. With Gcc, switches are front-end
1704 dependant things, but they rely on gcc routines. This function is
1705 placed here because it uses things defined locally in parse.y. */
1708 case_identity (t, v)
1709 tree t __attribute__ ((__unused__));
1716 java_lang_expand_expr (exp, target, tmode, modifier)
1719 enum machine_mode tmode;
1720 enum expand_modifier modifier;
1723 tree type = TREE_TYPE (exp);
1724 register enum machine_mode mode = TYPE_MODE (type);
1725 int unsignedp = TREE_UNSIGNED (type);
1729 switch (TREE_CODE (exp))
1732 if (BLOCK_EXPR_BODY (exp))
1735 tree body = BLOCK_EXPR_BODY (exp);
1736 struct rtx_def *to_return;
1737 pushlevel (2); /* 2 and above */
1738 expand_start_bindings (0);
1739 local = BLOCK_EXPR_DECLS (exp);
1742 tree next = TREE_CHAIN (local);
1743 layout_decl (local, 0);
1744 expand_decl (pushdecl (local));
1747 /* Avoid deep recursion for long block. */
1748 while (TREE_CODE (body) == COMPOUND_EXPR)
1750 expand_expr (TREE_OPERAND (body, 0), const0_rtx, VOIDmode, 0);
1751 body = TREE_OPERAND (body, 1);
1753 to_return = expand_expr (body, target, tmode, modifier);
1755 expand_end_bindings (getdecls (), 1, 0);
1763 if (pushcase (TREE_OPERAND (exp, 0), case_identity,
1764 build_decl (LABEL_DECL, NULL_TREE, NULL_TREE), &duplicate) == 2)
1766 EXPR_WFL_LINECOL (wfl_operator) = EXPR_WFL_LINECOL (exp);
1768 (wfl_operator, "Duplicate case label: `%s'",
1769 print_int_node (TREE_OPERAND (exp, 0)));
1775 pushcase (NULL_TREE, 0, build_decl (LABEL_DECL, NULL_TREE, NULL_TREE), NULL);
1779 expand_start_case (0, TREE_OPERAND (exp, 0), int_type_node, "switch");
1780 expand_expr_stmt (TREE_OPERAND (exp, 1));
1781 expand_end_case (TREE_OPERAND (exp, 0));
1785 /* We expand a try[-catch][-finally] block */
1787 /* Expand the try block */
1788 expand_eh_region_start ();
1789 expand_expr_stmt (TREE_OPERAND (exp, 0));
1790 expand_start_all_catch ();
1791 has_finally_p = (TREE_OPERAND (exp, 2) ? 1 : 0);
1793 /* Expand all catch clauses (EH handlers) */
1794 for (current = TREE_OPERAND (exp, 1); current;
1795 current = TREE_CHAIN (current))
1797 extern rtx return_label;
1799 /* If we have a finally, the last exception handler is the
1800 one that is supposed to catch everything. */
1801 if (has_finally_p && !TREE_CHAIN (current))
1805 tree catch = java_get_catch_block (current, has_finally_p);
1806 tree decl = BLOCK_EXPR_DECLS (catch);
1807 type = (decl ? TREE_TYPE (TREE_TYPE (decl)) : NULL_TREE);
1809 start_catch_handler (prepare_eh_table_type (type));
1810 expand_expr_stmt (TREE_OPERAND (current, 0));
1812 /* Need to expand a goto to the end of the function here,
1813 but not for the catch everything handler. */
1817 emit_jump (return_label);
1819 fatal ("No return_label for this function - "
1820 "java_lang_expand_expr");
1822 end_catch_handler ();
1825 /* Expand the finally block, if any */
1828 tree finally = TREE_OPERAND (exp, 2);
1829 if (FINALLY_EXPR_LABEL (finally))
1830 emit_label (label_rtx (FINALLY_EXPR_LABEL (finally)));
1831 expand_expr_stmt (FINALLY_EXPR_BLOCK (finally));
1833 expand_end_all_catch ();
1837 fatal ("Can't expand '%s' tree - java_lang_expand_expr",
1838 tree_code_name [TREE_CODE (exp)]);
1843 expand_byte_code (jcf, method)
1850 unsigned char *linenumber_pointer;
1851 struct eh_range *prev_eh_ranges = NULL_EH_RANGE;
1852 struct eh_range *eh_ranges;
1854 #undef RET /* Defined by config/i386/i386.h */
1855 #undef AND /* Causes problems with opcodes for iand and land. */
1857 #define BCODE byte_ops
1858 #define BYTE_type_node byte_type_node
1859 #define SHORT_type_node short_type_node
1860 #define INT_type_node int_type_node
1861 #define LONG_type_node long_type_node
1862 #define CHAR_type_node char_type_node
1863 #define PTR_type_node ptr_type_node
1864 #define FLOAT_type_node float_type_node
1865 #define DOUBLE_type_node double_type_node
1866 #define VOID_type_node void_type_node
1868 unsigned char* byte_ops;
1869 long length = DECL_CODE_LENGTH (method);
1872 JCF_SEEK (jcf, DECL_CODE_OFFSET (method));
1873 byte_ops = jcf->read_ptr;
1875 #define CONST_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1876 #define CONST_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1877 #define VAR_INDEX_1 (saw_index = 1, IMMEDIATE_u1)
1878 #define VAR_INDEX_2 (saw_index = 1, IMMEDIATE_u2)
1880 #define CHECK_PC_IN_RANGE(PC) 1 /* Already handled by verifier. */
1882 instruction_bits = oballoc (length + 1);
1883 bzero (instruction_bits, length + 1);
1885 /* We make an initial pass of the line number table, to note
1886 which instructions have associated line number entries. */
1887 linenumber_pointer = linenumber_table;
1888 for (i = 0; i < linenumber_count; i++)
1890 int pc = GET_u2 (linenumber_pointer);
1891 linenumber_pointer += 4;
1893 warning ("invalid PC in line number table");
1896 if ((instruction_bits[pc] & BCODE_HAS_LINENUMBER) != 0)
1897 instruction_bits[pc] |= BCODE_HAS_MULTI_LINENUMBERS;
1898 instruction_bits[pc] |= BCODE_HAS_LINENUMBER;
1902 /* Do a preliminary pass.
1903 * This figures out which PC can be the targets of jumps. */
1904 for (PC = 0; PC < length;)
1906 int oldpc = PC; /* PC at instruction start. */
1907 instruction_bits [PC] |= BCODE_INSTRUCTION_START;
1908 switch (byte_ops[PC++])
1910 #define JAVAOP(OPNAME, OPCODE, OPKIND, OPERAND_TYPE, OPERAND_VALUE) \
1912 PRE_##OPKIND(OPERAND_TYPE, OPERAND_VALUE); \
1915 #define NOTE_LABEL(PC) note_label(oldpc, PC)
1917 #define PRE_PUSHC(OPERAND_TYPE, OPERAND_VALUE) (void)(OPERAND_VALUE);
1918 #define PRE_LOAD(OPERAND_TYPE, OPERAND_VALUE) (void)(OPERAND_VALUE);
1919 #define PRE_STORE(OPERAND_TYPE, OPERAND_VALUE) (void)(OPERAND_VALUE);
1920 #define PRE_STACK(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1921 #define PRE_UNOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1922 #define PRE_BINOP(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1923 #define PRE_CONVERT(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1924 #define PRE_CONVERT2(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1926 #define PRE_SPECIAL(OPERAND_TYPE, INSTRUCTION) \
1927 PRE_SPECIAL_##INSTRUCTION(OPERAND_TYPE)
1928 #define PRE_SPECIAL_IINC(OPERAND_TYPE) \
1929 ((void) IMMEDIATE_u1, (void) IMMEDIATE_s1)
1930 #define PRE_SPECIAL_ENTER(IGNORE) /* nothing */
1931 #define PRE_SPECIAL_EXIT(IGNORE) /* nothing */
1932 #define PRE_SPECIAL_THROW(IGNORE) /* nothing */
1933 #define PRE_SPECIAL_BREAK(IGNORE) /* nothing */
1935 /* two forms of wide instructions */
1936 #define PRE_SPECIAL_WIDE(IGNORE) \
1938 int modified_opcode = IMMEDIATE_u1; \
1939 if (modified_opcode == OPCODE_iinc) \
1941 (void) IMMEDIATE_u2; /* indexbyte1 and indexbyte2 */ \
1942 (void) IMMEDIATE_s2; /* constbyte1 and constbyte2 */ \
1946 (void) IMMEDIATE_u2; /* indexbyte1 and indexbyte2 */ \
1950 /* nothing */ /* XXX JH */
1952 #define PRE_IMPL(IGNORE1, IGNORE2) /* nothing */
1954 #define PRE_MONITOR(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1956 #define PRE_RETURN(OPERAND_TYPE, OPERAND_VALUE) /* nothing */
1957 #define PRE_ARRAY(OPERAND_TYPE, SUBOP) \
1958 PRE_ARRAY_##SUBOP(OPERAND_TYPE)
1959 #define PRE_ARRAY_LOAD(TYPE) /* nothing */
1960 #define PRE_ARRAY_STORE(TYPE) /* nothing */
1961 #define PRE_ARRAY_LENGTH(TYPE) /* nothing */
1962 #define PRE_ARRAY_NEW(TYPE) PRE_ARRAY_NEW_##TYPE
1963 #define PRE_ARRAY_NEW_NUM ((void) IMMEDIATE_u1)
1964 #define PRE_ARRAY_NEW_PTR ((void) IMMEDIATE_u2)
1965 #define PRE_ARRAY_NEW_MULTI ((void) IMMEDIATE_u2, (void) IMMEDIATE_u1)
1967 #define PRE_TEST(OPERAND_TYPE, OPERAND_VALUE) NOTE_LABEL (oldpc+IMMEDIATE_s2)
1968 #define PRE_COND(OPERAND_TYPE, OPERAND_VALUE) NOTE_LABEL (oldpc+IMMEDIATE_s2)
1969 #define PRE_BRANCH(OPERAND_TYPE, OPERAND_VALUE) \
1970 saw_index = 0; INT_temp = (OPERAND_VALUE); \
1971 if (!saw_index) NOTE_LABEL(oldpc + INT_temp);
1972 #define PRE_JSR(OPERAND_TYPE, OPERAND_VALUE) \
1973 saw_index = 0; INT_temp = (OPERAND_VALUE); \
1974 if (!saw_index) NOTE_LABEL(oldpc + INT_temp);
1976 #define PRE_RET(OPERAND_TYPE, OPERAND_VALUE) (void)(OPERAND_VALUE)
1978 #define PRE_SWITCH(OPERAND_TYPE, TABLE_OR_LOOKUP) \
1979 PC = (PC + 3) / 4 * 4; PRE_##TABLE_OR_LOOKUP##_SWITCH
1981 #define PRE_LOOKUP_SWITCH \
1982 { jint default_offset = IMMEDIATE_s4; jint npairs = IMMEDIATE_s4; \
1983 NOTE_LABEL (default_offset+oldpc); \
1985 while (--npairs >= 0) { \
1986 jint match = IMMEDIATE_s4; jint offset = IMMEDIATE_s4; \
1987 NOTE_LABEL (offset+oldpc); } \
1990 #define PRE_TABLE_SWITCH \
1991 { jint default_offset = IMMEDIATE_s4; \
1992 jint low = IMMEDIATE_s4; jint high = IMMEDIATE_s4; \
1993 NOTE_LABEL (default_offset+oldpc); \
1995 while (low++ <= high) { \
1996 jint offset = IMMEDIATE_s4; \
1997 NOTE_LABEL (offset+oldpc); } \
2000 #define PRE_FIELD(MAYBE_STATIC, PUT_OR_GET) (void)(IMMEDIATE_u2);
2001 #define PRE_OBJECT(MAYBE_STATIC, PUT_OR_GET) (void)(IMMEDIATE_u2);
2002 #define PRE_INVOKE(MAYBE_STATIC, IS_INTERFACE) \
2003 (void)(IMMEDIATE_u2); \
2004 PC += 2 * IS_INTERFACE /* for invokeinterface */;
2006 #include "javaop.def"
2011 if (! verify_jvm_instructions (jcf, byte_ops, length))
2014 /* Translate bytecodes to rtl instructions. */
2015 linenumber_pointer = linenumber_table;
2016 for (PC = 0; PC < length;)
2018 if ((instruction_bits [PC] & BCODE_TARGET) != 0 || PC == 0)
2020 tree label = lookup_label (PC);
2021 flush_quick_stack ();
2022 if ((instruction_bits [PC] & BCODE_TARGET) != 0)
2023 expand_label (label);
2024 if (LABEL_VERIFIED (label) || PC == 0)
2025 load_type_state (label);
2028 if (! (instruction_bits [PC] & BCODE_VERIFIED))
2030 /* never executed - skip */
2031 warning ("Some bytecode operations (starting at pc %d) can never be executed", PC);
2033 && ! (instruction_bits [PC] & BCODE_VERIFIED))
2039 /* Handle possible line number entry for this PC.
2041 This code handles out-of-order and multiple linenumbers per PC,
2042 but is optimized for the case of line numbers increasing
2043 monotonically with PC. */
2044 if ((instruction_bits[PC] & BCODE_HAS_LINENUMBER) != 0)
2046 if ((instruction_bits[PC] & BCODE_HAS_MULTI_LINENUMBERS) != 0
2047 || GET_u2 (linenumber_pointer) != PC)
2048 linenumber_pointer = linenumber_table;
2049 while (linenumber_pointer < linenumber_table + linenumber_count * 4)
2051 int pc = GET_u2 (linenumber_pointer);
2052 linenumber_pointer += 4;
2055 lineno = GET_u2 (linenumber_pointer - 2);
2056 emit_line_note (input_filename, lineno);
2057 if (!(instruction_bits[PC] & BCODE_HAS_MULTI_LINENUMBERS))
2062 maybe_start_try (PC);
2063 maybe_pushlevels (PC);
2065 PC = process_jvm_instruction (PC, byte_ops, length);
2067 maybe_poplevels (PC);
2073 java_push_constant_from_pool (jcf, index)
2078 if (JPOOL_TAG (jcf, index) == CONSTANT_String)
2081 push_obstacks (&permanent_obstack, &permanent_obstack);
2082 name = get_name_constant (jcf, JPOOL_USHORT1 (jcf, index));
2083 index = alloc_name_constant (CONSTANT_String, name);
2084 c = build_ref_from_constant_pool (index);
2085 TREE_TYPE (c) = promote_type (string_type_node);
2089 c = get_constant (jcf, index);
2094 process_jvm_instruction (PC, byte_ops, length)
2096 unsigned char* byte_ops;
2099 char *opname; /* Temporary ??? */
2100 int oldpc = PC; /* PC at instruction start. */
2102 /* If the instruction is at the beginning of a exception handler,
2103 replace the top of the stack with the thrown object reference */
2104 if (instruction_bits [PC] & BCODE_EXCEPTION_TARGET)
2106 pop_value (ptr_type_node);
2107 push_value (soft_exceptioninfo_call_node);
2110 switch (byte_ops[PC++])
2112 #define JAVAOP(OPNAME, OPCODE, OPKIND, OPERAND_TYPE, OPERAND_VALUE) \
2115 OPKIND(OPERAND_TYPE, OPERAND_VALUE); \
2118 #define RET(OPERAND_TYPE, OPERAND_VALUE) \
2120 int saw_index = 0; \
2121 int index = OPERAND_VALUE; \
2122 build_java_ret (find_local_variable (index, ptr_type_node, oldpc)); \
2125 #define JSR(OPERAND_TYPE, OPERAND_VALUE) \
2127 tree where = lookup_label (oldpc+OPERAND_VALUE); \
2128 tree ret = lookup_label (PC); \
2129 build_java_jsr (where, ret); \
2132 /* Push a constant onto the stack. */
2133 #define PUSHC(OPERAND_TYPE, OPERAND_VALUE) \
2134 { int saw_index = 0; int ival = (OPERAND_VALUE); \
2135 if (saw_index) java_push_constant_from_pool (current_jcf, ival); \
2136 else expand_java_pushc (ival, OPERAND_TYPE##_type_node); }
2138 /* internal macro added for use by the WIDE case */
2139 #define LOAD_INTERNAL(OPTYPE, OPVALUE) \
2140 push_value (find_local_variable (OPVALUE, type_map[OPVALUE], oldpc));
2142 /* Push local variable onto the opcode stack. */
2143 #define LOAD(OPERAND_TYPE, OPERAND_VALUE) \
2145 /* have to do this since OPERAND_VALUE may have side-effects */ \
2146 int opvalue = OPERAND_VALUE; \
2147 LOAD_INTERNAL(OPERAND_TYPE##_type_node, opvalue); \
2150 #define RETURN(OPERAND_TYPE, OPERAND_VALUE) \
2151 expand_java_return (OPERAND_TYPE##_type_node)
2153 #define REM_EXPR TRUNC_MOD_EXPR
2154 #define BINOP(OPERAND_TYPE, OPERAND_VALUE) \
2155 expand_java_binop (OPERAND_TYPE##_type_node, OPERAND_VALUE##_EXPR)
2157 #define FIELD(IS_STATIC, IS_PUT) \
2158 expand_java_field_op (IS_STATIC, IS_PUT, IMMEDIATE_u2)
2160 #define TEST(OPERAND_TYPE, CONDITION) \
2161 expand_test (CONDITION##_EXPR, OPERAND_TYPE##_type_node, oldpc+IMMEDIATE_s2)
2163 #define COND(OPERAND_TYPE, CONDITION) \
2164 expand_cond (CONDITION##_EXPR, OPERAND_TYPE##_type_node, oldpc+IMMEDIATE_s2)
2166 #define BRANCH(OPERAND_TYPE, OPERAND_VALUE) \
2167 BRANCH_##OPERAND_TYPE (OPERAND_VALUE)
2169 #define BRANCH_GOTO(OPERAND_VALUE) \
2170 expand_java_goto (oldpc + OPERAND_VALUE)
2172 #define BRANCH_CALL(OPERAND_VALUE) \
2173 expand_java_call (oldpc + OPERAND_VALUE, oldpc)
2176 #define BRANCH_RETURN(OPERAND_VALUE) \
2178 tree type = OPERAND_TYPE##_type_node; \
2179 tree value = find_local_variable (OPERAND_VALUE, type, oldpc); \
2180 expand_java_ret (value); \
2184 #define NOT_IMPL(OPERAND_TYPE, OPERAND_VALUE) \
2185 fprintf (stderr, "%3d: %s ", oldpc, opname); \
2186 fprintf (stderr, "(not implemented)\n")
2187 #define NOT_IMPL1(OPERAND_VALUE) \
2188 fprintf (stderr, "%3d: %s ", oldpc, opname); \
2189 fprintf (stderr, "(not implemented)\n")
2191 #define BRANCH_RETURN(OPERAND_VALUE) NOT_IMPL1(OPERAND_VALUE)
2193 #define STACK(SUBOP, COUNT) STACK_##SUBOP (COUNT)
2195 #define STACK_POP(COUNT) java_stack_pop (COUNT)
2197 #define STACK_SWAP(COUNT) java_stack_swap()
2199 #define STACK_DUP(COUNT) java_stack_dup (COUNT, 0)
2200 #define STACK_DUPx1(COUNT) java_stack_dup (COUNT, 1)
2201 #define STACK_DUPx2(COUNT) java_stack_dup (COUNT, 2)
2203 #define SWITCH(OPERAND_TYPE, TABLE_OR_LOOKUP) \
2204 PC = (PC + 3) / 4 * 4; TABLE_OR_LOOKUP##_SWITCH
2206 #define LOOKUP_SWITCH \
2207 { jint default_offset = IMMEDIATE_s4; jint npairs = IMMEDIATE_s4; \
2208 tree selector = pop_value (INT_type_node); \
2209 tree duplicate, label; \
2210 tree type = TREE_TYPE (selector); \
2211 flush_quick_stack (); \
2212 expand_start_case (0, selector, type, "switch statement");\
2213 push_momentary (); \
2214 while (--npairs >= 0) \
2216 jint match = IMMEDIATE_s4; jint offset = IMMEDIATE_s4; \
2217 tree value = build_int_2 (match, match < 0 ? -1 : 0); \
2218 TREE_TYPE (value) = type; \
2219 label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); \
2220 pushcase (value, convert, label, &duplicate); \
2221 expand_java_goto (oldpc + offset); \
2223 label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); \
2224 pushcase (NULL_TREE, 0, label, &duplicate); \
2225 expand_java_goto (oldpc + default_offset); \
2227 expand_end_case (selector); \
2230 #define TABLE_SWITCH \
2231 { jint default_offset = IMMEDIATE_s4; \
2232 jint low = IMMEDIATE_s4; jint high = IMMEDIATE_s4; \
2233 tree selector = pop_value (INT_type_node); \
2234 tree duplicate, label; \
2235 tree type = TREE_TYPE (selector); \
2236 flush_quick_stack (); \
2237 expand_start_case (0, selector, type, "switch statement");\
2238 push_momentary (); \
2239 for (; low <= high; low++) \
2241 jint offset = IMMEDIATE_s4; \
2242 tree value = build_int_2 (low, low < 0 ? -1 : 0); \
2243 TREE_TYPE (value) = type; \
2244 label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); \
2245 pushcase (value, convert, label, &duplicate); \
2246 expand_java_goto (oldpc + offset); \
2248 label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); \
2249 pushcase (NULL_TREE, 0, label, &duplicate); \
2250 expand_java_goto (oldpc + default_offset); \
2252 expand_end_case (selector); \
2255 #define INVOKE(MAYBE_STATIC, IS_INTERFACE) \
2256 { int opcode = byte_ops[PC-1]; \
2257 int method_ref_index = IMMEDIATE_u2; \
2259 if (IS_INTERFACE) { nargs = IMMEDIATE_u1; (void) IMMEDIATE_u1; } \
2261 expand_invoke (opcode, method_ref_index, nargs); \
2264 /* Handle new, checkcast, instanceof */
2265 #define OBJECT(TYPE, OP) \
2266 expand_java_##OP (get_class_constant (current_jcf, IMMEDIATE_u2))
2268 #define ARRAY(OPERAND_TYPE, SUBOP) ARRAY_##SUBOP(OPERAND_TYPE)
2270 #define ARRAY_LOAD(OPERAND_TYPE) \
2272 expand_java_arrayload( OPERAND_TYPE##_type_node ); \
2275 #define ARRAY_STORE(OPERAND_TYPE) \
2277 expand_java_arraystore( OPERAND_TYPE##_type_node ); \
2280 #define ARRAY_LENGTH(OPERAND_TYPE) expand_java_array_length();
2281 #define ARRAY_NEW(OPERAND_TYPE) ARRAY_NEW_##OPERAND_TYPE()
2282 #define ARRAY_NEW_PTR() \
2283 push_value (build_anewarray (get_class_constant (current_jcf, \
2285 pop_value (int_type_node)));
2286 #define ARRAY_NEW_NUM() \
2288 int atype = IMMEDIATE_u1; \
2289 push_value (build_newarray (atype, pop_value (int_type_node)));\
2291 #define ARRAY_NEW_MULTI() \
2293 tree class = get_class_constant (current_jcf, IMMEDIATE_u2 ); \
2294 int ndims = IMMEDIATE_u1; \
2295 expand_java_multianewarray( class, ndims ); \
2298 #define UNOP(OPERAND_TYPE, OPERAND_VALUE) \
2299 push_value (fold (build1 (NEGATE_EXPR, OPERAND_TYPE##_type_node, \
2300 pop_value (OPERAND_TYPE##_type_node))));
2302 #define CONVERT2(FROM_TYPE, TO_TYPE) \
2304 push_value (build1 (NOP_EXPR, int_type_node, \
2305 (convert (TO_TYPE##_type_node, \
2306 pop_value (FROM_TYPE##_type_node))))); \
2309 #define CONVERT(FROM_TYPE, TO_TYPE) \
2311 push_value (convert (TO_TYPE##_type_node, \
2312 pop_value (FROM_TYPE##_type_node))); \
2315 /* internal macro added for use by the WIDE case
2316 Added TREE_TYPE (decl) assignment, apbianco */
2317 #define STORE_INTERNAL(OPTYPE, OPVALUE) \
2320 int var = OPVALUE; \
2321 tree type = OPTYPE; \
2322 value = pop_value (type); \
2323 type = TREE_TYPE (value); \
2324 decl = find_local_variable (var, type, oldpc); \
2325 set_local_type (var, type ); \
2326 expand_assignment (decl, value, 0, 0); \
2329 #define STORE(OPERAND_TYPE, OPERAND_VALUE) \
2331 /* have to do this since OPERAND_VALUE may have side-effects */ \
2332 int opvalue = OPERAND_VALUE; \
2333 STORE_INTERNAL(OPERAND_TYPE##_type_node, opvalue); \
2336 #define SPECIAL(OPERAND_TYPE, INSTRUCTION) \
2337 SPECIAL_##INSTRUCTION(OPERAND_TYPE)
2339 #define SPECIAL_ENTER(IGNORED) MONITOR_OPERATION (soft_monitorenter_node)
2340 #define SPECIAL_EXIT(IGNORED) MONITOR_OPERATION (soft_monitorexit_node)
2342 #define MONITOR_OPERATION(call) \
2344 tree o = pop_value (ptr_type_node); \
2346 flush_quick_stack (); \
2347 c = build_java_monitor (call, o); \
2348 TREE_SIDE_EFFECTS (c) = 1; \
2349 expand_expr_stmt (c); \
2352 #define SPECIAL_IINC(IGNORED) \
2354 unsigned int local_var_index = IMMEDIATE_u1; \
2355 int ival = IMMEDIATE_s1; \
2356 expand_iinc(local_var_index, ival, oldpc); \
2359 #define SPECIAL_WIDE(IGNORED) \
2361 int modified_opcode = IMMEDIATE_u1; \
2362 unsigned int local_var_index = IMMEDIATE_u2; \
2363 switch (modified_opcode) \
2367 int ival = IMMEDIATE_s2; \
2368 expand_iinc (local_var_index, ival, oldpc); \
2371 case OPCODE_iload: \
2372 case OPCODE_lload: \
2373 case OPCODE_fload: \
2374 case OPCODE_dload: \
2375 case OPCODE_aload: \
2377 /* duplicate code from LOAD macro */ \
2378 LOAD_INTERNAL(operand_type[modified_opcode], local_var_index); \
2381 case OPCODE_istore: \
2382 case OPCODE_lstore: \
2383 case OPCODE_fstore: \
2384 case OPCODE_dstore: \
2385 case OPCODE_astore: \
2387 STORE_INTERNAL(operand_type[modified_opcode], local_var_index); \
2391 error ("unrecogized wide sub-instruction"); \
2395 #define SPECIAL_THROW(IGNORED) \
2396 build_java_athrow (pop_value (throwable_type_node))
2398 #define SPECIAL_BREAK NOT_IMPL1
2399 #define IMPL NOT_IMPL
2401 #include "javaop.def"
2404 fprintf (stderr, "%3d: unknown(%3d)\n", oldpc, byte_ops[PC]);