Package edu.cmu.cs.crystal.tac.eclipse

Source Code of edu.cmu.cs.crystal.tac.eclipse.EclipseInstructionSequence

/**
* Copyright (c) 2006, 2007, 2008 Marwan Abi-Antoun, Jonathan Aldrich, Nels E. Beckman,
* Kevin Bierhoff, David Dickey, Ciera Jaspan, Thomas LaToza, Gabriel Zenarosa, and others.
*
* This file is part of Crystal.
*
* Crystal is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Crystal is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Crystal.  If not, see <http://www.gnu.org/licenses/>.
*/
package edu.cmu.cs.crystal.tac.eclipse;

import java.util.Collections;
import java.util.List;

import org.eclipse.jdt.core.dom.ASTNode;

import edu.cmu.cs.crystal.flow.AnalysisDirection;
import edu.cmu.cs.crystal.flow.ILabel;
import edu.cmu.cs.crystal.flow.IResult;
import edu.cmu.cs.crystal.flow.LabeledSingleResult;
import edu.cmu.cs.crystal.flow.NormalLabel;
import edu.cmu.cs.crystal.tac.ITACBranchSensitiveTransferFunction;
import edu.cmu.cs.crystal.tac.ITACTransferFunction;
import edu.cmu.cs.crystal.tac.model.TACInstruction;
import edu.cmu.cs.crystal.tac.model.Variable;

/**
* @author Kevin Bierhoff
*
*/
public class EclipseInstructionSequence extends ResultfulInstruction<ASTNode> {
 
  private final int useAsResult;
  private final TACInstruction[] instructions; // this must be a non-empty array

  public EclipseInstructionSequence(ASTNode node, TACInstruction[] instructions, int useAsResult, IEclipseVariableQuery tac) {
    super(node, tac);
    if(instructions == null || useAsResult < 0 || useAsResult >= instructions.length) {
      throw new IllegalArgumentException("Illegal instruction sequence arguments");
    }
    if(! (instructions[useAsResult] instanceof ResultfulInstruction))
      throw new IllegalArgumentException("Indicated instruction does not have result: " + instructions[useAsResult]);
    this.useAsResult = useAsResult;
    this.instructions = instructions;
    // TODO sanity check: make sure result of instructions[useAsResult] is not changed afterwards
  }

  public EclipseInstructionSequence(ASTNode node, TACInstruction[] instructions, IEclipseVariableQuery tac) {
    super(node, tac);
    if(instructions == null || instructions.length == 0) {
      throw new IllegalArgumentException("Illegal instruction sequence arguments");
    }
    if(! (instructions[instructions.length - 1] instanceof ResultfulInstruction))
      throw new IllegalArgumentException("Last instruction does not have result: " + instructions[instructions.length - 1]);
    this.useAsResult = instructions.length - 1;
    this.instructions = instructions;
    // TODO sanity check: make sure result of instructions[useAsResult] is not changed afterwards
  }

  /* (non-Javadoc)
   * @see edu.cmu.cs.crystal.tac.IUseAsOperand#getOperandVariable()
   */
  protected Variable getResultVariable() {
    return ((ResultfulInstruction<?>) instructions[useAsResult]).getResultVariable();
  }

  protected int getUseAsResult() {
    return useAsResult;
  }

  protected TACInstruction[] getInstructions() {
    return instructions;
  }

  @Override
  public <LE> LE transfer(ITACTransferFunction<LE> tf, LE value) {
    if(AnalysisDirection.FORWARD_ANALYSIS.equals(tf.getAnalysisDirection())) {
      for(TACInstruction instr : instructions)
        value = instr.transfer(tf, value);
    }
    else {
      for(int i = instructions.length - 1; i >= 0; i--)
        value = instructions[i].transfer(tf, value);
    }
    return value;
  }
 
  @Override
  public <LE> IResult<LE> transfer(ITACBranchSensitiveTransferFunction<LE> tf, List<ILabel> labels, LE value) {
    ILabel normal = NormalLabel.getNormalLabel();
    List<ILabel> normalOnly = Collections.singletonList(normal);
   
    // this implementation makes the simplifying assumption that the last instruction
    // in the sequence relative to the analysis direction should generate results for
    // provided list of labels.  All other instructions only transfer over NormalLabel.
    switch(tf.getAnalysisDirection()) {
    case FORWARD_ANALYSIS:
      for(int i = 0; i < instructions.length-1; i++) {
        IResult<LE> result = instructions[i].transfer(tf, normalOnly, value);
        value = result.get(normal);
      }
      return instructions[instructions.length-1].transfer(tf, labels, value);
    case BACKWARD_ANALYSIS:
      for(int i = instructions.length-1; i > 0; i--) {
        IResult<LE> result = instructions[i].transfer(tf, normalOnly, value);
        value = result.get(normal);
      }
      return instructions[0].transfer(tf, labels, value);
    default:
      throw new UnsupportedOperationException("Unknown analysis direction: " + tf.getAnalysisDirection());
    }
  }

  public <LE> LE deriveResult(ITACTransferFunction<LE> tf, TACInstruction targetInstr, LE value, boolean afterResult) {
    if(AnalysisDirection.FORWARD_ANALYSIS.equals(tf.getAnalysisDirection())) {
      if(!afterResult && targetInstr == this)
        return value;
      for(TACInstruction instr : instructions) {
        if(!afterResult && instr == targetInstr)
          return value;
        value = instr.transfer(tf, value);
        if(afterResult && instr == targetInstr)
          return value;
      }
      if(afterResult && targetInstr == this)
        return value;
    }
    else {
      if(afterResult && targetInstr == this)
        return value;
      for(int i = instructions.length - 1; i >= 0; i--) {
        TACInstruction instr = instructions[i];
        if(afterResult && instr == targetInstr)
          return value;
        value = instr.transfer(tf, value);
        if(!afterResult && instr == targetInstr)
          return value;
      }
      if(!afterResult && targetInstr == this)
        return value;
    }
    // should never reach this point
    throw new IllegalArgumentException("Given instruction is unknown: " + targetInstr);
  }

  public <LE> IResult<LE> deriveResult(ITACBranchSensitiveTransferFunction<LE> tf, List<ILabel> labels, TACInstruction targetInstr, LE value, boolean afterResult) {
    ILabel normal = NormalLabel.getNormalLabel();
    List<ILabel> normalOnly = Collections.singletonList(normal);
   
    // this implementation makes the simplifying assumption that the last instruction
    // in the sequence relative to the analysis direction should generate results for
    // provided list of labels.  All other instructions only transfer over NormalLabel.
    switch(tf.getAnalysisDirection()) {
    case FORWARD_ANALYSIS:
      if(!afterResult && targetInstr == this)
        return LabeledSingleResult.createResult(value, normalOnly);
      for(int i = 0; i < instructions.length-1; i++) {
        TACInstruction instr = instructions[i];
        if(!afterResult && instr == targetInstr)
          return LabeledSingleResult.createResult(value, normalOnly);
        IResult<LE> result = instr.transfer(tf, normalOnly, value);
        if(afterResult && instr == targetInstr)
          return result;
        value = result.get(normal);
      }
      TACInstruction last = instructions[instructions.length-1];
      if(!afterResult && last == targetInstr)
        return LabeledSingleResult.createResult(value, normalOnly);
      else if(afterResult && (last == targetInstr || this == targetInstr))
          return last.transfer(tf, labels, value);
      else
        break;
    case BACKWARD_ANALYSIS:
      if(afterResult && targetInstr == this)
        return LabeledSingleResult.createResult(value, normalOnly);
      for(int i = instructions.length-1; i > 0; i--) {
        TACInstruction instr = instructions[i];
        if(afterResult && instr == targetInstr)
          return LabeledSingleResult.createResult(value, normalOnly);
        IResult<LE> result = instr.transfer(tf, normalOnly, value);
        if(!afterResult && instr == targetInstr)
          return result;
        value = result.get(normal);
      }
      TACInstruction instr = instructions[0];
      if(afterResult && instr == targetInstr)
        return LabeledSingleResult.createResult(value, normalOnly);
      else if(!afterResult && (instr == targetInstr || this == targetInstr))
        return instr.transfer(tf, labels, value);
      else
        break;
    default:
      throw new UnsupportedOperationException("Unknown analysis direction: " + tf.getAnalysisDirection());
    }
    // should never reach this point
    throw new IllegalArgumentException("Given instruction is unknown: " + targetInstr);
  }

  @Override
  public String toString() {
    StringBuilder result_ = new StringBuilder("Instructions: ");
    for( TACInstruction instr : this.instructions ) {
      result_.append(instr.toString() + ", ");
    }
    result_.delete(result_.length()-2, result_.length()-1);
    return result_.toString();
  }
}
TOP

Related Classes of edu.cmu.cs.crystal.tac.eclipse.EclipseInstructionSequence

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.