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