Package org.jakstab.analysis.sign

Source Code of org.jakstab.analysis.sign.SignAnalysis

/*
* SignAnalysis.java - This file is part of the Jakstab project.
* Copyright 2007-2012 Johannes Kinder <jk@jakstab.org>
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code 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 General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, see <http://www.gnu.org/licenses/>.
*/
package org.jakstab.analysis.sign;

import java.util.Collections;
import java.util.Set;

import org.jakstab.AnalysisProperties;
import org.jakstab.analysis.*;
import org.jakstab.cfa.CFAEdge;
import org.jakstab.cfa.Location;
import org.jakstab.cfa.StateTransformer;
import org.jakstab.rtl.expressions.*;
import org.jakstab.rtl.statements.*;
import org.jakstab.solver.Solver;
import org.jakstab.util.Logger;
import org.jakstab.util.Pair;

/**
* Demo analysis for classroom use.
*
* @author Johannes Kinder
*/
public class SignAnalysis implements ConfigurableProgramAnalysis {

  public static void register(AnalysisProperties p) {
    p.setShortHand('g');
    p.setName("Sign analysis");
    p.setDescription("For each variable, compute its sign (-, 0, or +).");
  }

  @SuppressWarnings("unused")
  private static final Logger logger = Logger.getLogger(SignAnalysis.class);

  /*
   * @see org.jakstab.analysis.ConfigurableProgramAnalysis#initPrecision()
   */
  @Override
  public Precision initPrecision(Location location, StateTransformer transformer) {
    return null;
  }

  /*
   * @see org.jakstab.analysis.ConfigurableProgramAnalysis#initStartState(org.jakstab.cfa.Location)
   */
  @Override
  public AbstractState initStartState(Location label) {
    return SignState.TOP;
  }

  /*
   * @see org.jakstab.analysis.ConfigurableProgramAnalysis#merge(org.jakstab.analysis.AbstractState, org.jakstab.analysis.AbstractState, org.jakstab.analysis.Precision)
   */
  @Override
  public AbstractState merge(AbstractState s1, AbstractState s2,
      Precision precision) {
    if (s2.lessOrEqual(s1)) return s1;
    else return s2;
    //return CPAOperators.mergeSep(s1, s2, precision);
  }

  @Override
  public Set<AbstractState> post(final AbstractState state, CFAEdge edge, Precision precision) {
    final RTLStatement statement = (RTLStatement)edge.getTransformer();
    final SignState s = (SignState)state;
   
    return statement.accept(new DefaultStatementVisitor<Set<AbstractState>>() {

      protected final Set<AbstractState> visitDefault(RTLStatement stmt) {
        return Collections.singleton(state);
      }
     
      @Override
      public Set<AbstractState> visit(RTLVariableAssignment stmt) {
        SignState post = new SignState(s);
        SignElement evaledRhs = s.abstractEval(stmt.getRightHandSide());
        post.setValue(stmt.getLeftHandSide(), evaledRhs);
        if (post.equals(s)) return Collections.singleton(state);
        return Collections.singleton((AbstractState)post);
      }

      @Override
      public Set<AbstractState> visit(RTLAssume stmt) {

        RTLExpression assumption = stmt.getAssumption();

        // First analysis to use yices, demo implementation
       
        Solver solver = Solver.createSolver();
        solver.addAssertion(s.getStateFormula());
        solver.addAssertion(assumption);

        if (!solver.isSatisfiable()) {
          logger.info("Infeasible CFA edge: " + stmt);
          return Collections.emptySet();
        }
       
        SignState post = new SignState(s);
        for (RTLVariable v : assumption.getUsedVariables()) {
          // Check if we can restrict this variable
          if (s.getValue(v).isTop()) {

            solver.push();
            RTLExpression f = ExpressionFactory.createLessOrEqual(v, ExpressionFactory.createNumber(0, v.getBitWidth()));
            solver.addAssertion(f);
            if (!solver.isSatisfiable()) {
              post.setValue(v, SignElement.POSITIVE);
              logger.debug("Restricting state from " + s + " through " + assumption + " to " + post);
            } else {
              solver.pop();
              solver.push();
              f = ExpressionFactory.createNot(ExpressionFactory.createEqual(v, ExpressionFactory.createNumber(0, v.getBitWidth())));
              solver.addAssertion(f);
              if (!solver.isSatisfiable()) {
                post.setValue(v, SignElement.ZERO);
                logger.debug("Restricting state from " + s + " through " + assumption + " to " + post);
              } else {
                solver.pop();
                solver.push();
                f = ExpressionFactory.createLessOrEqual(ExpressionFactory.createNumber(0, v.getBitWidth()), v);
                solver.addAssertion(f);
                if (!solver.isSatisfiable()) {
                  post.setValue(v, SignElement.NEGATIVE);
                  logger.debug("Restricting state from " + s + " through " + assumption + " to " + post);
                }
              }
            }
            solver.pop();
          }
        }
        return Collections.singleton((AbstractState)post);
       
        /*
        // Modify state so that it respects the assumption
        // We should really enumerate all solutions and create the corresponding states (requires different return type)
        // Currently works only for simple assumptions
        // Correct handling would be:
        // build state formula
        // add assumption formula
        // abstract all satisfying assignments of this formula into new state(s)
        //   or
        // get new state that most closely overapproximates the combined formula
        // (i) generate DNF from combined formula (ii) 1 state per clause
        // (iii) overapproximate each literal
        //   or
        // (i) abstract assumption into sign-logic, (ii) build new state from intersection
       
        if (assumption instanceof RTLOperation) {
          RTLOperation operation = (RTLOperation)assumption;
         
          switch (operation.getOperator()) {

          // assume(var = value)
          case EQUAL:
            if (operation.getOperands()[0] instanceof RTLVariable) {
              RTLVariable var = (RTLVariable)operation.getOperands()[0];

              if (operation.getOperands()[1] instanceof RTLNumber) {
                SignElement value = ((SignState)state).abstractEval(operation.getOperands()[1]);
                if (value.lessOrEqual(s.getValue(var))) {
                  logger.debug("Restricting state to " + var + " = " + value);
                  SignState post = new SignState((SignState)state);
                  post.setValue(var, value);
                  return Collections.singleton((AbstractState)post);
                } else {
                  logger.debug("Assume " + assumption + " infeasible at " + stmt.getLabel());
                  return Collections.emptySet();
                }
              }
            }
            break;

          // assume(var < value)
          case LESS:
            if (operation.getOperands()[0] instanceof RTLVariable) {
              RTLVariable var = (RTLVariable)operation.getOperands()[0];

              if (operation.getOperands()[1] instanceof RTLNumber) {
                SignElement value = ((SignState)state).abstractEval(operation.getOperands()[1]);
                if (value.equals(SignElement.NEGATIVE) || value.equals(SignElement.ZERO)) {
                  if (s.getValue(var).isTop() || s.getValue(var).equals(SignElement.NEGATIVE)) {
                    logger.debug("Restricting state to " + var + " = " + value);
                    SignState post = new SignState(s);
                    post.setValue(var, SignElement.NEGATIVE);
                    return Collections.singleton((AbstractState)post);
                  } else {
                    logger.debug("Assume " + assumption + " infeasible at " + stmt.getLabel());
                    logger.debug("State is " + s);
                    return Collections.emptySet();
                  }
                }
              }
            }
            break;

          // assume (!something)
          case NOT:
            if (operation.getOperands()[0] instanceof RTLOperation) {
              operation = (RTLOperation)operation.getOperands()[0];
             
              switch (operation.getOperator()) {
              case LESS:
                if (operation.getOperands()[0] instanceof RTLVariable) {
                  RTLVariable var = (RTLVariable)operation.getOperands()[0];

                  if (operation.getOperands()[1] instanceof RTLNumber) {
                    SignElement value = ((SignState)state).abstractEval(operation.getOperands()[1]);
                    if (value.equals(SignElement.NEGATIVE) || value.equals(SignElement.ZERO)) {
                      if (s.getValue(var).isTop() || s.getValue(var).equals(SignElement.NEGATIVE)) {
                        logger.debug("Restricting state to " + var + " != " + value);
                        Set<AbstractState> posts = new FastSet<AbstractState>();
                        SignState post = new SignState(s);
                        post.setValue(var, SignElement.ZERO);
                        posts.add(post);
                        post = new SignState(s);
                        post.setValue(var, SignElement.POSITIVE);
                        posts.add(post);
                        return posts;
                      } else {
                        logger.debug("Assume " + assumption + " infeasible at " + stmt.getLabel());
                        return Collections.emptySet();
                      }
                    }
                  }
                }
                break;
              }
             
            }
            break;
          }

        }
        return fallThroughState();*/
      }

      @Override
      public Set<AbstractState> visit(RTLUnknownProcedureCall stmt) {
        // Remove all information       
        return Collections.singleton((AbstractState)SignState.TOP);
      }
    });
  }

  @Override
  public AbstractState strengthen(AbstractState s, Iterable<AbstractState> otherStates,
      CFAEdge cfaEdge, Precision precision) {
    return s;
  }

  /*
   * @see org.jakstab.analysis.ConfigurableProgramAnalysis#prec(org.jakstab.analysis.AbstractState, org.jakstab.analysis.Precision, org.jakstab.analysis.ReachedSet)
   */
  @Override
  public Pair<AbstractState, Precision> prec(AbstractState s,
      Precision precision, ReachedSet reached) {
    return Pair.create(s, precision);
  }

  /*
   * @see org.jakstab.analysis.ConfigurableProgramAnalysis#stop(org.jakstab.analysis.AbstractState, org.jakstab.analysis.ReachedSet, org.jakstab.analysis.Precision)
   */
  @Override
  public boolean stop(AbstractState s, ReachedSet reached, Precision precision) {
    return CPAOperators.stopSep(s, reached, precision);
  }

}
TOP

Related Classes of org.jakstab.analysis.sign.SignAnalysis

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.