OSDN Git Service

Tue Nov 30 12:36:15 1999 Anthony Green <green@cygnus.com>
[pf3gnuchains/gcc-fork.git] / gcc / java / verify.c
1 /* Handle verification of bytecoded methods for the GNU compiler for 
2    the Java(TM) language.
3    Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
4
5 This file is part of GNU CC.
6
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING.  If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.
21
22 Java and all Java-based marks are trademarks or registered trademarks
23 of Sun Microsystems, Inc. in the United States and other countries.
24 The Free Software Foundation is independent of Sun Microsystems, Inc.  */
25
26 #include "config.h"
27 #include "system.h"
28 #include "tree.h"
29 #include "java-tree.h"
30 #include "javaop.h"
31 #include "java-opcodes.h"
32 #include "jcf.h"
33 #include "java-except.h"
34 #include "toplev.h"
35
36 static void push_pending_label PROTO ((tree));
37 static tree merge_types PROTO ((tree, tree));
38 static const char *check_pending_block PROTO ((tree));
39 static void type_stack_dup PROTO ((int, int));
40 static int start_pc_cmp PROTO ((const PTR, const PTR));
41
42 extern int stack_pointer;
43
44 /* During verification, start of the current subroutine (jsr target). */
45 tree current_subr;
46
47 /* A list of pending blocks, chained using  LABEL_PENDING_CHAIN.
48    A pending block is one that has LABEL_CHANGED set, which means
49    it requires (re-) verification. */
50 tree pending_blocks;
51
52 /* Append TARGET_LABEL to the pending_block stack unless already in it. */
53
54 static void
55 push_pending_label (target_label) 
56      tree target_label;
57 {
58   if (! LABEL_CHANGED (target_label))
59     {
60       LABEL_PENDING_CHAIN (target_label) = pending_blocks;
61       pending_blocks = target_label;
62       LABEL_CHANGED (target_label) = 1;
63     }
64 }
65
66 /* Note that TARGET_LABEL is a possible successor instruction.
67    Merge the type state etc.
68    Return NULL on sucess, or an error message on failure. */
69
70 static const char *
71 check_pending_block (target_label)
72      tree target_label;
73 {
74   int changed = merge_type_state (target_label);
75
76   if (changed)
77     {
78       if (changed < 0)
79         return "types could not be merged";
80       push_pending_label (target_label);
81     }
82
83   if (current_subr == NULL)
84     {
85       if (LABEL_IN_SUBR (target_label))
86         return "might transfer control into subroutine";
87     }
88   else
89     {
90       if (LABEL_IN_SUBR (target_label))
91         {
92           if (LABEL_SUBR_START (target_label) != current_subr)
93             return "transfer out of subroutine";
94         }
95       else if (! LABEL_VERIFIED (target_label))
96         {
97           LABEL_IN_SUBR (target_label) = 1;
98           LABEL_SUBR_START (target_label) = current_subr;
99         }
100       else
101         return "transfer out of subroutine";
102     }
103   return NULL;
104 }
105
106 /* Return the "merged" types of TYPE1 and TYPE2.
107    If either is primitive, the other must match (after promotion to int).
108    For reference types, return the common super-class.
109    Return TYPE_UNKNOWN if the types cannot be merged. */   
110
111 static tree
112 merge_types (type1, type2)
113      tree type1, type2;
114 {
115   if (type1 == type2)
116     return type1;
117   if (type1 == TYPE_UNKNOWN || type2 == TYPE_UNKNOWN
118       || type1 == TYPE_RETURN_ADDR || type2 == TYPE_RETURN_ADDR)
119     return TYPE_UNKNOWN;
120   if (TREE_CODE (type1) == POINTER_TYPE && TREE_CODE (type2) == POINTER_TYPE)
121     {
122       int depth1, depth2;
123       tree tt1, tt2;
124       /* ptr_type_node is only used for a null reference,
125          which is compatible with any reference type. */
126       if (type1 == ptr_type_node || type2 == object_ptr_type_node)
127         return type2;
128       if (type2 == ptr_type_node || type1 == object_ptr_type_node)
129         return type1;
130
131       tt1 = HANDLE_TO_CLASS_TYPE (TREE_TYPE (type1));
132       tt2 = HANDLE_TO_CLASS_TYPE (TREE_TYPE (type2));
133
134       if (TYPE_ARRAY_P (tt1) || TYPE_ARRAY_P (tt2))
135         {
136           if (TYPE_ARRAY_P (tt1) == TYPE_ARRAY_P (tt2))
137             {
138               tree el_type1 = TYPE_ARRAY_ELEMENT (tt1);
139               tree el_type2 = TYPE_ARRAY_ELEMENT (tt2);
140               tree el_type = NULL_TREE;
141               if (el_type1 == el_type2)
142                 el_type = el_type1;
143               else if (TREE_CODE (el_type1) == POINTER_TYPE
144                        && TREE_CODE (el_type2) == POINTER_TYPE)
145                 el_type = merge_types (el_type1, el_type2);
146               if (el_type != NULL_TREE)
147                 {
148                   HOST_WIDE_INT len1 = java_array_type_length (tt1);
149                   HOST_WIDE_INT len2 = java_array_type_length (tt2);
150                   if (len1 != len2)
151                     len1 = -1;
152                   else if (el_type1 == el_type2)
153                     return type1;
154                   return promote_type (build_java_array_type (el_type, len1));
155                 }
156             }
157           return object_ptr_type_node;
158         }
159
160       if (CLASS_INTERFACE (TYPE_NAME (tt1)))
161         {
162           if (CLASS_INTERFACE (TYPE_NAME (tt2)))
163             {
164               /* This is a kludge, but matches what Sun's verifier does.
165                  It can be tricked, but is safe as long as type errors
166                  (i.e. interface method calls) are caught at run-time. */
167               return object_ptr_type_node;
168             }
169           else
170             {
171               if (can_widen_reference_to (tt2, tt1))
172                 return type1;
173               else
174                 return TYPE_UNKNOWN;
175             }
176         }
177       else if (CLASS_INTERFACE (TYPE_NAME (tt2)))
178         {
179           if (can_widen_reference_to (tt1, tt2))
180             return type2;
181           else
182             return TYPE_UNKNOWN;
183         }
184
185       type1 = tt1;
186       type2 = tt2;
187
188       depth1 = class_depth (type1);
189       depth2 = class_depth (type2);
190       for ( ; depth1 > depth2;  depth1--)
191         type1 = TYPE_BINFO_BASETYPE (type1, 0);
192       for ( ; depth2 > depth1;  depth2--)
193         type2 = TYPE_BINFO_BASETYPE (type2, 0);
194       while (type1 != type2)
195         {
196           type1 = TYPE_BINFO_BASETYPE (type1, 0);
197           type2 = TYPE_BINFO_BASETYPE (type2, 0);
198         }
199       return promote_type (type1);
200     }
201   if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2)
202       && TYPE_PRECISION (type1) <= 32 && TYPE_PRECISION (type2) <= 32)
203     return int_type_node;
204   return TYPE_UNKNOWN;
205 }
206
207 /* Merge the current type state with that at LABEL.
208    Return -1 the the states are incompatible (i.e. on error),
209    0 if there was no change, and 1 if there was a change. */
210
211 int
212 merge_type_state (label)
213      tree label;
214 {
215   int nlocals = DECL_MAX_LOCALS(current_function_decl);
216   int cur_length = stack_pointer + nlocals;
217   tree vec = LABEL_TYPE_STATE (label);
218   tree return_map;
219   if (vec == NULL_TREE || !LABEL_VERIFIED (label))
220     {
221       if (!vec)
222         {
223           vec = make_tree_vec (cur_length);
224           LABEL_TYPE_STATE (label) = vec;
225         }
226       while (--cur_length >= 0)
227         TREE_VEC_ELT (vec, cur_length) = type_map [cur_length];
228       return 1;
229     }
230   else
231     {
232       int i;
233       int changed = 0;
234       if (LABEL_IS_SUBR_START (label) && LABEL_VERIFIED (label)
235           && current_subr != label)
236         return_map = LABEL_RETURN_TYPE_STATE (label);
237       else
238         return_map = NULL_TREE;
239       if (TREE_VEC_LENGTH (vec) != cur_length)
240         {
241           return -1;
242         }
243       for (i = 0; i < cur_length; i++)
244         {
245           tree old_type = TREE_VEC_ELT (vec, i);
246           tree new_type = merge_types (old_type, type_map [i]);
247           if (TREE_VEC_ELT (vec, i) != new_type)
248             {
249               /* If there has been a change, note that since we must re-verify.
250                  However, if the label is the start of a subroutine,
251                  we don't care about local variables that are neither
252                  set nor used in the sub-routine. */
253               if (return_map == NULL_TREE || i >= nlocals
254                   || TREE_VEC_ELT (return_map, i) != TYPE_UNUSED
255                   || (TYPE_IS_WIDE (new_type)
256                       && TREE_VEC_ELT (return_map, i+1) != TYPE_UNUSED))
257                 changed = 1;
258             }
259           TREE_VEC_ELT (vec, i) = new_type;
260           if (new_type == TYPE_UNKNOWN)
261             {
262               if (i >= nlocals)
263                 return -1;
264             }
265           else if (TYPE_IS_WIDE (new_type))
266             i++;
267         }
268       return changed;
269     }
270 }
271
272 /* Handle dup-like operations. */
273
274 static void
275 type_stack_dup (size, offset)
276      int size, offset;
277 {
278   tree type[4];
279   int index;
280   if (size + offset > stack_pointer)
281     error ("stack underflow - dup* operation");
282   for (index = 0;  index < size + offset; index++)
283     {
284       type[index] = stack_type_map[stack_pointer - 1];
285       if (type[index] == void_type_node)
286         {
287           index++;
288           type[index] = stack_type_map[stack_pointer - 2];
289           if (! TYPE_IS_WIDE (type[index]))
290             fatal ("internal error - dup operation");
291           if (index == size || index == size + offset)
292             fatal ("dup operation splits 64-bit number");
293         }
294       pop_type (type[index]);
295     }
296   for (index = size;  --index >= 0; )
297     {
298       if (type[index] != void_type_node)
299         push_type (type[index]);
300     }
301
302   for (index = size + offset;  --index >= 0; )
303     {
304       if (type[index] != void_type_node)
305         push_type (type[index]);
306     }
307 }
308
309 /* This keeps track of a start PC and corresponding initial index.  */
310 struct pc_index
311 {
312   int start_pc;
313   int index;
314 };
315
316 /* A helper that is used when sorting exception ranges.  */
317 static int
318 start_pc_cmp (xp, yp)
319      const PTR xp;
320      const PTR yp;
321 {
322   const struct pc_index *x = (const struct pc_index *) xp;
323   const struct pc_index *y = (const struct pc_index *) yp;
324   return x->start_pc - y->start_pc;
325 }
326
327 /* This causes the next iteration to ignore the next instruction
328    and look for some other unhandled instruction. */
329 #define INVALIDATE_PC (prevpc = -1, oldpc = PC, PC = INVALID_PC)
330 #define INVALID_PC (-1)
331
332 #define VERIFICATION_ERROR(MESSAGE) \
333   do { message = MESSAGE;  goto verify_error; } while (0)
334
335 #define PUSH_PENDING(LABEL) \
336      do { if ((message = check_pending_block (LABEL)) != NULL) \
337              goto verify_error; } while (0)
338
339 #ifdef __GNUC__
340 #define CHECK_PC_IN_RANGE(PC) ({if (PC < 0 || PC > length) goto bad_pc; 1;})
341 #else
342 #define CHECK_PC_IN_RANGE(PC) (PC < 0 || PC > length ? \
343   (fatal("Bad byte codes.\n"), 0) : 1)
344 #endif
345
346 #define BCODE byte_ops
347
348 /* Verify the bytecodes of the current method.
349    Return 1 on sucess, 0 on failure. */
350 int
351 verify_jvm_instructions (jcf, byte_ops, length)
352      JCF* jcf;
353      const unsigned char *byte_ops;
354      long length;
355 {
356   tree label;
357   int wide = 0;
358   int op_code;
359   int PC;
360   int oldpc = 0; /* PC of start of instruction. */
361   int prevpc = 0;  /* If >= 0, PC of previous instruction. */
362   const char *message;
363   int i;
364   register unsigned char *p;
365   struct eh_range *prev_eh_ranges = NULL_EH_RANGE;
366   struct eh_range *eh_ranges;
367   tree return_type = TREE_TYPE (TREE_TYPE (current_function_decl));
368   struct pc_index *starts;
369   int eh_count;
370
371   jint int_value = -1;
372
373   pending_blocks = NULL_TREE;
374
375   /* Handle the exception table. */
376   method_init_exceptions ();
377   JCF_SEEK (jcf, DECL_CODE_OFFSET (current_function_decl) + length);
378   eh_count = JCF_readu2 (jcf);
379
380   /* We read the exception handlers in order of increasing start PC.
381      To do this we first read and sort the start PCs.  */
382   starts = (struct pc_index *) xmalloc (eh_count * sizeof (struct pc_index));
383   for (i = 0; i < eh_count; ++i)
384     {
385       starts[i].start_pc = GET_u2 (jcf->read_ptr + 8 * i);
386       starts[i].index = i;
387     }
388   qsort (starts, eh_count, sizeof (struct pc_index), start_pc_cmp);
389
390   for (i = 0; i < eh_count; ++i)
391     {
392       int start_pc, end_pc, handler_pc, catch_type;
393
394       p = jcf->read_ptr + 8 * starts[i].index;
395
396       start_pc = GET_u2 (p);
397       end_pc = GET_u2 (p+2);
398       handler_pc = GET_u2 (p+4);
399       catch_type = GET_u2 (p+6);
400
401       if (start_pc < 0 || start_pc >= length
402           || end_pc < 0 || end_pc > length || start_pc >= end_pc
403           || handler_pc < 0 || handler_pc >= length
404           || (handler_pc >= start_pc && handler_pc < end_pc)
405           || ! (instruction_bits [start_pc] & BCODE_INSTRUCTION_START)
406           || (end_pc < length &&
407              ! (instruction_bits [end_pc] & BCODE_INSTRUCTION_START))
408           || ! (instruction_bits [handler_pc] & BCODE_INSTRUCTION_START))
409         {
410           error ("bad pc in exception_table");
411           free (starts);
412           return 0;
413         }
414
415       add_handler (start_pc, end_pc,
416                    lookup_label (handler_pc),
417                    catch_type == 0 ? NULL_TREE
418                    : get_class_constant (jcf, catch_type));
419
420       instruction_bits [handler_pc] |= BCODE_EXCEPTION_TARGET;
421     }
422
423   free (starts);
424   handle_nested_ranges ();
425
426   for (PC = 0;;)
427     {
428       int index;
429       tree type, tmp;
430       if (((PC != INVALID_PC
431            && instruction_bits [PC] & BCODE_TARGET) != 0)
432           || PC == 0)
433         {
434           PUSH_PENDING (lookup_label (PC));
435           INVALIDATE_PC;
436         }
437       /* Check if there are any more pending blocks in the current
438          subroutine.  Because we push pending blocks in a
439          last-in-first-out order, and because we don't push anything
440          from our caller until we are done with this subroutine or
441          anything nested in it, then we are done if the top of the
442          pending_blocks stack is not in a subroutine, or it is in our
443          caller. */
444       if (current_subr 
445           && PC == INVALID_PC)
446         {
447           tree caller = LABEL_SUBR_CONTEXT (current_subr);
448
449           if (pending_blocks == NULL_TREE
450               || ! LABEL_IN_SUBR (pending_blocks)
451               || LABEL_SUBR_START (pending_blocks) == caller)
452             {
453               int size = DECL_MAX_LOCALS(current_function_decl)+stack_pointer;
454               tree ret_map = LABEL_RETURN_TYPE_STATE (current_subr);
455               tmp = LABEL_RETURN_LABELS (current_subr);
456               
457               /* FIXME: If we exit a subroutine via a throw, we might
458                  have returned to an earlier caller.  Obviously a
459                  "ret" can only return one level, but a throw may
460                  return many levels.*/
461               current_subr = caller;
462
463               if (RETURN_MAP_ADJUSTED (ret_map))
464                 {
465                   /* Since we are done with this subroutine , set up
466                      the (so far known) return address as pending -
467                      with the merged type state. */
468                   for ( ; tmp != NULL_TREE;  tmp = TREE_CHAIN (tmp))
469                     {
470                       tree return_label = TREE_VALUE (tmp);
471                       tree return_state = LABEL_TYPE_STATE (return_label);
472                       if (return_state == NULL_TREE)
473                         {
474                           /* This means means we had not verified the
475                              subroutine earlier, so this is the first jsr to
476                              call it.  In this case, the type_map of the return
477                              address is just the current type_map - and that
478                              is handled by the following PUSH_PENDING. */
479                         }
480                       else
481                         {
482                           /* In this case we have to do a merge.  But first
483                              restore the type_map for unused slots to those
484                              that were in effect at the jsr. */
485                           for (index = size;  --index >= 0; )
486                             {
487                               type_map[index] = TREE_VEC_ELT (ret_map, index);
488                               if (type_map[index] == TYPE_UNUSED)
489                                 type_map[index]
490                                   = TREE_VEC_ELT (return_state, index);
491                             }
492                         }
493                       PUSH_PENDING (return_label);
494                     }
495                 }
496             }
497         }
498       if (PC == INVALID_PC)
499         {
500           label = pending_blocks;
501           if (label == NULL_TREE)
502             break;  /* We're done! */
503           pending_blocks = LABEL_PENDING_CHAIN (label);
504           LABEL_CHANGED (label) = 0;
505
506           if (LABEL_IN_SUBR (label))
507             current_subr = LABEL_SUBR_START (label);
508           else
509             current_subr = NULL_TREE;
510
511           /* Restore type_map and stack_pointer from
512              LABEL_TYPE_STATE (label), and continue
513              compiling from there. */
514           load_type_state (label);
515           PC = LABEL_PC (label);
516         }
517       else if (PC >= length)
518         VERIFICATION_ERROR ("falling through end of method");
519
520       /* fprintf (stderr, "** %d\n", PC); */
521
522       oldpc = PC;
523
524       if (!(instruction_bits [PC] & BCODE_INSTRUCTION_START) && ! wide)
525         VERIFICATION_ERROR ("PC not at instruction start");
526
527       instruction_bits[PC] |= BCODE_VERIFIED;
528
529       eh_ranges = find_handler (oldpc);
530
531       op_code = byte_ops[PC++];
532       switch (op_code)
533         {
534           int is_static, is_putting;
535         case OPCODE_nop:
536           break;
537         case OPCODE_iconst_m1:
538         case OPCODE_iconst_0:   case OPCODE_iconst_1:   case OPCODE_iconst_2:
539         case OPCODE_iconst_3:   case OPCODE_iconst_4:   case OPCODE_iconst_5:
540           i = op_code - OPCODE_iconst_0;
541           goto push_int;
542         push_int:
543           if (byte_ops[PC] == OPCODE_newarray
544               || byte_ops[PC] == OPCODE_newarray)
545             int_value = i;
546           push_type (int_type_node);  break;
547         case OPCODE_lconst_0:   case OPCODE_lconst_1:
548           push_type (long_type_node);  break;
549         case OPCODE_fconst_0:   case OPCODE_fconst_1:   case OPCODE_fconst_2:
550           push_type (float_type_node);  break;
551         case OPCODE_dconst_0:   case OPCODE_dconst_1:
552           push_type (double_type_node);  break;
553         case OPCODE_bipush:
554           i = IMMEDIATE_s1;
555           goto push_int;
556         case OPCODE_sipush:
557           i = IMMEDIATE_s2;
558           goto push_int;
559         case OPCODE_iload:  type = int_type_node;  goto general_load;
560         case OPCODE_lload:  type = long_type_node;  goto general_load;
561         case OPCODE_fload:  type = float_type_node;  goto general_load;
562         case OPCODE_dload:  type = double_type_node;  goto general_load;
563         case OPCODE_aload:  type = ptr_type_node;  goto general_load;
564         general_load:
565         index = wide ? IMMEDIATE_u2 : IMMEDIATE_u1;
566         wide = 0;
567         goto load;
568         case OPCODE_iload_0:  type = int_type_node;  index = 0; goto load;
569         case OPCODE_iload_1:  type = int_type_node;  index = 1; goto load;
570         case OPCODE_iload_2:  type = int_type_node;  index = 2; goto load;
571         case OPCODE_iload_3:  type = int_type_node;  index = 3; goto load;
572         case OPCODE_lload_0:  type = long_type_node; index = 0; goto load;
573         case OPCODE_lload_1:  type = long_type_node; index = 1; goto load;
574         case OPCODE_lload_2:  type = long_type_node; index = 2; goto load;
575         case OPCODE_lload_3:  type = long_type_node; index = 3; goto load;
576         case OPCODE_fload_0:  type = float_type_node; index = 0; goto load;
577         case OPCODE_fload_1:  type = float_type_node; index = 1; goto load;
578         case OPCODE_fload_2:  type = float_type_node; index = 2; goto load;
579         case OPCODE_fload_3:  type = float_type_node; index = 3; goto load;
580         case OPCODE_dload_0: type = double_type_node; index = 0; goto load;
581         case OPCODE_dload_1: type = double_type_node; index = 1; goto load;
582         case OPCODE_dload_2: type = double_type_node; index = 2; goto load;
583         case OPCODE_dload_3: type = double_type_node; index = 3; goto load;
584         case OPCODE_aload_0:  type = ptr_type_node;  index = 0;  goto load;
585         case OPCODE_aload_1:  type = ptr_type_node;  index = 1;  goto load;
586         case OPCODE_aload_2:  type = ptr_type_node;  index = 2;  goto load;
587         case OPCODE_aload_3:  type = ptr_type_node;  index = 3;  goto load;
588         load:
589         if (index < 0
590             || (index + TYPE_IS_WIDE (type)
591                 >= DECL_MAX_LOCALS (current_function_decl)))
592           VERIFICATION_ERROR ("invalid local variable index in load");
593         tmp = type_map[index];
594         if (tmp == TYPE_UNKNOWN || tmp == TYPE_SECOND
595             || (TYPE_IS_WIDE (type)
596                 && type_map[index+1] != void_type_node)
597             || (type == ptr_type_node
598                 ? TREE_CODE (tmp) != POINTER_TYPE
599                 : type == int_type_node
600                 ? (! INTEGRAL_TYPE_P (tmp) || TYPE_PRECISION (tmp) > 32)
601                 : type != tmp))
602           VERIFICATION_ERROR("invalid local variable type in load");
603         push_type (tmp);
604         goto note_used;
605         case OPCODE_istore:  type = int_type_node;  goto general_store;
606         case OPCODE_lstore:  type = long_type_node;  goto general_store;
607         case OPCODE_fstore:  type = float_type_node;  goto general_store;
608         case OPCODE_dstore:  type = double_type_node;  goto general_store;
609         case OPCODE_astore:  type = ptr_type_node;  goto general_store;
610         general_store:
611         index = wide ? IMMEDIATE_u2 : IMMEDIATE_u1;
612         wide = 0;
613         goto store;
614         case OPCODE_istore_0:  type = int_type_node; index = 0; goto store;
615         case OPCODE_istore_1:  type = int_type_node; index = 1; goto store;
616         case OPCODE_istore_2:  type = int_type_node; index = 2; goto store;
617         case OPCODE_istore_3:  type = int_type_node; index = 3; goto store;
618         case OPCODE_lstore_0:  type = long_type_node; index=0; goto store;
619         case OPCODE_lstore_1:  type = long_type_node; index=1; goto store;
620         case OPCODE_lstore_2:  type = long_type_node; index=2; goto store;
621         case OPCODE_lstore_3:  type = long_type_node; index=3; goto store;
622         case OPCODE_fstore_0:  type=float_type_node; index=0; goto store;
623         case OPCODE_fstore_1:  type=float_type_node; index=1; goto store;
624         case OPCODE_fstore_2:  type=float_type_node; index=2; goto store;
625         case OPCODE_fstore_3:  type=float_type_node; index=3; goto store;
626         case OPCODE_dstore_0:  type=double_type_node; index=0; goto store;
627         case OPCODE_dstore_1:  type=double_type_node; index=1; goto store;
628         case OPCODE_dstore_2:  type=double_type_node; index=2; goto store;
629         case OPCODE_dstore_3:  type=double_type_node; index=3; goto store;
630         case OPCODE_astore_0:  type = ptr_type_node; index = 0; goto store;
631         case OPCODE_astore_1:  type = ptr_type_node; index = 1; goto store;
632         case OPCODE_astore_2:  type = ptr_type_node; index = 2; goto store;
633         case OPCODE_astore_3:  type = ptr_type_node; index = 3; goto store;
634         store:
635         if (index < 0
636             || (index + TYPE_IS_WIDE (type)
637                 >= DECL_MAX_LOCALS (current_function_decl)))
638           {
639             VERIFICATION_ERROR ("invalid local variable index in store");
640             return 0;
641           }
642         type = pop_type (type);
643         type_map[index] = type;
644
645         /* If local variable changed, we need to reconsider eh handlers. */
646         prev_eh_ranges = NULL_EH_RANGE;
647
648         /* Allocate decl and rtx for this variable now, so if we're not
649            optmizing, we get a temporary that survives the whole method. */
650         find_local_variable (index, type, oldpc);
651
652         if (TYPE_IS_WIDE (type))
653           type_map[index+1] = TYPE_SECOND;
654         /* ... fall through to note_used ... */
655         note_used:
656           /* For store or load, note that local variable INDEX is used.
657              This is needed to verify try-finally sub-routines. */
658           if (current_subr)
659             {
660               tree vec = LABEL_RETURN_TYPE_STATE (current_subr);
661               tree subr_vec = LABEL_TYPE_STATE (current_subr);
662               int len = 1 + TYPE_IS_WIDE (type);
663               while (--len >= 0)
664                 {
665                   if (TREE_VEC_ELT (vec, index) == TYPE_UNUSED)
666                     TREE_VEC_ELT (vec, index) = TREE_VEC_ELT (subr_vec, index);
667                 }
668             }
669         break;
670         case OPCODE_iadd:
671         case OPCODE_iand:
672         case OPCODE_idiv:
673         case OPCODE_imul:
674         case OPCODE_ior:
675         case OPCODE_irem:
676         case OPCODE_ishl:
677         case OPCODE_ishr:
678         case OPCODE_isub:
679         case OPCODE_iushr:
680         case OPCODE_ixor:
681           type = int_type_node;  goto binop;
682         case OPCODE_ineg:
683         case OPCODE_i2c:
684         case OPCODE_i2b:
685         case OPCODE_i2s:
686           type = int_type_node;  goto unop;
687         case OPCODE_ladd:
688         case OPCODE_land:
689         case OPCODE_ldiv:
690         case OPCODE_lsub:
691         case OPCODE_lmul:
692         case OPCODE_lrem:
693         case OPCODE_lor:
694         case OPCODE_lxor:
695           type = long_type_node;  goto binop;
696         case OPCODE_lneg:
697           type = long_type_node;  goto unop;
698         case OPCODE_fadd:       case OPCODE_fsub:
699         case OPCODE_fmul:       case OPCODE_fdiv:       case OPCODE_frem:
700           type = float_type_node;  goto binop;
701         case OPCODE_fneg:
702           type = float_type_node;  goto unop;
703         case OPCODE_dadd:       case OPCODE_dsub:
704         case OPCODE_dmul:       case OPCODE_ddiv:       case OPCODE_drem:
705           type = double_type_node;  goto binop;
706         case OPCODE_dneg:
707           type = double_type_node;  goto unop;
708         unop:
709           pop_type (type);
710           push_type (type);
711           break;
712         binop:
713           pop_type (type);
714           pop_type (type);
715           push_type (type);
716           break;
717         case OPCODE_lshl:
718         case OPCODE_lshr:
719         case OPCODE_lushr:
720           pop_type (int_type_node);
721           pop_type (long_type_node);
722           push_type (long_type_node);
723           break;
724         case OPCODE_iinc:
725           index = wide ? IMMEDIATE_u2 : IMMEDIATE_u1;
726           PC += wide + 1;
727           wide = 0;
728           if (index < 0 || index >= DECL_MAX_LOCALS (current_function_decl))
729             VERIFICATION_ERROR ("invalid local variable index in iinc");
730           tmp = type_map[index];
731           if (! INTEGRAL_TYPE_P (tmp) || TYPE_PRECISION (tmp) > 32)
732             VERIFICATION_ERROR ("invalid local variable type in iinc");
733           break;
734         case OPCODE_i2l:
735           pop_type (int_type_node);    push_type (long_type_node);   break;
736         case OPCODE_i2f:
737           pop_type (int_type_node);    push_type (float_type_node);  break;
738         case OPCODE_i2d:
739           pop_type (int_type_node);    push_type (double_type_node); break;
740         case OPCODE_l2i:
741           pop_type (long_type_node);   push_type (int_type_node);    break;
742         case OPCODE_l2f:
743           pop_type (long_type_node);   push_type (float_type_node);  break;
744         case OPCODE_l2d:
745           pop_type (long_type_node);   push_type (double_type_node); break;
746         case OPCODE_f2i:
747           pop_type (float_type_node);  push_type (int_type_node);    break;
748         case OPCODE_f2l:
749           pop_type (float_type_node);  push_type (long_type_node);   break;
750         case OPCODE_f2d:
751           pop_type (float_type_node);  push_type (double_type_node); break;
752         case OPCODE_d2i:
753           pop_type (double_type_node); push_type (int_type_node);    break;
754         case OPCODE_d2l:
755           pop_type (double_type_node); push_type (long_type_node);   break;
756         case OPCODE_d2f:
757           pop_type (double_type_node); push_type (float_type_node);  break;
758         case OPCODE_lcmp:
759           type = long_type_node;  goto compare;
760         case OPCODE_fcmpl:
761         case OPCODE_fcmpg:
762           type = float_type_node;  goto compare;
763         case OPCODE_dcmpl:
764         case OPCODE_dcmpg:
765           type = double_type_node;  goto compare;
766         compare:
767           pop_type (type);  pop_type (type);
768           push_type (int_type_node);  break;
769         case OPCODE_ifeq:
770         case OPCODE_ifne:
771         case OPCODE_iflt:
772         case OPCODE_ifge:
773         case OPCODE_ifgt:
774         case OPCODE_ifle:
775           pop_type (int_type_node);  goto cond;
776         case OPCODE_ifnull:
777         case OPCODE_ifnonnull:
778           pop_type (ptr_type_node ); goto cond;
779         case OPCODE_if_icmpeq:
780         case OPCODE_if_icmpne:
781         case OPCODE_if_icmplt:
782         case OPCODE_if_icmpge:
783         case OPCODE_if_icmpgt:
784         case OPCODE_if_icmple:
785           pop_type (int_type_node);  pop_type (int_type_node);  goto cond;
786         case OPCODE_if_acmpeq:
787         case OPCODE_if_acmpne:
788           pop_type (object_ptr_type_node);  pop_type (object_ptr_type_node);
789           goto cond;
790         cond:
791           PUSH_PENDING (lookup_label (oldpc + IMMEDIATE_s2));
792           break;
793         case OPCODE_goto:
794           PUSH_PENDING (lookup_label (oldpc + IMMEDIATE_s2));
795           INVALIDATE_PC;
796           break;
797         case OPCODE_wide:
798           switch (byte_ops[PC])
799             {
800             case OPCODE_iload:  case OPCODE_lload:
801             case OPCODE_fload:  case OPCODE_dload:  case OPCODE_aload:
802             case OPCODE_istore:  case OPCODE_lstore:
803             case OPCODE_fstore:  case OPCODE_dstore:  case OPCODE_astore:
804             case OPCODE_iinc:
805             case OPCODE_ret:
806               wide = 1;
807               break;
808             default:
809               VERIFICATION_ERROR ("invalid use of wide instruction");
810             }
811           break;
812         case OPCODE_return:   type = void_type_node;   goto ret;
813         case OPCODE_ireturn:
814           if ((TREE_CODE (return_type) == BOOLEAN_TYPE
815                || TREE_CODE (return_type) == CHAR_TYPE
816                || TREE_CODE (return_type) == INTEGER_TYPE)
817               && TYPE_PRECISION (return_type) <= 32)
818             type = return_type;
819           else
820             type = NULL_TREE;
821           goto ret;
822         case OPCODE_lreturn:  type = long_type_node;   goto ret;
823         case OPCODE_freturn:  type = float_type_node;  goto ret;
824         case OPCODE_dreturn:  type = double_type_node; goto ret;
825         case OPCODE_areturn:
826           if (TREE_CODE (return_type) == POINTER_TYPE)
827             type = return_type;
828           else
829             type = NULL_TREE;
830           goto ret;
831         ret:
832           if (type != return_type)
833             VERIFICATION_ERROR ("incorrect ?return opcode");
834           if (type != void_type_node)
835             {
836               if (pop_type_0 (type) == NULL_TREE)
837                 VERIFICATION_ERROR ("return value has wrong type");
838             }
839           INVALIDATE_PC;
840           break;
841         case OPCODE_getstatic: is_putting = 0;  is_static = 1;  goto field;
842         case OPCODE_putstatic: is_putting = 1;  is_static = 1;  goto field;
843         case OPCODE_getfield:  is_putting = 0;  is_static = 0;  goto field;
844         case OPCODE_putfield:  is_putting = 1;  is_static = 0;  goto field;
845         field:
846           {
847             int index = IMMEDIATE_u2;
848             tree field_signature = COMPONENT_REF_SIGNATURE (&current_jcf->cpool, index);
849             tree field_type = get_type_from_signature (field_signature);
850             if (is_putting)
851               pop_type (field_type);
852             if (! is_static)
853               {
854                 int clindex = COMPONENT_REF_CLASS_INDEX (&current_jcf->cpool,
855                                                         index);
856                 tree self_type = get_class_constant (current_jcf, clindex);
857                 /* Defer actual checking until next pass. */
858                 if (pop_type_0 (self_type) == NULL_TREE)
859                   VERIFICATION_ERROR ("incorrect type for field reference");
860               }
861             if (! is_putting)
862               push_type (field_type);
863             break;
864           }
865         case OPCODE_new:
866           push_type (get_class_constant (jcf, IMMEDIATE_u2));
867           break;
868         case OPCODE_dup:     type_stack_dup (1, 0);  break;
869         case OPCODE_dup_x1:  type_stack_dup (1, 1);  break;
870         case OPCODE_dup_x2:  type_stack_dup (1, 2);  break;
871         case OPCODE_dup2:    type_stack_dup (2, 0);  break;
872         case OPCODE_dup2_x1: type_stack_dup (2, 1);  break;
873         case OPCODE_dup2_x2: type_stack_dup (2, 2);  break;
874         case OPCODE_pop:  index = 1;  goto pop;
875         case OPCODE_pop2: index = 2;  goto pop;
876         pop:
877           if (stack_pointer < index)
878             VERIFICATION_ERROR ("stack underflow");
879           stack_pointer -= index;
880           break;
881         case OPCODE_swap:
882           if (stack_pointer < 2)
883             VERIFICATION_ERROR ("stack underflow (in swap)");
884           else
885             {
886               tree type1 = stack_type_map[stack_pointer - 1];
887               tree type2 = stack_type_map[stack_pointer - 2];
888               if (type1 == void_type_node || type2 == void_type_node)
889                 VERIFICATION_ERROR ("verifier (swap):  double or long value");
890               stack_type_map[stack_pointer - 2] = type1;
891               stack_type_map[stack_pointer - 1] = type2;
892             }
893           break;
894         case OPCODE_ldc:   index = IMMEDIATE_u1;  goto ldc;
895         case OPCODE_ldc2_w:
896         case OPCODE_ldc_w:
897           index = IMMEDIATE_u2;  goto ldc;
898         ldc:
899           if (index <= 0 || index >= JPOOL_SIZE(current_jcf))
900             VERIFICATION_ERROR ("bad constant pool index in ldc");
901           int_value = -1;
902           switch (JPOOL_TAG (current_jcf, index) & ~CONSTANT_ResolvedFlag)
903             {
904             case CONSTANT_Integer:  type = int_type_node;  goto check_ldc;
905             case CONSTANT_Float:    type = float_type_node;  goto check_ldc;
906             case CONSTANT_String:   type = string_type_node; goto check_ldc;
907             case CONSTANT_Long:    type = long_type_node;    goto check_ldc;
908             case CONSTANT_Double:  type = double_type_node;  goto check_ldc;
909             check_ldc:
910               if (TYPE_IS_WIDE (type) == (op_code == OPCODE_ldc2_w))
911                 break;
912               /* ... else fall through ... */
913             default:
914               VERIFICATION_ERROR ("bad constant pool tag in ldc");
915             }
916           if (type == int_type_node)
917             {
918               i = TREE_INT_CST_LOW (get_constant (current_jcf, index));
919               goto push_int;
920             }
921           push_type (type);
922           break;
923
924         case OPCODE_invokevirtual:
925         case OPCODE_invokespecial:
926         case OPCODE_invokestatic:
927         case OPCODE_invokeinterface:
928           {
929             int index = IMMEDIATE_u2;
930             tree sig = COMPONENT_REF_SIGNATURE (&current_jcf->cpool, index);
931             tree self_type = get_class_constant
932               (current_jcf, COMPONENT_REF_CLASS_INDEX (&current_jcf->cpool,
933                                                        index));
934             tree method_name = COMPONENT_REF_NAME (&current_jcf->cpool, index);
935             tree method_type;
936             method_type = parse_signature_string (IDENTIFIER_POINTER (sig),
937                                                   IDENTIFIER_LENGTH (sig));
938             if (TREE_CODE (method_type) != FUNCTION_TYPE)
939               VERIFICATION_ERROR ("bad method signature");
940             pop_argument_types (TYPE_ARG_TYPES (method_type));
941
942             /* Can't invoke <clinit> */
943             if (method_name == clinit_identifier_node)
944               VERIFICATION_ERROR ("invoke opcode can't invoke <clinit>");
945             /* Apart invokespecial, can't invoke <init> */
946             if (op_code != OPCODE_invokespecial
947                 && method_name == init_identifier_node)
948               VERIFICATION_ERROR ("invoke opcode can't invoke <init>");
949
950             if (op_code != OPCODE_invokestatic)
951               pop_type (self_type);
952
953             switch (op_code)
954               {
955               case OPCODE_invokeinterface:
956                 {
957                   int nargs    = IMMEDIATE_u1;
958                   int notZero  = IMMEDIATE_u1;
959                 
960                   if (!nargs || notZero)
961                       VERIFICATION_ERROR 
962                         ("invalid argument number in invokeinterface");
963                   break;                  
964                 }
965               }
966
967             if (TREE_TYPE (method_type) != void_type_node)
968               push_type (TREE_TYPE (method_type));
969             break;
970           }
971
972         case OPCODE_arraylength:
973             /* Type checking actually made during code generation */
974             pop_type( ptr_type_node );
975             push_type( int_type_node );
976             break;
977             
978         /* Q&D verification *or* more checking done during code generation
979            for byte/boolean/char/short, the value popped is a int coerced
980            into the right type before being stored.  */
981         case OPCODE_iastore: type = int_type_node;     goto astore;
982         case OPCODE_lastore: type = long_type_node;    goto astore;
983         case OPCODE_fastore: type = float_type_node;   goto astore;
984         case OPCODE_dastore: type = double_type_node;  goto astore;
985         case OPCODE_aastore: type = ptr_type_node;     goto astore;
986         case OPCODE_bastore: type = int_type_node; goto astore;
987         case OPCODE_castore: type = int_type_node; goto astore;
988         case OPCODE_sastore: type = int_type_node; goto astore;
989         astore:
990           /* FIXME - need better verification here */
991           pop_type (type);           /* new value */
992           pop_type (int_type_node);  /* index */
993           pop_type (ptr_type_node);  /* array */
994           break;
995
996         /* Q&D verification *or* more checking done during code generation
997            for byte/boolean/char/short, the value pushed is a int.  */
998         case OPCODE_iaload: type = int_type_node;     goto aload;
999         case OPCODE_laload: type = long_type_node;    goto aload;
1000         case OPCODE_faload: type = float_type_node;   goto aload;
1001         case OPCODE_daload: type = double_type_node;  goto aload;
1002         case OPCODE_aaload: type = ptr_type_node;     goto aload;
1003         case OPCODE_baload: type = promote_type (byte_type_node);  goto aload;
1004         case OPCODE_caload: type = promote_type (char_type_node);  goto aload;
1005         case OPCODE_saload: type = promote_type (short_type_node); goto aload;
1006         aload:
1007           pop_type (int_type_node);
1008           tmp = pop_type (ptr_type_node);
1009           if (is_array_type_p (tmp))
1010             type = TYPE_ARRAY_ELEMENT (TREE_TYPE (tmp));
1011           else if (tmp != TYPE_NULL)
1012             VERIFICATION_ERROR ("array load from non-array type");
1013           push_type (type);
1014           break;
1015
1016         case OPCODE_anewarray:
1017           type = get_class_constant (current_jcf, IMMEDIATE_u2);
1018           type = promote_type (type);
1019           goto newarray;
1020
1021         case OPCODE_newarray:
1022           index = IMMEDIATE_u1;
1023           type = decode_newarray_type (index);
1024           if (type == NULL_TREE)
1025             VERIFICATION_ERROR ("invalid type code in newarray opcode");
1026           goto newarray;
1027
1028         newarray:
1029           if (int_value >= 0 && prevpc >= 0)
1030             {
1031               /* If previous instruction pushed int constant,
1032                  we want to use it. */
1033               switch (byte_ops[prevpc])
1034                 {
1035                 case OPCODE_iconst_0: case OPCODE_iconst_1:
1036                 case OPCODE_iconst_2: case OPCODE_iconst_3:
1037                 case OPCODE_iconst_4: case OPCODE_iconst_5:
1038                 case OPCODE_bipush:  case OPCODE_sipush:
1039                 case OPCODE_ldc: case OPCODE_ldc_w:
1040                   break;
1041                 default:
1042                   int_value = -1;
1043                 }
1044             }
1045           else
1046             int_value = -1;
1047           type = build_java_array_type (type, int_value);
1048           pop_type (int_type_node);
1049           push_type (type);
1050           break;
1051
1052         case OPCODE_multianewarray:
1053           {
1054             int ndim, i;
1055             index = IMMEDIATE_u2;
1056             ndim  = IMMEDIATE_u1;
1057
1058             if( ndim < 1 )
1059               VERIFICATION_ERROR ("number of dimension lower that 1 in multianewarray" );
1060
1061             for( i = 0; i < ndim; i++ )
1062               pop_type (int_type_node);
1063             push_type (get_class_constant (current_jcf, index));
1064             break;
1065           }
1066
1067         case OPCODE_aconst_null:
1068           push_type (ptr_type_node);
1069           break;
1070
1071         case OPCODE_athrow:
1072           /* FIXME: athrow also empties the stack. */
1073           pop_type (throwable_type_node);
1074           INVALIDATE_PC;
1075           break;
1076
1077         case OPCODE_checkcast:
1078           pop_type (ptr_type_node);
1079           type = get_class_constant (current_jcf, IMMEDIATE_u2);
1080           push_type (type);
1081           break;
1082         case OPCODE_instanceof:
1083           pop_type (ptr_type_node);
1084           get_class_constant (current_jcf, IMMEDIATE_u2);
1085           push_type (int_type_node);
1086           break;
1087
1088         case OPCODE_tableswitch:
1089           {
1090             jint low, high;
1091
1092             pop_type (int_type_node);
1093             while (PC%4)
1094               {
1095                 if (byte_ops[PC++])
1096                   VERIFICATION_ERROR ("bad alignment in tableswitch pad");
1097               }
1098             PUSH_PENDING (lookup_label (oldpc+IMMEDIATE_s4));
1099             low  = IMMEDIATE_s4;
1100             high = IMMEDIATE_s4;
1101
1102             if (low > high)
1103               VERIFICATION_ERROR ("unsorted low/high value in tableswitch");
1104
1105             while (low++ <= high)
1106               PUSH_PENDING (lookup_label (oldpc + IMMEDIATE_s4));
1107             INVALIDATE_PC;
1108             break;
1109           }
1110
1111         case OPCODE_lookupswitch:
1112           {
1113             jint npairs, last = 0, not_registered = 1;
1114
1115             pop_type (int_type_node);
1116             while (PC%4)
1117               {
1118                 if (byte_ops[PC++])
1119                   VERIFICATION_ERROR ("bad alignment in lookupswitch pad");
1120               }
1121
1122             PUSH_PENDING (lookup_label (oldpc+IMMEDIATE_s4));
1123             npairs = IMMEDIATE_s4;
1124             
1125             if (npairs < 0)
1126               VERIFICATION_ERROR ("invalid number of targets in lookupswitch");
1127
1128             while (npairs--)
1129               {
1130                 int match = IMMEDIATE_s4;
1131                 if (not_registered)
1132                   not_registered = 0;
1133                 else if (last >= match)
1134                   VERIFICATION_ERROR ("unsorted match value in lookupswitch");
1135
1136                 last = match;
1137                 PUSH_PENDING (lookup_label (oldpc + IMMEDIATE_s4));
1138               }
1139             INVALIDATE_PC;
1140             break;
1141           }
1142
1143         case OPCODE_monitorenter: 
1144           /* fall thru */
1145         case OPCODE_monitorexit:
1146           pop_type (ptr_type_node);
1147           break;
1148
1149         case OPCODE_goto_w:
1150           PUSH_PENDING (lookup_label (oldpc + IMMEDIATE_s4));
1151           INVALIDATE_PC;
1152           break;
1153
1154         case OPCODE_jsr:
1155           {
1156             tree target = lookup_label (oldpc + IMMEDIATE_s2);
1157             tree return_label = lookup_label (PC);
1158             push_type (return_address_type_node);
1159             /* The return label chain will be null if this is the first
1160                time we've seen this jsr target.  */
1161             if (LABEL_RETURN_LABEL (target) == NULL_TREE)
1162               {
1163                 tree return_type_map;
1164                 int nlocals = DECL_MAX_LOCALS (current_function_decl);
1165                 index = nlocals + DECL_MAX_STACK (current_function_decl);
1166                 return_type_map = make_tree_vec (index);
1167                 while (index > nlocals)
1168                   TREE_VEC_ELT (return_type_map, --index) = TYPE_UNKNOWN;
1169                 while (index > 0)
1170                   TREE_VEC_ELT (return_type_map, --index) = TYPE_UNUSED;
1171                 LABEL_RETURN_LABEL (target)
1172                   = build_decl (LABEL_DECL, NULL_TREE, TREE_TYPE (target));
1173                 LABEL_PC (LABEL_RETURN_LABEL (target)) = -1;
1174                 LABEL_RETURN_TYPE_STATE (target) = return_type_map;
1175                 LABEL_IS_SUBR_START (target) = 1;
1176                 LABEL_IN_SUBR (target) = 1;
1177                 LABEL_SUBR_START (target) = target;
1178                 LABEL_SUBR_CONTEXT (target) = current_subr;
1179               }
1180             else if (! LABEL_IS_SUBR_START (target)
1181                      || LABEL_SUBR_CONTEXT (target) != current_subr)
1182               VERIFICATION_ERROR ("label part of different subroutines");
1183
1184             i = merge_type_state (target);
1185             if (i != 0)
1186               {
1187                 if (i < 0)
1188                   VERIFICATION_ERROR ("types could not be merged at jsr");
1189                 push_pending_label (target);
1190               }
1191             current_subr = target;
1192
1193             /* Chain return_pc onto LABEL_RETURN_LABELS (target) if needed. */
1194             if (! value_member (return_label, LABEL_RETURN_LABELS (target)))
1195               {
1196                 LABEL_RETURN_LABELS (target)
1197                   = tree_cons (NULL_TREE, return_label,
1198                                LABEL_RETURN_LABELS (target));
1199               }
1200
1201             if (LABEL_VERIFIED (target))
1202               {
1203                 tree return_map = LABEL_RETURN_TYPE_STATE (target);
1204                 int len = TREE_VEC_LENGTH (return_map);
1205                 stack_pointer = len - DECL_MAX_LOCALS (current_function_decl);
1206                 while (--len >= 0)
1207                   {
1208                     if (TREE_VEC_ELT (return_map, len) != TYPE_UNUSED)
1209                       type_map[len] = TREE_VEC_ELT (return_map, len);
1210                   }
1211                 current_subr = LABEL_SUBR_CONTEXT (target);
1212                 PUSH_PENDING (return_label);
1213               }
1214
1215             INVALIDATE_PC;
1216           }
1217           break;
1218         case OPCODE_ret:
1219           if (current_subr == NULL)
1220             VERIFICATION_ERROR ("ret instruction not in a jsr subroutine");
1221           else
1222             {
1223               tree ret_map = LABEL_RETURN_TYPE_STATE (current_subr);
1224               int size = DECL_MAX_LOCALS(current_function_decl)+stack_pointer;
1225               index = wide ? IMMEDIATE_u2 : IMMEDIATE_u1;
1226               wide = 0;
1227               INVALIDATE_PC;
1228               if (index < 0 || index >= DECL_MAX_LOCALS (current_function_decl)
1229                   || type_map[index] != TYPE_RETURN_ADDR)
1230                 VERIFICATION_ERROR ("invalid ret index");
1231
1232               /* The next chunk of code is similar to an inlined version of
1233                *     merge_type_state (LABEL_RETURN_LABEL (current_subr)).
1234                * The main differences are that LABEL_RETURN_LABEL is
1235                * pre-allocated by the jsr (but we don't know the size then);
1236                * and that we have to handle TYPE_UNUSED. */
1237
1238               if (! RETURN_MAP_ADJUSTED (ret_map))
1239                 { /* First return from this subroutine - fix stack pointer. */
1240                   TREE_VEC_LENGTH (ret_map) = size;
1241                   for (index = size;  --index >= 0; )
1242                     {
1243                       if (TREE_VEC_ELT (ret_map, index) != TYPE_UNUSED)
1244                         TREE_VEC_ELT (ret_map, index) = type_map[index];
1245                     }
1246                   RETURN_MAP_ADJUSTED (ret_map) = 1;
1247                 }
1248               else
1249                 {
1250                   if (TREE_VEC_LENGTH (ret_map) != size)
1251                     VERIFICATION_ERROR ("inconsistent stack size on ret");
1252                   for (index = 0;  index < size;  index++)
1253                     {
1254                       tree type = TREE_VEC_ELT (ret_map, index);
1255                       if (type != TYPE_UNUSED)
1256                         {
1257                           type = merge_types (type, type_map [index]);
1258                           TREE_VEC_ELT (ret_map, index) = type;
1259                           if (type == TYPE_UNKNOWN)
1260                             {
1261                               if (index >= size - stack_pointer)
1262                                 VERIFICATION_ERROR
1263                                   ("inconsistent types on ret from jsr");
1264                             }
1265                           else if (TYPE_IS_WIDE (type))
1266                             index++;
1267                         }
1268                     }
1269                 }
1270
1271
1272             }
1273           break;
1274         case OPCODE_jsr_w:        
1275         case OPCODE_ret_w:
1276         default:
1277           error ("unknown opcode %d@pc=%d during verification", op_code, PC-1);
1278           return 0;
1279         }
1280
1281       prevpc = oldpc;
1282
1283       /* The following test is true if we have entered or exited an exception
1284          handler range *or* we have done a store to a local variable.
1285          In either case we need to consider any exception handlers that
1286          might "follow" this instruction. */
1287
1288       if (eh_ranges != prev_eh_ranges)
1289         {
1290           int save_stack_pointer = stack_pointer;
1291           int index = DECL_MAX_LOCALS (current_function_decl);
1292           tree save_type = type_map[index];
1293           tree save_current_subr = current_subr;
1294           struct eh_range *ranges = find_handler (oldpc);
1295           stack_pointer = 1;
1296           for (; ranges != NULL_EH_RANGE;  ranges = ranges->outer)
1297             {
1298               tree chain = ranges->handlers;
1299
1300               /* We need to determine if the handler is part of current_subr.
1301                  The are two cases:  (1) The exception catch range
1302                  is entirely within current_subr.  In that case the handler
1303                  is also part of current_subr.
1304                  (2) Some of the catch range is not in current_subr.
1305                  In that case, the handler is *not* part of current_subr.
1306
1307                  Figuring out which is the case is not necessarily obvious,
1308                  in the presence of clever code generators (and obfuscators).
1309                  We make a simplifying assumption that in case (2) we
1310                  have that the current_subr is entirely within the catch range.
1311                  In that case we can assume if that if a caller (the jsr) of
1312                  a subroutine is within the catch range, then the handler is
1313                  *not* part of the subroutine, and vice versa. */
1314
1315               current_subr = save_current_subr;
1316               for ( ; current_subr != NULL_TREE;
1317                     current_subr = LABEL_SUBR_CONTEXT (current_subr))
1318                 {
1319                   tree return_labels = LABEL_RETURN_LABELS (current_subr);
1320                   /* There could be multiple return_labels, but
1321                      we only need to check one. */
1322                   int return_pc = LABEL_PC (TREE_VALUE (return_labels));
1323                   if (return_pc <= ranges->start_pc
1324                       || return_pc > ranges->end_pc)
1325                     break;
1326                 }
1327
1328               for ( ;  chain != NULL_TREE;  chain = TREE_CHAIN (chain))
1329                 {
1330                   tree handler = TREE_VALUE (chain);
1331                   tree type = TREE_PURPOSE (chain);
1332                   if (type == NULL_TREE)  /* a finally handler */
1333                     type = throwable_type_node;
1334                   type_map[index] = promote_type (type);
1335
1336                   PUSH_PENDING (handler);
1337                 }
1338             }
1339           stack_pointer = save_stack_pointer;
1340           current_subr = save_current_subr;
1341           type_map[index] = save_type;
1342           prev_eh_ranges = eh_ranges;
1343         }
1344     }
1345   return 1;
1346  bad_pc:
1347   message = "program counter out of range";
1348   goto verify_error;
1349  verify_error:
1350   error ("verification error at PC=%d", oldpc);
1351   error ("%s", message);
1352   return 0;
1353 }