Package edu.cmu.cs.fusion.relationship

Source Code of edu.cmu.cs.fusion.relationship.ConstraintChecker

package edu.cmu.cs.fusion.relationship;

import java.util.LinkedList;
import java.util.List;

import edu.cmu.cs.crystal.tac.model.TACInstruction;
import edu.cmu.cs.crystal.util.ConsList;
import edu.cmu.cs.crystal.util.Pair;
import edu.cmu.cs.crystal.util.TypeHierarchy;
import edu.cmu.cs.fusion.Binding;
import edu.cmu.cs.fusion.FusionEnvironment;
import edu.cmu.cs.fusion.Method;
import edu.cmu.cs.fusion.ThreeValue;
import edu.cmu.cs.fusion.Variant;
import edu.cmu.cs.fusion.alias.AliasContext;
import edu.cmu.cs.fusion.alias.AliasDelta;
import edu.cmu.cs.fusion.constraint.Constraint;
import edu.cmu.cs.fusion.constraint.ConstraintEnvironment;
import edu.cmu.cs.fusion.constraint.Effect;
import edu.cmu.cs.fusion.constraint.Substitution;
import edu.cmu.cs.fusion.constraint.predicates.TruePredicate;

public class ConstraintChecker {
  private ConstraintEnvironment constraints;
  protected TypeHierarchy types;
  protected Variant variant;
  protected Method method;
 
  public ConstraintChecker(ConstraintEnvironment constraints, TypeHierarchy types, Variant var, Method method) {
    this.constraints = constraints;
    this.types = types;
    this.variant = var;
    this.method = method;
  }

  /**
   * Run the flow function for each constraint. Join the results from each constraint together and adjust the lattice
   * @param env
   * @param instr
   * @return The new relationship lattice.
   */
  public <AC extends AliasContext> Pair<AC, RelationshipContext> runGenericTransfer(FusionEnvironment<AC> env, TACInstruction instr) {
    List<RelationshipDelta> relDeltas = new LinkedList<RelationshipDelta>();
    List<AliasDelta> aliasDeltas = new LinkedList<AliasDelta>();
   
    for (Constraint cons : constraints) {
      Pair<RelationshipDelta, AliasDelta> deltas = runSingleConstraint(env, cons, instr);
      relDeltas.add(deltas.fst());
      aliasDeltas.add(deltas.snd());
    }
   
    RelationshipDelta relDelta;
    AliasDelta aliasDelta;
   
    //try to avoid calling joins
    if (relDeltas.isEmpty()) {
      relDelta = new RelationshipDelta();
      aliasDelta = new AliasDelta();
    }
    else if (relDeltas.size() == 1) {
      relDelta = relDeltas.get(0);
      aliasDelta = aliasDeltas.get(0);
    }
    else {
      relDelta = RelationshipDelta.joinAlt(relDeltas);
      aliasDelta = AliasDelta.join(aliasDeltas);
    }
   
    RelationshipContext relContext = env.getContext().applyChangesFromDelta(relDelta);
    AC aliasContext = env.makeNewAliases(aliasDelta);
   
    return new Pair<AC, RelationshipContext>(aliasContext, relContext);
  }

  public List<FusionErrorReport> checkForErrors(FusionEnvironment<?> triggerEnv, TACInstruction instr) {
    List<FusionErrorReport> errors = new LinkedList<FusionErrorReport>();
    FusionErrorReport err;
   
    for (Constraint cons : constraints) {
      if (!(cons.getRequires() instanceof TruePredicate && cons.getRestrict() instanceof TruePredicate)) {
        err = checkSingleConstraint(triggerEnv, cons, instr);
        if (err != null)
          errors.add(err);
      }
    }
   
    return errors;
  }

  /**
   * @param env The alias and relation lattices
   * @param cons The constraint to check
   * @param instr The instruction we are checking the constraint on
   * @return a relationship delta for all possible aliasing configurations, assuming the constraint
   * triggers.
   */
  protected Pair<RelationshipDelta, AliasDelta> runSingleConstraint(FusionEnvironment<?> env,
      Constraint cons, TACInstruction instr) {
    ConsList<Binding> boundVars = cons.getOp().matches(types, method, instr);
   
    if (boundVars == null)
      return new Pair<RelationshipDelta, AliasDelta>(new RelationshipDelta(), new AliasDelta());
   
    List<RelationshipDelta> relDeltas = new LinkedList<RelationshipDelta>();
    List<Substitution> changeSubs = new LinkedList<Substitution>();
    List<Substitution> subs = env.findLabels(boundVars, cons.getUniversalFreeVars());
   
    for (Substitution sub : subs) {
      Pair<RelationshipDelta, Substitution> deltas = runFullyBound(env, sub, cons);
      relDeltas.add(deltas.fst());
      changeSubs.add(deltas.snd());
    }
   
    RelationshipDelta relDelta;
    AliasDelta aliasDelta;
     
    if (relDeltas.isEmpty()) {
      relDelta = RelationshipDelta.getTrueBottom();
      aliasDelta = new AliasDelta();
    }
    else if (relDeltas.size() == 1) {
      relDelta = relDeltas.get(0);
      aliasDelta = new AliasDelta(boundVars, changeSubs);
    }
    else {
      relDelta = RelationshipDelta.join(relDeltas);
      aliasDelta = new AliasDelta(boundVars, changeSubs);
    }
     
    return new Pair<RelationshipDelta, AliasDelta>(relDelta, aliasDelta);
  }

 
  /**
   *
   * @param env
   * @param cons
   * @param instr
   * @return The error report from this constraint, or null if there were no errors.
   */
  protected FusionErrorReport checkSingleConstraint(FusionEnvironment<?> triggerEnv, Constraint cons, TACInstruction instr) {
    ConsList<Binding> boundVars = cons.getOp().matches(types, method, instr);

    if (boundVars == null)
      return null;

    List<Substitution> subs = triggerEnv.findLabels(boundVars, cons.getUniversalFreeVars());
   
    List<Substitution> failingSubs = new LinkedList<Substitution>();   
   
    boolean hasGoodSub = false;
    for (Substitution sub : subs) {
      ThreeValue trigger = cons.getTrigger().getTruth(triggerEnv, sub);
      if (isGoodSubs(trigger, triggerEnv, sub, cons)) {     
        if (checkFullyBound(triggerEnv, sub, cons))
          failingSubs.add(sub);
        hasGoodSub = true;
      }
    }
       
    if (!failingSubs.isEmpty())
      return new FusionErrorReport(cons, failingSubs, triggerEnv, false);
    else if (!subs.isEmpty() && !hasGoodSub)
      return new FusionErrorReport(cons, failingSubs, triggerEnv, true);    
    else
      return null;
  }

  /**
   * Check a constraint with the fully bound substitutions
   * @param env The stating lattices
   * @param partialSubs The substitutions for FV(cons) - FV(req)
   * @param cons The constraint to check
   * @param instr The instruction to report errors on
   * @return Any change effects
   */
  protected Pair<RelationshipDelta, Substitution> runFullyBound(FusionEnvironment<?> env, Substitution partialSubs, Constraint cons) { 
    ThreeValue trigger = cons.getTrigger().getTruth(env, partialSubs);
    Substitution keepSub = isGoodSubs(trigger, env, partialSubs, cons) ? partialSubs : null;
    RelationshipDelta delta;
   
    if (trigger == ThreeValue.FALSE) {
      delta = RelationshipDelta.getTrueBottom();
    }
    else  {
      delta = new RelationshipDelta();
     
      //now make the effects
      for (Effect effect : cons.getEffects())
        delta.override(effect.makeEffects(env, partialSubs));

      if (trigger == ThreeValue.UNKNOWN) {
        delta = delta.polarize();
      }
    }
    return new Pair<RelationshipDelta, Substitution>(delta, keepSub);
  }


  private boolean isGoodSubs(ThreeValue trigger, FusionEnvironment<?> env, Substitution partialSubs, Constraint cons) {
   
    if (trigger == ThreeValue.FALSE || trigger == ThreeValue.UNKNOWN) {
      return true;
    }
    else {
      if (cons.getRestrict() instanceof TruePredicate)
        return true;
      List<Substitution> subs = env.allValidSubs(partialSubs, cons.getFreeVars());
       
      for (Substitution sub : subs) {
        ThreeValue restrict = cons.getRestrict().getTruth(env, sub);
       
        if ((restrict == ThreeValue.TRUE) || (restrict == ThreeValue.UNKNOWN && !variant.isPragmatic()))
          return true;
      }
      return false;
    }
  }

  /**
   *
   * @param triggerEnv
   * @param postRestrict
   * @param partialSubs
   * @param cons
   * @return True if there is an error, false if there is not an error
   */
  protected boolean checkFullyBound(FusionEnvironment<?> triggerEnv, Substitution partialSubs, Constraint cons) {     
    ThreeValue trigger = cons.getTrigger().getTruth(triggerEnv, partialSubs);
   
    if (trigger == ThreeValue.FALSE)
      return false;
    else if (trigger == ThreeValue.UNKNOWN){
      if (variant.isComplete() || variant.isPragmatic())
        return false;
      else
        return checkSoundly(triggerEnv, partialSubs, cons);
    }
    else  {
      if (variant.isComplete())
        return checkCompletely(triggerEnv, partialSubs, cons);
      else if (variant.isSound())
        return checkSoundly(triggerEnv, partialSubs, cons);
      else
        return checkPragmatically(triggerEnv, partialSubs, cons);
    }
  }

  /**
   * @return true if there is an error, false if it passes
   */
  private boolean checkPragmatically(FusionEnvironment<?> env,
      Substitution partialSubs, Constraint cons) {   
    List<Substitution> subs = env.allValidSubs(partialSubs, cons.getFreeVars());
   
    for (Substitution fullSub : subs) {
      ThreeValue req = cons.getRequires().getTruth(env, fullSub);
      if (req == ThreeValue.TRUE)
        return false;
    }
    return true;
  }

  /**
   * @return true if there is an error, false if it passes
   */
  private boolean checkSoundly(FusionEnvironment<?> env,
      Substitution partialSubs, Constraint cons) {
    List<Substitution> subs = env.allValidSubs(partialSubs, cons.getFreeVars());
   
    if (subs.isEmpty())
      return true;
   
    for (Substitution fullSub : subs) {
      ThreeValue req = cons.getRequires().getTruth(env, fullSub);
      if (req != ThreeValue.TRUE)
        return true;
    }
    return false;
  }
 
  /**
   * @return true if there is an error, false if it passes
   */
  private boolean checkCompletely(FusionEnvironment<?> env,
      Substitution partialSubs, Constraint cons) {
    List<Substitution> subs = env.allValidSubs(partialSubs, cons.getFreeVars());
   
    for (Substitution fullSub : subs) {
      ThreeValue req = cons.getRequires().getTruth(env, fullSub);
      if (req != ThreeValue.FALSE)
        return false;
    }
    return true;
  }


}
TOP

Related Classes of edu.cmu.cs.fusion.relationship.ConstraintChecker

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.