* src/vm/resolve.c (resolve_method_verifier_checks)
[cacao.git] / src / vm / jit / parse.c
1 /* src/vm/jit/parse.c - parser for JavaVM to intermediate code translation
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Author: Andreas Krall
28
29    Changes: Carolyn Oates
30             Edwin Steiner
31             Joseph Wenninger
32             Christian Thalinger
33
34    $Id: parse.c 4863 2006-04-30 16:17:44Z edwin $
35
36 */
37
38
39 #include "config.h"
40
41 #include <assert.h>
42 #include <string.h>
43
44 #include "vm/types.h"
45
46 #include "mm/memory.h"
47 #include "native/native.h"
48 #include "toolbox/logging.h"
49 #include "vm/builtin.h"
50 #include "vm/exceptions.h"
51 #include "vm/global.h"
52 #include "vm/linker.h"
53 #include "vm/loader.h"
54 #include "vm/resolve.h"
55 #include "vm/options.h"
56 #include "vm/statistics.h"
57 #include "vm/stringlocal.h"
58 #include "vm/jit/asmpart.h"
59 #include "vm/jit/jit.h"
60 #include "vm/jit/parse.h"
61 #include "vm/jit/patcher.h"
62 #include "vm/jit/loop/loop.h"
63
64 /*******************************************************************************
65
66         function 'parse' scans the JavaVM code and generates intermediate code
67
68         During parsing the block index table is used to store at bit pos 0
69         a flag which marks basic block starts and at position 1 to 31 the
70         intermediate instruction index. After parsing the block index table
71         is scanned, for marked positions a block is generated and the block
72         number is stored in the block index table.
73
74 *******************************************************************************/
75
76 static exceptiontable * fillextable(methodinfo *m, 
77                                                                         exceptiontable *extable, 
78                                                                         exceptiontable *raw_extable, 
79                                                                 int exceptiontablelength, 
80                                                                         int *block_count)
81 {
82         int b_count, p, src;
83         
84         if (exceptiontablelength == 0) 
85                 return extable;
86
87         b_count = *block_count;
88
89         for (src = exceptiontablelength-1; src >=0; src--) {
90                 /* the start of the handled region becomes a basic block start */
91                 p = raw_extable[src].startpc;
92                 CHECK_BYTECODE_INDEX(p);
93                 extable->startpc = p;
94                 block_insert(p);
95                 
96                 p = raw_extable[src].endpc; /* see JVM Spec 4.7.3 */
97                 CHECK_BYTECODE_INDEX_EXCLUSIVE(p);
98
99 #if defined(ENABLE_VERIFIER)
100                 if (p <= raw_extable[src].startpc) {
101                         *exceptionptr = new_verifyerror(m,
102                                 "Invalid exception handler range");
103                         return NULL;
104                 }
105 #endif
106                 extable->endpc = p;
107                 
108                 /* end of handled region becomes a basic block boundary  */
109                 /* (If it is the bytecode end, we'll use the special     */
110                 /* end block that is created anyway.)                    */
111                 if (p < m->jcodelength) 
112                         block_insert(p);
113
114                 /* the start of the handler becomes a basic block start  */
115                 p = raw_extable[src].handlerpc;
116                 CHECK_BYTECODE_INDEX(p);
117                 extable->handlerpc = p;
118                 block_insert(p);
119
120                 extable->catchtype = raw_extable[src].catchtype;
121                 extable->next = NULL;
122                 extable->down = &extable[1];
123                 extable--;
124         }
125
126         *block_count = b_count;
127         
128         /* everything ok */
129         return extable;
130
131 #if defined(ENABLE_VERIFIER)
132 throw_invalid_bytecode_index:
133         *exceptionptr =
134                 new_verifyerror(m, "Illegal bytecode index in exception table");
135         return NULL;
136 #endif
137 }
138
139 /*** macro for checking the length of the bytecode ***/
140
141 #if defined(ENABLE_VERIFIER)
142 #define CHECK_END_OF_BYTECODE(neededlength) \
143         do { \
144                 if ((neededlength) > m->jcodelength) \
145                         goto throw_unexpected_end_of_bytecode; \
146         } while (0)
147 #else /* !ENABLE_VERIFIER */
148 #define CHECK_END_OF_BYTECODE(neededlength)
149 #endif /* ENABLE_VERIFIER */
150
151 bool parse(jitdata *jd)
152 {
153         methodinfo  *m;
154         codegendata *cd;
155         int  p;                     /* java instruction counter           */
156         int  nextp;                 /* start of next java instruction     */
157         int  opcode;                /* java opcode                        */
158         int  i;                     /* temporary for different uses (ctrs)*/
159         int  ipc = 0;               /* intermediate instruction counter   */
160         int  b_count = 0;           /* basic block counter                */
161         int  s_count = 0;           /* stack element counter              */
162         bool blockend = false;      /* true if basic block end has been reached   */
163         bool iswide = false;        /* true if last instruction was a wide*/
164         instruction *iptr;          /* current ptr into instruction array */
165         int gp;                     /* global java instruction counter    */
166
167         u1 *instructionstart;       /* 1 for pcs which are valid instr. starts    */
168
169         constant_classref  *cr;
170         constant_classref  *compr;
171         classinfo          *c;
172         builtintable_entry *bte;
173
174         constant_FMIref   *mr;
175         methoddesc        *md;
176         unresolved_method *um;
177         resolve_result_t   result;
178
179         u2 lineindex = 0;
180         u2 currentline = 0;
181         u2 linepcchange = 0;
182
183         /* get required compiler data */
184
185         m  = jd->m;
186         cd = jd->cd;
187
188         /* allocate instruction array and block index table */
189         
190         /* 1 additional for end ipc  */
191         m->basicblockindex = DMNEW(s4, m->jcodelength + 1);
192         memset(m->basicblockindex, 0, sizeof(s4) * (m->jcodelength + 1));
193
194         instructionstart = DMNEW(u1, m->jcodelength + 1);
195         memset(instructionstart, 0, sizeof(u1) * (m->jcodelength + 1));
196
197         /* 1 additional for TRACEBUILTIN and 4 for MONITORENTER/EXIT */
198         /* additional MONITOREXITS are reached by branches which are 3 bytes */
199         
200         iptr = m->instructions = DMNEW(instruction, m->jcodelength + 5);
201
202         /* Zero the intermediate instructions array so we don't have any
203          * invalid pointers in it if we cannot finish analyse_stack(). */
204
205         memset(iptr, 0, sizeof(instruction) * (m->jcodelength + 5));
206         
207         /* compute branch targets of exception table */
208
209         if (!fillextable(m, 
210                         &(cd->exceptiontable[cd->exceptiontablelength-1]), 
211                         m->exceptiontable, 
212                         m->exceptiontablelength, 
213                         &b_count))
214         {
215                 return false;
216         }
217
218         s_count = 1 + m->exceptiontablelength; /* initialize stack element counter   */
219
220 #if defined(USE_THREADS)
221         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
222                 m->isleafmethod = false;
223         }                       
224 #endif
225
226         /* scan all java instructions */
227         currentline = 0;
228         linepcchange = 0;
229
230         if (m->linenumbercount == 0) {
231                 lineindex = 0;
232         } 
233         else {
234                 linepcchange = m->linenumbers[0].start_pc;
235         }
236
237         for (p = 0, gp = 0; p < m->jcodelength; gp += (nextp - p), p = nextp) {
238           
239                 /* mark this position as a valid instruction start */
240                 instructionstart[gp] = 1;
241                 if (linepcchange == p) {
242                         if (m->linenumbercount > lineindex) {
243 next_linenumber:
244                                 currentline = m->linenumbers[lineindex].line_number;
245                                 lineindex++;
246                                 if (lineindex < m->linenumbercount) {
247                                         linepcchange = m->linenumbers[lineindex].start_pc;
248                                         if (linepcchange == p)
249                                                 goto next_linenumber;
250                                 }
251                         }
252                 }
253
254                 /* fetch next opcode  */
255 fetch_opcode:
256                 opcode = code_get_u1(p, m);
257
258                 m->basicblockindex[gp] |= (ipc << 1); /*store intermed cnt*/
259
260                 /* some compilers put a JAVA_NOP after a blockend instruction */
261
262                 if (blockend && (opcode != JAVA_NOP)) {
263                         /* start new block */
264
265                         block_insert(gp);
266                         blockend = false;
267                 }
268
269                 nextp = p + jcommandsize[opcode];   /* compute next instruction start */
270
271                 CHECK_END_OF_BYTECODE(nextp);
272
273                 s_count += stackreq[opcode];            /* compute stack element count    */
274                 switch (opcode) {
275                 case JAVA_NOP:
276                         break;
277
278                         /* pushing constants onto the stack p */
279
280                 case JAVA_BIPUSH:
281                         LOADCONST_I(code_get_s1(p+1,m));
282                         break;
283
284                 case JAVA_SIPUSH:
285                         LOADCONST_I(code_get_s2(p+1,m));
286                         break;
287
288                 case JAVA_LDC1:
289                         i = code_get_u1(p + 1, m);
290                         goto pushconstantitem;
291
292                 case JAVA_LDC2:
293                 case JAVA_LDC2W:
294                         i = code_get_u2(p + 1, m);
295
296                 pushconstantitem:
297
298 #if defined(ENABLE_VERIFIER)
299                         if (i >= m->class->cpcount) {
300                                 *exceptionptr = new_verifyerror(m,
301                                         "Attempt to access constant outside range");
302                                 return false;
303                         }
304 #endif
305
306                         switch (m->class->cptags[i]) {
307                         case CONSTANT_Integer:
308                                 LOADCONST_I(((constant_integer *) (m->class->cpinfos[i]))->value);
309                                 break;
310                         case CONSTANT_Long:
311                                 LOADCONST_L(((constant_long *) (m->class->cpinfos[i]))->value);
312                                 break;
313                         case CONSTANT_Float:
314                                 LOADCONST_F(((constant_float *) (m->class->cpinfos[i]))->value);
315                                 break;
316                         case CONSTANT_Double:
317                                 LOADCONST_D(((constant_double *) (m->class->cpinfos[i]))->value);
318                                 break;
319                         case CONSTANT_String:
320                                 LOADCONST_A(literalstring_new((utf *) (m->class->cpinfos[i])));
321                                 break;
322                         case CONSTANT_Class:
323                                 cr = (constant_classref *) (m->class->cpinfos[i]);
324
325                                 if (!resolve_classref(m, cr, resolveLazy, true,
326                                                                           true, &c))
327                                         return false;
328
329                                 /* if not resolved, c == NULL */
330
331                                 if (c) {
332                                         iptr->target = (void*) 0x02; /* XXX target used temporarily as flag */
333                                         LOADCONST_A(c);
334                                 }
335                                 else {
336                                         iptr->target = (void*) 0x03; /* XXX target used temporarily as flag */
337                                         LOADCONST_A(cr);
338                                 }
339                                 break;
340
341 #if defined(ENABLE_VERIFIER)
342                         default:
343                                 *exceptionptr = new_verifyerror(m,
344                                                 "Invalid constant type to push");
345                                 return false;
346 #endif
347                         }
348                         break;
349
350                 case JAVA_ACONST_NULL:
351                         LOADCONST_A(NULL);
352                         break;
353
354                 case JAVA_ICONST_M1:
355                 case JAVA_ICONST_0:
356                 case JAVA_ICONST_1:
357                 case JAVA_ICONST_2:
358                 case JAVA_ICONST_3:
359                 case JAVA_ICONST_4:
360                 case JAVA_ICONST_5:
361                         LOADCONST_I(opcode - JAVA_ICONST_0);
362                         break;
363
364                 case JAVA_LCONST_0:
365                 case JAVA_LCONST_1:
366                         LOADCONST_L(opcode - JAVA_LCONST_0);
367                         break;
368
369                 case JAVA_FCONST_0:
370                 case JAVA_FCONST_1:
371                 case JAVA_FCONST_2:
372                         LOADCONST_F(opcode - JAVA_FCONST_0);
373                         break;
374
375                 case JAVA_DCONST_0:
376                 case JAVA_DCONST_1:
377                         LOADCONST_D(opcode - JAVA_DCONST_0);
378                         break;
379
380                         /* loading variables onto the stack */
381
382                 case JAVA_ILOAD:
383                 case JAVA_FLOAD:
384                 case JAVA_ALOAD:
385                         if (!iswide) {
386                                 i = code_get_u1(p + 1,m);
387                         } 
388                         else {
389                                 i = code_get_u2(p + 1,m);
390                                 nextp = p + 3;
391                                 iswide = false;
392                         }
393                         OP1LOAD_ONEWORD(opcode, i);
394                         break;
395
396                 case JAVA_LLOAD:
397                 case JAVA_DLOAD:
398                         if (!iswide) {
399                                 i = code_get_u1(p + 1,m);
400                         } 
401                         else {
402                                 i = code_get_u2(p + 1,m);
403                                 nextp = p + 3;
404                                 iswide = false;
405                         }
406                         OP1LOAD_TWOWORD(opcode, i);
407                         break;
408
409                 case JAVA_ILOAD_0:
410                 case JAVA_ILOAD_1:
411                 case JAVA_ILOAD_2:
412                 case JAVA_ILOAD_3:
413                         OP1LOAD_ONEWORD(ICMD_ILOAD, opcode - JAVA_ILOAD_0);
414                         break;
415
416                 case JAVA_LLOAD_0:
417                 case JAVA_LLOAD_1:
418                 case JAVA_LLOAD_2:
419                 case JAVA_LLOAD_3:
420                         OP1LOAD_TWOWORD(ICMD_LLOAD, opcode - JAVA_LLOAD_0);
421                         break;
422
423                 case JAVA_FLOAD_0:
424                 case JAVA_FLOAD_1:
425                 case JAVA_FLOAD_2:
426                 case JAVA_FLOAD_3:
427                         OP1LOAD_ONEWORD(ICMD_FLOAD, opcode - JAVA_FLOAD_0);
428                         break;
429
430                 case JAVA_DLOAD_0:
431                 case JAVA_DLOAD_1:
432                 case JAVA_DLOAD_2:
433                 case JAVA_DLOAD_3:
434                         OP1LOAD_TWOWORD(ICMD_DLOAD, opcode - JAVA_DLOAD_0);
435                         break;
436
437                 case JAVA_ALOAD_0:
438                 case JAVA_ALOAD_1:
439                 case JAVA_ALOAD_2:
440                 case JAVA_ALOAD_3:
441                         OP1LOAD_ONEWORD(ICMD_ALOAD, opcode - JAVA_ALOAD_0);
442                         break;
443
444                         /* storing stack values into local variables */
445
446                 case JAVA_ISTORE:
447                 case JAVA_FSTORE:
448                 case JAVA_ASTORE:
449                         if (!iswide) {
450                                 i = code_get_u1(p + 1,m);
451                         } 
452                         else {
453                                 i = code_get_u2(p + 1,m);
454                                 iswide = false;
455                                 nextp = p + 3;
456                         }
457                         OP1STORE_ONEWORD(opcode, i);
458                         break;
459
460                 case JAVA_LSTORE:
461                 case JAVA_DSTORE:
462                         if (!iswide) {
463                                 i = code_get_u1(p + 1,m);
464                         } 
465                         else {
466                                 i = code_get_u2(p + 1,m);
467                                 iswide = false;
468                                 nextp = p + 3;
469                         }
470                         OP1STORE_TWOWORD(opcode, i);
471                         break;
472
473                 case JAVA_ISTORE_0:
474                 case JAVA_ISTORE_1:
475                 case JAVA_ISTORE_2:
476                 case JAVA_ISTORE_3:
477                         OP1STORE_ONEWORD(ICMD_ISTORE, opcode - JAVA_ISTORE_0);
478                         break;
479
480                 case JAVA_LSTORE_0:
481                 case JAVA_LSTORE_1:
482                 case JAVA_LSTORE_2:
483                 case JAVA_LSTORE_3:
484                         OP1STORE_TWOWORD(ICMD_LSTORE, opcode - JAVA_LSTORE_0);
485                         break;
486
487                 case JAVA_FSTORE_0:
488                 case JAVA_FSTORE_1:
489                 case JAVA_FSTORE_2:
490                 case JAVA_FSTORE_3:
491                         OP1STORE_ONEWORD(ICMD_FSTORE, opcode - JAVA_FSTORE_0);
492                         break;
493
494                 case JAVA_DSTORE_0:
495                 case JAVA_DSTORE_1:
496                 case JAVA_DSTORE_2:
497                 case JAVA_DSTORE_3:
498                         OP1STORE_TWOWORD(ICMD_DSTORE, opcode - JAVA_DSTORE_0);
499                         break;
500
501                 case JAVA_ASTORE_0:
502                 case JAVA_ASTORE_1:
503                 case JAVA_ASTORE_2:
504                 case JAVA_ASTORE_3:
505                         OP1STORE_ONEWORD(ICMD_ASTORE, opcode - JAVA_ASTORE_0);
506                         break;
507
508                 case JAVA_IINC:
509                         {
510                                 int v;
511                                 
512                                 if (!iswide) {
513                                         i = code_get_u1(p + 1,m);
514                                         v = code_get_s1(p + 2,m);
515
516                                 } 
517                                 else {
518                                         i = code_get_u2(p + 1,m);
519                                         v = code_get_s2(p + 3,m);
520                                         iswide = false;
521                                         nextp = p + 5;
522                                 }
523                                 INDEX_ONEWORD(i);
524                                 OP2I(opcode, i, v);
525                         }
526                         break;
527
528                         /* wider index for loading, storing and incrementing */
529
530                 case JAVA_WIDE:
531                         iswide = true;
532                         gp++;
533                         p++;
534                         goto fetch_opcode;
535
536                 /* managing arrays ****************************************************/
537
538                 case JAVA_NEWARRAY:
539                         switch (code_get_s1(p + 1, m)) {
540                         case 4:
541                                 bte = builtintable_get_internal(BUILTIN_newarray_boolean);
542                                 break;
543                         case 5:
544                                 bte = builtintable_get_internal(BUILTIN_newarray_char);
545                                 break;
546                         case 6:
547                                 bte = builtintable_get_internal(BUILTIN_newarray_float);
548                                 break;
549                         case 7:
550                                 bte = builtintable_get_internal(BUILTIN_newarray_double);
551                                 break;
552                         case 8:
553                                 bte = builtintable_get_internal(BUILTIN_newarray_byte);
554                                 break;
555                         case 9:
556                                 bte = builtintable_get_internal(BUILTIN_newarray_short);
557                                 break;
558                         case 10:
559                                 bte = builtintable_get_internal(BUILTIN_newarray_int);
560                                 break;
561                         case 11:
562                                 bte = builtintable_get_internal(BUILTIN_newarray_long);
563                                 break;
564 #if defined(ENABLE_VERIFIER)
565                         default:
566                                 *exceptionptr = new_verifyerror(m,
567                                                 "Invalid array-type to create");
568                                 return false;
569 #endif
570                         }
571                         BUILTIN(bte, true, NULL, currentline);
572                         break;
573
574                 case JAVA_ANEWARRAY:
575                         i = code_get_u2(p + 1, m);
576                         compr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
577                         if (!compr)
578                                 return false;
579
580                         if (!(cr = class_get_classref_multiarray_of(1, compr)))
581                                 return false;
582
583                         if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
584                                 return false;
585
586                         LOADCONST_A_BUILTIN(c, cr);
587                         bte = builtintable_get_internal(BUILTIN_newarray);
588                         BUILTIN(bte, true, NULL, currentline);
589                         s_count++;
590                         break;
591
592                 case JAVA_MULTIANEWARRAY:
593                         m->isleafmethod = false;
594                         i = code_get_u2(p + 1, m);
595                         {
596                                 s4 v = code_get_u1(p + 3, m);
597
598                                 cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
599                                 if (!cr)
600                                         return false;
601
602                                 if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
603                                         return false;
604
605                                 /* if unresolved, c == NULL */
606                                 OP2AT(opcode, v, c, cr, currentline);
607                         }
608                         break;
609
610                 case JAVA_IFEQ:
611                 case JAVA_IFLT:
612                 case JAVA_IFLE:
613                 case JAVA_IFNE:
614                 case JAVA_IFGT:
615                 case JAVA_IFGE:
616                 case JAVA_IFNULL:
617                 case JAVA_IFNONNULL:
618                 case JAVA_IF_ICMPEQ:
619                 case JAVA_IF_ICMPNE:
620                 case JAVA_IF_ICMPLT:
621                 case JAVA_IF_ICMPGT:
622                 case JAVA_IF_ICMPLE:
623                 case JAVA_IF_ICMPGE:
624                 case JAVA_IF_ACMPEQ:
625                 case JAVA_IF_ACMPNE:
626                 case JAVA_GOTO:
627                 case JAVA_JSR:
628                         i = p + code_get_s2(p + 1,m);
629                         CHECK_BYTECODE_INDEX(i);
630                         block_insert(i);
631                         blockend = true;
632                         OP1(opcode, i);
633                         break;
634
635                 case JAVA_GOTO_W:
636                 case JAVA_JSR_W:
637                         i = p + code_get_s4(p + 1,m);
638                         CHECK_BYTECODE_INDEX(i);
639                         block_insert(i);
640                         blockend = true;
641                         OP1(opcode, i);
642                         break;
643
644                 case JAVA_RET:
645                         if (!iswide) {
646                                 i = code_get_u1(p + 1,m);
647                         } 
648                         else {
649                                 i = code_get_u2(p + 1,m);
650                                 nextp = p + 3;
651                                 iswide = false;
652                         }
653                         blockend = true;
654                                 
655                         OP1LOAD_ONEWORD(opcode, i);
656                         break;
657
658                 case JAVA_IRETURN:
659                 case JAVA_LRETURN:
660                 case JAVA_FRETURN:
661                 case JAVA_DRETURN:
662                 case JAVA_ARETURN:
663                 case JAVA_RETURN:
664                         blockend = true;
665                         /* zero val.a so no patcher is inserted */
666                         /* the type checker may set this later  */
667                         iptr->val.a = NULL;
668                         OP(opcode);
669                         break;
670
671                 case JAVA_ATHROW:
672                         blockend = true;
673                         /* zero val.a so no patcher is inserted */
674                         /* the type checker may set this later  */
675                         iptr->val.a = NULL;
676                         OP(opcode);
677                         break;
678                                 
679
680                 /* table jumps ********************************************************/
681
682                 case JAVA_LOOKUPSWITCH:
683                         {
684                                 s4 num, j;
685                                 s4 *tablep;
686 #if defined(ENABLE_VERIFIER)
687                                 s4 prevvalue = 0;
688 #endif
689
690                                 blockend = true;
691                                 nextp = ALIGN((p + 1), 4);
692
693                                 CHECK_END_OF_BYTECODE(nextp + 8);
694
695                                 tablep = (s4 *) (m->jcode + nextp);
696
697                                 OP2A(opcode, 0, tablep, currentline);
698
699                                 /* default target */
700
701                                 j =  p + code_get_s4(nextp, m);
702                                 *tablep = j;     /* restore for little endian */
703                                 tablep++;
704                                 nextp += 4;
705                                 CHECK_BYTECODE_INDEX(j);
706                                 block_insert(j);
707
708                                 /* number of pairs */
709
710                                 num = code_get_u4(nextp, m);
711                                 *tablep = num;
712                                 tablep++;
713                                 nextp += 4;
714
715                                 CHECK_END_OF_BYTECODE(nextp + 8 * num);
716
717                                 for (i = 0; i < num; i++) {
718                                         /* value */
719
720                                         j = code_get_s4(nextp, m);
721                                         *tablep = j; /* restore for little endian */
722                                         tablep++;
723                                         nextp += 4;
724
725 #if defined(ENABLE_VERIFIER)
726                                         /* check if the lookup table is sorted correctly */
727                                         
728                                         if (i && (j <= prevvalue)) {
729                                                 *exceptionptr = new_verifyerror(m, "Unsorted lookup switch");
730                                                 return false;
731                                         }
732                                         prevvalue = j;
733 #endif
734
735                                         /* target */
736
737                                         j = p + code_get_s4(nextp,m);
738                                         *tablep = j; /* restore for little endian */
739                                         tablep++;
740                                         nextp += 4;
741                                         CHECK_BYTECODE_INDEX(j);
742                                         block_insert(j);
743                                 }
744
745                                 break;
746                         }
747
748
749                 case JAVA_TABLESWITCH:
750                         {
751                                 s4 num, j;
752                                 s4 *tablep;
753
754                                 blockend = true;
755                                 nextp = ALIGN((p + 1), 4);
756
757                                 CHECK_END_OF_BYTECODE(nextp + 12);
758
759                                 tablep = (s4 *) (m->jcode + nextp);
760
761                                 OP2A(opcode, 0, tablep, currentline);
762
763                                 /* default target */
764
765                                 j = p + code_get_s4(nextp, m);
766                                 *tablep = j;     /* restore for little endian */
767                                 tablep++;
768                                 nextp += 4;
769                                 CHECK_BYTECODE_INDEX(j);
770                                 block_insert(j);
771
772                                 /* lower bound */
773
774                                 j = code_get_s4(nextp, m);
775                                 *tablep = j;     /* restore for little endian */
776                                 tablep++;
777                                 nextp += 4;
778
779                                 /* upper bound */
780
781                                 num = code_get_s4(nextp, m);
782                                 *tablep = num;   /* restore for little endian */
783                                 tablep++;
784                                 nextp += 4;
785
786                                 num -= j;  /* difference of upper - lower */
787
788 #if defined(ENABLE_VERIFIER)
789                                 if (num < 0) {
790                                         *exceptionptr = new_verifyerror(m,
791                                                         "invalid TABLESWITCH: upper bound < lower bound");
792                                         return false;
793                                 }
794 #endif
795
796                                 CHECK_END_OF_BYTECODE(nextp + 4 * (num + 1));
797
798                                 for (i = 0; i <= num; i++) {
799                                         j = p + code_get_s4(nextp,m);
800                                         *tablep = j; /* restore for little endian */
801                                         tablep++;
802                                         nextp += 4;
803                                         CHECK_BYTECODE_INDEX(j);
804                                         block_insert(j);
805                                 }
806
807                                 break;
808                         }
809
810
811                 /* load and store of object fields ************************************/
812
813                 case JAVA_AASTORE:
814                         OP(opcode);
815                         m->isleafmethod = false;
816                         break;
817
818                 case JAVA_GETSTATIC:
819                 case JAVA_PUTSTATIC:
820                 case JAVA_GETFIELD:
821                 case JAVA_PUTFIELD:
822                         {
823                                 constant_FMIref  *fr;
824                                 unresolved_field *uf;
825
826                                 i = code_get_u2(p + 1, m);
827                                 fr = class_getconstant(m->class, i,
828                                                                            CONSTANT_Fieldref);
829                                 if (!fr)
830                                         return false;
831
832                                 OP2A_NOINC(opcode, fr->parseddesc.fd->type, fr, currentline);
833
834                                 /* only with -noverify, otherwise the typechecker does this */
835
836 #if defined(ENABLE_VERIFIER)
837                                 if (!opt_verify) {
838 #endif
839                                         result = resolve_field_lazy(iptr,NULL,m);
840                                         if (result == resolveFailed)
841                                                 return false;
842
843                                         if (result != resolveSucceeded) {
844                                                 uf = create_unresolved_field(m->class,
845                                                                                                          m, iptr);
846
847                                                 if (!uf)
848                                                         return false;
849
850                                                 /* store the unresolved_field pointer */
851
852                                                 /* XXX this will be changed */
853                                                 iptr->val.a = uf;
854                                                 iptr->target = (void*) 0x01; /* XXX target temporarily used as flag */
855                                         }
856                                         else {
857                                                 iptr->target = NULL;
858                                         }
859 #if defined(ENABLE_VERIFIER)
860                                 }
861                                 else {
862                                         iptr->target = NULL;
863                                 }
864 #endif
865                                 PINC;
866                         }
867                         break;
868                                 
869
870                 /* method invocation **************************************************/
871
872                 case JAVA_INVOKESTATIC:
873                         i = code_get_u2(p + 1, m);
874                         mr = class_getconstant(m->class, i,
875                                         CONSTANT_Methodref);
876                         if (!mr)
877                                 return false;
878
879                         md = mr->parseddesc.md;
880
881                         if (!md->params)
882                                 if (!descriptor_params_from_paramtypes(md, ACC_STATIC))
883                                         return false;
884
885                         goto invoke_method;
886
887                 case JAVA_INVOKEINTERFACE:
888                         i = code_get_u2(p + 1, m);
889                                 
890                         mr = class_getconstant(m->class, i,
891                                         CONSTANT_InterfaceMethodref);
892
893                         goto invoke_nonstatic_method;
894
895                 case JAVA_INVOKESPECIAL:
896                 case JAVA_INVOKEVIRTUAL:
897                         i = code_get_u2(p + 1, m);
898                         mr = class_getconstant(m->class, i,
899                                         CONSTANT_Methodref);
900
901 invoke_nonstatic_method:
902                         if (!mr)
903                                 return false;
904
905                         md = mr->parseddesc.md;
906
907                         if (!md->params)
908                                 if (!descriptor_params_from_paramtypes(md, 0))
909                                         return false;
910
911 invoke_method:
912                         m->isleafmethod = false;
913
914                         OP2A_NOINC(opcode, 0, mr, currentline);
915
916                         /* only with -noverify, otherwise the typechecker does this */
917
918 #if defined(ENABLE_VERIFIER)
919                         if (!opt_verify) {
920 #endif
921                                 result = resolve_method_lazy(iptr,NULL,m);
922                                 if (result == resolveFailed)
923                                         return false;
924
925                                 if (result != resolveSucceeded) {
926                                         um = create_unresolved_method(m->class,
927                                                         m, iptr);
928
929                                         if (!um)
930                                                 return false;
931
932                                         /* store the unresolved_method pointer */
933
934                                         /* XXX this will be changed */
935                                         iptr->val.a = um;
936                                         iptr->target = (void*) 0x01; /* XXX target temporarily used as flag */
937                                 }
938                                 else {
939                                         /* the method could be resolved */
940                                         iptr->target = NULL;
941                                 }
942 #if defined(ENABLE_VERIFIER)
943                         }
944                         else {
945                                 iptr->target = NULL;
946                         }
947 #endif
948                         PINC;
949                         break;
950
951                 /* miscellaneous object operations ************************************/
952
953                 case JAVA_NEW:
954                         i = code_get_u2(p + 1, m);
955                         cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
956                         if (!cr)
957                                 return false;
958
959                         if (!resolve_classref(m, cr, resolveLazy, true, true,
960                                                                   &c))
961                                 return false;
962
963                         LOADCONST_A_BUILTIN(c, cr);
964                         bte = builtintable_get_internal(BUILTIN_new);
965                         BUILTIN(bte, true, NULL, currentline);
966                         s_count++;
967                         break;
968
969                 case JAVA_CHECKCAST:
970                         i = code_get_u2(p + 1, m);
971                         cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
972                         if (!cr)
973                                 return false;
974
975                         if (!resolve_classref(m, cr, resolveLazy, true,
976                                                                   true, &c))
977                                 return false;
978
979                         if (cr->name->text[0] == '[') {
980                                 /* array type cast-check */
981                                 OP2AT(opcode, 0, c, cr, currentline);
982                                 m->isleafmethod = false;
983
984                         } 
985                         else {
986                                 /* object type cast-check */
987                                 OP2AT(opcode, 1, c, cr, currentline);
988                         }
989                         break;
990
991                 case JAVA_INSTANCEOF:
992                         i = code_get_u2(p + 1,m);
993                         cr = (constant_classref *) class_getconstant(m->class, i, CONSTANT_Class);
994                         if (!cr)
995                                 return false;
996
997                         if (!resolve_classref(m, cr, resolveLazy, true, true, &c))
998                                 return false;
999
1000                         if (cr->name->text[0] == '[') {
1001                                 /* array type cast-check */
1002                                 LOADCONST_A_BUILTIN(c, cr);
1003                                 bte = builtintable_get_internal(BUILTIN_arrayinstanceof);
1004                                 BUILTIN(bte, false, NULL, currentline);
1005                                 s_count++;
1006
1007                         } 
1008                         else {
1009                                 /* object type cast-check */
1010                                 OP2AT(opcode, 1, c, cr, currentline);
1011                         }
1012                         break;
1013
1014                 case JAVA_MONITORENTER:
1015 #if defined(USE_THREADS)
1016                         if (checksync) {
1017                                 OP(ICMD_CHECKNULL);
1018                                 bte = builtintable_get_internal(BUILTIN_monitorenter);
1019                                 BUILTIN(bte, false, NULL, currentline);
1020                         } 
1021                         else
1022 #endif
1023                                 {
1024                                         OP(ICMD_CHECKNULL);
1025                                         OP(ICMD_POP);
1026                                 }
1027                         break;
1028
1029                 case JAVA_MONITOREXIT:
1030 #if defined(USE_THREADS)
1031                         if (checksync) {
1032                                 bte = builtintable_get_internal(BUILTIN_monitorexit);
1033                                 BUILTIN(bte, false, NULL, currentline);
1034                         } 
1035                         else
1036 #endif
1037                                 {
1038                                         OP(ICMD_POP);
1039                                 }
1040                         break;
1041
1042                 /* any other basic operation ******************************************/
1043
1044                 case JAVA_IDIV:
1045 #if !SUPPORT_DIVISION
1046                         bte = builtintable_get_internal(BUILTIN_idiv);
1047                         OP2A(opcode, bte->md->paramcount, bte, currentline);
1048                         m->isleafmethod = false;
1049 #else
1050                         OP(opcode);
1051 #endif
1052                         break;
1053
1054                 case JAVA_IREM:
1055 #if !SUPPORT_DIVISION
1056                         bte = builtintable_get_internal(BUILTIN_irem);
1057                         OP2A(opcode, bte->md->paramcount, bte, currentline);
1058                         m->isleafmethod = false;
1059 #else
1060                         OP(opcode);
1061 #endif
1062                         break;
1063
1064                 case JAVA_LDIV:
1065 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1066                         bte = builtintable_get_internal(BUILTIN_ldiv);
1067                         OP2A(opcode, bte->md->paramcount, bte, currentline);
1068                         m->isleafmethod = false;
1069 #else
1070                         OP(opcode);
1071 #endif
1072                         break;
1073
1074                 case JAVA_LREM:
1075 #if !(SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_DIV)
1076                         bte = builtintable_get_internal(BUILTIN_lrem);
1077                         OP2A(opcode, bte->md->paramcount, bte, currentline);
1078                         m->isleafmethod = false;
1079 #else
1080                         OP(opcode);
1081 #endif
1082                         break;
1083
1084                 case JAVA_FREM:
1085 #if defined(__I386__)
1086                         OP(opcode);
1087 #else
1088                         bte = builtintable_get_internal(BUILTIN_frem);
1089                         BUILTIN(bte, false, NULL, currentline);
1090 #endif
1091                         break;
1092
1093                 case JAVA_DREM:
1094 #if defined(__I386__)
1095                         OP(opcode);
1096 #else
1097                         bte = builtintable_get_internal(BUILTIN_drem);
1098                         BUILTIN(bte, false, NULL, currentline);
1099 #endif
1100                         break;
1101
1102                 case JAVA_F2I:
1103 #if defined(__ALPHA__)
1104                         if (!opt_noieee) {
1105                                 bte = builtintable_get_internal(BUILTIN_f2i);
1106                                 BUILTIN(bte, false, NULL, currentline);
1107                         } 
1108                         else
1109 #endif
1110                                 {
1111                                         OP(opcode);
1112                                 }
1113                         break;
1114
1115                 case JAVA_F2L:
1116 #if defined(__ALPHA__)
1117                         if (!opt_noieee) {
1118                                 bte = builtintable_get_internal(BUILTIN_f2l);
1119                                 BUILTIN(bte, false, NULL, currentline);
1120                         } 
1121                         else 
1122 #endif
1123                                 {
1124                                         OP(opcode);
1125                                 }
1126                         break;
1127
1128                 case JAVA_D2I:
1129 #if defined(__ALPHA__)
1130                         if (!opt_noieee) {
1131                                 bte = builtintable_get_internal(BUILTIN_d2i);
1132                                 BUILTIN(bte, false, NULL, currentline);
1133                         } 
1134                         else
1135 #endif
1136                                 {
1137                                         OP(opcode);
1138                                 }
1139                         break;
1140
1141                 case JAVA_D2L:
1142 #if defined(__ALPHA__)
1143                         if (!opt_noieee) {
1144                                 bte = builtintable_get_internal(BUILTIN_d2l);
1145                                 BUILTIN(bte, false, NULL, currentline);
1146                         } 
1147                         else
1148 #endif
1149                                 {
1150                                         OP(opcode);
1151                                 }
1152                         break;
1153
1154                         /* check for invalid opcodes if the verifier is enabled */
1155 #if defined(ENABLE_VERIFIER)
1156                 case JAVA_BREAKPOINT:
1157                         *exceptionptr =
1158                                 new_verifyerror(m, "Quick instructions shouldn't appear yet.");
1159                         return false;
1160
1161                 case 186: /* unused opcode */
1162                 case 203:
1163                 case 204:
1164                 case 205:
1165                 case 206:
1166                 case 207:
1167                 case 208:
1168                 case 209:
1169                 case 210:
1170                 case 211:
1171                 case 212:
1172                 case 213:
1173                 case 214:
1174                 case 215:
1175                 case 216:
1176                 case 217:
1177                 case 218:
1178                 case 219:
1179                 case 220:
1180                 case 221:
1181                 case 222:
1182                 case 223:
1183                 case 224:
1184                 case 225:
1185                 case 226:
1186                 case 227:
1187                 case 228:
1188                 case 229:
1189                 case 230:
1190                 case 231:
1191                 case 232:
1192                 case 233:
1193                 case 234:
1194                 case 235:
1195                 case 236:
1196                 case 237:
1197                 case 238:
1198                 case 239:
1199                 case 240:
1200                 case 241:
1201                 case 242:
1202                 case 243:
1203                 case 244:
1204                 case 245:
1205                 case 246:
1206                 case 247:
1207                 case 248:
1208                 case 249:
1209                 case 250:
1210                 case 251:
1211                 case 252:
1212                 case 253:
1213                 case 254:
1214                 case 255:
1215                         *exceptionptr =
1216                                 new_verifyerror(m,"Illegal opcode %d at instr %d\n",
1217                                                                   opcode, ipc);
1218                         return false;
1219                         break;
1220 #endif /* defined(ENABLE_VERIFIER) */
1221
1222                 default:
1223                         /* straight-forward translation to ICMD */
1224                         OP(opcode);
1225                         break;
1226                                 
1227                 } /* end switch */
1228
1229 #if defined(ENABLE_VERIFIER)
1230                 /* If WIDE was used correctly, iswide should have been reset by now. */
1231                 if (iswide) {
1232                         *exceptionptr = new_verifyerror(m,
1233                                         "Illegal instruction: WIDE before incompatible opcode");
1234                         return false;
1235                 }
1236 #endif /* defined(ENABLE_VERIFIER) */
1237
1238         } /* end for */
1239
1240 #if defined(ENABLE_VERIFIER)
1241         if (p != m->jcodelength) {
1242                 *exceptionptr = new_verifyerror(m,
1243                                 "Command-sequence crosses code-boundary");
1244                 return false;
1245         }
1246
1247         if (!blockend) {
1248                 *exceptionptr = new_verifyerror(m, "Falling off the end of the code");
1249                 return false;
1250         }
1251 #endif /* defined(ENABLE_VERIFIER) */
1252
1253         /* adjust block count if target 0 is not first intermediate instruction */
1254
1255         if (!m->basicblockindex[0] || (m->basicblockindex[0] > 1))
1256                 b_count++;
1257
1258         /* copy local to method variables */
1259
1260         m->instructioncount = ipc;
1261         m->basicblockcount = b_count;
1262         m->stackcount = s_count + m->basicblockcount * m->maxstack;
1263
1264         /* allocate stack table */
1265
1266         m->stack = DMNEW(stackelement, m->stackcount);
1267
1268         {
1269                 basicblock *bptr;
1270
1271                 bptr = m->basicblocks = DMNEW(basicblock, b_count + 1);    /* one more for end ipc */
1272
1273                 b_count = 0;
1274                 m->c_debug_nr = 0;
1275         
1276                 /* additional block if target 0 is not first intermediate instruction */
1277
1278                 if (!m->basicblockindex[0] || (m->basicblockindex[0] > 1)) {
1279                         BASICBLOCK_INIT(bptr,m);
1280
1281                         bptr->iinstr = m->instructions;
1282                         /* bptr->icount is set when the next block is allocated */
1283
1284                         bptr++;
1285                         b_count++;
1286                         bptr[-1].next = bptr;
1287                 }
1288
1289                 /* allocate blocks */
1290
1291                 for (p = 0; p < m->jcodelength; p++) { 
1292                         if (m->basicblockindex[p] & 1) {
1293                                 /* Check if this block starts at the beginning of an          */
1294                                 /* instruction.                                               */
1295 #if defined(ENABLE_VERIFIER)
1296                                 if (!instructionstart[p]) {
1297                                         *exceptionptr = new_verifyerror(m,
1298                                                 "Branch into middle of instruction");
1299                                         return false;
1300                                 }
1301 #endif
1302
1303                                 /* allocate the block */
1304
1305                                 BASICBLOCK_INIT(bptr,m);
1306
1307                                 bptr->iinstr = m->instructions + (m->basicblockindex[p] >> 1);
1308                                 if (b_count) {
1309                                         bptr[-1].icount = bptr->iinstr - bptr[-1].iinstr;
1310                                 }
1311                                 /* bptr->icount is set when the next block is allocated */
1312
1313                                 m->basicblockindex[p] = b_count;
1314
1315                                 bptr++;
1316                                 b_count++;
1317                                 bptr[-1].next = bptr;
1318                         }
1319                 }
1320
1321                 /* set instruction count of last real block */
1322
1323                 if (b_count) {
1324                         bptr[-1].icount = (m->instructions + m->instructioncount) - bptr[-1].iinstr;
1325                 }
1326
1327                 /* allocate additional block at end */
1328
1329                 BASICBLOCK_INIT(bptr,m);
1330                 
1331                 bptr->instack = bptr->outstack = NULL;
1332                 bptr->indepth = bptr->outdepth = 0;
1333                 bptr->iinstr = NULL;
1334                 bptr->icount = 0;
1335                 bptr->next = NULL;
1336
1337                 /* set basicblock pointers in exception table */
1338
1339                 if (cd->exceptiontablelength > 0) {
1340                         cd->exceptiontable[cd->exceptiontablelength - 1].down = NULL;
1341                 }
1342                 
1343                 for (i = 0; i < cd->exceptiontablelength; ++i) {
1344                         p = cd->exceptiontable[i].startpc;
1345                         cd->exceptiontable[i].start = m->basicblocks + m->basicblockindex[p];
1346
1347                         p = cd->exceptiontable[i].endpc;
1348                         cd->exceptiontable[i].end = (p == m->jcodelength) ? (m->basicblocks + m->basicblockcount /*+ 1*/) : (m->basicblocks + m->basicblockindex[p]);
1349
1350                         p = cd->exceptiontable[i].handlerpc;
1351                         cd->exceptiontable[i].handler = m->basicblocks + m->basicblockindex[p];
1352             }
1353
1354                 /* XXX activate this if you want to try inlining */
1355 #if 0
1356                 for (i = 0; i < m->exceptiontablelength; ++i) {
1357                         p = m->exceptiontable[i].startpc;
1358                         m->exceptiontable[i].start = m->basicblocks + m->basicblockindex[p];
1359
1360                         p = m->exceptiontable[i].endpc;
1361                         m->exceptiontable[i].end = (p == m->jcodelength) ? (m->basicblocks + m->basicblockcount /*+ 1*/) : (m->basicblocks + m->basicblockindex[p]);
1362
1363                         p = m->exceptiontable[i].handlerpc;
1364                         m->exceptiontable[i].handler = m->basicblocks + m->basicblockindex[p];
1365             }
1366 #endif
1367
1368         }
1369
1370         /* everything's ok */
1371
1372         return true;
1373
1374 #if defined(ENABLE_VERIFIER)
1375
1376 throw_unexpected_end_of_bytecode:
1377         *exceptionptr = new_verifyerror(m, "Unexpected end of bytecode");
1378         return false;
1379
1380 throw_invalid_bytecode_index:
1381         *exceptionptr =
1382                 new_verifyerror(m, "Illegal target of branch instruction");
1383         return false;
1384
1385 throw_illegal_local_variable_number:
1386         *exceptionptr =
1387                 new_verifyerror(m, "Illegal local variable number");
1388         return false;
1389                 
1390 #endif /* ENABLE_VERIFIER */
1391 }
1392
1393
1394 /*
1395  * These are local overrides for various environment variables in Emacs.
1396  * Please do not remove this and leave it at the end of the file, where
1397  * Emacs will automagically detect them.
1398  * ---------------------------------------------------------------------
1399  * Local variables:
1400  * mode: c
1401  * indent-tabs-mode: t
1402  * c-basic-offset: 4
1403  * tab-width: 4
1404  * End:
1405  * vim:noexpandtab:sw=4:ts=4:
1406  */