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