if (opt_verify) set iptr->val.a to NULL to indicate unresolved reference
[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 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    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., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Author: Andreas Krall
28
29    Changes: Carolyn Oates
30             Edwin Steiner
31             Joseph Wenninger
32             Christian Thalinger
33
34    $Id: parse.c 2783 2005-06-22 12:05:49Z edwin $
35
36 */
37
38
39 #include <assert.h>
40 #include <string.h>
41
42 #include "config.h"
43 #include "types.h"
44 #include "mm/memory.h"
45 #include "native/native.h"
46 #include "toolbox/logging.h"
47 #include "vm/builtin.h"
48 #include "vm/exceptions.h"
49 #include "vm/global.h"
50 #include "vm/linker.h"
51 #include "vm/loader.h"
52 #include "vm/resolve.h"
53 #include "vm/options.h"
54 #include "vm/statistics.h"
55 #include "vm/stringlocal.h"
56 #include "vm/tables.h"
57 #include "vm/jit/asmpart.h"
58 #include "vm/jit/jit.h"
59 #include "vm/jit/parse.h"
60 #include "vm/jit/patcher.h"
61 #include "vm/jit/inline/parseRT.h"
62 #include "vm/jit/inline/parseXTA.h"
63 #include "vm/jit/inline/inline.h"
64 #include "vm/jit/loop/loop.h"
65 #include "vm/jit/inline/parseRTprint.h"
66
67 bool DEBUG = false;
68 bool DEBUG2 = false;
69 bool DEBUG3 = false;
70 bool DEBUG4 = false;  /*opcodes for parse.c*/
71
72
73 /*INLINING*/
74 #define debug_writebranch if (DEBUG2==true) printf("op:: %s i: %d label_index[i]: %d label_index=0x%p\n",opcode_names[opcode], i, label_index[i], (void *)label_index);
75 #define debug_writebranch1
76
77 /*******************************************************************************
78
79         function 'parse' scans the JavaVM code and generates intermediate code
80
81         During parsing the block index table is used to store at bit pos 0
82         a flag which marks basic block starts and at position 1 to 31 the
83         intermediate instruction index. After parsing the block index table
84         is scanned, for marked positions a block is generated and the block
85         number is stored in the block index table.
86
87 *******************************************************************************/
88
89 static exceptiontable* fillextable(methodinfo *m, 
90                 exceptiontable* extable, exceptiontable *raw_extable, 
91                 int exceptiontablelength, 
92                 int *label_index, int *block_count, 
93                 t_inlining_globals *inline_env)
94 {
95         int b_count, p, src, insertBlock;
96         
97         if (exceptiontablelength == 0) 
98                 return extable;
99
100         /*if (m->exceptiontablelength > 0) {
101           METHINFOx(m);
102           printf("m->exceptiontablelength=%i\n",m->exceptiontablelength);
103           assert(0);
104           }*/
105
106         b_count = *block_count;
107
108         for (src = exceptiontablelength-1; src >=0; src--) {
109                 /* printf("Excepiont table index: %d\n",i); */
110                 p = raw_extable[src].startpc;
111                 if (label_index != NULL) p = label_index[p];
112                 extable->startpc = p;
113                 bound_check(p);
114                 block_insert(p);
115                 
116 /*** if (DEBUG==true){printf("---------------------block_inserted:b_count=%i m->basicblockindex[(p=%i)]=%i=%p\n",b_count,p,m->basicblockindex[(p)],m->basicblockindex[(p)]); 
117   fflush(stdout); } ***/   
118                 p = raw_extable[src].endpc; /* see JVM Spec 4.7.3 */
119                 if (p <= raw_extable[src].startpc) {
120                         log_text("Invalid exception handler range");
121                         assert(0);
122                 }
123
124                 if (p >inline_env->method->jcodelength) {
125                         log_text("Invalid exception handler end is after code end");
126                         assert(0);
127                 }
128
129                 if (p<inline_env->method->jcodelength) insertBlock=1; else insertBlock=0;
130                 /*if (label_index !=NULL) printf("%s:translating endpc:%ld to %ld, label_index:%p\n",m->name->text,p,label_index[p],label_index); else
131                         printf("%s:fillextab: endpc:%ld\n",m->name->text,p);*/
132                 if (label_index != NULL) p = label_index[p];
133                 extable->endpc = p;
134                 bound_check1(p);
135                 /*if (p < inline_env->method->jcodelength) {
136                         block_insert(p); }*/
137                 if (insertBlock) block_insert(p);
138
139                 p = raw_extable[src].handlerpc;
140                 if (label_index != NULL) p = label_index[p];
141                 extable->handlerpc = p;
142                 bound_check(p);
143                 block_insert(p);
144
145                 extable->catchtype  = raw_extable[src].catchtype;
146                 extable->next = NULL;
147                 extable->down = &extable[1];
148                 extable--;
149         }
150
151         *block_count = b_count;
152         return extable; /*&extable[i];*/  /* return the next free xtable* */
153 }
154
155
156
157 methodinfo *parse(methodinfo *m, codegendata *cd, t_inlining_globals *inline_env)
158 {
159         int  p;                     /* java instruction counter           */
160         int  nextp;                 /* start of next java instruction     */
161         int  opcode;                /* java opcode                        */
162         int  i;                     /* temporary for different uses (ctrs)*/
163         int  ipc = 0;               /* intermediate instruction counter   */
164         int  b_count = 0;           /* basic block counter                */
165         int  s_count = 0;           /* stack element counter              */
166         bool blockend = false;      /* true if basic block end has been reached   */
167         bool iswide = false;        /* true if last instruction was a wide*/
168         instruction *iptr;          /* current ptr into instruction array */
169         int gp;                     /* global java instruction counter    */
170                                     /* inlining info for current method   */
171
172         inlining_methodinfo *inlinfo = inline_env->inlining_rootinfo;
173         inlining_methodinfo *tmpinlinf;
174         int nextgp = -1;            /* start of next method to be inlined */
175         int *label_index = NULL;    /* label redirection table            */
176         int firstlocal = 0;         /* first local variable of method     */
177         exceptiontable* nextex;     /* points next free entry in extable  */
178         u1 *instructionstart;       /* 1 for pcs which are valid instr. starts    */
179
180         constant_classref  *cr;
181         constant_classref  *compr;
182         classinfo          *c;
183         builtintable_entry *bte;
184
185         u2 lineindex = 0;
186         u2 currentline = 0;
187         u2 linepcchange = 0;
188
189         u2 skipBasicBlockChange;
190
191 #if defined(USE_INLINING)
192 METHINFOt(m,"\nPARSING: ",DEBUG4);
193 if ((opt_rt) || (opt_xta)) {
194   FILE *Missed;
195
196   if (opt_rt)  Missed =  rtMissed;  
197   if (opt_xta) Missed = xtaMissed;  
198
199   if (m->methodUsed != USED) {
200     if (opt_verbose) {
201       printf(" rta/xta missed: "); fflush(stdout);
202       METHINFO(m,opt_verbose);
203       }
204     if ( (Missed = fopen("Missed", "a")) == NULL) {
205       printf("CACAO - rt/xtaMissed file: cant open file to write append \n");
206       }
207     else {
208       utf_fprint(Missed,m->class->name); 
209        fprintf(Missed," "); fflush(Missed);
210       utf_fprint(Missed,m->name);
211        fprintf(Missed," "); fflush(Missed);
212       utf_fprint(Missed,m->descriptor); 
213        fprintf(Missed,"\n"); fflush(Missed);
214       fclose(Missed);
215       }
216    } 
217 }
218 #endif
219
220 #if defined(USE_INLINING)
221         if (useinlining) {
222                 label_index = inlinfo->label_index;
223                 m->maxstack = inline_env->cummaxstack;
224                 /*JOWENN m->exceptiontablelength = inline_env->cumextablelength;*/
225
226                 tmpinlinf = (inlining_methodinfo *) list_first(inlinfo->inlinedmethods);
227
228                 if (tmpinlinf != NULL)
229                         nextgp = tmpinlinf->startgp;
230         }
231 #endif
232
233 /**** static analysis has to be called before inlining
234         which has to be called before reg_set
235         which has to be called before parse (or ???)
236         will check if method being parsed was analysed here
237         if (opt_xta && opt_verbose) { 
238                 **RT_jit_parse(m);**
239                 printf("XTA requested, not available\n");
240                 }
241         if (opt_vta && opt_verbose)  
242                     printf("VTA requested, not yet implemented\n");
243         ****/ 
244
245         /* allocate instruction array and block index table */
246         
247         /* 1 additional for end ipc * # cum inline methods*/
248         
249         m->basicblockindex = DMNEW(s4, inline_env->cumjcodelength + inline_env->cummethods);
250         memset(m->basicblockindex, 0, sizeof(s4) * (inline_env->cumjcodelength + inline_env->cummethods));
251
252         instructionstart = DMNEW(u1, inline_env->cumjcodelength + inline_env->cummethods);
253         memset(instructionstart, 0, sizeof(u1) * (inline_env->cumjcodelength + inline_env->cummethods));
254
255         /* 1 additional for TRACEBUILTIN and 4 for MONITORENTER/EXIT */
256         /* additional MONITOREXITS are reached by branches which are 3 bytes */
257         
258         iptr = m->instructions = DMNEW(instruction, inline_env->cumjcodelength + 5);
259
260         /* Zero the intermediate instructions array so we don't have any
261          * invalid pointers in it if we cannot finish analyse_stack(). */
262
263         memset(iptr, 0, sizeof(instruction) * (inline_env->cumjcodelength + 5));
264         
265         /* compute branch targets of exception table */
266         /*
267 if (m->exceptiontable == NULL) {
268   printf("m->exceptiontable=NULL\n");fflush(stdout);
269   }
270 else {
271   printf("m->exceptiontable != NULL\n");fflush(stdout);
272   }
273 printf("m->exceptiontablelength=%i, inline_env->method->exceptiontablelength=%i,inline_env->cumextablelength=%i\n",
274 m->exceptiontablelength, inline_env->method->exceptiontablelength,inline_env->cumextablelength);
275         */
276         /*
277 if (m->exceptiontablelength > 0)
278         m->exceptiontable = DMNEW(exceptiontable, m->exceptiontablelength + 1); 
279         */
280
281         nextex = fillextable(m, 
282           &(cd->exceptiontable[cd->exceptiontablelength-1]), m->exceptiontable, m->exceptiontablelength, 
283           label_index, &b_count, inline_env);
284         s_count = 1 + m->exceptiontablelength; /* initialize stack element counter   */
285
286 #if defined(USE_THREADS)
287         if (checksync && (m->flags & ACC_SYNCHRONIZED)) {
288                 m->isleafmethod = false;
289                 inline_env->method->isleafmethod = false;
290         }                       
291 #endif
292
293         /* scan all java instructions */
294         currentline = 0;
295         linepcchange = 0;
296
297         if (m->linenumbercount == 0) {
298                 lineindex = 0;
299                 /*printf("linenumber count == 0\n");*/
300         } else {
301                 linepcchange = m->linenumbers[0].start_pc;
302         }
303
304         skipBasicBlockChange=0;
305         for (p = 0, gp = 0; p < inline_env->method->jcodelength; gp += (nextp - p), p = nextp) {
306           
307                 /* DEBUG */      if (DEBUG==true) printf("----- p:%d gp:%d\n",p,gp);
308
309                 /* mark this position as a valid instruction start */
310                 if (!iswide) {
311                         instructionstart[gp] = 1;
312                         /*log_text("new start of instruction");*/
313                         /*printf ("%s, linepcchange %d,p %d\n",inline_env->method->name->text,linepcchange,p);*/
314                         if (linepcchange==p) {
315                                 if (inline_env->method->linenumbercount > lineindex) {
316                                         currentline = inline_env->method->linenumbers[lineindex].line_number;
317                                         lineindex++;
318                                         if (lineindex < inline_env->method->linenumbercount)
319                                                 linepcchange = inline_env->method->linenumbers[lineindex].start_pc;
320                                         /*printf("Line number changed to: %ld\n",currentline);*/
321                                 }
322                         }
323                 }
324
325 #if defined(USE_INLINING)
326                 if ((useinlining) && (gp == nextgp)) {
327                         u1 *tptr;
328                         bool *readonly = NULL;
329                         int argBlockIdx=0;
330
331                         block_insert(gp);               /* JJJJJJJJJJ */
332                         blockend=false;
333                         instructionstart[gp] = 1;
334                         m->basicblockindex[gp] |= (ipc << 1);  /*FIXME: necessary ? */
335
336                         opcode = code_get_u1(p,inline_env->method);
337                         nextp = p += jcommandsize[opcode];
338                         if (nextp > inline_env->method->jcodelength) {
339                                 log_text("Unexpected end of bytecode");
340                                 assert(0);
341                         }
342
343                         tmpinlinf = list_first(inlinfo->inlinedmethods);
344                         firstlocal = tmpinlinf->firstlocal;
345                         label_index = tmpinlinf->label_index;
346                         readonly = tmpinlinf->readonly;
347
348                         for (i=0,tptr=tmpinlinf->method->paramtypes;i<tmpinlinf->method->paramcount;i++,tptr++) {
349                                 if ( ((*tptr)==TYPE_LNG) ||
350                                   ((*tptr)==TYPE_DBL) )
351                                         argBlockIdx+=2;
352                                 else
353                                         argBlockIdx++;
354                         }
355
356                         for (i = 0, tptr = tmpinlinf->method->paramtypes + tmpinlinf->method->paramcount - 1; i < tmpinlinf->method->paramcount; i++, tptr--) {
357                                 int op;
358
359                                 if ((i == 0) && inlineparamopt) {
360                                         OP1(ICMD_CLEAR_ARGREN, firstlocal);
361                                 }
362
363                                 if (!inlineparamopt || !readonly[i]) {
364                                         op = ICMD_ISTORE;
365
366                                 } else {
367                                         op = ICMD_READONLY_ARG;
368                                 }
369
370                                 op += *tptr;
371                                 if ( ((*tptr)==TYPE_LNG) ||
372                                   ((*tptr)==TYPE_DBL) )
373                                         argBlockIdx-=2;
374                                 else
375                                         argBlockIdx--;
376
377                                 OP1(op, firstlocal + argBlockIdx);
378                                 /* OP1(op, firstlocal + tmpinlinf->method->paramcount - 1 - i); */
379                                 /* printf("inline argument load operation for local: %ld\n",firstlocal + tmpinlinf->method->paramcount - 1 - i); */
380                         }
381                         skipBasicBlockChange=1;
382 METHINFOt(inline_env->method,"BEFORE SAVE: ",DEBUG);
383                         inlining_save_compiler_variables();
384 METHINFOt(inline_env->method,"AFTER SAVE: ",DEBUG);
385                         inlining_set_compiler_variables(tmpinlinf);
386 METHINFOt(inline_env->method,"AFTER SET :: ",DEBUG);
387 METHINFOt(m,"\n.......Parsing (inlined): ",DEBUG);
388 METHINFO(inline_env->method,DEBUG);
389
390                         OP1(ICMD_INLINE_START,tmpinlinf->level);
391
392                         if (inlinfo->inlinedmethods == NULL) {
393                                 gp = -1;
394                         } else {
395                                 tmpinlinf = list_first(inlinfo->inlinedmethods);
396                                 nextgp = (tmpinlinf != NULL) ? tmpinlinf->startgp : -1;
397                         }
398                         if (inline_env->method->exceptiontablelength > 0) 
399                           nextex = fillextable(m, nextex, 
400                             inline_env->method->exceptiontable, inline_env->method->exceptiontablelength, 
401                             label_index, &b_count, inline_env);
402                         continue;
403                 }
404 #endif /* defined(USE_INLINING) */
405
406                 opcode = code_get_u1(p,inline_env->method);            /* fetch op code  */
407          if (DEBUG==true) 
408                 {
409                         printf("Parse p=%i<%i<%i<   opcode=<%i> %s\n",
410                            p, gp, inline_env->jcodelength, opcode, opcode_names[opcode]);
411                         if (label_index)
412                                 printf("label_index[%d]=%d\n",p,label_index[p]);
413                 }
414          /*
415 printf("basicblockindex[gp=%i]=%i=%p ipc=%i=%p shifted ipc=%i=%p\n",
416 gp,m->basicblockindex[gp],m->basicblockindex[gp],ipc,ipc,(ipc<<1),(ipc<<1));
417 fflush(stdout);
418          */
419                 if (!skipBasicBlockChange) {
420                         m->basicblockindex[gp] |= (ipc << 1); /*store intermed cnt*/
421                 } else skipBasicBlockChange=0;
422                 /*
423 printf("basicblockindex[gp=%i]=%i=%p \n",
424 gp,m->basicblockindex[gp],m->basicblockindex[gp]);
425 fflush(stdout);
426                 */
427
428                 if (blockend) {
429                         block_insert(gp);               /* start new block                */
430                         blockend = false;
431                         /*printf("blockend was set: new blockcount: %ld at:%ld\n",b_count,gp);*/
432                 }
433
434                 nextp = p + jcommandsize[opcode];   /* compute next instruction start */
435
436                 if (nextp > inline_env->method->jcodelength) {
437                         log_text("Unexpected end of bytecode");
438                         assert(0);
439                 }
440
441                 s_count += stackreq[opcode];            /* compute stack element count    */
442 SHOWOPCODE(DEBUG4)
443                 switch (opcode) {
444                 case JAVA_NOP:
445                         break;
446
447                         /* pushing constants onto the stack p */
448
449                 case JAVA_BIPUSH:
450                         LOADCONST_I(code_get_s1(p+1,inline_env->method));
451                         break;
452
453                 case JAVA_SIPUSH:
454                         LOADCONST_I(code_get_s2(p+1,inline_env->method));
455                         break;
456
457                 case JAVA_LDC1:
458                         i = code_get_u1(p + 1, inline_env->method);
459                         goto pushconstantitem;
460
461                 case JAVA_LDC2:
462                 case JAVA_LDC2W:
463                         i = code_get_u2(p + 1, inline_env->method);
464
465                 pushconstantitem:
466
467                         if (i >= inline_env->method->class->cpcount) {
468                                 dolog("Attempt to access constant outside range: %d >= %d", i, inline_env->method->class->cpcount);
469                                 assert(0);
470                         }
471
472                         switch (inline_env->method->class->cptags[i]) {
473                         case CONSTANT_Integer:
474                                 LOADCONST_I(((constant_integer *) (inline_env->method->class->cpinfos[i]))->value);
475                                 break;
476                         case CONSTANT_Long:
477                                 LOADCONST_L(((constant_long *) (inline_env->method->class->cpinfos[i]))->value);
478                                 break;
479                         case CONSTANT_Float:
480                                 LOADCONST_F(((constant_float *) (inline_env->method->class->cpinfos[i]))->value);
481                                 break;
482                         case CONSTANT_Double:
483                                 LOADCONST_D(((constant_double *) (inline_env->method->class->cpinfos[i]))->value);
484                                 break;
485                         case CONSTANT_String:
486                                 LOADCONST_A(literalstring_new((utf *) (inline_env->method->class->cpinfos[i])));
487                                 break;
488                         default:
489                                 log_text("Invalid constant type to push");
490                                 assert(0);
491                         }
492                         break;
493
494                 case JAVA_ACONST_NULL:
495                         LOADCONST_A(NULL);
496                         break;
497
498                 case JAVA_ICONST_M1:
499                 case JAVA_ICONST_0:
500                 case JAVA_ICONST_1:
501                 case JAVA_ICONST_2:
502                 case JAVA_ICONST_3:
503                 case JAVA_ICONST_4:
504                 case JAVA_ICONST_5:
505                         LOADCONST_I(opcode - JAVA_ICONST_0);
506                         break;
507
508                 case JAVA_LCONST_0:
509                 case JAVA_LCONST_1:
510                         LOADCONST_L(opcode - JAVA_LCONST_0);
511                         break;
512
513                 case JAVA_FCONST_0:
514                 case JAVA_FCONST_1:
515                 case JAVA_FCONST_2:
516                         LOADCONST_F(opcode - JAVA_FCONST_0);
517                         break;
518
519                 case JAVA_DCONST_0:
520                 case JAVA_DCONST_1:
521                         LOADCONST_D(opcode - JAVA_DCONST_0);
522                         break;
523
524                         /* loading variables onto the stack */
525
526                 case JAVA_ILOAD:
527                 case JAVA_LLOAD:
528                 case JAVA_FLOAD:
529                 case JAVA_DLOAD:
530                 case JAVA_ALOAD:
531                         if (!iswide) {
532                                 i = code_get_u1(p + 1,inline_env->method);
533                         } else {
534                                 i = code_get_u2(p + 1,inline_env->method);
535                                 nextp = p + 3;
536                                 iswide = false;
537                         }
538                         OP1LOAD(opcode, i + firstlocal);
539                         break;
540
541                 case JAVA_ILOAD_0:
542                 case JAVA_ILOAD_1:
543                 case JAVA_ILOAD_2:
544                 case JAVA_ILOAD_3:
545                         OP1LOAD(ICMD_ILOAD, opcode - JAVA_ILOAD_0 + firstlocal);
546                         break;
547
548                 case JAVA_LLOAD_0:
549                 case JAVA_LLOAD_1:
550                 case JAVA_LLOAD_2:
551                 case JAVA_LLOAD_3:
552                         OP1LOAD(ICMD_LLOAD, opcode - JAVA_LLOAD_0 + firstlocal);
553                         break;
554
555                 case JAVA_FLOAD_0:
556                 case JAVA_FLOAD_1:
557                 case JAVA_FLOAD_2:
558                 case JAVA_FLOAD_3:
559                         OP1LOAD(ICMD_FLOAD, opcode - JAVA_FLOAD_0 + firstlocal);
560                         break;
561
562                 case JAVA_DLOAD_0:
563                 case JAVA_DLOAD_1:
564                 case JAVA_DLOAD_2:
565                 case JAVA_DLOAD_3:
566                         OP1LOAD(ICMD_DLOAD, opcode - JAVA_DLOAD_0 + firstlocal);
567                         break;
568
569                 case JAVA_ALOAD_0:
570                 case JAVA_ALOAD_1:
571                 case JAVA_ALOAD_2:
572                 case JAVA_ALOAD_3:
573                         OP1LOAD(ICMD_ALOAD, opcode - JAVA_ALOAD_0 + firstlocal);
574                         break;
575
576                         /* storing stack values into local variables */
577
578                 case JAVA_ISTORE:
579                 case JAVA_LSTORE:
580                 case JAVA_FSTORE:
581                 case JAVA_DSTORE:
582                 case JAVA_ASTORE:
583                         if (!iswide) {
584                                 i = code_get_u1(p + 1,inline_env->method);
585                         } else {
586                                 i = code_get_u2(p + 1,inline_env->method);
587                                 iswide = false;
588                                 nextp = p + 3;
589                         }
590                         OP1STORE(opcode, i + firstlocal);
591                         break;
592
593                 case JAVA_ISTORE_0:
594                 case JAVA_ISTORE_1:
595                 case JAVA_ISTORE_2:
596                 case JAVA_ISTORE_3:
597                         OP1STORE(ICMD_ISTORE, opcode - JAVA_ISTORE_0 + firstlocal);
598                         break;
599
600                 case JAVA_LSTORE_0:
601                 case JAVA_LSTORE_1:
602                 case JAVA_LSTORE_2:
603                 case JAVA_LSTORE_3:
604                         OP1STORE(ICMD_LSTORE, opcode - JAVA_LSTORE_0 + firstlocal);
605                         break;
606
607                 case JAVA_FSTORE_0:
608                 case JAVA_FSTORE_1:
609                 case JAVA_FSTORE_2:
610                 case JAVA_FSTORE_3:
611                         OP1STORE(ICMD_FSTORE, opcode - JAVA_FSTORE_0 + firstlocal);
612                         break;
613
614                 case JAVA_DSTORE_0:
615                 case JAVA_DSTORE_1:
616                 case JAVA_DSTORE_2:
617                 case JAVA_DSTORE_3:
618                         OP1STORE(ICMD_DSTORE, opcode - JAVA_DSTORE_0 + firstlocal);
619                         break;
620
621                 case JAVA_ASTORE_0:
622                 case JAVA_ASTORE_1:
623                 case JAVA_ASTORE_2:
624                 case JAVA_ASTORE_3:
625                         OP1STORE(ICMD_ASTORE, opcode - JAVA_ASTORE_0 + firstlocal);
626                         break;
627
628                 case JAVA_IINC:
629                         {
630                                 int v;
631                                 
632                                 if (!iswide) {
633                                         i = code_get_u1(p + 1,inline_env->method);
634                                         v = code_get_s1(p + 2,inline_env->method);
635
636                                 } else {
637                                         i = code_get_u2(p + 1,inline_env->method);
638                                         v = code_get_s2(p + 3,inline_env->method);
639                                         iswide = false;
640                                         nextp = p + 5;
641                                 }
642                                 INDEX_ONEWORD(i + firstlocal);
643                                 OP2I(opcode, i + firstlocal, v);
644                         }
645                         break;
646
647                         /* wider index for loading, storing and incrementing */
648
649                 case JAVA_WIDE:
650                         iswide = true;
651                         nextp = p + 1;
652                         break;
653
654                 /* managing arrays ****************************************************/
655
656                 case JAVA_NEWARRAY:
657                         OP(ICMD_CHECKASIZE);
658                         switch (code_get_s1(p + 1, inline_env->method)) {
659                         case 4:
660                                 bte = builtintable_get_internal(BUILTIN_newarray_boolean);
661                                 break;
662                         case 5:
663                                 bte = builtintable_get_internal(BUILTIN_newarray_char);
664                                 break;
665                         case 6:
666                                 bte = builtintable_get_internal(BUILTIN_newarray_float);
667                                 break;
668                         case 7:
669                                 bte = builtintable_get_internal(BUILTIN_newarray_double);
670                                 break;
671                         case 8:
672                                 bte = builtintable_get_internal(BUILTIN_newarray_byte);
673                                 break;
674                         case 9:
675                                 bte = builtintable_get_internal(BUILTIN_newarray_short);
676                                 break;
677                         case 10:
678                                 bte = builtintable_get_internal(BUILTIN_newarray_int);
679                                 break;
680                         case 11:
681                                 bte = builtintable_get_internal(BUILTIN_newarray_long);
682                                 break;
683                         default:
684                                 log_text("Invalid array-type to create");
685                                 assert(0);
686                         }
687                         BUILTIN(bte, bte->md->paramcount, NULL, currentline);
688                         OP(ICMD_CHECKEXCEPTION);
689                         break;
690
691                 case JAVA_ANEWARRAY:
692                         OP(ICMD_CHECKASIZE);
693                         i = code_get_u2(p + 1, inline_env->method);
694                         compr = (constant_classref *) class_getconstant(inline_env->method->class, i, CONSTANT_Class);
695
696                         if (!(cr = class_get_classref_multiarray_of(1, compr)))
697                                 return NULL;
698
699                         if (!resolve_classref(inline_env->method, cr, resolveLazy, true, &c))
700                                 return NULL;
701
702                         if (c) {
703                                 bte = builtintable_get_internal(BUILTIN_newarray);
704                                 LOADCONST_A_BUILTIN(c->vftbl);
705                                 BUILTIN(bte, bte->md->paramcount, NULL, currentline);
706
707                         } else {
708                                 bte = builtintable_get_internal(PATCHER_builtin_newarray);
709                                 LOADCONST_A_BUILTIN(cr);
710                                 BUILTIN(bte, bte->md->paramcount, cr, currentline);
711                         }
712                         s_count++;
713                         OP(ICMD_CHECKEXCEPTION);
714                         break;
715
716                 case JAVA_MULTIANEWARRAY:
717                         inline_env->method->isleafmethod = false;
718                         i = code_get_u2(p + 1, inline_env->method);
719                         {
720                                 constant_classref *cr;
721                                 classinfo *c;
722                                 s4 v = code_get_u1(p + 3, inline_env->method);
723
724                                 cr = (constant_classref *) class_getconstant(inline_env->method->class, i, CONSTANT_Class);
725
726                                 if (!resolve_classref(inline_env->method, cr, resolveLazy, true, &c))
727                                         return NULL;
728
729                                 if (c) {
730                                         OP2AT(opcode, v, c->vftbl, NULL, currentline);
731
732                                 } else {
733                                         OP2AT(opcode, v, cr,
734                                                   (voidptr) (ptrint) PATCHER_builtin_multianewarray,
735                                                   currentline);
736                                 }
737                         }
738                         break;
739
740                 case JAVA_IFEQ:
741                 case JAVA_IFLT:
742                 case JAVA_IFLE:
743                 case JAVA_IFNE:
744                 case JAVA_IFGT:
745                 case JAVA_IFGE:
746                 case JAVA_IFNULL:
747                 case JAVA_IFNONNULL:
748                 case JAVA_IF_ICMPEQ:
749                 case JAVA_IF_ICMPNE:
750                 case JAVA_IF_ICMPLT:
751                 case JAVA_IF_ICMPGT:
752                 case JAVA_IF_ICMPLE:
753                 case JAVA_IF_ICMPGE:
754                 case JAVA_IF_ACMPEQ:
755                 case JAVA_IF_ACMPNE:
756                 case JAVA_GOTO:
757                 case JAVA_JSR:
758                         i = p + code_get_s2(p + 1,inline_env->method);
759                         if (useinlining) { 
760                                 debug_writebranch;
761                                 i = label_index[i];
762                         }
763                         /*printf("GOTO: %d\n",i);*/
764                         bound_check(i);
765                         block_insert(i);
766                         blockend = true;
767                         OP1(opcode, i);
768                         break;
769                 case JAVA_GOTO_W:
770                 case JAVA_JSR_W:
771                         i = p + code_get_s4(p + 1,inline_env->method);
772                         if (useinlining) { 
773                                 debug_writebranch;
774                                 i = label_index[i];
775                         }
776                         bound_check(i);
777                         /*printf("B6 JSR_W\t"); fflush(stdout);*/
778                         block_insert(i);
779                         blockend = true;
780                         OP1(opcode, i);
781                         break;
782
783                 case JAVA_RET:
784                         if (!iswide) {
785                                 i = code_get_u1(p + 1,inline_env->method);
786                         } else {
787                                 i = code_get_u2(p + 1,inline_env->method);
788                                 nextp = p + 3;
789                                 iswide = false;
790                         }
791                         blockend = true;
792                                 
793                         /*
794                           if (inline_env->isinlinedmethod) {
795                           OP1(ICMD_GOTO, inlinfo->stopgp);
796                           break;
797                           }*/
798
799                         OP1LOAD(opcode, i + firstlocal);
800                         break;
801
802                 case JAVA_IRETURN:
803                 case JAVA_LRETURN:
804                 case JAVA_FRETURN:
805                 case JAVA_DRETURN:
806                 case JAVA_ARETURN:
807                 case JAVA_RETURN:
808                         if (inline_env->isinlinedmethod) {
809                                 /*                                      if (p==m->jcodelength-1) {*/ /* return is at end of inlined method */
810                                 /*                                              OP(ICMD_NOP); */
811                                 /*                                              break; */
812                                 /*                                      } */
813                                 if (nextp>inline_env->method->jcodelength-1) {
814                                         /* OP1(ICMD_GOTO, inlinfo->stopgp);
815                                            OP(ICMD_NOP);
816                                            OP(ICMD_NOP);
817                                         */
818                                         blockend=true;
819                                         break;
820                                 } /* JJJJJJJ */
821                                 blockend = true;
822                                 OP1(ICMD_GOTO, inlinfo->stopgp);
823                                 break;
824                         }
825
826                         blockend = true;
827                         OP(opcode);
828                         break;
829
830                 case JAVA_ATHROW:
831                         blockend = true;
832                         OP(opcode);
833                         break;
834                                 
835
836                 /* table jumps ********************************************************/
837
838                 case JAVA_LOOKUPSWITCH:
839                         {
840                                 s4 num, j;
841                                 s4 *tablep;
842                                 s4 prevvalue=0;
843
844                                 blockend = true;
845                                 nextp = ALIGN((p + 1), 4);
846
847                                 if (nextp + 8 > inline_env->method->jcodelength) {
848                                         log_text("Unexpected end of bytecode");
849                                         assert(0);
850                                 }
851
852                                 if (!useinlining) {
853                                         tablep = (s4 *) (inline_env->method->jcode + nextp);
854
855                                 } else {
856                                         num = code_get_u4(nextp + 4, inline_env->method);
857                                         tablep = DMNEW(s4, num * 2 + 2);
858                                 }
859
860                                 OP2A(opcode, 0, tablep, currentline);
861
862                                 /* default target */
863
864                                 j =  p + code_get_s4(nextp, inline_env->method);
865                                 if (useinlining) 
866                                         j = label_index[j];
867                                 *tablep = j;     /* restore for little endian */
868                                 tablep++;
869                                 nextp += 4;
870                                 bound_check(j);
871                                 block_insert(j);
872
873                                 /* number of pairs */
874
875                                 num = code_get_u4(nextp, inline_env->method);
876                                 *tablep = num;
877                                 tablep++;
878                                 nextp += 4;
879
880                                 if (nextp + 8 * num > inline_env->method->jcodelength) {
881                                         /* XXX TODO VerifyError */
882                                         log_text("Unexpected end of bytecode");
883                                         assert(0);
884                                 }
885
886                                 for (i = 0; i < num; i++) {
887                                         /* value */
888
889                                         j = code_get_s4(nextp, inline_env->method);
890                                         *tablep = j; /* restore for little endian */
891                                         tablep++;
892                                         nextp += 4;
893
894                                         /* check if the lookup table is sorted correctly */
895                                         
896                                         if (i && (j <= prevvalue)) {
897                                                 *exceptionptr = new_verifyerror(m, "Unsorted lookup switch");
898                                                 return NULL;
899                                         }
900                                         prevvalue = j;
901
902                                         /* target */
903
904                                         j = p + code_get_s4(nextp,inline_env->method);
905                                         if (useinlining)
906                                                 j = label_index[j];
907                                         *tablep = j; /* restore for little endian */
908                                         tablep++;
909                                         nextp += 4;
910                                         bound_check(j);
911                                         block_insert(j);
912                                 }
913
914                                 break;
915                         }
916
917
918                 case JAVA_TABLESWITCH:
919                         {
920                                 s4 num, j;
921                                 s4 *tablep;
922
923                                 blockend = true;
924                                 nextp = ALIGN((p + 1), 4);
925                                 if (nextp + 12 > inline_env->method->jcodelength) {
926                                         /* XXX TODO VerifyError */
927                                         log_text("Unexpected end of bytecode");
928                                         assert(0);
929                                 }
930
931                                 if (!useinlining) {
932                                         tablep = (s4 *) (inline_env->method->jcode + nextp);
933
934                                 } else {
935                                         num = code_get_u4(nextp + 8,inline_env->method) - code_get_u4(nextp + 4,inline_env->method);
936                                         tablep = DMNEW(s4, num + 1 + 3);
937                                 }
938
939                                 OP2A(opcode, 0, tablep, currentline);
940
941                                 /* default target */
942
943                                 j = p + code_get_s4(nextp, inline_env->method);
944                                 if (useinlining)
945                                         j = label_index[j];
946                                 *tablep = j;     /* restore for little endian */
947                                 tablep++;
948                                 nextp += 4;
949                                 bound_check(j);
950                                 block_insert(j);
951
952                                 /* lower bound */
953
954                                 j = code_get_s4(nextp, inline_env->method);
955                                 *tablep = j;     /* restore for little endian */
956                                 tablep++;
957                                 nextp += 4;
958
959                                 /* upper bound */
960
961                                 num = code_get_s4(nextp, inline_env->method);
962                                 *tablep = num;   /* restore for little endian */
963                                 tablep++;
964                                 nextp += 4;
965
966                                 num -= j;  /* difference of upper - lower */
967
968                                 if (num < 0) {
969                                         /* XXX TODO VerifyError */
970                                         log_text("invalid TABLESWITCH: upper bound < lower bound");
971                                         assert(0);
972                                 }
973
974                                 if (nextp + 4 * (num + 1) > inline_env->method->jcodelength) {
975                                         /* XXX TODO VerifyError */
976                                         log_text("Unexpected end of bytecode");
977                                         assert(0);
978                                 }
979
980                                 for (i = 0; i <= num; i++) {
981                                         j = p + code_get_s4(nextp,inline_env->method);
982                                         if (useinlining) {
983                                                 /*printf("TABLESWITCH: j before mapping=%ld\n",j);*/
984                                                 j = label_index[j];
985                                         }
986                                         *tablep = j; /* restore for little endian */
987                                         tablep++;
988                                         nextp += 4;
989                                         bound_check(j);
990                                         block_insert(j);
991                                         /*printf("TABLESWITCH: block_insert(%ld)\n",j);*/
992                                 }
993
994                                 break;
995                         }
996
997
998                 /* load and store of object fields ************************************/
999
1000                 case JAVA_AASTORE:
1001                         bte = builtintable_get_internal(BUILTIN_aastore);
1002                         BUILTIN(bte, bte->md->paramcount, NULL, currentline);
1003                         break;
1004
1005                 case JAVA_GETSTATIC:
1006                 case JAVA_PUTSTATIC:
1007                 case JAVA_GETFIELD:
1008                 case JAVA_PUTFIELD:
1009                         {
1010                                 constant_FMIref  *fr;
1011                                 unresolved_field *uf;
1012                                 fieldinfo        *fi;
1013
1014                                 i = code_get_u2(p + 1, inline_env->method);
1015                                 fr = class_getconstant(inline_env->method->class, i,
1016                                                                            CONSTANT_Fieldref);
1017
1018                                 OP2A_NOINC(opcode, fr->parseddesc.fd->type, fr, currentline);
1019
1020                                 if (!(uf = create_unresolved_field(inline_env->method->class,
1021                                                                                                    inline_env->method,
1022                                                                                                    iptr)))
1023                                         return NULL;
1024
1025                                 /* store unresolved_field pointer */
1026
1027                                 iptr->target = uf;
1028
1029                                 /* only with -noverify, otherwise the typechecker does this */
1030
1031                                 if (!opt_verify) {
1032                                         if (!resolve_field(uf, resolveLazy, &fi))
1033                                                 return NULL;
1034
1035                                         iptr->val.a = fi;
1036                                 }
1037                                 else {
1038                                         iptr->val.a = NULL;
1039                                 }
1040                                 PINC;
1041 #if defined(__MIPS__) || defined(__POWERPC__)
1042                                 if (!fi || !fi->class->initialized)
1043                                         inline_env->method->isleafmethod = false;
1044 #endif
1045                         }
1046                         break;
1047
1048
1049                 /* method invocation **************************************************/
1050
1051                 case JAVA_INVOKESTATIC:
1052                         i = code_get_u2(p + 1, inline_env->method);
1053                         {
1054                                 constant_FMIref   *mr;
1055                                 methoddesc        *md;
1056                                 unresolved_method *um;
1057                                 methodinfo        *mi;
1058
1059                                 inline_env->method->isleafmethod = false;
1060
1061                                 mr = class_getconstant(inline_env->method->class, i,
1062                                                                            CONSTANT_Methodref);
1063
1064                                 md = mr->parseddesc.md;
1065
1066                                 if (!md->params)
1067                                         if (!descriptor_params_from_paramtypes(md, ACC_STATIC))
1068                                                 return NULL;
1069
1070                                 OP2A_NOINC(opcode, md->paramcount, mr, currentline);
1071
1072                                 um = create_unresolved_method(inline_env->method->class,
1073                                                                                           inline_env->method, iptr);
1074
1075                                 if (!um)
1076                                         return NULL;
1077
1078                                 /* store the unresolved_method pointer */
1079
1080                                 iptr->target = um;
1081
1082                                 /* only with -noverify, otherwise the typechecker does this */
1083
1084                                 if (!opt_verify) {
1085                                         if (!resolve_method(um, resolveLazy, &mi))
1086                                                 return NULL;
1087
1088                                         iptr->val.a = mi;
1089                                 }
1090                                 else {
1091                                         iptr->val.a = NULL;
1092                                 }
1093                                 PINC;
1094                         }
1095                         break;
1096
1097                 case JAVA_INVOKESPECIAL:
1098                 case JAVA_INVOKEVIRTUAL:
1099                         {
1100                                 constant_FMIref   *mr;
1101                                 methoddesc        *md;
1102                                 unresolved_method *um;
1103                                 methodinfo        *mi;
1104
1105                                 inline_env->method->isleafmethod = false;
1106
1107                                 i = code_get_u2(p + 1, inline_env->method);
1108                                 mr = class_getconstant(inline_env->method->class, i,
1109                                                                            CONSTANT_Methodref);
1110
1111                                 md = mr->parseddesc.md;
1112
1113                                 if (!md->params)
1114                                         if (!descriptor_params_from_paramtypes(md, 0))
1115                                                 return NULL;
1116                                 
1117                                 OP2A_NOINC(opcode, md->paramcount, mr, currentline);
1118
1119                                 um = create_unresolved_method(inline_env->method->class,
1120                                                                                           inline_env->method, iptr);
1121
1122                                 if (!um)
1123                                         return NULL;
1124
1125                                 /* store the unresolved_method* */
1126
1127                                 iptr->target = um;
1128
1129                                 /* only with -noverify, otherwise the typechecker does this */
1130
1131                                 if (!opt_verify) {
1132                                         if (!resolve_method(um, resolveLazy, &mi))
1133                                                 return NULL;
1134
1135                                         iptr->val.a = mi;
1136                                 }
1137                                 else {
1138                                         iptr->val.a = NULL;
1139                                 }
1140                                 PINC;
1141                         }
1142                         break;
1143
1144                 case JAVA_INVOKEINTERFACE:
1145                         i = code_get_u2(p + 1, inline_env->method);
1146                         {
1147                                 constant_FMIref   *mr;
1148                                 methoddesc        *md;
1149                                 unresolved_method *um;
1150                                 methodinfo        *mi;
1151                                 
1152                                 inline_env->method->isleafmethod = false;
1153
1154                                 mr = class_getconstant(inline_env->method->class, i,
1155                                                                            CONSTANT_InterfaceMethodref);
1156
1157                                 md = mr->parseddesc.md;
1158
1159                                 if (!md->params)
1160                                         if (!descriptor_params_from_paramtypes(md, 0))
1161                                                 return NULL;
1162
1163                                 OP2A_NOINC(opcode, md->paramcount, mr, currentline);
1164
1165                                 um = create_unresolved_method(inline_env->method->class,
1166                                                                                           inline_env->method, iptr);
1167
1168                                 if (!um)
1169                                         return NULL;
1170
1171                                 /* store the unresolved_method* */
1172
1173                                 iptr->target = um;
1174
1175                                 /* only with -noverify, otherwise the typechecker does this */
1176
1177                                 if (!opt_verify) {
1178                                         if (!resolve_method(um, resolveLazy, &mi))
1179                                                 return NULL;
1180
1181                                         iptr->val.a = mi;
1182                                 }
1183                                 else {
1184                                         iptr->val.a = NULL;
1185                                 }
1186                                 PINC;
1187                         }
1188                         break;
1189
1190                 /* miscellaneous object operations ************************************/
1191
1192                 case JAVA_NEW:
1193                         i = code_get_u2(p + 1, inline_env->method);
1194                         cr = (constant_classref *) class_getconstant(inline_env->method->class, i, CONSTANT_Class);
1195
1196                         if (!resolve_classref(inline_env->method, cr, resolveLazy, true,
1197                                                                   &c))
1198                                 return NULL;
1199
1200                         if (c && c->initialized) {
1201                                 bte = builtintable_get_internal(BUILTIN_new);
1202                                 LOADCONST_A_BUILTIN(c);
1203                                 BUILTIN(bte, bte->md->paramcount, NULL, currentline);
1204
1205                         } else {
1206                                 bte = builtintable_get_internal(PATCHER_builtin_new);
1207                                 LOADCONST_A_BUILTIN(cr);
1208                                 BUILTIN(bte, bte->md->paramcount, cr, currentline);
1209                         }
1210
1211                         s_count++;
1212                         OP(ICMD_CHECKEXCEPTION);
1213                         break;
1214
1215                 case JAVA_CHECKCAST:
1216                         i = code_get_u2(p + 1, inline_env->method);
1217                         cr = (constant_classref *) class_getconstant(inline_env->method->class, i, CONSTANT_Class);
1218
1219                         if (!resolve_classref(inline_env->method, cr, resolveLazy, true, &c))
1220                                 return NULL;
1221
1222                         if (cr->name->text[0] == '[') {
1223                                 /* array type cast-check */
1224                                 if (c) {
1225                                         bte = builtintable_get_internal(BUILTIN_arraycheckcast);
1226                                         LOADCONST_A_BUILTIN(c->vftbl);
1227                                         BUILTIN(bte, bte->md->paramcount, NULL, currentline);
1228
1229                                 } else {
1230                                         bte = builtintable_get_internal(PATCHER_builtin_arraycheckcast);
1231                                         LOADCONST_A_BUILTIN(cr);
1232                                         BUILTIN(bte, bte->md->paramcount, cr, currentline);
1233                                 }
1234                                 s_count++;
1235
1236                         } else {
1237                                 /* object type cast-check */
1238                                 OP2AT(opcode, 1, c, cr, currentline);
1239                         }
1240 #if defined(__MIPS__) || defined(__POWERPC__)
1241                         if (!c)
1242                                 inline_env->method->isleafmethod = false;
1243 #endif
1244                         break;
1245
1246                 case JAVA_INSTANCEOF:
1247                         i = code_get_u2(p + 1,inline_env->method);
1248                         cr = (constant_classref *) class_getconstant(inline_env->method->class, i, CONSTANT_Class);
1249
1250                         if (!resolve_classref(inline_env->method, cr, resolveLazy, true, &c))
1251                                 return NULL;
1252
1253                         if (cr->name->text[0] == '[') {
1254                                 /* array type cast-check */
1255                                 if (c) {
1256                                         bte = builtintable_get_internal(BUILTIN_arrayinstanceof);
1257                                         LOADCONST_A_BUILTIN(c->vftbl);
1258                                         BUILTIN(bte, bte->md->paramcount, NULL, currentline);
1259
1260                                 } else {
1261                                         bte = builtintable_get_internal(PATCHER_builtin_arrayinstanceof);
1262                                         LOADCONST_A_BUILTIN(cr);
1263                                         BUILTIN(bte, bte->md->paramcount, cr, currentline);
1264                                 }
1265                                 s_count++;
1266
1267                         } else {
1268                                 /* object type cast-check */
1269                                 OP2AT(opcode, 1, c, cr, currentline);
1270                         }
1271 #if defined(__MIPS__) || defined(__POWERPC__)
1272                         if (!c)
1273                                 inline_env->method->isleafmethod = false;
1274 #endif
1275                         break;
1276
1277                 case JAVA_MONITORENTER:
1278 #if defined(USE_THREADS)
1279                         if (checksync) {
1280                                 OP(ICMD_CHECKNULL);
1281                                 bte = builtintable_get_internal(BUILTIN_monitorenter);
1282                                 BUILTIN(bte, bte->md->paramcount, NULL, currentline);
1283                         } else
1284 #endif
1285                                 {
1286                                         OP(ICMD_CHECKNULL);
1287                                         OP(ICMD_POP);
1288                                 }
1289                         break;
1290
1291                 case JAVA_MONITOREXIT:
1292 #if defined(USE_THREADS)
1293                         if (checksync) {
1294                                 bte = builtintable_get_internal(BUILTIN_monitorexit);
1295                                 BUILTIN(bte, bte->md->paramcount, NULL, currentline);
1296                         } else
1297 #endif
1298                                 {
1299                                         OP(ICMD_POP);
1300                                 }
1301                         break;
1302
1303                 /* any other basic operation ******************************************/
1304
1305                 case JAVA_IDIV:
1306                         OP(opcode);
1307                         break;
1308
1309                 case JAVA_IREM:
1310                         OP(opcode);
1311                         break;
1312
1313                 case JAVA_LDIV:
1314                         OP(opcode);
1315                         break;
1316
1317                 case JAVA_LREM:
1318                         OP(opcode);
1319                         break;
1320
1321                 case JAVA_FREM:
1322 #if defined(__I386__)
1323                         OP(opcode);
1324 #else
1325                         bte = builtintable_get_internal(BUILTIN_frem);
1326                         BUILTIN(bte, bte->md->paramcount, NULL, currentline);
1327 #endif
1328                         break;
1329
1330                 case JAVA_DREM:
1331 #if defined(__I386__)
1332                         OP(opcode);
1333 #else
1334                         bte = builtintable_get_internal(BUILTIN_drem);
1335                         BUILTIN(bte, bte->md->paramcount, NULL, currentline);
1336 #endif
1337                         break;
1338
1339                 case JAVA_F2I:
1340 #if defined(__ALPHA__)
1341                         if (!opt_noieee) {
1342                                 bte = builtintable_get_internal(BUILTIN_f2i);
1343                                 BUILTIN(bte, bte->md->paramcount, NULL, currentline);
1344                         } else
1345 #endif
1346                                 {
1347                                         OP(opcode);
1348                                 }
1349                         break;
1350
1351                 case JAVA_F2L:
1352 #if defined(__ALPHA__)
1353                         if (!opt_noieee) {
1354                                 bte = builtintable_get_internal(BUILTIN_f2l);
1355                                 BUILTIN(bte, bte->md->paramcount, NULL, currentline);
1356                         } else 
1357 #endif
1358                                 {
1359                                         OP(opcode);
1360                                 }
1361                         break;
1362
1363                 case JAVA_D2I:
1364 #if defined(__ALPHA__)
1365                         if (!opt_noieee) {
1366                                 bte = builtintable_get_internal(BUILTIN_d2i);
1367                                 BUILTIN(bte, bte->md->paramcount, NULL, currentline);
1368                         } else
1369 #endif
1370                                 {
1371                                         OP(opcode);
1372                                 }
1373                         break;
1374
1375                 case JAVA_D2L:
1376 #if defined(__ALPHA__)
1377                         if (!opt_noieee) {
1378                                 bte = builtintable_get_internal(BUILTIN_d2l);
1379                                 BUILTIN(bte, bte->md->paramcount, NULL, currentline);
1380                         } else
1381 #endif
1382                                 {
1383                                         OP(opcode);
1384                                 }
1385                         break;
1386
1387                 case JAVA_BREAKPOINT:
1388                         *exceptionptr =
1389                                 new_verifyerror(m, "Quick instructions shouldn't appear yet.");
1390                         return NULL;
1391
1392                 case 204: /* unused opcode */
1393                 case 205:
1394                 case 206:
1395                 case 207:
1396                 case 208:
1397                 case 209:
1398                 case 210:
1399                 case 211:
1400                 case 212:
1401                 case 213:
1402                 case 214:
1403                 case 215:
1404                 case 216:
1405                 case 217:
1406                 case 218:
1407                 case 219:
1408                 case 220:
1409                 case 221:
1410                 case 222:
1411                 case 223:
1412                 case 224:
1413                 case 225:
1414                 case 226:
1415                 case 227:
1416                 case 228:
1417                 case 229:
1418                 case 230:
1419                 case 231:
1420                 case 232:
1421                 case 233:
1422                 case 234:
1423                 case 235:
1424                 case 236:
1425                 case 237:
1426                 case 238:
1427                 case 239:
1428                 case 240:
1429                 case 241:
1430                 case 242:
1431                 case 243:
1432                 case 244:
1433                 case 245:
1434                 case 246:
1435                 case 247:
1436                 case 248:
1437                 case 249:
1438                 case 250:
1439                 case 251:
1440                 case 252:
1441                 case 253:
1442                 case 254:
1443                 case 255:
1444                         *exceptionptr =
1445                                 new_internalerror("Illegal opcode %d at instr %d\n",
1446                                                                   opcode, ipc);
1447                         return NULL;
1448                         break;
1449
1450                 default:
1451                         OP(opcode);
1452                         break;
1453                                 
1454                 } /* end switch */
1455
1456                 /* If WIDE was used correctly, iswide should have been reset by now. */
1457                 if (iswide && opcode != JAVA_WIDE) {
1458                         log_text("Illegal instruction: WIDE before incompatible opcode");
1459                         assert(0);
1460                 }
1461
1462 #if defined(USE_INLINING)
1463                 /* if (inline_env->isinlinedmethod && p == inline_env->method->jcodelength - 1) { */ /* end of an inlined method */
1464                 if (inline_env->isinlinedmethod && (nextp >= inline_env->method->jcodelength) ) { /* end of an inlined method */
1465                         /*                printf("setting gp from %d to %d\n",gp, inlinfo->stopgp); */
1466                         gp = inlinfo->stopgp; 
1467                         inlining_restore_compiler_variables();
1468                         OP(ICMD_INLINE_END);
1469 /*label_index = inlinfo->label_index;*/
1470
1471 METHINFOt(inline_env->method,"AFTER RESTORE : ",DEBUG);
1472                         list_remove(inlinfo->inlinedmethods, list_first(inlinfo->inlinedmethods));
1473                         if (inlinfo->inlinedmethods == NULL) { /* JJJJ */
1474                                 nextgp = -1;
1475                         } else {
1476                                 tmpinlinf = list_first(inlinfo->inlinedmethods);
1477                                 nextgp = (tmpinlinf != NULL) ? tmpinlinf->startgp : -1;
1478                         }
1479                         /*                printf("nextpgp: %d\n", nextgp); */
1480                         label_index=inlinfo->label_index;
1481                         firstlocal = inlinfo->firstlocal;
1482                 }
1483 #endif /* defined(USE_INLINING) */
1484
1485         } /* end for */
1486
1487
1488         if (p != m->jcodelength) {
1489                 printf("p (%d) != m->jcodelength (%d)\n",p,m->jcodelength);
1490                 log_text("Command-sequence crosses code-boundary");
1491                 assert(0);
1492         }
1493
1494         if (!blockend) {
1495                 *exceptionptr = new_verifyerror(m, "Falling off the end of the code");
1496                 return NULL;
1497         }
1498
1499         /* adjust block count if target 0 is not first intermediate instruction */
1500
1501         if (!m->basicblockindex[0] || (m->basicblockindex[0] > 1))
1502                 b_count++;
1503
1504         /* copy local to method variables */
1505
1506         m->instructioncount = ipc;
1507         m->basicblockcount = b_count;
1508         m->stackcount = s_count + m->basicblockcount * m->maxstack;
1509
1510         /* allocate stack table */
1511
1512         m->stack = DMNEW(stackelement, m->stackcount);
1513
1514         {
1515                 basicblock *bptr;
1516
1517                 bptr = m->basicblocks = DMNEW(basicblock, b_count + 1);    /* one more for end ipc */
1518
1519                 b_count = 0;
1520                 m->c_debug_nr = 0;
1521         
1522                 /* additional block if target 0 is not first intermediate instruction */
1523
1524                 if (!m->basicblockindex[0] || (m->basicblockindex[0] > 1)) {
1525                         bptr->iinstr = m->instructions;
1526                         bptr->mpc = -1;
1527                         bptr->flags = -1;
1528                         bptr->type = BBTYPE_STD;
1529                         bptr->branchrefs = NULL;
1530                         bptr->pre_count = 0;
1531                         bptr->debug_nr = m->c_debug_nr++;
1532                         bptr++;
1533                         b_count++;
1534                         (bptr - 1)->next = bptr;
1535                 }
1536
1537                 /* allocate blocks */
1538
1539                 for (p = 0; p < inline_env->cumjcodelength; p++) { 
1540                 /* for (p = 0; p < m->jcodelength; p++) { */
1541                         if (m->basicblockindex[p] & 1) {
1542                                 /* Check if this block starts at the beginning of an          */
1543                                 /* instruction.                                               */
1544
1545                                 if (!instructionstart[p]) {
1546                                         /* XXX TODO throw exception? which one? */
1547                                         dolog("Branch into middle of instruction: Basic Block beginn: %d\n", p);
1548                                         assert(0);
1549                                 }
1550
1551                                 /* allocate the block */
1552                                 bptr->iinstr = m->instructions + (m->basicblockindex[p] >> 1);
1553                                 bptr->debug_nr = m->c_debug_nr++;
1554                                 if (b_count != 0)
1555                                         (bptr - 1)->icount = bptr->iinstr - (bptr - 1)->iinstr;
1556                                 bptr->mpc = -1;
1557                                 bptr->flags = -1;
1558                                 bptr->lflags = 0;
1559                                 bptr->type = BBTYPE_STD;
1560                                 bptr->branchrefs = NULL;
1561                                 m->basicblockindex[p] = b_count;
1562                                 bptr->pre_count = 0;
1563                                 bptr++;
1564                                 b_count++;
1565                                 (bptr - 1)->next = bptr;
1566                         }
1567                 }
1568
1569                 /* allocate additional block at end */
1570
1571                 bptr->instack = bptr->outstack = NULL;
1572                 bptr->indepth = bptr->outdepth = 0;
1573                 bptr->iinstr = NULL;
1574                 (bptr - 1)->icount = (m->instructions + m->instructioncount) - (bptr - 1)->iinstr;
1575                 bptr->icount = 0;
1576                 bptr->mpc = -1;
1577                 bptr->flags = -1;
1578                 bptr->lflags = 0;
1579                 bptr->type = BBTYPE_STD;
1580                 bptr->branchrefs = NULL;
1581                 bptr->pre_count = 0;
1582                 bptr->debug_nr = m->c_debug_nr++;
1583                 (bptr - 1)->next = bptr;
1584                 bptr->next = NULL;
1585
1586                 if (cd->exceptiontablelength > 0) {
1587                         cd->exceptiontable[cd->exceptiontablelength - 1].down = NULL;
1588                 }
1589                 
1590                 for (i = 0; i < cd->exceptiontablelength; ++i) {
1591                         p = cd->exceptiontable[i].startpc;
1592                         cd->exceptiontable[i].start = m->basicblocks + m->basicblockindex[p];
1593
1594                         p = cd->exceptiontable[i].endpc;
1595                         cd->exceptiontable[i].end = (p == inline_env->method->jcodelength) ? (m->basicblocks + m->basicblockcount /*+ 1*/) : (m->basicblocks + m->basicblockindex[p]);
1596
1597                         p = cd->exceptiontable[i].handlerpc;
1598                         cd->exceptiontable[i].handler = m->basicblocks + m->basicblockindex[p];
1599             }
1600         }
1601
1602 #if defined(USE_INLINING)       
1603         if (useinlining)
1604                 inlining_cleanup(inline_env);
1605 #endif
1606
1607         /* just return methodinfo* to signal everything was ok */
1608
1609         return m;
1610 }
1611
1612
1613 /*
1614  * These are local overrides for various environment variables in Emacs.
1615  * Please do not remove this and leave it at the end of the file, where
1616  * Emacs will automagically detect them.
1617  * ---------------------------------------------------------------------
1618  * Local variables:
1619  * mode: c
1620  * indent-tabs-mode: t
1621  * c-basic-offset: 4
1622  * tab-width: 4
1623  * End:
1624  */