コード例 #1
0
 public void visitLocalVariableInfo(
     Clazz clazz,
     Method method,
     CodeAttribute codeAttribute,
     LocalVariableInfo localVariableInfo) {
   // Let the visitor visit the class referenced in the local variable.
   localVariableInfo.referencedClassAccept(classVisitor);
 }
コード例 #2
0
  /**
   * Does the extraction.
   *
   * @return {@code non-null;} the extracted information
   */
  private LocalVariableInfo doit() {

    // FIXME why is this needed here?
    if (method.getRegCount() > 0) {
      for (int bi = method.getEntryBlockIndex(); bi >= 0; bi = workSet.nextSetBit(0)) {
        workSet.clear(bi);
        processBlock(bi);
      }
    }

    resultInfo.setImmutable();
    return resultInfo;
  }
コード例 #3
0
  /**
   * Processes a single block.
   *
   * @param blockIndex {@code >= 0;} block index of the block to process
   */
  private void processBlock(int blockIndex) {
    RegisterSpecSet primaryState = resultInfo.mutableCopyOfStarts(blockIndex);
    SsaBasicBlock block = blocks.get(blockIndex);
    List<SsaInsn> insns = block.getInsns();
    int insnSz = insns.size();

    // The exit block has no insns and no successors
    if (blockIndex == method.getExitBlockIndex()) {
      return;
    }

    /*
     * We may have to treat the last instruction specially: If it
     * can (but doesn't always) throw, and the exception can be
     * caught within the same method, then we need to use the
     * state *before* executing it to be what is merged into
     * exception targets.
     */
    SsaInsn lastInsn = insns.get(insnSz - 1);
    boolean hasExceptionHandlers = lastInsn.getOriginalRopInsn().getCatches().size() != 0;
    boolean canThrowDuringLastInsn = hasExceptionHandlers && (lastInsn.getResult() != null);
    int freezeSecondaryStateAt = insnSz - 1;
    RegisterSpecSet secondaryState = primaryState;

    /*
     * Iterate over the instructions, adding information for each place
     * that the active variable set changes.
     */

    for (int i = 0; i < insnSz; i++) {
      if (canThrowDuringLastInsn && (i == freezeSecondaryStateAt)) {
        // Until this point, primaryState == secondaryState.
        primaryState.setImmutable();
        primaryState = primaryState.mutableCopy();
      }

      SsaInsn insn = insns.get(i);
      RegisterSpec result;

      result = insn.getLocalAssignment();

      if (result == null) {
        // We may be nuking an existing local

        result = insn.getResult();

        if (result != null && primaryState.get(result.getReg()) != null) {
          primaryState.remove(primaryState.get(result.getReg()));
        }
        continue;
      }

      result = result.withSimpleType();

      RegisterSpec already = primaryState.get(result);
      /*
       * The equals() check ensures we only add new info if
       * the instruction causes a change to the set of
       * active variables.
       */
      if (!result.equals(already)) {
        /*
         * If this insn represents a local moving from one register
         * to another, remove the association between the old register
         * and the local.
         */
        RegisterSpec previous = primaryState.localItemToSpec(result.getLocalItem());

        if (previous != null && (previous.getReg() != result.getReg())) {

          primaryState.remove(previous);
        }

        resultInfo.addAssignment(insn, result);
        primaryState.put(result);
      }
    }

    primaryState.setImmutable();

    /*
     * Merge this state into the start state for each successor,
     * and update the work set where required (that is, in cases
     * where the start state for a block changes).
     */

    IntList successors = block.getSuccessorList();
    int succSz = successors.size();
    int primarySuccessor = block.getPrimarySuccessorIndex();

    for (int i = 0; i < succSz; i++) {
      int succ = successors.get(i);
      RegisterSpecSet state = (succ == primarySuccessor) ? primaryState : secondaryState;

      if (resultInfo.mergeStarts(succ, state)) {
        workSet.set(succ);
      }
    }
  }
コード例 #4
0
ファイル: BlockWriter.java プロジェクト: Saalma/aparapi
  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()));
    }
  }