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