1 /****************************** ncomp/nparse.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 Parser for JavaVM to intermediate code translation
9 Author: Andreas Krall EMAIL: cacao@complang.tuwien.ac.at
11 Last Change: 1998/05/07
13 *******************************************************************************/
17 /*********************** function allocate_literals ****************************
19 Scans the JavaVM code of a method and allocates string literals. Needed
20 to generate the same addresses as the old JIT compiler.
22 *******************************************************************************/
24 static void allocate_literals()
31 for (p = 0; p < jcodelength; p = nextp) {
34 nextp = p + jcommandsize[opcode];
38 if (code_get_u1(p + 1) == JAVA_IINC)
44 case JAVA_LOOKUPSWITCH:
45 nextp = ALIGN((p + 1), 4);
46 num = code_get_u4(nextp + 4);
47 nextp = nextp + 8 + 8 * num;
50 case JAVA_TABLESWITCH:
51 nextp = ALIGN ((p + 1),4);
52 num = code_get_s4(nextp + 4);
53 num = code_get_s4(nextp + 8) - num;
54 nextp = nextp + 16 + 4 * num;
59 goto pushconstantitem;
62 i = code_get_u2(p + 1);
64 if (class_constanttype(class, i) == CONSTANT_String) {
65 s = class_getconstant(class, i, CONSTANT_String);
66 (void) literalstring_new(s);
75 /*******************************************************************************
77 function 'parse' scans the JavaVM code and generates intermediate code
79 During parsing the block index table is used to store at bit pos 0
80 a flag which marks basic block starts and at position 1 to 31 the
81 intermediate instruction index. After parsing the block index table
82 is scanned, for marked positions a block is generated and the block
83 number is stored in the block index table.
85 *******************************************************************************/
87 /* intermediate code generating macros */
89 #define PINC iptr++;ipc++
90 #define LOADCONST_I(v) iptr->opc=ICMD_ICONST;iptr->op1=0;iptr->val.i=(v);PINC
91 #define LOADCONST_L(v) iptr->opc=ICMD_LCONST;iptr->op1=0;iptr->val.l=(v);PINC
92 #define LOADCONST_F(v) iptr->opc=ICMD_FCONST;iptr->op1=0;iptr->val.f=(v);PINC
93 #define LOADCONST_D(v) iptr->opc=ICMD_DCONST;iptr->op1=0;iptr->val.d=(v);PINC
94 #define LOADCONST_A(v) iptr->opc=ICMD_ACONST;iptr->op1=0;iptr->val.a=(v);PINC
95 #define OP(o) iptr->opc=(o);iptr->op1=0;iptr->val.l=0;PINC
96 #define OP1(o,o1) iptr->opc=(o);iptr->op1=(o1);iptr->val.l=(0);PINC
97 #define OP2I(o,o1,v) iptr->opc=(o);iptr->op1=(o1);iptr->val.i=(v);PINC
98 #define OP2A(o,o1,v) iptr->opc=(o);iptr->op1=(o1);iptr->val.a=(v);PINC
99 #define BUILTIN1(v,t) isleafmethod=false;iptr->opc=ICMD_BUILTIN1;iptr->op1=t;\
101 #define BUILTIN2(v,t) isleafmethod=false;iptr->opc=ICMD_BUILTIN2;iptr->op1=t;\
103 #define BUILTIN3(v,t) isleafmethod=false;iptr->opc=ICMD_BUILTIN3;iptr->op1=t;\
107 /* block generating and checking macros */
109 #define block_insert(i) {if(!(block_index[i]&1))\
110 {b_count++;block_index[i] |= 1;}}
111 #define bound_check(i) {if((i< 0) || (i>=jcodelength)) \
112 panic("branch target out of code-boundary");}
113 #define bound_check1(i) {if((i< 0) || (i>jcodelength)) \
114 panic("branch target out of code-boundary");}
119 int p; /* java instruction counter */
120 int nextp; /* start of next java instruction */
121 int opcode; /* java opcode */
122 int i; /* temporary for different uses (counters) */
123 int ipc = 0; /* intermediate instruction counter */
124 int b_count = 0; /* basic block counter */
125 int s_count = 0; /* stack element counter */
126 bool blockend = false; /* true if basic block end has reached */
127 bool iswide = false; /* true if last instruction was a wide */
128 instruction *iptr; /* current pointer into instruction array */
131 /* allocate instruction array and block index table */
133 /* 1 additional for end ipc and 3 for loop unrolling */
135 block_index = DMNEW(int, jcodelength + 3);
137 /* 1 additional for TRACEBUILTIN and 4 for MONITORENTER/EXIT */
138 /* additional MONITOREXITS are reached by branches which are 3 bytes */
140 iptr = instr = DMNEW(instruction, jcodelength + 5);
142 /* initialize block_index table (unrolled four times) */
147 for (i = 0, ip = block_index; i <= jcodelength; i += 4, ip += 4) {
155 /* compute branch targets of exception table */
157 for (i = 0; i < exceptiontablelength; i++) {
158 p = extable[i].startpc;
161 p = extable[i].endpc;
165 p = extable[i].handlerpc;
170 s_count = 1 + exceptiontablelength; /* initialize stack element counter */
173 /* isleafmethod=false; */
177 if (checksync && (method->flags & ACC_SYNCHRONIZED)) {
182 /* scan all java instructions */
184 for (p = 0; p < jcodelength; p = nextp) {
186 opcode = code_get_u1 (p); /* fetch op code */
188 block_index[p] |= (ipc << 1); /* store intermediate count */
191 block_insert(p); /* start new block */
195 nextp = p + jcommandsize[opcode]; /* compute next instruction start */
196 s_count += stackreq[opcode]; /* compute stack element count */
203 /* pushing constants onto the stack p */
206 LOADCONST_I(code_get_s1(p+1));
210 LOADCONST_I(code_get_s2(p+1));
214 i = code_get_u1(p+1);
215 goto pushconstantitem;
218 i = code_get_u2(p + 1);
222 if (i >= class->cpcount)
223 panic ("Attempt to access constant outside range");
225 switch (class->cptags[i]) {
226 case CONSTANT_Integer:
227 LOADCONST_I(((constant_integer*)
228 (class->cpinfos[i]))->value);
231 LOADCONST_L(((constant_long*)
232 (class->cpinfos[i]))->value);
235 LOADCONST_F(((constant_float*)
236 (class->cpinfos[i]))->value);
238 case CONSTANT_Double:
239 LOADCONST_D(((constant_double*)
240 (class->cpinfos[i]))->value);
242 case CONSTANT_String:
243 LOADCONST_A(literalstring_new((unicode*)
244 (class->cpinfos[i])));
246 default: panic("Invalid constant type to push");
250 case JAVA_ACONST_NULL:
261 LOADCONST_I(opcode - JAVA_ICONST_0);
266 LOADCONST_L(opcode - JAVA_LCONST_0);
272 LOADCONST_F(opcode - JAVA_FCONST_0);
277 LOADCONST_D(opcode - JAVA_DCONST_0);
280 /* loading variables onto the stack */
288 i = code_get_u1(p+1);
290 i = code_get_u2(p+1);
301 OP1(ICMD_ILOAD, opcode - JAVA_ILOAD_0);
308 OP1(ICMD_LLOAD, opcode - JAVA_LLOAD_0);
315 OP1(ICMD_FLOAD, opcode - JAVA_FLOAD_0);
322 OP1(ICMD_DLOAD, opcode - JAVA_DLOAD_0);
329 OP1(ICMD_ALOAD, opcode - JAVA_ALOAD_0);
332 /* storing stack values into local variables */
340 i = code_get_u1(p+1);
342 i = code_get_u2(p+1);
353 OP1(ICMD_ISTORE, opcode - JAVA_ISTORE_0);
360 OP1(ICMD_LSTORE, opcode - JAVA_LSTORE_0);
367 OP1(ICMD_FSTORE, opcode - JAVA_FSTORE_0);
374 OP1(ICMD_DSTORE, opcode - JAVA_DSTORE_0);
381 OP1(ICMD_ASTORE, opcode - JAVA_ASTORE_0);
389 i = code_get_u1(p + 1);
390 v = code_get_s1(p + 2);
393 i = code_get_u2(p + 1);
394 v = code_get_s2(p + 3);
402 /* wider index for loading, storing and incrementing */
409 /*********************** managing arrays **************************/
412 OP2I(ICMD_CHECKASIZE, 0, 0);
413 switch (code_get_s1(p+1)) {
415 BUILTIN1((functionptr)builtin_newarray_boolean, TYPE_ADR);
418 BUILTIN1((functionptr)builtin_newarray_char, TYPE_ADR);
421 BUILTIN1((functionptr)builtin_newarray_float, TYPE_ADR);
424 BUILTIN1((functionptr)builtin_newarray_double, TYPE_ADR);
427 BUILTIN1((functionptr)builtin_newarray_byte, TYPE_ADR);
430 BUILTIN1((functionptr)builtin_newarray_short, TYPE_ADR);
433 BUILTIN1((functionptr)builtin_newarray_int, TYPE_ADR);
436 BUILTIN1((functionptr)builtin_newarray_long, TYPE_ADR);
438 default: panic("Invalid array-type to create");
443 OP2I(ICMD_CHECKASIZE, 0, 0);
444 i = code_get_u2(p+1);
445 /* array or class type ? */
446 if (class_constanttype (class, i) == CONSTANT_Arraydescriptor) {
447 LOADCONST_A(class_getconstant(class, i,
448 CONSTANT_Arraydescriptor));
449 BUILTIN2((functionptr)builtin_newarray_array, TYPE_ADR);
452 LOADCONST_A(class_getconstant(class, i, CONSTANT_Class));
453 BUILTIN2((functionptr)builtin_anewarray, TYPE_ADR);
457 case JAVA_MULTIANEWARRAY:
459 i = code_get_u2(p+1);
461 int v = code_get_u1(p+3);
462 constant_arraydescriptor *desc =
463 class_getconstant (class, i, CONSTANT_Arraydescriptor);
464 OP2A(opcode, v, desc);
486 i = p + code_get_s2(p+1);
494 i = p + code_get_s4(p+1);
503 i = code_get_u1(p+1);
505 i = code_get_u2(p+1);
529 /**************** table jumps *****************/
531 case JAVA_LOOKUPSWITCH:
536 nextp = ALIGN((p + 1), 4);
537 OP2A(opcode, 0, jcode + nextp);
541 j = p + code_get_s4(nextp);
542 *((s4*)(jcode + nextp)) = j; /* restore for little endian */
547 /* number of pairs */
549 num = code_get_u4(nextp);
550 *((s4*)(jcode + nextp)) = num;
553 for (i = 0; i < num; i++) {
557 j = code_get_s4(nextp);
558 *((s4*)(jcode + nextp)) = j; /* restore for little endian */
563 j = p + code_get_s4(nextp);
564 *((s4*)(jcode + nextp)) = j; /* restore for little endian */
574 case JAVA_TABLESWITCH:
579 nextp = ALIGN((p + 1), 4);
580 OP2A(opcode, 0, jcode + nextp);
584 j = p + code_get_s4(nextp);
585 *((s4*)(jcode + nextp)) = j; /* restore for little endian */
592 j = code_get_s4(nextp);
593 *((s4*)(jcode + nextp)) = j; /* restore for little endian */
598 num = code_get_s4(nextp);
599 *((s4*)(jcode + nextp)) = num; /* restore for little endian */
604 for (i = 0; i <= num; i++) {
605 j = p + code_get_s4(nextp);
606 *((s4*)(jcode + nextp)) = j; /* restore for little endian */
616 /************ load and store of object fields ********/
619 BUILTIN3((functionptr) new_builtin_aastore, TYPE_VOID);
624 i = code_get_u2(p + 1);
628 fr = class_getconstant (class, i, CONSTANT_Fieldref);
629 fi = class_findfield (fr->class, fr->name, fr->descriptor);
630 compiler_addinitclass (fr->class);
631 OP2A(opcode, fi->type, &(fi->value));
636 i = code_get_u2(p + 1);
640 fr = class_getconstant (class, i, CONSTANT_Fieldref);
641 fi = class_findfield (fr->class, fr->name, fr->descriptor);
642 OP2I(opcode, fi->type, fi->offset);
647 /*** method invocation ***/
649 case JAVA_INVOKESTATIC:
650 i = code_get_u2(p + 1);
655 mr = class_getconstant (class, i, CONSTANT_Methodref);
656 mi = class_findmethod (mr->class, mr->name, mr->descriptor);
657 if (! (mi->flags & ACC_STATIC))
658 panic ("Static/Nonstatic mismatch calling static method");
659 descriptor2types(mi);
661 OP2A(opcode, mi->paramcount, mi);
664 case JAVA_INVOKESPECIAL:
665 case JAVA_INVOKEVIRTUAL:
666 i = code_get_u2(p + 1);
671 mr = class_getconstant (class, i, CONSTANT_Methodref);
672 mi = class_findmethod (mr->class, mr->name, mr->descriptor);
673 if (mi->flags & ACC_STATIC)
674 panic ("Static/Nonstatic mismatch calling static method");
675 descriptor2types(mi);
677 OP2A(opcode, mi->paramcount, mi);
680 case JAVA_INVOKEINTERFACE:
681 i = code_get_u2(p + 1);
686 mr = class_getconstant (class, i, CONSTANT_InterfaceMethodref);
687 mi = class_findmethod (mr->class, mr->name, mr->descriptor);
688 if (mi->flags & ACC_STATIC)
689 panic ("Static/Nonstatic mismatch calling static method");
690 descriptor2types(mi);
692 OP2A(opcode, mi->paramcount, mi);
696 /***** miscellaneous object operations ****/
699 i = code_get_u2 (p+1);
700 LOADCONST_A(class_getconstant(class, i, CONSTANT_Class));
701 BUILTIN1((functionptr) builtin_new, TYPE_ADR);
705 i = code_get_u2(p+1);
707 /* array type cast-check */
708 if (class_constanttype (class, i) == CONSTANT_Arraydescriptor) {
709 LOADCONST_A(class_getconstant(class, i, CONSTANT_Arraydescriptor));
710 BUILTIN2((functionptr) new_builtin_checkarraycast, TYPE_ADR);
712 else { /* object type cast-check */
713 LOADCONST_A(class_getconstant(class, i, CONSTANT_Class));
714 BUILTIN2((functionptr) new_builtin_checkcast, TYPE_ADR);
718 case JAVA_INSTANCEOF:
719 i = code_get_u2(p+1);
721 /* array type cast-check */
722 if (class_constanttype (class, i) == CONSTANT_Arraydescriptor) {
723 LOADCONST_A(class_getconstant(class, i, CONSTANT_Arraydescriptor));
724 BUILTIN2((functionptr) builtin_arrayinstanceof, TYPE_INT);
726 else { /* object type cast-check */
727 LOADCONST_A(class_getconstant(class, i, CONSTANT_Class));
728 BUILTIN2((functionptr) builtin_instanceof, TYPE_INT);
732 case JAVA_MONITORENTER:
735 #ifdef SOFTNULLPTRCHECK
737 BUILTIN1((functionptr) new_builtin_monitorenter, TYPE_VOID);
740 /* BUILTIN1((functionptr) builtin_monitorenter, TYPE_VOID); */
741 BUILTIN1((functionptr) new_builtin_monitorenter, TYPE_VOID);
744 BUILTIN1((functionptr) builtin_monitorenter, TYPE_VOID);
750 OP(ICMD_NULLCHECKPOP);
754 case JAVA_MONITOREXIT:
757 BUILTIN1((functionptr) builtin_monitorexit, TYPE_VOID);
766 /************** any other basic operation **********/
769 if (SUPPORT_DIVISION) {
773 BUILTIN2((functionptr) new_builtin_idiv, TYPE_INT);
778 if (SUPPORT_DIVISION) {
782 BUILTIN2((functionptr) new_builtin_irem, TYPE_INT);
787 if (SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_MULDIV) {
791 BUILTIN2((functionptr) new_builtin_ldiv, TYPE_LONG);
796 if (SUPPORT_DIVISION && SUPPORT_LONG && SUPPORT_LONG_MULDIV) {
800 BUILTIN2((functionptr) new_builtin_lrem, TYPE_LONG);
805 BUILTIN2((functionptr) builtin_frem, TYPE_FLOAT);
809 BUILTIN2((functionptr) builtin_drem, TYPE_DOUBLE);
814 BUILTIN1((functionptr) builtin_f2i, TYPE_INT);
823 BUILTIN1((functionptr) builtin_f2l, TYPE_LONG);
832 BUILTIN1((functionptr) builtin_d2i, TYPE_INT);
841 BUILTIN1((functionptr) builtin_d2l, TYPE_LONG);
848 case JAVA_BREAKPOINT:
849 panic("Illegal opcode Breakpoint encountered");
905 printf("Illegal opcode %d at instr %d", opcode, ipc);
906 panic("encountered");
917 if (p != jcodelength)
918 panic("Command-sequence crosses code-boundary");
921 panic("Code does not end with branch/return/athrow - stmt");
923 /* adjust block count if target 0 is not first intermediate instruction */
925 if (!block_index[0] || (block_index[0] > 1))
928 /* copy local to global variables */
931 block_count = b_count;
932 stack_count = s_count + block_count * maxstack;
934 /* allocate stack table */
936 stack = DMNEW(stackelement, stack_count);
941 bptr = block = DMNEW(basicblock, b_count + 1); /* one more for end ipc */
945 /* additional block if target 0 is not first intermediate instruction */
947 if (!block_index[0] || (block_index[0] > 1)) {
951 bptr->type = BBTYPE_STD;
952 bptr->branchrefs = NULL;
957 /* allocate blocks */
959 for (p = 0; p < jcodelength; p++)
960 if (block_index[p] & 1) {
961 bptr->ipc = block_index[p] >> 1;
964 bptr->type = BBTYPE_STD;
965 bptr->branchrefs = NULL;
966 block_index[p] = b_count;
971 /* allocate additional block at end */
973 bptr->ipc = instr_count;
976 bptr->type = BBTYPE_STD;
977 bptr->branchrefs = NULL;