OSDN Git Service

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