예제 #1
0
  public void writeConditionalBranch16(ConditionalBranch16 _branch16, boolean _invert)
      throws CodeGenException {

    if (_branch16 instanceof If) {
      final If iff = (If) _branch16;

      writeInstruction(iff.getLhs());
      write(_branch16.getOperator().getText(_invert));
      writeInstruction(iff.getRhs());
    } else if (_branch16 instanceof I_IFNULL) {
      final I_IFNULL iff = (I_IFNULL) _branch16;
      writeInstruction(iff.getFirstChild());

      if (_invert) {
        write(" != NULL");
      } else {
        write(" == NULL");
      }

    } else if (_branch16 instanceof I_IFNONNULL) {
      final I_IFNONNULL iff = (I_IFNONNULL) _branch16;
      writeInstruction(iff.getFirstChild());

      if (_invert) {
        write(" == NULL");
      } else {
        write(" != NULL");
      }
    } else if (_branch16 instanceof IfUnary) {
      final IfUnary branch16 = (IfUnary) _branch16;
      final Instruction comparison = branch16.getUnary();
      final ByteCode comparisonByteCode = comparison.getByteCode();
      final String comparisonOperator = _branch16.getOperator().getText(_invert);

      switch (comparisonByteCode) {
        case FCMPG:
        case DCMPG:
        case FCMPL:
        case DCMPL:
          if (Config.verboseComparitor) {
            write("/* bytecode=" + comparisonByteCode.getName() + " invert=" + _invert + "*/");
          }
          writeInstruction(comparison.getFirstChild());
          write(comparisonOperator);
          writeInstruction(comparison.getLastChild());
          break;
        default:
          if (Config.verboseComparitor) {
            write(
                "/* default bytecode="
                    + comparisonByteCode.getName()
                    + " invert="
                    + _invert
                    + "*/");
          }
          writeInstruction(comparison);
          write(comparisonOperator);
          write("0");
      }
    }
  }
예제 #2
0
  public void writeInstruction(Instruction _instruction) throws CodeGenException {
    if (_instruction instanceof CompositeIfElseInstruction) {
      write("(");
      final Instruction lhs =
          writeConditional(((CompositeInstruction) _instruction).getBranchSet());
      write(")?");
      writeInstruction(lhs);
      write(":");
      writeInstruction(lhs.getNextExpr().getNextExpr());
    } else if (_instruction instanceof CompositeInstruction) {
      writeComposite((CompositeInstruction) _instruction);

    } else if (_instruction instanceof AssignToLocalVariable) {
      final AssignToLocalVariable assignToLocalVariable = (AssignToLocalVariable) _instruction;

      final LocalVariableInfo localVariableInfo = assignToLocalVariable.getLocalVariableInfo();
      if (assignToLocalVariable.isDeclaration()) {
        final String descriptor = localVariableInfo.getVariableDescriptor();
        // Arrays always map to __global arrays
        if (descriptor.startsWith("[")) {
          write(" __global ");
        }
        write(convertType(descriptor, true));
      }
      if (localVariableInfo == null) {
        throw new CodeGenException("outOfScope" + _instruction.getThisPC() + " = ");
      } else {
        write(localVariableInfo.getVariableName() + " = ");
      }

      for (Instruction operand = _instruction.getFirstChild();
          operand != null;
          operand = operand.getNextExpr()) {
        writeInstruction(operand);
      }

    } else if (_instruction instanceof AssignToArrayElement) {
      final AssignToArrayElement arrayAssignmentInstruction = (AssignToArrayElement) _instruction;
      writeInstruction(arrayAssignmentInstruction.getArrayRef());
      write("[");
      writeInstruction(arrayAssignmentInstruction.getArrayIndex());
      write("]");
      write(" ");
      write(" = ");
      writeInstruction(arrayAssignmentInstruction.getValue());
    } else if (_instruction instanceof AccessArrayElement) {

      // we're getting an element from an array
      // if the array is a primitive then we just return the value
      // so the generated code looks like
      // arrayName[arrayIndex];
      // but if the array is an object, or multidimensional array, then we want to return
      // a pointer to our index our position in the array.  The code will look like
      // &(arrayName[arrayIndex * this->arrayNameLen_dimension]
      //
      final AccessArrayElement arrayLoadInstruction = (AccessArrayElement) _instruction;

      // object array, get address
      if (arrayLoadInstruction instanceof I_AALOAD) {
        write("(&");
      }
      writeInstruction(arrayLoadInstruction.getArrayRef());
      write("[");
      writeInstruction(arrayLoadInstruction.getArrayIndex());

      // object array, find the size of each object in the array
      // for 2D arrays, this size is the size of a row.
      if (arrayLoadInstruction instanceof I_AALOAD) {
        int dim = 0;
        Instruction load = arrayLoadInstruction.getArrayRef();
        while (load instanceof I_AALOAD) {
          load = load.getFirstChild();
          dim++;
        }

        String arrayName =
            ((AccessInstanceField) load)
                .getConstantPoolFieldEntry()
                .getNameAndTypeEntry()
                .getNameUTF8Entry()
                .getUTF8();
        write(" * this->" + arrayName + arrayDimMangleSuffix + dim);
      }

      write("]");

      // object array, close parentheses
      if (arrayLoadInstruction instanceof I_AALOAD) {
        write(")");
      }
    } else if (_instruction instanceof AccessField) {
      final AccessField accessField = (AccessField) _instruction;
      if (accessField instanceof AccessInstanceField) {
        Instruction accessInstanceField = ((AccessInstanceField) accessField).getInstance();
        if (accessInstanceField instanceof CloneInstruction) {
          accessInstanceField = ((CloneInstruction) accessInstanceField).getReal();
        }
        if (!(accessInstanceField instanceof I_ALOAD_0)) {
          writeInstruction(accessInstanceField);
          write(".");
        } else {
          writeThisRef();
        }
      }
      write(
          accessField
              .getConstantPoolFieldEntry()
              .getNameAndTypeEntry()
              .getNameUTF8Entry()
              .getUTF8());

    } else if (_instruction instanceof I_ARRAYLENGTH) {

      // getting the length of an array.
      // if this is a primitive array, then this is trivial
      // if we're getting an object array, then we need to find what dimension
      // we're looking at
      int dim = 0;
      Instruction load = _instruction.getFirstChild();
      while (load instanceof I_AALOAD) {
        load = load.getFirstChild();
        dim++;
      }
      final AccessInstanceField child = (AccessInstanceField) load;
      final String arrayName =
          child.getConstantPoolFieldEntry().getNameAndTypeEntry().getNameUTF8Entry().getUTF8();
      write("this->" + arrayName + arrayLengthMangleSuffix + dim);
    } else if (_instruction instanceof AssignToField) {
      final AssignToField assignedField = (AssignToField) _instruction;

      if (assignedField instanceof AssignToInstanceField) {
        final Instruction accessInstanceField =
            ((AssignToInstanceField) assignedField).getInstance().getReal();

        if (!(accessInstanceField instanceof I_ALOAD_0)) {
          writeInstruction(accessInstanceField);
          write(".");
        } else {
          writeThisRef();
        }
      }
      write(
          assignedField
              .getConstantPoolFieldEntry()
              .getNameAndTypeEntry()
              .getNameUTF8Entry()
              .getUTF8());
      write("=");
      writeInstruction(assignedField.getValueToAssign());
    } else if (_instruction instanceof Constant<?>) {
      final Constant<?> constantInstruction = (Constant<?>) _instruction;
      final Object value = constantInstruction.getValue();

      if (value instanceof Float) {

        final Float f = (Float) value;
        if (f.isNaN()) {
          write("NAN");
        } else if (f.isInfinite()) {
          if (f < 0) {
            write("-");
          }
          write("INFINITY");
        } else {
          write(value.toString());
          write("f");
        }
      } else if (value instanceof Double) {

        final Double d = (Double) value;
        if (d.isNaN()) {
          write("NAN");
        } else if (d.isInfinite()) {
          if (d < 0) {
            write("-");
          }
          write("INFINITY");
        } else {
          write(value.toString());
        }
      } else {
        write(value.toString());
        if (value instanceof Long) {
          write("L");
        }
      }

    } else if (_instruction instanceof AccessLocalVariable) {
      final AccessLocalVariable localVariableLoadInstruction = (AccessLocalVariable) _instruction;
      final LocalVariableInfo localVariable = localVariableLoadInstruction.getLocalVariableInfo();
      write(localVariable.getVariableName());
    } else if (_instruction instanceof I_IINC) {
      final I_IINC location = (I_IINC) _instruction;
      final LocalVariableInfo localVariable = location.getLocalVariableInfo();
      final int adjust = location.getAdjust();

      write(localVariable.getVariableName());
      if (adjust == 1) {
        write("++");
      } else if (adjust == -1) {
        write("--");
      } else if (adjust > 1) {
        write("+=" + adjust);
      } else if (adjust < -1) {
        write("-=" + (-adjust));
      }
    } else if (_instruction instanceof BinaryOperator) {
      final BinaryOperator binaryInstruction = (BinaryOperator) _instruction;
      final Instruction parent = binaryInstruction.getParentExpr();
      boolean needsParenthesis = true;

      if (parent instanceof AssignToLocalVariable) {
        needsParenthesis = false;
      } else if (parent instanceof AssignToField) {
        needsParenthesis = false;
      } else if (parent instanceof AssignToArrayElement) {
        needsParenthesis = false;
      } else {
        /**
         * if (parent instanceof BinaryOperator) { BinaryOperator parentBinaryOperator =
         * (BinaryOperator) parent; if (parentBinaryOperator.getOperator().ordinal() >
         * binaryInstruction.getOperator().ordinal()) { needsParenthesis = false; } }
         */
      }

      if (needsParenthesis) {
        write("(");
      }

      writeInstruction(binaryInstruction.getLhs());

      write(" " + binaryInstruction.getOperator().getText() + " ");
      writeInstruction(binaryInstruction.getRhs());

      if (needsParenthesis) {
        write(")");
      }

    } else if (_instruction instanceof CastOperator) {
      final CastOperator castInstruction = (CastOperator) _instruction;
      //  write("(");
      write(convertCast(castInstruction.getOperator().getText()));

      writeInstruction(castInstruction.getUnary());
      //    write(")");
    } else if (_instruction instanceof UnaryOperator) {
      final UnaryOperator unaryInstruction = (UnaryOperator) _instruction;
      //   write("(");
      write(unaryInstruction.getOperator().getText());

      writeInstruction(unaryInstruction.getUnary());
      //   write(")");
    } else if (_instruction instanceof Return) {

      final Return ret = (Return) _instruction;
      write("return");
      if (ret.getStackConsumeCount() > 0) {
        write("(");
        writeInstruction(ret.getFirstChild());
        write(")");
      }

    } else if (_instruction instanceof MethodCall) {
      final MethodCall methodCall = (MethodCall) _instruction;

      final MethodEntry methodEntry = methodCall.getConstantPoolMethodEntry();

      writeMethod(methodCall, methodEntry);
    } else if (_instruction.getByteCode().equals(ByteCode.CLONE)) {
      final CloneInstruction cloneInstruction = (CloneInstruction) _instruction;
      writeInstruction(cloneInstruction.getReal());
    } else if (_instruction.getByteCode().equals(ByteCode.INCREMENT)) {
      final IncrementInstruction incrementInstruction = (IncrementInstruction) _instruction;

      if (incrementInstruction.isPre()) {
        if (incrementInstruction.isInc()) {
          write("++");
        } else {
          write("--");
        }
      }

      writeInstruction(incrementInstruction.getFieldOrVariableReference());
      if (!incrementInstruction.isPre()) {
        if (incrementInstruction.isInc()) {
          write("++");
        } else {
          write("--");
        }
      }
    } else if (_instruction.getByteCode().equals(ByteCode.MULTI_ASSIGN)) {
      final MultiAssignInstruction multiAssignInstruction = (MultiAssignInstruction) _instruction;
      AssignToLocalVariable from = (AssignToLocalVariable) multiAssignInstruction.getFrom();
      final AssignToLocalVariable last = (AssignToLocalVariable) multiAssignInstruction.getTo();
      final Instruction common = multiAssignInstruction.getCommon();
      final Stack<AssignToLocalVariable> stack = new Stack<AssignToLocalVariable>();

      while (from != last) {
        stack.push(from);
        from = (AssignToLocalVariable) ((Instruction) from).getNextExpr();
      }

      for (AssignToLocalVariable alv = stack.pop();
          alv != null;
          alv = stack.size() > 0 ? stack.pop() : null) {

        final LocalVariableInfo localVariableInfo = alv.getLocalVariableInfo();
        if (alv.isDeclaration()) {
          write(convertType(localVariableInfo.getVariableDescriptor(), true));
        }
        if (localVariableInfo == null) {
          throw new CodeGenException("outOfScope" + _instruction.getThisPC() + " = ");
        } else {
          write(localVariableInfo.getVariableName() + " = ");
        }
      }
      writeInstruction(common);
    } else if (_instruction.getByteCode().equals(ByteCode.INLINE_ASSIGN)) {
      final InlineAssignInstruction inlineAssignInstruction =
          (InlineAssignInstruction) _instruction;
      final AssignToLocalVariable assignToLocalVariable =
          inlineAssignInstruction.getAssignToLocalVariable();

      final LocalVariableInfo localVariableInfo = assignToLocalVariable.getLocalVariableInfo();
      if (assignToLocalVariable.isDeclaration()) {
        // this is bad! we need a general way to hoist up a required declaration
        throw new CodeGenException(
            "/* we can't declare this "
                + convertType(localVariableInfo.getVariableDescriptor(), true)
                + " here */");
      }
      write(localVariableInfo.getVariableName());
      write("=");
      writeInstruction(inlineAssignInstruction.getRhs());
    } else if (_instruction.getByteCode().equals(ByteCode.FIELD_ARRAY_ELEMENT_ASSIGN)) {
      final FieldArrayElementAssign inlineAssignInstruction =
          (FieldArrayElementAssign) _instruction;
      final AssignToArrayElement arrayAssignmentInstruction =
          inlineAssignInstruction.getAssignToArrayElement();

      writeInstruction(arrayAssignmentInstruction.getArrayRef());
      write("[");
      writeInstruction(arrayAssignmentInstruction.getArrayIndex());
      write("]");
      write(" ");
      write(" = ");

      writeInstruction(inlineAssignInstruction.getRhs());
    } else if (_instruction.getByteCode().equals(ByteCode.FIELD_ARRAY_ELEMENT_INCREMENT)) {

      final FieldArrayElementIncrement fieldArrayElementIncrement =
          (FieldArrayElementIncrement) _instruction;
      final AssignToArrayElement arrayAssignmentInstruction =
          fieldArrayElementIncrement.getAssignToArrayElement();
      if (fieldArrayElementIncrement.isPre()) {
        if (fieldArrayElementIncrement.isInc()) {
          write("++");
        } else {
          write("--");
        }
      }
      writeInstruction(arrayAssignmentInstruction.getArrayRef());

      write("[");
      writeInstruction(arrayAssignmentInstruction.getArrayIndex());
      write("]");
      if (!fieldArrayElementIncrement.isPre()) {
        if (fieldArrayElementIncrement.isInc()) {
          write("++");
        } else {
          write("--");
        }
      }

    } else if (_instruction.getByteCode().equals(ByteCode.NONE)) {
      // we are done
    } else if (_instruction instanceof Branch) {
      throw new CodeGenException(
          String.format(
              "%s -> %04d",
              _instruction.getByteCode().toString().toLowerCase(),
              ((Branch) _instruction).getTarget().getThisPC()));
    } else if (_instruction instanceof I_POP) {
      // POP discarded void call return?
      writeInstruction(_instruction.getFirstChild());
    } else {
      throw new CodeGenException(
          String.format("%s", _instruction.getByteCode().toString().toLowerCase()));
    }
  }