org.sosy_lab.cpachecker.cpa.smg.refiner.SMGPrecision.java Source code

Java tutorial

Introduction

Here is the source code for org.sosy_lab.cpachecker.cpa.smg.refiner.SMGPrecision.java

Source

/*
 *  CPAchecker is a tool for configurable software verification.
 *  This file is part of CPAchecker.
 *
 *  Copyright (C) 2007-2016  Dirk Beyer
 *  All rights reserved.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *
 *  CPAchecker web page:
 *    http://cpachecker.sosy-lab.org
 */
package org.sosy_lab.cpachecker.cpa.smg.refiner;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.SetMultimap;

import org.sosy_lab.common.log.LogManager;
import org.sosy_lab.cpachecker.cfa.model.CFANode;
import org.sosy_lab.cpachecker.core.interfaces.Precision;
import org.sosy_lab.cpachecker.cpa.smg.SMGAbstractionBlock;
import org.sosy_lab.cpachecker.cpa.smg.refiner.SMGInterpolant.SMGPrecisionIncrement;
import org.sosy_lab.cpachecker.util.predicates.BlockOperator;
import org.sosy_lab.cpachecker.util.states.MemoryLocation;

import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public abstract class SMGPrecision implements Precision {

    private final SMGPrecisionAbstractionOptions options;
    private final BlockOperator blockOperator;
    private final LogManager logger;
    private final int threshold = 0;

    public SMGPrecision(LogManager pLogger, SMGPrecisionAbstractionOptions pOptions, BlockOperator pBlockOperator) {
        logger = pLogger;
        options = pOptions;
        blockOperator = pBlockOperator;
    }

    public static SMGPrecision createStaticPrecision(boolean pEnableHeapAbstraction, LogManager pLogger,
            BlockOperator pBlockOperator) {
        SMGPrecisionAbstractionOptions options = new SMGPrecisionAbstractionOptions(pEnableHeapAbstraction, false,
                false);
        return new SMGStaticPrecision(pLogger, options, pBlockOperator);
    }

    public abstract Precision withIncrement(Map<CFANode, SMGPrecisionIncrement> pPrecisionIncrement);

    public abstract SMGPrecision join(SMGPrecision pPrecision);

    public static SMGPrecision createRefineablePrecision(SMGPrecision pPrecision) {

        SetMultimap<CFANode, SMGMemoryPath> emptyMemoryPaths = ImmutableSetMultimap.of();
        SetMultimap<CFANode, SMGAbstractionBlock> emptyAbstractionBlocks = ImmutableSetMultimap.of();
        SetMultimap<CFANode, MemoryLocation> emptyStackVariable = ImmutableSetMultimap.of();

        return new SMGRefineablePrecision(pPrecision.logger,
                new SMGPrecisionAbstractionOptions(pPrecision.allowsHeapAbstraction(), true, true),
                pPrecision.getBlockOperator(), emptyMemoryPaths, emptyAbstractionBlocks, emptyStackVariable);
    }

    public LogManager getLogger() {
        return logger;
    }

    public abstract boolean isTracked(SMGMemoryPath pPath, CFANode pCfaNode);

    public abstract Set<SMGMemoryPath> getTrackedMemoryPathsOnNode(CFANode pCfaNode);

    public abstract Set<MemoryLocation> getTrackedStackVariablesOnNode(CFANode pCfaNode);

    public abstract boolean usesHeapInterpoaltion();

    public boolean allowsHeapAbstractionOnNode(CFANode pCfaNode) {
        return options.allowsHeapAbstraction() && blockOperator.isBlockEnd(pCfaNode, threshold);
    }

    public final boolean allowsHeapAbstraction() {
        return options.allowsHeapAbstraction();
    }

    public final boolean allowsFieldAbstraction() {
        return options.allowsFieldAbstraction();
    }

    public final boolean allowsStackAbstraction() {
        return options.allowsStackAbstraction();
    }

    protected SMGPrecisionAbstractionOptions getAbstractionOptions() {
        return options;
    }

    public BlockOperator getBlockOperator() {
        return blockOperator;
    }

    public abstract Set<SMGAbstractionBlock> getAbstractionBlocks(CFANode location);

    private static class SMGRefineablePrecision extends SMGPrecision {

        private final ImmutableSetMultimap<CFANode, SMGMemoryPath> trackedMemoryPaths;
        private final ImmutableSetMultimap<CFANode, MemoryLocation> trackedStackVariables;
        private final ImmutableSetMultimap<CFANode, SMGAbstractionBlock> abstractionBlocks;

        private SMGRefineablePrecision(LogManager pLogger, SMGPrecisionAbstractionOptions pOptions,
                BlockOperator pBlockOperator, SetMultimap<CFANode, SMGMemoryPath> pTrackedMemoryPaths,
                SetMultimap<CFANode, SMGAbstractionBlock> pAbstractionBlocks,
                SetMultimap<CFANode, MemoryLocation> pTrackedStackVariables) {
            super(pLogger, pOptions, pBlockOperator);
            trackedMemoryPaths = ImmutableSetMultimap.copyOf(pTrackedMemoryPaths);
            abstractionBlocks = ImmutableSetMultimap.copyOf(pAbstractionBlocks);
            trackedStackVariables = ImmutableSetMultimap.copyOf(pTrackedStackVariables);
        }

        @Override
        public boolean usesHeapInterpoaltion() {
            return allowsHeapAbstraction();
        }

        @Override
        public Set<SMGMemoryPath> getTrackedMemoryPathsOnNode(CFANode pLocationNode) {
            if (trackedMemoryPaths.containsKey(pLocationNode)) {
                return trackedMemoryPaths.get(pLocationNode);
            } else {
                return ImmutableSet.of();
            }
        }

        @Override
        public Set<MemoryLocation> getTrackedStackVariablesOnNode(CFANode pCfaNode) {
            if (trackedStackVariables.containsKey(pCfaNode)) {
                return trackedStackVariables.get(pCfaNode);
            } else {
                return ImmutableSet.of();
            }
        }

        @Override
        public Precision withIncrement(Map<CFANode, SMGPrecisionIncrement> pPrecisionIncrement) {

            SetMultimap<CFANode, SMGMemoryPath> resultMemoryPaths = HashMultimap.create();
            resultMemoryPaths.putAll(trackedMemoryPaths);
            SetMultimap<CFANode, MemoryLocation> resultStackVariables = HashMultimap.create();
            resultStackVariables.putAll(trackedStackVariables);
            SetMultimap<CFANode, SMGAbstractionBlock> resultAbstractionBlocks = HashMultimap.create();
            resultAbstractionBlocks.putAll(abstractionBlocks);

            for (Entry<CFANode, SMGPrecisionIncrement> entry : pPrecisionIncrement.entrySet()) {
                SMGPrecisionIncrement inc = entry.getValue();
                CFANode cfaNode = entry.getKey();
                Collection<SMGAbstractionBlock> incAbstractionBlocks = inc.getAbstractionBlock();
                Collection<SMGMemoryPath> incMemoryPaths = inc.getPathsToTrack();
                Collection<MemoryLocation> incStackVariables = inc.getStackVariablesToTrack();
                resultAbstractionBlocks.putAll(cfaNode, incAbstractionBlocks);
                resultMemoryPaths.putAll(cfaNode, incMemoryPaths);
                resultStackVariables.putAll(cfaNode, incStackVariables);
            }

            return new SMGRefineablePrecision(getLogger(), getAbstractionOptions(), getBlockOperator(),
                    resultMemoryPaths, resultAbstractionBlocks, resultStackVariables);
        }

        @Override
        public SMGPrecision join(SMGPrecision pPrecision) {

            if (pPrecision instanceof SMGStaticPrecision) {
                return pPrecision;
            }

            SMGRefineablePrecision other = (SMGRefineablePrecision) pPrecision;

            SetMultimap<CFANode, SMGMemoryPath> resultMemoryPaths = HashMultimap.create();
            resultMemoryPaths.putAll(trackedMemoryPaths);
            resultMemoryPaths.putAll(other.trackedMemoryPaths);
            SetMultimap<CFANode, MemoryLocation> resultStackVariables = HashMultimap.create();
            resultStackVariables.putAll(trackedStackVariables);
            resultStackVariables.putAll(other.trackedStackVariables);
            SetMultimap<CFANode, SMGAbstractionBlock> resultAbstractionBlocks = HashMultimap.create();
            resultAbstractionBlocks.putAll(abstractionBlocks);
            resultAbstractionBlocks.putAll(other.abstractionBlocks);

            assert getAbstractionOptions().equals(pPrecision.getAbstractionOptions());

            return new SMGRefineablePrecision(getLogger(), getAbstractionOptions(), getBlockOperator(),
                    resultMemoryPaths, resultAbstractionBlocks, resultStackVariables);
        }

        @Override
        public boolean isTracked(SMGMemoryPath pPath, CFANode pCfaNode) {

            if (trackedMemoryPaths.containsKey(pCfaNode)) {
                Set<SMGMemoryPath> trackedMemPaths = trackedMemoryPaths.get(pCfaNode);
                return trackedMemPaths.contains(pPath);
            } else {
                return false;
            }
        }

        @Override
        public Set<SMGAbstractionBlock> getAbstractionBlocks(CFANode location) {
            return abstractionBlocks.get(location);
        }

        @Override
        public String toString() {
            return "SMGRefineablePrecision [trackedMemoryPaths=" + trackedMemoryPaths + ", trackedStackVariables="
                    + trackedStackVariables + ", abstractionBlocks=" + abstractionBlocks + "]";
        }
    }

    private static class SMGStaticPrecision extends SMGPrecision {

        private SMGStaticPrecision(LogManager pLogger, SMGPrecisionAbstractionOptions pAllowsHeapAbstraction,
                BlockOperator pBlockOperator) {
            super(pLogger, pAllowsHeapAbstraction, pBlockOperator);
        }

        @Override
        public boolean usesHeapInterpoaltion() {
            return false;
        }

        @Override
        public boolean isTracked(SMGMemoryPath pPath, CFANode pCfaNode) {
            return true;
        }

        @Override
        public Precision withIncrement(Map<CFANode, SMGPrecisionIncrement> pPrecisionIncrement) {
            return this;
        }

        @Override
        public SMGPrecision join(SMGPrecision pPrecision) {
            return this;
        }

        @Override
        public Set<SMGAbstractionBlock> getAbstractionBlocks(CFANode pLocation) {
            return ImmutableSet.of();
        }

        @Override
        public Set<SMGMemoryPath> getTrackedMemoryPathsOnNode(CFANode pCfaNode) {
            throw new UnsupportedOperationException("Method not yet implemented.");
        }

        @Override
        public Set<MemoryLocation> getTrackedStackVariablesOnNode(CFANode pCfaNode) {
            throw new UnsupportedOperationException("Method not yet implemented.");
        }

        @Override
        public String toString() {
            return "Static precision " + getAbstractionOptions().toString();
        }
    }

    private static final class SMGPrecisionAbstractionOptions {

        private final boolean heapAbstraction;
        private final boolean fieldAbstraction;
        private final boolean stackAbstraction;

        public SMGPrecisionAbstractionOptions(boolean pHeapAbstraction, boolean pFieldAbstraction,
                boolean pStackAbstraction) {
            super();
            heapAbstraction = pHeapAbstraction;
            fieldAbstraction = pFieldAbstraction;
            stackAbstraction = pStackAbstraction;
        }

        public boolean allowsHeapAbstraction() {
            return heapAbstraction;
        }

        public boolean allowsFieldAbstraction() {
            return fieldAbstraction;
        }

        public boolean allowsStackAbstraction() {
            return stackAbstraction;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + (fieldAbstraction ? 1231 : 1237);
            result = prime * result + (heapAbstraction ? 1231 : 1237);
            result = prime * result + (stackAbstraction ? 1231 : 1237);
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            SMGPrecisionAbstractionOptions other = (SMGPrecisionAbstractionOptions) obj;
            if (fieldAbstraction != other.fieldAbstraction) {
                return false;
            }
            if (heapAbstraction != other.heapAbstraction) {
                return false;
            }
            if (stackAbstraction != other.stackAbstraction) {
                return false;
            }
            return true;
        }

        @Override
        public String toString() {
            return "SMGPrecisionAbstractionOptions [heapAbstraction=" + heapAbstraction + ", fieldAbstraction="
                    + fieldAbstraction + ", stackAbstraction=" + stackAbstraction + "]";
        }
    }
}