189 lines
6.3 KiB
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();
|
|
}
|
|
|
|
}
|