1 /****************************** comp/parse.c ***********************************
3 Copyright (c) 1997 A. Krall, R. Grafl, M. Gschwind, M. Probst
5 See file COPYRIGHT for information on usage and disclaimer of warranties
7 Enth"alt den Parser f"ur die Bytecode-Darstellung der Methoden
9 Authors: Reinhard Grafl EMAIL: cacao@complang.tuwien.ac.at
10 Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
12 Last Change: 1997/10/17
14 *******************************************************************************/
17 /* Kurzschreibweise f"ur oft verwendete Funktionen */
19 #define LOADCONST_I pcmd_loadconst_i
20 #define LOADCONST_L pcmd_loadconst_l
21 #define LOADCONST_F pcmd_loadconst_f
22 #define LOADCONST_D pcmd_loadconst_d
23 #define LOADCONST_A pcmd_loadconst_a
24 #define MOVE pcmd_move
25 #define IINC pcmd_iinc
29 #define TABLEJUMP pcmd_tablejump
30 #define METHOD pcmd_method
32 #define BUILTIN1 pcmd_builtin1
33 #define BUILTIN2 pcmd_builtin2
34 #define BUILTIN3 pcmd_builtin3
36 #define DROP pcmd_drop
37 #define ACTIVATE pcmd_activate
38 #define BRA_N_DROP pcmd_bra_n_drop
39 #define MOVE_N_DROP pcmd_move_n_drop
41 #define OP1(opcode,s,d) OP(opcode,s,NOVAR,NOVAR,d)
42 #define OP2(opcode,s1,s2,d) OP(opcode,s1,s2,NOVAR,d)
43 #define OP3(opcode,s1,s2,s3,d) OP(opcode,s1,s2,s3,d)
46 #define EXCREATOR(exclass) block_createexcreator (exclass, p)
47 #define EXFORWARDER(exvar) block_createexforwarder (exvar, p)
52 /****************** Funktion: addreturnlog ************************************
54 f"ugt in den Code einen Aufruf der Methoden-R"uckkehr-Protokollierung
57 ******************************************************************************/
59 static void addreturnhandling()
61 if (checksync && (method->flags & ACC_SYNCHRONIZED) ) {
64 if (method->flags & ACC_STATIC) {
65 varid v = var_create (TYPE_ADDRESS);
66 LOADCONST_A (class, v);
67 BUILTIN1 ( (functionptr) builtin_monitorexit, v, NOVAR);
70 BUILTIN1 ( (functionptr) builtin_monitorexit,
71 local_get (0, TYPE_ADDRESS) , NOVAR);
78 /*************** Funktion: addreturnexceptionlog *****************************
80 f"ugt in den Code einen Aufruf der Methoden-R"uckkehr-Protokollierung
83 ******************************************************************************/
85 static void addreturnexceptionhandling()
92 v = var_create (TYPE_ADDRESS);
93 LOADCONST_A (method, v);
94 BUILTIN1 ( (functionptr) builtin_displaymethodexception, v, NOVAR);
97 if (checksync && (method->flags & ACC_SYNCHRONIZED) ) {
100 if (method->flags & ACC_STATIC) {
101 varid v = var_create (TYPE_ADDRESS);
102 LOADCONST_A (class, v);
103 BUILTIN1 ( (functionptr) builtin_monitorexit, v, NOVAR);
106 BUILTIN1 ( (functionptr) builtin_monitorexit,
107 local_get (0, TYPE_ADDRESS) , NOVAR);
115 /******************************************************************************
116 *************** Funktion 'parse' zum Durcharbeiten des Bytecodes **************
117 ******************************************************************************/
119 static void parse (basicblock *b)
125 basicblock *target=NULL;
128 stack_restore (b->stack);
129 subroutine_set (b->subroutine);
134 /* Code fuer einen Exception-Forwarder generieren */
137 case BLOCKTYPE_EXFORWARDER:
140 stack_repush (b->exvar);
143 for (i=0; i<exceptiontablelength; i++) {
144 target = block_find (extable[i].handlerpc);
145 if ( extable[i].startpc <= b->throwpos
146 && extable[i].endpc > b->throwpos) {
148 if (!extable[i].catchtype) goto exceptionfits;
151 v1 = var_create (TYPE_ADDRESS);
152 v2 = var_create (TYPE_ADDRESS);
153 v = var_create (TYPE_INT);
154 MOVE (TYPE_ADDRESS, b->exvar, v1);
155 LOADCONST_A (extable[i].catchtype, v2);
156 BUILTIN2 ((functionptr) builtin_instanceof, v1,v2, v);
158 block_reach (target);
159 BRA_N_DROP (CMD_IFNE, v,NOVAR, NOVAR, target);
167 /* Code fuer einen Exception-Creator generieren */
168 case BLOCKTYPE_EXCREATOR:
170 java_objectheader *o = b->exproto;
171 LOADCONST_A (o, stack_push(TYPE_ADDRESS) );
173 for (i=0; i<exceptiontablelength; i++) {
174 target = block_find (extable[i].handlerpc);
175 if ( extable[i].startpc <= b->throwpos
176 && extable[i].endpc > b->throwpos) {
178 if (!extable[i].catchtype) goto exceptionfits;
179 if (builtin_instanceof (o, extable[i].catchtype) ) goto exceptionfits;
185 /*** Der Sprung zum Exception-Handler (oder Methodenbeendigung) ***/
190 block_reach (target);
191 BRA (CMD_GOTO, NOVAR,NOVAR,NOVAR, target);
196 count_pcmd_returnx++;
199 switch (mreturntype) {
201 addreturnexceptionhandling();
203 v1 = var_create (TYPE_INT);
205 BRA_N_DROP (CMD_IRETURN, v1,stack_pop(TYPE_ADDRESS), NOVAR, NULL);
208 addreturnexceptionhandling();
210 v1 = var_create (TYPE_LONG);
212 BRA_N_DROP (CMD_LRETURN, v1,stack_pop(TYPE_ADDRESS), NOVAR, NULL);
215 addreturnexceptionhandling();
217 v1 = var_create (TYPE_FLOAT);
218 LOADCONST_F (0.0, v1);
219 BRA_N_DROP (CMD_FRETURN, v1,stack_pop(TYPE_ADDRESS), NOVAR, NULL);
222 addreturnexceptionhandling();
224 v1 = var_create (TYPE_DOUBLE);
225 LOADCONST_D (0.0, v1);
226 BRA_N_DROP (CMD_DRETURN, v1,stack_pop(TYPE_ADDRESS), NOVAR, NULL);
229 addreturnexceptionhandling();
231 v1 = var_create (TYPE_ADDRESS);
232 LOADCONST_A (NULL, v1);
233 BRA_N_DROP (CMD_ARETURN, v1,stack_pop(TYPE_ADDRESS), NOVAR, NULL);
236 addreturnexceptionhandling();
238 BRA (CMD_RETURN, NOVAR,stack_pop(TYPE_ADDRESS), NOVAR, NULL);
246 /* Code fuer einen (normalen) JavaVM - Block generieren */
253 /* Method call protocolling */
260 /* Synchronization */
261 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
264 if (method->flags & ACC_STATIC) {
265 varid v = var_create (TYPE_ADDRESS);
266 LOADCONST_A (class, v);
267 BUILTIN1 ( (functionptr) builtin_monitorenter, v, NOVAR);
270 BUILTIN1 ( (functionptr) builtin_monitorenter,
271 local_get (0, TYPE_ADDRESS), NOVAR );
281 opcode = code_get_u1 (p);
282 nextp = p + jcommandsize[opcode];
289 printf ("PC: %3d OPCODE: %3d Stack: ",(int) p, (int) opcode);
290 stack_display (stack_get());
298 /*** Pushing constants onto the stack ***/
301 LOADCONST_I (code_get_s1 (p+1), stack_push (TYPE_INT) );
305 LOADCONST_I (code_get_s2 (p+1), stack_push (TYPE_INT) );
308 case CMD_LDC1: poolindex = code_get_u1 (p+1);
309 goto pushconstantitem;
311 case CMD_LDC2W: poolindex = code_get_u2 (p+1);
313 switch (class_constanttype(class, poolindex)) {
314 case CONSTANT_Integer:
315 { constant_integer *c;
316 c = class_getconstant (class, poolindex, CONSTANT_Integer);
317 LOADCONST_I (c->value, stack_push(TYPE_INT) );
322 c = class_getconstant (class, poolindex, CONSTANT_Long);
323 LOADCONST_L (c->value, stack_push(TYPE_LONG) );
328 c = class_getconstant (class, poolindex, CONSTANT_Float);
329 LOADCONST_F (c->value, stack_push(TYPE_FLOAT) );
332 case CONSTANT_Double:
333 { constant_double *c;
334 c = class_getconstant (class, poolindex, CONSTANT_Double);
335 LOADCONST_D (c->value, stack_push(TYPE_DOUBLE) );
339 case CONSTANT_String:
342 s = class_getconstant (class, poolindex, CONSTANT_String);
344 LOADCONST_A ( literalstring_new (s),
345 stack_push(TYPE_ADDRESS) );
349 default: panic ("Invalid constant type to push");
354 case CMD_ACONST_NULL:
355 LOADCONST_A (0, stack_push (TYPE_ADDRESS) );
365 LOADCONST_I (opcode - CMD_ICONST_0, stack_push (TYPE_INT) );
371 LOADCONST_L (opcode - CMD_LCONST_0, stack_push (TYPE_LONG) );
374 v.low = opcode - CMD_LCONST_0;
376 LOADCONST_L (v, stack_push(TYPE_LONG) );
384 LOADCONST_F (opcode - CMD_FCONST_0, stack_push (TYPE_FLOAT) );
389 LOADCONST_D (opcode - CMD_DCONST_0, stack_push (TYPE_DOUBLE) );
393 /*** Loading variables onto the Stack ***/
398 local_get (code_get_u1 (p+1), TYPE_INT),
399 stack_push (TYPE_INT) );
403 local_get (code_get_u2 (p+1), TYPE_INT),
404 stack_push (TYPE_INT) );
415 local_get (opcode - CMD_ILOAD_0, TYPE_INT),
416 stack_push (TYPE_INT) );
422 local_get (code_get_u1 (p+1), TYPE_LONG),
423 stack_push (TYPE_LONG) );
427 local_get (code_get_u2 (p+1), TYPE_LONG),
428 stack_push (TYPE_LONG) );
439 local_get (opcode - CMD_LLOAD_0, TYPE_LONG),
440 stack_push (TYPE_LONG) );
446 local_get (code_get_u1 (p+1), TYPE_FLOAT),
447 stack_push (TYPE_FLOAT) );
451 local_get (code_get_u2 (p+1), TYPE_FLOAT),
452 stack_push (TYPE_FLOAT) );
463 local_get (opcode - CMD_FLOAD_0, TYPE_FLOAT),
464 stack_push (TYPE_FLOAT) );
470 local_get (code_get_u1 (p+1), TYPE_DOUBLE),
471 stack_push (TYPE_DOUBLE) );
475 local_get (code_get_u2 (p+1), TYPE_DOUBLE),
476 stack_push (TYPE_DOUBLE) );
487 local_get (opcode - CMD_DLOAD_0, TYPE_DOUBLE),
488 stack_push (TYPE_DOUBLE) );
494 local_get (code_get_u1 (p+1), TYPE_ADDRESS),
495 stack_push (TYPE_ADDRESS) );
499 local_get (code_get_u2 (p+1), TYPE_ADDRESS),
500 stack_push (TYPE_ADDRESS) );
511 local_get (opcode - CMD_ALOAD_0, TYPE_ADDRESS),
512 stack_push (TYPE_ADDRESS) );
516 /*** Storing Stack Values into Local Variables ***/
519 v = stack_pop (TYPE_INT);
521 MOVE_N_DROP (TYPE_INT, v,
522 local_get (code_get_u1 (p+1), TYPE_INT) );
525 MOVE_N_DROP (TYPE_INT, v,
526 local_get (code_get_u2 (p+1), TYPE_INT) );
536 v = stack_pop (TYPE_INT);
537 MOVE_N_DROP (TYPE_INT,
538 v, local_get (opcode - CMD_ISTORE_0, TYPE_INT) );
542 v = stack_pop (TYPE_LONG);
544 MOVE_N_DROP (TYPE_LONG, v,
545 local_get (code_get_u1 (p+1), TYPE_LONG) );
548 MOVE_N_DROP (TYPE_LONG, v,
549 local_get (code_get_u2 (p+1), TYPE_LONG) );
559 v = stack_pop (TYPE_LONG);
560 MOVE_N_DROP (TYPE_LONG,
561 v, local_get (opcode - CMD_LSTORE_0, TYPE_LONG) );
565 v = stack_pop (TYPE_FLOAT);
567 MOVE_N_DROP (TYPE_FLOAT, v,
568 local_get (code_get_u1 (p+1), TYPE_FLOAT) );
571 MOVE_N_DROP (TYPE_FLOAT, v,
572 local_get (code_get_u2 (p+1), TYPE_FLOAT) );
582 v = stack_pop (TYPE_FLOAT);
583 MOVE_N_DROP (TYPE_FLOAT,
584 v, local_get (opcode - CMD_FSTORE_0, TYPE_FLOAT) );
588 v = stack_pop (TYPE_DOUBLE);
590 MOVE_N_DROP (TYPE_DOUBLE, v,
591 local_get (code_get_u1 (p+1), TYPE_DOUBLE) );
594 MOVE_N_DROP (TYPE_DOUBLE, v,
595 local_get (code_get_u2 (p+1), TYPE_DOUBLE) );
605 v = stack_pop (TYPE_DOUBLE);
606 MOVE_N_DROP (TYPE_DOUBLE,
607 v, local_get (opcode - CMD_DSTORE_0, TYPE_DOUBLE) );
611 v = stack_pop (TYPE_ADDRESS);
613 MOVE_N_DROP (TYPE_ADDRESS, v,
614 local_get (code_get_u1 (p+1), TYPE_ADDRESS) );
617 MOVE_N_DROP (TYPE_ADDRESS, v,
618 local_get (code_get_u2 (p+1), TYPE_ADDRESS) );
628 v = stack_pop (TYPE_ADDRESS);
629 MOVE_N_DROP (TYPE_ADDRESS,
630 v, local_get (opcode - CMD_ASTORE_0, TYPE_ADDRESS) );
636 v1 = local_get (code_get_u1 (p+1), TYPE_INT);
637 IINC (code_get_s1 (p+2), v1 );
641 v1 = local_get (code_get_u2 (p+1), TYPE_INT);
642 IINC (code_get_s2 (p+3), v1 );
650 /*** Wider index for Loading, Storing and Incrementing ***/
658 /******************** Managing Arrays **************************/
661 v1 = stack_pop (TYPE_INT);
662 BRA (CMD_IFLT, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NegativeArraySizeException) );
665 v = stack_push (TYPE_ADDRESS);
666 switch ( code_get_s1 (p+1) ) {
667 case 4: BUILTIN1 ((functionptr) builtin_newarray_boolean, v1, v);
669 case 5: BUILTIN1 ((functionptr) builtin_newarray_char, v1, v);
671 case 6: BUILTIN1 ((functionptr) builtin_newarray_float, v1, v);
673 case 7: BUILTIN1 ((functionptr) builtin_newarray_double, v1, v);
675 case 8: BUILTIN1 ((functionptr) builtin_newarray_byte, v1, v);
677 case 9: BUILTIN1 ((functionptr) builtin_newarray_short, v1, v);
679 case 10: BUILTIN1 ((functionptr) builtin_newarray_int, v1, v);
681 case 11: BUILTIN1 ((functionptr) builtin_newarray_long, v1, v);
683 default: panic ("Invalid array-type to create");
686 BRA (CMD_IFNULL, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_OutOfMemoryError) );
691 poolindex = code_get_u2(p+1);
692 if (class_constanttype (class, poolindex) == CONSTANT_Arraydescriptor) {
693 /* anewarray mit Array-Typ! */
694 constant_arraydescriptor *desc =
695 class_getconstant (class, poolindex, CONSTANT_Arraydescriptor);
697 v1 = stack_pop (TYPE_INT);
698 BRA (CMD_IFLT, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NegativeArraySizeException) );
700 v2 = var_create (TYPE_ADDRESS);
701 LOADCONST_A (desc, v2);
704 v = stack_push (TYPE_ADDRESS);
705 BUILTIN2 ((functionptr) builtin_newarray_array, v1,v2, v);
706 BRA (CMD_IFNULL, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_OutOfMemoryError) );
709 classinfo *c = class_getconstant (class, poolindex, CONSTANT_Class);
711 v1 = stack_pop (TYPE_INT);
712 BRA (CMD_IFLT, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NegativeArraySizeException) );
714 v2 = var_create (TYPE_ADDRESS);
718 v = stack_push (TYPE_ADDRESS);
719 BUILTIN2 ((functionptr) builtin_anewarray, v1,v2, v);
720 BRA (CMD_IFNULL, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_OutOfMemoryError) );
726 case CMD_MULTIANEWARRAY:
727 { constant_arraydescriptor *desc =
728 class_getconstant (class, code_get_u2(p+1), CONSTANT_Arraydescriptor);
729 int i, n = code_get_u1 (p+3);
730 varid dims = var_create (TYPE_ADDRESS); /* array for dimensions */
731 varid dimsdim = var_create (TYPE_INT); /* groesse des arrays */
734 LOADCONST_I (n, dimsdim);
735 BUILTIN1 ((functionptr) builtin_newarray_int, dimsdim, dims);
736 BRA (CMD_IFNULL, dims,NOVAR, NOVAR, EXCREATOR(proto_java_lang_OutOfMemoryError) );
738 for (i=0; i<n; i++) {
739 varid dimn = stack_pop (TYPE_INT);
740 BRA (CMD_IFLT, dimn,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NegativeArraySizeException) );
742 LOADCONST_I ((n-i)-1, dimsdim);
743 OP3 (CMD_IASTORE, dims, dimsdim, dimn, NOVAR);
748 v = stack_push (TYPE_ADDRESS);
750 v1 = var_create (TYPE_ADDRESS);
751 LOADCONST_A (desc, v1);
753 BUILTIN2 ((functionptr) builtin_multianewarray, dims, v1, v);
754 BRA (CMD_IFNULL, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_OutOfMemoryError) );
760 case CMD_ARRAYLENGTH:
761 v = stack_pop (TYPE_ADDRESS);
766 BRA (CMD_IFNULL, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NullPointerException) );
768 OP1 (opcode, v, stack_push (TYPE_INT) );
773 type = TYPE_ADDRESS; goto do_aXload;
775 type = TYPE_LONG; goto do_aXload;
777 type = TYPE_FLOAT; goto do_aXload;
779 type = TYPE_DOUBLE; goto do_aXload;
784 type = TYPE_INT; goto do_aXload;
786 v2 = stack_pop (TYPE_INT);
787 v1 = stack_pop (TYPE_ADDRESS);
792 BRA (CMD_IFNULL, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NullPointerException) );
798 v = var_create (TYPE_INT);
799 OP1 (CMD_ARRAYLENGTH, v1, v);
800 BRA (CMD_IF_UCMPGE, v2,v, NOVAR, EXCREATOR(proto_java_lang_ArrayIndexOutOfBoundsException) );
803 OP2 (opcode, v1,v2, stack_push (type) );
809 type = TYPE_ADDRESS; goto do_aXstore;
811 type = TYPE_LONG; goto do_aXstore;
813 type = TYPE_FLOAT; goto do_aXstore;
815 type = TYPE_DOUBLE; goto do_aXstore;
820 type = TYPE_INT; goto do_aXstore;
822 v3 = stack_pop (type);
823 v2 = stack_pop (TYPE_INT);
824 v1 = stack_pop (TYPE_ADDRESS);
829 BRA (CMD_IFNULL, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NullPointerException) );
835 v = var_create (TYPE_INT);
836 OP1 (CMD_ARRAYLENGTH, v1, v);
837 BRA (CMD_IF_UCMPGE, v2,v, NOVAR, EXCREATOR(proto_java_lang_ArrayIndexOutOfBoundsException) );
841 if (opcode!=CMD_AASTORE) {
842 OP3 (opcode, v1,v2,v3, NOVAR);
849 v = var_create (TYPE_INT);
850 BUILTIN3 ((functionptr) builtin_aastore, v1,v2,v3, v);
851 BRA (CMD_IFEQ, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_ArrayStoreException) );
859 /******************* Stack instructions **************************/
865 v1 = stack_popany (1);
873 varcount = stack_popmany (vararray, 2);
874 for (i=0; i<varcount; i++) DROP(vararray[i]);
879 v1 = stack_popany(1);
881 v = stack_push ( var_type (v1) );
882 MOVE (var_type(v1), v1,v);
889 varcount = stack_popmany (vararray, 2);
890 stack_repushmany (varcount, vararray);
891 for (i=0; i<varcount; i++) {
892 v = stack_push ( var_type(vararray[varcount-1-i]) );
893 MOVE ( var_type(v), vararray[varcount-1-i], v);
899 v1 = stack_popany(1);
900 v2 = stack_popany(1);
904 v = stack_push ( var_type (v1) );
905 MOVE (var_type(v1), v1,v);
912 varcount = stack_popmany (vararray, 2);
913 v3 = stack_popany (1);
914 stack_repushmany (varcount, vararray);
916 for (i=0; i<varcount; i++) {
917 v = stack_push ( var_type(vararray[varcount-1-i]) );
918 MOVE ( var_type(v), vararray[varcount-1-i], v);
927 v1 = stack_popany(1);
928 varcount = stack_popmany (vararray, 2);
930 stack_repushmany (varcount, vararray);
931 MOVE (var_type(v1), v1, stack_push(var_type(v1)) );
936 { int varcount1, varcount2, i;
937 varid vararray1[2],vararray2[2];
939 varcount1 = stack_popmany (vararray1, 2);
940 varcount2 = stack_popmany (vararray2, 2);
941 stack_repushmany (varcount2, vararray2);
942 stack_repushmany (varcount1, vararray1);
943 for (i=0; i<varcount1; i++) {
944 v = stack_push ( var_type(vararray1[varcount1-1-i]) );
945 MOVE ( var_type(v), vararray1[varcount1-1-i], v);
951 v1 = stack_popany (1);
952 v2 = stack_popany (1);
959 /*** Arithmetic & logical instructions ***/
963 v2 = stack_pop (TYPE_INT);
964 v1 = stack_pop (TYPE_INT);
965 BRA (CMD_IFEQ, v2,NOVAR, NOVAR, EXCREATOR(proto_java_lang_ArithmeticException) );
967 if (SUPPORT_DIVISION) {
968 OP2 (opcode, v1,v2, stack_push(TYPE_INT));
975 (opcode == CMD_IDIV) ?
976 ((functionptr) builtin_idiv)
977 : ((functionptr) builtin_irem)
978 ,v1,v2, stack_push (TYPE_INT) );
984 v2 = stack_pop (TYPE_LONG);
985 v1 = stack_pop (TYPE_LONG);
986 BRA (CMD_IFEQL, v2,NOVAR, NOVAR, EXCREATOR(proto_java_lang_ArithmeticException) );
988 if (SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_MULDIV) {
989 OP2 (opcode, v1,v2, stack_push(TYPE_LONG));
996 (opcode == CMD_LDIV) ?
997 ((functionptr) builtin_ldiv)
998 : ((functionptr) builtin_lrem)
999 ,v1,v2, stack_push (TYPE_LONG) );
1004 /*** Control transfer instructions ***/
1012 target = block_find (p + code_get_s2 (p+1) );
1013 v = stack_pop (TYPE_INT);
1014 block_reach (target);
1015 BRA_N_DROP (opcode, v,NOVAR, NOVAR, target);
1020 target = block_find (p + code_get_s2 (p+1));
1021 v = stack_pop (TYPE_ADDRESS);
1022 block_reach (target);
1023 BRA_N_DROP (opcode, v,NOVAR, NOVAR, target);
1032 target = block_find (p + code_get_s2 (p+1) );
1033 v2 = stack_pop (TYPE_INT);
1034 v1 = stack_pop (TYPE_INT);
1035 block_reach (target);
1036 BRA_N_DROP (opcode, v1,v2, NOVAR, target );
1041 target = block_find (p + code_get_s2 (p+1) );
1042 v2 = stack_pop (TYPE_ADDRESS);
1043 v1 = stack_pop (TYPE_ADDRESS);
1044 block_reach (target);
1045 BRA_N_DROP (opcode, v1,v2, NOVAR, target);
1050 target = block_find (p + code_get_s2 (p+1) );
1053 target = block_find (p + code_get_s4 (p+1) );
1055 block_reach (target);
1056 BRA (CMD_GOTO, NOVAR,NOVAR, NOVAR, target );
1061 target = block_find (p + code_get_s2 (p+1) );
1064 target = block_find (p + code_get_s4 (p+1) );
1067 subroutineinfo *sub;
1069 ACTIVATE (stack_push (TYPE_ADDRESS) );
1071 sub = target->subroutine;
1073 sub = subroutine_new();
1074 target->subroutine = sub;
1077 subroutine_set (sub);
1078 block_reach (target);
1079 subroutine_set (b->subroutine);
1081 BRA (CMD_JSR, NOVAR,NOVAR, stack_pop(TYPE_ADDRESS), target );
1083 while (! stack_isempty() ) {
1084 v = stack_popany ( stack_topslots() );
1088 if (sub->returnfinished) {
1089 stackinfo *s = sub->returnstack;
1095 block_reach ( block_find(nextp) );
1098 basicblock *n = block_find(nextp);
1099 n -> subroutine = b->subroutine;
1101 chain_addlast (sub->callers, n );
1110 v = local_get (code_get_u1 (p+1), TYPE_ADDRESS);
1113 v = local_get (code_get_u2 (p+1), TYPE_ADDRESS);
1119 subroutineinfo *sub;
1122 sub = b->subroutine;
1123 if (!sub) panic ("RET outside of subroutine");
1124 if (sub->returnfinished) panic ("Multiple RET in a subroutine");
1126 sub->returnfinished = true;
1127 sub->returnstack = stack_get() ;
1129 while ( (bb = chain_first(sub->callers)) ) {
1130 chain_remove (sub->callers);
1132 subroutine_set (bb->subroutine);
1134 subroutine_set (sub);
1137 BRA (CMD_RET, v,NOVAR, NOVAR, NULL);
1143 /*************** Function Return **************/
1146 addreturnhandling();
1148 v = stack_pop (TYPE_INT);
1149 ve = var_create (TYPE_ADDRESS);
1150 LOADCONST_A (NULL, ve);
1151 BRA_N_DROP (opcode, v, ve, NOVAR, NULL);
1153 count_pcmd_return++;
1158 addreturnhandling();
1160 v = stack_pop (TYPE_LONG);
1161 var_proposereg (v, reg_parlistresult(TYPE_LONG) );
1162 ve = var_create (TYPE_ADDRESS);
1163 LOADCONST_A (NULL, ve);
1164 var_proposereg (ve, reg_parlistexception() );
1165 BRA_N_DROP (opcode, v, ve, NOVAR, NULL);
1167 count_pcmd_return++;
1172 addreturnhandling();
1174 v = stack_pop (TYPE_FLOAT);
1175 var_proposereg (v, reg_parlistresult(TYPE_FLOAT) );
1176 ve = var_create (TYPE_ADDRESS);
1177 LOADCONST_A (NULL, ve);
1178 var_proposereg (ve, reg_parlistexception() );
1179 BRA_N_DROP (opcode, v, ve, NOVAR, NULL);
1181 count_pcmd_return++;
1186 addreturnhandling();
1188 v = stack_pop (TYPE_DOUBLE);
1189 var_proposereg (v, reg_parlistresult(TYPE_DOUBLE) );
1190 ve = var_create (TYPE_ADDRESS);
1191 LOADCONST_A (NULL, ve);
1192 var_proposereg (ve, reg_parlistexception() );
1193 BRA_N_DROP (opcode, v, ve, NOVAR, NULL);
1195 count_pcmd_return++;
1200 addreturnhandling();
1202 v = stack_pop (TYPE_ADDRESS);
1203 var_proposereg (v, reg_parlistresult(TYPE_ADDRESS) );
1204 ve = var_create (TYPE_ADDRESS);
1205 LOADCONST_A (NULL, ve);
1206 var_proposereg (ve, reg_parlistexception() );
1207 BRA_N_DROP (opcode, v, ve, NOVAR, NULL);
1210 count_pcmd_return++;
1214 addreturnhandling();
1216 ve = var_create (TYPE_ADDRESS);
1217 LOADCONST_A (NULL, ve);
1218 var_proposereg (ve, reg_parlistexception() );
1219 BRA_N_DROP (opcode, NOVAR,ve, NOVAR, NULL);
1221 count_pcmd_return++;
1226 case CMD_BREAKPOINT:
1231 /**************** Table Jumping *****************/
1233 case CMD_LOOKUPSWITCH:
1234 { u4 p2 = ALIGN((p+1), 4);
1235 basicblock *defaulttarget;
1238 defaulttarget = block_find (p + code_get_s4 (p2) );
1239 num = code_get_s4 (p2+4);
1241 v = stack_pop (TYPE_INT);
1242 for (i=0; i<num; i++) {
1243 s4 value = code_get_s4 (p2 + 8 + 8*i);
1244 target = block_find (p + code_get_s4 (p2 + 8 + 4 + 8*i) );
1246 v1 = var_create (TYPE_INT);
1247 v2 = var_create (TYPE_INT);
1248 MOVE (TYPE_INT, v, v1);
1249 LOADCONST_I (value, v2);
1250 block_reach (target);
1251 BRA_N_DROP (CMD_IF_ICMPEQ, v1,v2, NOVAR, target );
1255 block_reach (defaulttarget);
1256 BRA (CMD_GOTO, NOVAR,NOVAR, NOVAR, defaulttarget );
1258 nextp = p2 + 8 + 8*num;
1263 case CMD_TABLESWITCH:
1264 { u4 p2 = ALIGN((p+1), 4);
1266 basicblock **targets;
1269 low = code_get_s4 (p2+4);
1270 high = code_get_s4 (p2+8);
1271 if (high<low) panic ("Tablejump range invalid");
1273 v = stack_pop (TYPE_INT);
1275 target = block_find (p + code_get_s4 (p2) );
1276 block_reach(target);
1278 v1 = var_create (TYPE_INT);
1279 LOADCONST_I (high, v1);
1280 BRA (CMD_IF_ICMPGT, v,v1, NOVAR, target);
1284 v1 = var_create (TYPE_INT);
1285 v2 = var_create (TYPE_INT);
1286 LOADCONST_I (low, v1);
1287 OP2 (CMD_ISUB, v,v1, v2);
1292 BRA (CMD_IFLT, v,NOVAR, NOVAR, target);
1294 targets = DMNEW (basicblock*, (high-low)+1);
1295 for (i=0; i < (high-low)+1; i++) {
1296 target = block_find (p + code_get_s4 (p2 + 12 + 4*i) );
1297 block_reach (target);
1299 targets[i] = target;
1302 TABLEJUMP (v, (high-low)+1, targets);
1305 nextp = p2 + 12 + 4 * ((high-low)+1);
1311 /************ Manipulating Object Fields ********/
1318 poolindex = code_get_u2 (p+1);
1319 { constant_FMIref *fr;
1322 fr = class_getconstant (class, poolindex, CONSTANT_Fieldref);
1323 fi = class_findfield (fr->class, fr->name, fr->descriptor);
1327 compiler_addinitclass (fr->class);
1329 v1 = var_create (TYPE_ADDRESS);
1330 v = stack_pop (fi->type);
1331 LOADCONST_A (&(fi->value), v1);
1333 MEM (CMD_PUTFIELD, fi->type, v1,v, NOVAR, 0);
1339 compiler_addinitclass (fr->class);
1341 v1 = var_create (TYPE_ADDRESS);
1342 v = stack_push (fi->type);
1343 LOADCONST_A (&(fi->value), v1);
1345 MEM (CMD_GETFIELD, fi->type, v1,NOVAR, v, 0);
1351 v = stack_pop (fi->type);
1352 v1 = stack_pop (TYPE_ADDRESS);
1357 BRA (CMD_IFNULL, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NullPointerException) );
1359 MEM (CMD_PUTFIELD, fi->type, v1,v, NOVAR, fi->offset);
1365 v1 = stack_pop (TYPE_ADDRESS);
1366 v = stack_push (fi->type);
1371 BRA (CMD_IFNULL, v1,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NullPointerException) );
1373 MEM (CMD_GETFIELD, fi->type, v1,NOVAR, v, fi->offset);
1383 /*** Method invocation ***/
1385 case CMD_INVOKEVIRTUAL:
1386 case CMD_INVOKESPECIAL:
1387 case CMD_INVOKESTATIC:
1388 case CMD_INVOKEINTERFACE:
1392 { constant_FMIref *mr;
1399 bool stat = (opcode == CMD_INVOKESTATIC);
1401 if (opcode==CMD_INVOKEINTERFACE) {
1402 poolindex = code_get_u2 (p+1);
1403 mr = class_getconstant (class, poolindex, CONSTANT_InterfaceMethodref);
1406 poolindex = code_get_u2 (p+1);
1407 mr = class_getconstant (class, poolindex, CONSTANT_Methodref);
1410 mi = class_findmethod (mr->class, mr->name, mr->descriptor);
1412 if ( ((mi->flags & ACC_STATIC) != 0) != stat)
1413 panic ("Static/Nonstatic mismatch on method call");
1415 descriptor2types (mi->descriptor, stat,
1416 ¶mnum, ¶mtypes, &returntype);
1417 mi->paramcount = paramnum;
1419 params = DMNEW (varid, paramnum);
1420 for (i=0; i<paramnum; i++) {
1421 params[paramnum-i-1] = stack_pop (paramtypes[paramnum-i-1]);
1426 if ((!stat) && checknull) {
1430 BRA (CMD_IFNULL, params[0],NOVAR, NOVAR, EXCREATOR(proto_java_lang_NullPointerException) );
1433 ve = var_create (TYPE_ADDRESS);
1434 if (returntype != TYPE_VOID) {
1435 v = stack_push (returntype);
1436 METHOD (opcode, mi, NULL, paramnum, params, v, ve);
1439 METHOD (opcode, mi, NULL, paramnum, params, NOVAR, ve);
1442 BRA (CMD_IFNONNULL, ve,NOVAR, NOVAR, EXFORWARDER(ve) );
1449 /********* Exception Handling *****************/
1452 v = stack_pop (TYPE_ADDRESS);
1457 BRA (CMD_IFNULL, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_NullPointerException) );
1459 BRA (CMD_GOTO, NOVAR,NOVAR, NOVAR, EXFORWARDER (v) );
1464 /***** Miscellaneous Object Operations ****/
1467 poolindex = code_get_u2 (p+1);
1470 ci = class_getconstant (class, poolindex, CONSTANT_Class);
1472 v1 = var_create (TYPE_ADDRESS);
1473 LOADCONST_A (ci, v1);
1477 v = stack_push (TYPE_ADDRESS);
1478 BUILTIN1 ((functionptr) builtin_new, v1, v);
1479 BRA (CMD_IFNULL, v,NOVAR, NOVAR, EXCREATOR(proto_java_lang_OutOfMemoryError) );
1486 poolindex = code_get_u2 (p+1);
1488 if (class_constanttype (class, poolindex) == CONSTANT_Arraydescriptor) {
1489 /* cast-check auf Array-Typ! */
1491 constant_arraydescriptor *desc =
1492 class_getconstant (class, poolindex, CONSTANT_Arraydescriptor);
1494 v = stack_pop (TYPE_ADDRESS);
1496 v1 = var_create (TYPE_ADDRESS);
1497 MOVE (TYPE_ADDRESS, v,v1);
1498 v2 = var_create (TYPE_ADDRESS);
1499 LOADCONST_A (desc, v2);
1502 ve = var_create (TYPE_INT);
1503 BUILTIN2 ((functionptr) builtin_checkarraycast, v1,v2, ve);
1505 BRA (CMD_IFEQ,ve,NOVAR, NOVAR, EXCREATOR(proto_java_lang_ClassCastException) );
1509 /* cast-check auf Object-Typ */
1511 classinfo *ci = class_getconstant (class, poolindex, CONSTANT_Class);
1513 v = stack_pop (TYPE_ADDRESS);
1515 v1 = var_create (TYPE_ADDRESS);
1516 MOVE (TYPE_ADDRESS, v, v1);
1517 v2 = var_create (TYPE_ADDRESS);
1518 LOADCONST_A (ci, v2);
1521 ve = var_create (TYPE_INT);
1522 BUILTIN2 ((functionptr) builtin_checkcast, v1,v2, ve);
1524 BRA (CMD_IFEQ,ve,NOVAR, NOVAR, EXCREATOR(proto_java_lang_ClassCastException) );
1531 case CMD_INSTANCEOF:
1532 poolindex = code_get_u2 (p+1);
1534 if (class_constanttype (class, poolindex) == CONSTANT_Arraydescriptor) {
1535 /* cast-check auf Array-Typ! */
1537 constant_arraydescriptor *desc =
1538 class_getconstant (class, poolindex, CONSTANT_Arraydescriptor);
1540 v = stack_pop (TYPE_ADDRESS);
1541 v1 = var_create (TYPE_ADDRESS);
1542 LOADCONST_A (desc, v1);
1546 BUILTIN2 ((functionptr) builtin_arrayinstanceof, v,v1,
1547 stack_push (TYPE_INT) );
1551 ci = class_getconstant (class, poolindex, CONSTANT_Class);
1553 v = stack_pop (TYPE_ADDRESS);
1554 v1 = var_create (TYPE_ADDRESS);
1555 LOADCONST_A (ci, v1);
1559 BUILTIN2 ((functionptr) builtin_instanceof, v,v1,
1560 stack_push (TYPE_INT) );
1567 /*************** Monitors ************************/
1569 case CMD_MONITORENTER:
1571 v = stack_pop (TYPE_ADDRESS);
1576 BRA (CMD_IFNULL, v, NOVAR, NOVAR,
1577 EXCREATOR(proto_java_lang_NullPointerException));
1579 BUILTIN1 ((functionptr) builtin_monitorenter, v, NOVAR);
1581 DROP (stack_pop (TYPE_ADDRESS));
1585 case CMD_MONITOREXIT:
1587 BUILTIN1 ((functionptr) builtin_monitorexit,
1588 stack_pop(TYPE_ADDRESS), NOVAR );
1590 DROP (stack_pop (TYPE_ADDRESS));
1597 /************** any other Basic-Operation **********/
1602 stdopdescriptor *s = stdopdescriptors[opcode];
1605 if (s->type_s2 != TYPE_VOID) v2 = stack_pop(s->type_s2);
1606 v1 = stack_pop(s->type_s1);
1609 v = stack_push (s->type_d);
1611 OP2 (opcode, v1,v2, v);
1616 OP1 (opcode, v1, v);
1622 v = stack_push (s->type_d);
1624 BUILTIN2 (s->builtin, v1,v2, v);
1627 BUILTIN1 (s->builtin, v1, v);
1633 /*************** invalid Opcode ***************/
1636 sprintf (logtext, "Invalid opcode %d at position %ld",
1637 opcode, (long int) p);
1651 if ( block_isany (p) ) {
1652 block_reach ( block_find (p) );