home *** CD-ROM | disk | FTP | other *** search
/ Java 1996 August / Java - Summer 1996.iso / kaffe-0.2 / kaffe / codegen / translator.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-13  |  14.2 KB  |  568 lines

  1. /*
  2.  * translator.c
  3.  * Bytecode translator.
  4.  *
  5.  * Copyright (c) 1996 Systems Architecture Research Centre,
  6.  *           City University, London, UK.
  7.  *
  8.  * See the file "license.terms" for information on usage and redistribution
  9.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  10.  *
  11.  * Written by Tim Wilkinson <tim@sarc.city.ac.uk>, February 1996.
  12.  */
  13.  
  14. #include <stdio.h>
  15. #include <assert.h>
  16. #include "errors.h"
  17. #include "file.h"
  18. #include "bytecode.h"
  19. #include "instruction.h"
  20. #include "code.h"
  21. #include "classMethod.h"
  22. #include "constants.h"
  23. #include "lookup.h"
  24. #include "translator.h"
  25. #include "object.h"
  26.  
  27. /* Translate table block */
  28. static int level;
  29. static instn* block;
  30. static int blockLen;
  31.  
  32. /*
  33.  * Translate a method into native code.
  34.  */
  35. void
  36. translate(methods* m)
  37. {
  38.     instn* baseipc;
  39.     instn* ipc;
  40.     bytecode* pc;
  41.     int i;
  42.     int wide;
  43.     int ret;
  44.     bytecode* start;
  45.     bytecode* end;
  46.     int len;
  47.     int offset;
  48.     char* cname;
  49.     int low;
  50.     int high;
  51.     int nargs;
  52.     callInfo cinfo;
  53.     createInfo crinfo;
  54.     fieldInfo flinfo;
  55.     tableswitch* table;
  56.     lookupswitch* lookup;
  57.     int adjust;
  58.  
  59.     /* First, if its native then dont do any of this stuff */
  60.     if (m->accflags & ACC_NATIVE) {
  61.         native(m);
  62.         return;
  63.     }
  64.  
  65.     start = m->code;
  66.     assert(start != 0);
  67.     len = m->codelen;
  68.     assert(len > 0);
  69.     nargs = m->ins;
  70.     /* One extra argument for non-static methods */
  71.     if (!(m->accflags & ACC_STATIC)) {
  72.         nargs++;
  73.     }
  74.  
  75.     level++;
  76.     assert(level == 1);
  77.  
  78.     /* Reuse old block if we can */
  79.     if (len < blockLen) {
  80.         baseipc = block;
  81.     }
  82.     /* Otherwise allocate a new larger one */
  83.     else {
  84.         baseipc = (instn*)malloc(sizeof(instn) * len);
  85.         if (baseipc == 0) {
  86.             fprintf(stderr, "Insufficient translation space %d\n", len);
  87.             level--;
  88.             throwException(OutOfMemoryError);
  89.         }
  90.         if (block != 0) {
  91.             free(block);
  92.         }
  93.         block = baseipc;
  94.         blockLen = len;
  95.     }
  96.  
  97.     m->insn = baseipc;
  98.     pc = start;
  99.     wide = 0;
  100.     end = start + len;
  101.  
  102.     /* Mark out the instruction block with nulls initially. */
  103.     for (i = 0; i < len; i++) {
  104.         baseipc[i].type = i_null;
  105.         baseipc[i].op = NOP;
  106.     }
  107.     baseipc[len - 1].type = i_endblock;
  108.  
  109.     /* Decode the instructions into the instruction block */
  110.     for (pc = start; pc < end;) {
  111.  
  112.         ipc = &baseipc[pc - start];
  113.         ipc->op = *pc++;
  114.  
  115.         switch (ipc->op) {
  116.         case NOP:
  117.         case ICONST_M1: case ACONST_NULL: case ICONST_0: case LCONST_0:
  118.         case ICONST_1: case LCONST_1: case ICONST_2: case ICONST_3:
  119.         case ICONST_4: case ICONST_5:
  120.         case FCONST_0: case DCONST_0: case FCONST_1: case DCONST_1:
  121.         case FCONST_2:
  122.         case POP: case POP2: case SWAP:
  123.         case DUP: case DUP_X1: case DUP_X2:
  124.         case DUP2: case DUP2_X1: case DUP2_X2:
  125.         case IADD: case LADD: case FADD: case DADD:
  126.         case ISUB: case LSUB: case FSUB: case DSUB:
  127.         case IMUL: case LMUL: case FMUL: case DMUL:
  128.         case IDIV: case LDIV: case FDIV: case DDIV:
  129.         case IREM: case LREM: case FREM: case DREM:
  130.         case INEG: case LNEG: case FNEG: case DNEG:
  131.         case ISHL: case LSHL: case ISHR: case LSHR:
  132.         case IUSHR: case LUSHR: case IAND: case LAND:
  133.         case IOR: case LOR: case IXOR: case LXOR:
  134.         case I2L: case L2I: case I2F: case I2D:
  135.         case L2F: case L2D: case F2I: case F2L:
  136.         case F2D: case D2I: case D2L: case D2F:
  137.         case INT2BYTE: case INT2CHAR: case INT2SHORT:
  138.         case LCMP: case FCMPL: case FCMPG:
  139.         case DCMPL: case DCMPG:
  140.         case BREAKPOINT:
  141.         case ATHROW:
  142.         case MONITORENTER: case MONITOREXIT:
  143.             break;
  144.  
  145.         case IRETURN: case LRETURN: case FRETURN:
  146.         case DRETURN: case ARETURN: case RETURN:
  147.             if (m->accflags & ACC_SYNCHRONISED) {
  148.                 if (m->accflags & ACC_STATIC) {
  149.                     ipc->value[0] = 0;
  150.                     ipc->value[1] = (int)m->class;
  151.                 }
  152.                 else {
  153.                     ipc->value[0] = LOCAL_FIXUP(0, nargs);
  154.                     ipc->value[1] = 0;
  155.                 }
  156.             }
  157.             else {
  158.                 ipc->value[0] = 0;
  159.                 ipc->value[1] = 0;
  160.             }
  161.             break;
  162.  
  163.         case IALOAD: case FALOAD: case AALOAD:
  164.         case BALOAD: case CALOAD: case SALOAD:
  165.         case IASTORE: case FASTORE: case AASTORE:
  166.         case BASTORE: case CASTORE: case SASTORE:
  167.             ipc->value[0] = OBJECT_DATA;
  168.             break;
  169.  
  170.         case LALOAD: case DALOAD:
  171.         case LASTORE: case DASTORE:
  172.             ipc->value[0] = OBJECT_DATA;
  173.             ipc->value[1] = OBJECT_DATA+4;
  174.             break;
  175.  
  176.         case BIPUSH:
  177.             ipc->value[0] = (int8)*pc++;
  178.             break;
  179.  
  180.         case SIPUSH:
  181.             ipc->value[0] = (int16)(256 * pc[0] + pc[1]);
  182.             pc += 2;
  183.             break;
  184.  
  185.         case LDC1:
  186.             offset = *pc++;
  187.             if (m->constants->tags[offset] == CONSTANT_Chararray) {
  188.                 makeStringObject(offset, m->constants);
  189.             }
  190.             ipc->value[0] = m->constants->data[offset];
  191.             break;
  192.  
  193.         case LDC2:
  194.         case LDC2W:
  195.             offset = 256 * pc[0] + pc[1];
  196.             pc += 2;
  197.             if (m->constants->tags[offset] == CONSTANT_Chararray) {
  198.                 makeStringObject(offset, m->constants);
  199.             }
  200.             ipc->value[0] = m->constants->data[offset];
  201.             ipc->value[1] = m->constants->data[offset+1];
  202.             break;
  203.  
  204.         case ILOAD: case ALOAD: case FLOAD:
  205.         case ISTORE: case ASTORE: case FSTORE:
  206.             offset = wide + *pc++;
  207.             ipc->value[0] = LOCAL_FIXUP(offset, nargs);
  208.             wide = 0;
  209.             break;
  210.  
  211.         case LLOAD: case DLOAD: case LSTORE: case DSTORE:
  212.             offset = wide + *pc++;
  213.             ipc->value[0] = LOCAL_FIXUP(offset, nargs);
  214.             ipc->value[1] = LOCAL_FIXUP(offset+1, nargs);
  215.             wide = 0;
  216.             break;
  217.  
  218.         case ILOAD_0: case FLOAD_0: case ALOAD_0:
  219.         case ISTORE_0: case FSTORE_0: case ASTORE_0:
  220.             ipc->value[0] = LOCAL_FIXUP(0, nargs);
  221.             break;
  222.  
  223.         case LLOAD_0: case DLOAD_0:
  224.         case LSTORE_0: case DSTORE_0:
  225.             ipc->value[0] = LOCAL_FIXUP(0, nargs);
  226.             ipc->value[1] = LOCAL_FIXUP(1, nargs);
  227.             break;
  228.  
  229.         case ILOAD_1: case FLOAD_1: case ALOAD_1:
  230.         case ISTORE_1: case FSTORE_1: case ASTORE_1:
  231.             ipc->value[0] = LOCAL_FIXUP(1, nargs);
  232.             break;
  233.  
  234.         case LLOAD_1: case DLOAD_1:
  235.         case LSTORE_1: case DSTORE_1:
  236.             ipc->value[0] = LOCAL_FIXUP(1, nargs);
  237.             ipc->value[1] = LOCAL_FIXUP(2, nargs);
  238.             break;
  239.  
  240.         case ILOAD_2: case FLOAD_2: case ALOAD_2:
  241.         case ISTORE_2: case FSTORE_2: case ASTORE_2:
  242.             ipc->value[0] = LOCAL_FIXUP(2, nargs);
  243.             break;
  244.  
  245.         case LLOAD_2: case DLOAD_2:
  246.         case LSTORE_2: case DSTORE_2:
  247.             ipc->value[0] = LOCAL_FIXUP(2, nargs);
  248.             ipc->value[1] = LOCAL_FIXUP(3, nargs);
  249.             break;
  250.  
  251.         case ILOAD_3: case FLOAD_3: case ALOAD_3:
  252.         case ISTORE_3: case FSTORE_3: case ASTORE_3:
  253.             ipc->value[0] = LOCAL_FIXUP(3, nargs);
  254.             break;
  255.  
  256.         case LLOAD_3: case DLOAD_3:
  257.         case LSTORE_3: case DSTORE_3:
  258.             ipc->value[0] = LOCAL_FIXUP(3, nargs);
  259.             ipc->value[1] = LOCAL_FIXUP(4, nargs);
  260.             break;
  261.  
  262.         case IINC:
  263.             ipc->value[0] = LOCAL_FIXUP(pc[0], nargs);
  264.             ipc->value[1] = (int8)pc[1];
  265.             pc += 2;
  266.             break;
  267.  
  268.         case IFEQ: case IFNE: case IFGE: case IFGT:
  269.         case IFLT: case IFLE:
  270.         case IF_ICMPEQ: case IF_ICMPNE: case IF_ICMPLT:
  271.         case IF_ICMPGE: case IF_ICMPGT: case IF_ICMPLE:
  272.         case IF_ACMPEQ: case IF_ACMPNE:
  273.         case IFNULL: case IFNONNULL:
  274.         case GOTO: case JSR:
  275.             ipc[0].type |= i_endblock;
  276.             offset = (int16)(256 * pc[0] + pc[1]);
  277.             ipc[0].value[0] = (pc - 1 - start) + offset;
  278.             pc += 2;
  279.             if (&ipc[offset] != &baseipc[0]) {
  280.                 assert(&ipc[offset-1] >= &baseipc[0]);
  281.                 assert(&ipc[offset-1] < &baseipc[len]);
  282.                 ipc[offset-1].type = i_endblock;
  283.             }
  284.             break;
  285.  
  286.         case GOTO_W: case JSR_W:
  287.             ipc[0].type |= i_endblock;
  288.             offset = (int32)(0x1000000*pc[0] + 0x10000*pc[1] + 0x100*pc[1] + pc[2]);
  289.             ipc[0].value[0] = (pc - 1 - start) + offset;
  290.             pc += 4;
  291.             if (&ipc[offset] != &baseipc[0]) {
  292.                 assert(&ipc[offset-1] >= &baseipc[0]);
  293.                 assert(&ipc[offset-1] < &baseipc[len]);
  294.                 ipc[offset-1].type = i_endblock;
  295.             }
  296.             break;
  297.  
  298.         case RET:
  299.             ipc->type |= i_endblock;
  300.             offset = *pc++;
  301.             ipc->value[0] = LOCAL_FIXUP(offset, nargs);
  302.             break;
  303.  
  304.         case RET_W:
  305.             ipc->type |= i_endblock;
  306.             offset = 256 * pc[0] + pc[1];
  307.             pc += 2;
  308.             ipc->value[0] = LOCAL_FIXUP(offset, nargs);
  309.             break;
  310.  
  311.         case WIDE:
  312.             wide = 256 * (*pc++);
  313.             break;
  314.  
  315.         case INVOKEVIRTUAL:
  316.             offset = 256 * pc[0] + pc[1];
  317.             pc += 2;
  318.             getMethodSignatureClass(offset, m->constants, &cinfo);
  319.             ipc->value[0] = cinfo.in * 4;
  320.             ipc->value[1] = MTABLE_METHODOFFSET + MTABLE_METHODSIZE * (int)cinfo.offset;
  321.             ipc->value[2] = ipc->value[1] + MTABLE_METHOD;
  322.             ipc->value[3] = cinfo.mtag;
  323.             /* Extra in argument is object itself */
  324.             ipc->value[4] = (cinfo.in+1) * 4;
  325.             /* Return arguments */
  326.             ipc->value[7] = cinfo.out;
  327.             break;
  328.  
  329.         case INVOKESTATIC:
  330.             offset = 256 * pc[0] + pc[1];
  331.             pc += 2;
  332.             getMethodSignatureClass(offset, m->constants, &cinfo);
  333.             ipc->value[0] = (int)cinfo.mtable;
  334.             ipc->value[1] = MTABLE_METHODOFFSET + MTABLE_METHODSIZE * (int)cinfo.offset;
  335.             ipc->value[2] = ipc->value[1] + MTABLE_METHOD;
  336.             ipc->value[3] = cinfo.mtag;
  337.             ipc->value[4] = cinfo.in * 4;
  338.             /* Return arguments */
  339.             ipc->value[7] = cinfo.out;
  340.             break;
  341.  
  342.         case INVOKENONVIRTUAL:
  343.             offset = 256 * pc[0] + pc[1];
  344.             pc += 2;
  345.             getMethodSignatureClass(offset, m->constants, &cinfo);
  346.             ipc->value[0] = (int)cinfo.mtable;
  347.             ipc->value[1] = MTABLE_METHODOFFSET + MTABLE_METHODSIZE * (int)cinfo.offset;
  348.             ipc->value[2] = ipc->value[1] + MTABLE_METHOD;
  349.             ipc->value[3] = cinfo.mtag;
  350.             /* Extra in argument is object itself */
  351.             ipc->value[4] = (cinfo.in+1) * 4;
  352.             /* Return arguments */
  353.             ipc->value[7] = cinfo.out;
  354.             break;
  355.  
  356.         case INVOKEINTERFACE:
  357.             offset = 256 * pc[0] + pc[1];
  358.             low = pc[2];
  359.             pc += 4; /* pc[3] is unused */
  360.             getMethodSignatureClass(offset, m->constants, &cinfo);
  361.             ipc->value[0] = (low - 1) * 4;
  362.             ipc->value[1] = MTABLE_METHODOFFSET + MTABLE_METHODSIZE * (int)cinfo.offset;
  363.             ipc->value[2] = ipc->value[1] + MTABLE_METHOD;
  364.             ipc->value[3] = cinfo.mtag;
  365.             ipc->value[4] = low * 4;
  366.             /* Return arguments */
  367.             ipc->value[7] = cinfo.out;
  368.             break;
  369.  
  370.         case TABLESWITCH:
  371.             ipc[0].type |= i_endblock;
  372.             adjust = pc - 1 - start;
  373.             pc = (bytecode*)((((uint32)pc) + 3) & -4);
  374.             offset =  0x1000000*pc[0] + 0x10000*pc[1] + 0x100*pc[2] + pc[3];
  375.             low =  0x1000000*pc[4] + 0x10000*pc[5] + 0x100*pc[6] + pc[7];
  376.             high = 0x1000000*pc[8] + 0x10000*pc[9] + 0x100*pc[10] + pc[11];
  377.             pc += 12;
  378.  
  379.             table = (tableswitch*)malloc(sizeof(tableswitch) + 4 * (high - low + 2));
  380.             assert(table != 0);
  381.             table->len = high - low + 2;
  382.  
  383.             if (&ipc[offset] != &baseipc[0]) {
  384.                 assert(&ipc[offset-1] >= &baseipc[0]);
  385.                 assert(&ipc[offset-1] < &baseipc[len]);
  386.                 ipc[offset-1].type = i_endblock;
  387.             }
  388.             table->offsets[high-low+1] = adjust + offset;
  389.             for (i = 0; i < high - low + 1; i++) {
  390.                 offset = 0x1000000*pc[0] + 0x10000*pc[1] + 0x100*pc[2] + pc[3];
  391.                 if (&ipc[offset] != &baseipc[0]) {
  392.                     assert(&ipc[offset-1] >= &baseipc[0]);
  393.                     assert(&ipc[offset-1] < &baseipc[len]);
  394.                     ipc[offset-1].type = i_endblock;
  395.                 }
  396.                 table->offsets[i] = adjust + offset;
  397.                 pc += 4;
  398.             }
  399.             ipc->value[0] = (int)table->offsets;
  400.             ipc->value[1] = low;
  401.             ipc->value[2] = high - low + 1;
  402.  
  403.             table->next = m->tableswitches;
  404.             m->tableswitches = table;
  405.             break;
  406.             
  407.         case LOOKUPSWITCH:
  408.             ipc[0].type |= i_endblock;
  409.             adjust = pc - 1 - start;
  410.             pc = (bytecode*)((((uint32)pc) + 3) & -4);
  411.             offset =  0x1000000*pc[0] + 0x10000*pc[1] + 0x100*pc[2] + pc[3];
  412.             low =  0x1000000*pc[4] + 0x10000*pc[5] + 0x100*pc[6] + pc[7];
  413.             pc += 8;
  414.  
  415.             lookup = (lookupswitch*)malloc(sizeof(lookupswitch) + 8 * (low + 1));
  416.             assert(lookup != 0);
  417.             lookup->next = 0;
  418.             lookup->len = low + 1;
  419.  
  420.             if (&ipc[offset] != &baseipc[0]) {
  421.                 assert(&ipc[offset-1] >= &baseipc[0]);
  422.                 assert(&ipc[offset-1] < &baseipc[len]);
  423.                 ipc[offset-1].type = i_endblock;
  424.             }
  425.             lookup->offsets[0] = 0;
  426.             lookup->offsets[1] = adjust + offset;
  427.             for (i = 1; i <= low; i++) {
  428.                 lookup->offsets[i*2] = 0x1000000*pc[0] + 0x10000*pc[1] + 0x100*pc[2] + pc[3];
  429.                 offset = 0x1000000*pc[4] + 0x10000*pc[5] + 0x100*pc[6] + pc[7];
  430.                 if (&ipc[offset] != &baseipc[0]) {
  431.                     assert(&ipc[offset-1] >= &baseipc[0]);
  432.                     assert(&ipc[offset-1] < &baseipc[len]);
  433.                     ipc[offset-1].type = i_endblock;
  434.                 }
  435.                 lookup->offsets[i*2+1] = adjust + offset;
  436.                 pc += 8;
  437.             }
  438.             ipc->value[0] = (int)&lookup->offsets[0];
  439.             ipc->value[1] = (int)&lookup->offsets[low*2];
  440.  
  441.             lookup->next = m->lookupswitches;
  442.             m->lookupswitches = lookup;
  443.             break;
  444.  
  445.         case NEW:
  446.         case ANEWARRAY:
  447.             offset = 256 * pc[0] + pc[1];
  448.             pc += 2;
  449.             getClass(offset, m->constants, &crinfo);
  450.             ipc->value[0] = (int)crinfo.class;
  451.             break;
  452.  
  453.         case MULTIANEWARRAY:
  454.             offset = 256 * pc[0] + pc[1];
  455.             ipc->value[1] = pc[2];
  456.             ipc->value[3] = (ipc->value[1] + 1) * 4;
  457.             pc += 3;
  458.             getClass(offset, m->constants, &crinfo);
  459.             ipc->value[0] = (int)crinfo.class;
  460.             break;
  461.  
  462.         case GETSTATIC:
  463.             offset = 256 * pc[0] + pc[1];
  464.             getField(offset, true, m->constants, &flinfo);
  465.             ipc->value[0] = ((int)flinfo.class->staticFields)
  466.                     + (4 * flinfo.offset);
  467.             if (flinfo.size == 2) {
  468.                 ipc->value[1]= ((int)flinfo.class->staticFields)
  469.                     + (4 * (1 + flinfo.offset));
  470.                 ipc->op = GETSTATIC2_QUICK;
  471.             }
  472.             else {
  473.                 ipc->op = GETSTATIC_QUICK;
  474.             }
  475.             pc += 2;
  476.             break;
  477.  
  478.         case PUTSTATIC:
  479.             offset = 256 * pc[0] + pc[1];
  480.             getField(offset, true, m->constants, &flinfo);
  481.             ipc->value[0] = ((int)flinfo.class->staticFields)
  482.                     + (4 * flinfo.offset);
  483.             if (flinfo.size == 2) {
  484.                 ipc->value[1]= ((int)flinfo.class->staticFields)
  485.                     + (4 * (1 + flinfo.offset));
  486.                 ipc->op = PUTSTATIC2_QUICK;
  487.             }
  488.             else {
  489.                 ipc->op = PUTSTATIC_QUICK;
  490.             }
  491.             pc += 2;
  492.             break;
  493.  
  494.         case GETFIELD:
  495.             offset = 256 * pc[0] + pc[1];
  496.             getField(offset, false, m->constants, &flinfo);
  497.             ipc->value[0] = OBJECT_DATA + 4 * flinfo.offset;
  498.             if (flinfo.size == 2) {
  499.                 ipc->value[1] = ipc->value[0] + 4;
  500.                 ipc->op = GETFIELD2_QUICK;
  501.             }
  502.             else {
  503.                 ipc->op = GETFIELD_QUICK;
  504.             }
  505.             pc += 2;
  506.             break;
  507.  
  508.         case PUTFIELD:
  509.             offset = 256 * pc[0] + pc[1];
  510.             getField(offset, false, m->constants, &flinfo);
  511.             ipc->value[0] = OBJECT_DATA + 4 * flinfo.offset;
  512.             if (flinfo.size == 2) {
  513.                 ipc->value[1] = ipc->value[0] + 4;
  514.                 ipc->op = PUTFIELD2_QUICK;
  515.             }
  516.             else {
  517.                 ipc->op = PUTFIELD_QUICK;
  518.             }
  519.             pc += 2;
  520.             break;
  521.  
  522.         case CHECKCAST:
  523.         case INSTANCEOF:
  524.             offset = 256 * pc[0] + pc[1];
  525.             pc += 2;
  526.             getClass(offset, m->constants, &crinfo);
  527.             ipc->value[0] = (int)crinfo.class;
  528.             break;
  529.  
  530.         case NEWARRAY:
  531.             ipc->value[0] = *pc++;
  532.             break;
  533.  
  534.         case ARRAYLENGTH:
  535.             ipc->value[0] = OBJECT_SIZE;
  536.             break;
  537.  
  538.         default:
  539.             fprintf(stderr, "Bad opcode %d\n", ipc->op);
  540.             level--;
  541.             throwException(VirtualMachineError);
  542.             abort();
  543.         }
  544.     }
  545.  
  546.     /* Allocate registers */
  547.     allocateRegisters(m);
  548.  
  549.     /* Translate */
  550.     dumpInstn(m);
  551.  
  552.     /* Translate exception table */
  553.     dumpExceptions(m);
  554.  
  555.     /* Translate switches */
  556.     dumpSwitches(m);
  557.  
  558.     free(m->code);
  559.     m->code = 0;
  560.     m->insn = 0;
  561.  
  562.     /* Establish to method so it can take exceptions */
  563.     establishMethod(m);
  564.  
  565.     level--;
  566.     assert(level == 0);
  567. }
  568.