All Downloads are FREE. Search and download functionalities are using the official Maven repository.

it.unive.lisa.analysis.dataflow.ConstantPropagation Maven / Gradle / Ivy

The newest version!
package it.unive.lisa.analysis.dataflow;

import it.unive.lisa.analysis.ScopeToken;
import it.unive.lisa.analysis.SemanticException;
import it.unive.lisa.program.cfg.ProgramPoint;
import it.unive.lisa.symbolic.SymbolicExpression;
import it.unive.lisa.symbolic.value.BinaryExpression;
import it.unive.lisa.symbolic.value.Constant;
import it.unive.lisa.symbolic.value.Identifier;
import it.unive.lisa.symbolic.value.OutOfScopeIdentifier;
import it.unive.lisa.symbolic.value.UnaryExpression;
import it.unive.lisa.symbolic.value.ValueExpression;
import it.unive.lisa.symbolic.value.operator.AdditionOperator;
import it.unive.lisa.symbolic.value.operator.DivisionOperator;
import it.unive.lisa.symbolic.value.operator.ModuloOperator;
import it.unive.lisa.symbolic.value.operator.MultiplicationOperator;
import it.unive.lisa.symbolic.value.operator.SubtractionOperator;
import it.unive.lisa.symbolic.value.operator.unary.NumericNegation;
import it.unive.lisa.util.representation.ListRepresentation;
import it.unive.lisa.util.representation.StringRepresentation;
import it.unive.lisa.util.representation.StructuredRepresentation;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
 * An implementation of the overflow-insensitive constant propagation dataflow
 * analysis, that focuses only on integers.
 * 
 * @author Luca Negrini
 */
public class ConstantPropagation
		implements
		DataflowElement, ConstantPropagation> {

	private final Identifier id;
	private final Integer constant;

	/**
	 * Builds an empty constant propagation object.
	 */
	public ConstantPropagation() {
		this(null, null);
	}

	/**
	 * Builds the new constant propagation object.
	 * 
	 * @param id the constant variable
	 * @param v  the constant value
	 */
	public ConstantPropagation(
			Identifier id,
			Integer v) {
		this.id = id;
		this.constant = v;
	}

	@Override
	public String toString() {
		return representation().toString();
	}

	@Override
	public Collection getInvolvedIdentifiers() {
		return Collections.singleton(id);
	}

	private static Integer eval(
			SymbolicExpression e,
			DefiniteDataflowDomain domain) {

		if (e instanceof Constant) {
			Constant c = (Constant) e;
			return c.getValue() instanceof Integer ? (Integer) c.getValue() : null;
		}

		if (e instanceof Identifier) {
			for (ConstantPropagation cp : domain.getDataflowElements())
				if (cp.id.equals(e))
					return cp.constant;

			return null;
		}

		if (e instanceof UnaryExpression) {
			UnaryExpression unary = (UnaryExpression) e;
			Integer i = eval(unary.getExpression(), domain);

			if (i == null)
				return i;

			if (unary.getOperator() == NumericNegation.INSTANCE)
				return -i;
		}

		if (e instanceof BinaryExpression) {
			BinaryExpression binary = (BinaryExpression) e;
			Integer right = eval(binary.getRight(), domain);
			Integer left = eval(binary.getLeft(), domain);

			if (right == null || left == null)
				return null;

			if (binary.getOperator() instanceof AdditionOperator)
				return left + right;
			if (binary.getOperator() instanceof DivisionOperator)
				return left == 0 ? null : (int) left / right;
			if (binary.getOperator() instanceof ModuloOperator)
				return right == 0 ? null : left % right;
			if (binary.getOperator() instanceof MultiplicationOperator)
				return left * right;
			if (binary.getOperator() instanceof SubtractionOperator)
				return left - right;
		}

		return null;
	}

	@Override
	public Collection gen(
			Identifier id,
			ValueExpression expression,
			ProgramPoint pp,
			DefiniteDataflowDomain domain) {
		Set gen = new HashSet<>();

		Integer v = eval(expression, domain);
		if (v != null)
			gen.add(new ConstantPropagation(id, v));

		return gen;
	}

	@Override
	public Collection gen(
			ValueExpression expression,
			ProgramPoint pp,
			DefiniteDataflowDomain domain) {
		return Collections.emptyList();
	}

	@Override
	public Collection kill(
			Identifier id,
			ValueExpression expression,
			ProgramPoint pp,
			DefiniteDataflowDomain domain) {
		Collection result = new HashSet<>();

		for (ConstantPropagation cp : domain.getDataflowElements())
			if (cp.id.equals(id))
				result.add(cp);

		return result;
	}

	@Override
	public Collection kill(
			ValueExpression expression,
			ProgramPoint pp,
			DefiniteDataflowDomain domain) {
		return Collections.emptyList();
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		result = prime * result + ((constant == null) ? 0 : constant.hashCode());
		return result;
	}

	@Override
	public boolean equals(
			Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		ConstantPropagation other = (ConstantPropagation) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		if (constant == null) {
			if (other.constant != null)
				return false;
		} else if (!constant.equals(other.constant))
			return false;
		return true;
	}

	@Override
	public StructuredRepresentation representation() {
		return new ListRepresentation(new StringRepresentation(id), new StringRepresentation(constant));
	}

	@Override
	public ConstantPropagation pushScope(
			ScopeToken scope)
			throws SemanticException {
		return new ConstantPropagation((Identifier) id.pushScope(scope), constant);
	}

	@Override
	public ConstantPropagation popScope(
			ScopeToken scope)
			throws SemanticException {
		if (!(id instanceof OutOfScopeIdentifier))
			return this;

		return new ConstantPropagation(((OutOfScopeIdentifier) id).popScope(scope), constant);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy