WALA/com.ibm.wala.core/src/com/ibm/wala/cfg/exc/inter/IntraprocAnalysisState.java

189 lines
6.3 KiB
Java

/******************************************************************************
* Copyright (c) 2002 - 2014 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*****************************************************************************/
package com.ibm.wala.cfg.exc.inter;
import java.util.HashMap;
import com.ibm.wala.cfg.ControlFlowGraph;
import com.ibm.wala.cfg.exc.ExceptionPruningAnalysis;
import com.ibm.wala.cfg.exc.intra.NullPointerState;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ssa.SSAAbstractInvokeInstruction;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.ssa.SymbolTable;
import com.ibm.wala.ssa.analysis.IExplodedBasicBlock;
import com.ibm.wala.util.CancelException;
import com.ibm.wala.util.MonitorUtil.IProgressMonitor;
import com.ibm.wala.util.graph.GraphIntegrity.UnsoundGraphException;
/**
* Saves interprocedural state of a single method.
*
* This class has been developed as part of a student project "Studienarbeit" by Markus Herhoffer.
* It has been adapted and integrated into the WALA project by Juergen Graf.
*
* @author Markus Herhoffer <markus.herhoffer@student.kit.edu>
* @author Juergen Graf <graf@kit.edu>
*
*/
final class IntraprocAnalysisState implements ExceptionPruningAnalysis<SSAInstruction, IExplodedBasicBlock> {
private final ControlFlowGraph<SSAInstruction, IExplodedBasicBlock> cfg;
private final HashMap<IExplodedBasicBlock, NullPointerState> statesOfSsaVars =
new HashMap<IExplodedBasicBlock, NullPointerState>();
private final HashMap<IExplodedBasicBlock, Object[]> valuesOfSsaVars = new HashMap<IExplodedBasicBlock, Object[]>();
private final HashMap<IExplodedBasicBlock, int[]> numbersOfSsaVarsThatAreParemerters =
new HashMap<IExplodedBasicBlock, int[]>();
private final boolean noAnalysisPossible;
private final int deletedEdges;
private boolean throwsException = true;
/**
* Constructor for the state of a method that has not been analyzed. These are methods with an empty IR or methods
* left out explicitly.
*
* Use it if you have nothing to tell about the node.
*/
IntraprocAnalysisState() {
this.cfg = null;
this.noAnalysisPossible = true;
this.deletedEdges = 0;
}
/**
* Constructor if you have informations on the node.
*
* All values are saved at construction time. So if the analysis changes
* anything after this OptimizationInfo was created, it won't affect its final
* attributes.
*
* @param intra
* The <code>node</code>'s intraprocedural analysis
* @param node
* the node itself
* @throws UnsoundGraphException
* @throws CancelException
*/
IntraprocAnalysisState(final ExceptionPruningAnalysis<SSAInstruction, IExplodedBasicBlock> intra, final CGNode node,
final ControlFlowGraph<SSAInstruction, IExplodedBasicBlock> cfg, final int deletedEdges)
throws UnsoundGraphException, CancelException {
this.cfg = cfg;
this.noAnalysisPossible = false;
this.deletedEdges = deletedEdges;
final SymbolTable sym = node.getIR().getSymbolTable();
for (final IExplodedBasicBlock block : cfg) {
// set states
final NullPointerState state = intra.getState(block);
this.statesOfSsaVars.put(block, state);
// set values
if (block.getInstruction() != null) {
final int numberOfSSAVars = block.getInstruction().getNumberOfUses();
final Object[] values = new Object[numberOfSSAVars];
for (int j = 0; j < numberOfSSAVars; j++) {
final boolean isContant = sym.isConstant(j);
values[j] = (isContant ? sym.getConstantValue(j) : null);
}
this.valuesOfSsaVars.put(block, values);
} else {
this.valuesOfSsaVars.put(block, null);
}
// set nr. of parameters
if (block.getInstruction() instanceof SSAAbstractInvokeInstruction) {
final SSAAbstractInvokeInstruction instr = (SSAAbstractInvokeInstruction) block.getInstruction();
final int[] numbersOfParams = AnalysisUtil.getParameterNumbers(instr);
this.numbersOfSsaVarsThatAreParemerters.put(block, numbersOfParams);
} else {
// default to null
this.numbersOfSsaVarsThatAreParemerters.put(block, null);
}
}
}
@Override
public int compute(IProgressMonitor progress) throws UnsoundGraphException, CancelException {
return deletedEdges;
}
@Override
public NullPointerState getState(final IExplodedBasicBlock block) {
if (noAnalysisPossible) {
throw new IllegalStateException();
}
return statesOfSsaVars.get(block);
}
public Object[] getValues(final IExplodedBasicBlock block) {
if (noAnalysisPossible) {
throw new IllegalStateException();
}
return valuesOfSsaVars.get(block);
}
public int[] getInjectedParameters(final IExplodedBasicBlock block) {
if (noAnalysisPossible) {
throw new IllegalStateException();
} else if (!((block.getInstruction() instanceof SSAAbstractInvokeInstruction))) {
throw new IllegalArgumentException();
}
assert (block.getInstruction() instanceof SSAAbstractInvokeInstruction);
return numbersOfSsaVarsThatAreParemerters.get(block);
}
/**
* Returns the CFG.
*
* @return the CFG or null if there is no CFG for the CGNode.
*/
@Override
public ControlFlowGraph<SSAInstruction, IExplodedBasicBlock> getCFG() {
return (noAnalysisPossible ? null : this.cfg);
}
public boolean canBeAnalyzed() {
return !noAnalysisPossible;
}
public void setHasExceptions(final boolean throwsException) {
this.throwsException = throwsException;
}
@Override
public boolean hasExceptions() {
return throwsException;
}
@Override
public String toString() {
if (noAnalysisPossible) {
return "";
}
final String ls = System.getProperty("line.separator");
final StringBuffer output = new StringBuffer();
output.append(statesOfSsaVars.toString() + ls);
output.append(valuesOfSsaVars.toString() + ls);
output.append(numbersOfSsaVarsThatAreParemerters.toString());
return output.toString();
}
}