/*******************************************************************************
* Copyright (c) 2002 - 2006 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.ide.ui;
import java.util.Iterator;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.viewers.IStructuredSelection;
import com.ibm.wala.dataflow.IFDS.ISupergraph;
import com.ibm.wala.dataflow.IFDS.TabulationResult;
import com.ibm.wala.ipa.cfg.BasicBlockInContext;
import com.ibm.wala.ssa.SSAAbstractInvokeInstruction;
import com.ibm.wala.ssa.SSAGetInstruction;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.ssa.SSAPhiInstruction;
import com.ibm.wala.ssa.analysis.IExplodedBasicBlock;
import com.ibm.wala.util.WalaException;
import com.ibm.wala.util.Predicate;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.graph.Graph;
import com.ibm.wala.util.graph.GraphSlicer;
import com.ibm.wala.viz.DotUtil;
import com.ibm.wala.viz.NodeDecorator;
import com.ibm.wala.viz.PDFViewUtil;
/**
* An SWT action that spawns spawns a ghostview to see the local supergraph for a procedure node which is the current selection in a
* tree viewer.
*
* @author sfink
*/
public class ViewIFDSLocalAction<T, P, F> extends Action {
/**
* Governing tree viewer
*/
private final SWTTreeViewer viewer;
/**
* Governing supergraph
*/
private final ISupergraph<T, P> supergraph;
/**
* name of PDF file to generate
*/
private final String pdfFile;
/**
* name of dot file to generate
*/
private final String dotFile;
/**
* path to dot.exe
*/
private final String dotExe;
/**
* path to pdf view executable
*/
private final String pdfViewExe;
private final NodeDecorator labels;
public ViewIFDSLocalAction(SWTTreeViewer viewer, TabulationResult<T, P, F> result, String pdfFile, String dotFile, String dotExe,
String pdfViewExe, NodeDecorator labels) {
if (result == null) {
throw new IllegalArgumentException("null result");
}
this.viewer = viewer;
this.supergraph = result.getProblem().getSupergraph();
this.pdfFile = pdfFile;
this.dotFile = dotFile;
this.dotExe = dotExe;
this.pdfViewExe = pdfViewExe;
this.labels = labels;
setText("View Local Supergraph");
}
public ViewIFDSLocalAction(SWTTreeViewer viewer, TabulationResult<T, P, F> result, String psFile, String dotFile, String dotExe,
String gvExe) {
if (result == null) {
throw new IllegalArgumentException("null result");
}
this.viewer = viewer;
this.supergraph = result.getProblem().getSupergraph();
this.pdfFile = psFile;
this.dotFile = dotFile;
this.dotExe = dotExe;
this.pdfViewExe = gvExe;
this.labels = new Labels<T, P, F>(result);
setText("View Local Supergraph");
}
private static class Labels<T, P, F> implements NodeDecorator {
private TabulationResult<T, P, F> result;
Labels(TabulationResult<T, P, F> result) {
this.result = result;
}
@Override
@SuppressWarnings("unchecked")
public String getLabel(Object o) throws WalaException {
T t = (T) o;
if (t instanceof BasicBlockInContext) {
BasicBlockInContext bb = (BasicBlockInContext) t;
if (bb.getDelegate() instanceof IExplodedBasicBlock) {
IExplodedBasicBlock delegate = (IExplodedBasicBlock) bb.getDelegate();
String s = delegate.getNumber() + " " + result.getResult(t) + "\\n" + stringify(delegate.getInstruction());
for (Iterator<SSAPhiInstruction> phis = delegate.iteratePhis(); phis.hasNext();) {
SSAPhiInstruction phi = phis.next();
s += " " + phi;
}
if (delegate.isCatchBlock()) {
s += " " + delegate.getCatchInstruction();
}
return s;
}
}
return t + " " + result.getResult(t);
}
}
/**
* Print a short-ish representation of s as a String
*/
public static String stringify(SSAInstruction s) {
if (s == null) {
return null;
}
if (s instanceof SSAAbstractInvokeInstruction) {
SSAAbstractInvokeInstruction call = (SSAAbstractInvokeInstruction) s;
String def = call.hasDef() ? Integer.valueOf(call.getDef()) + "=" : "";
String result = def + "call " + call.getDeclaredTarget().getDeclaringClass().getName().getClassName() + "."
+ call.getDeclaredTarget().getName();
result += " exc:" + call.getException();
for (int i = 0; i < s.getNumberOfUses(); i++) {
result += " ";
result += s.getUse(i);
}
return result;
}
if (s instanceof SSAGetInstruction) {
SSAGetInstruction g = (SSAGetInstruction) s;
String fieldName = g.getDeclaredField().getName().toString();
StringBuffer result = new StringBuffer();
result.append(g.getDef());
result.append(":=");
result.append(g.isStatic() ? "getstatic " : "getfield ");
result.append(fieldName);
if (!g.isStatic()) {
result.append(" ");
result.append(g.getUse(0));
}
return result.toString();
}
return s.toString();
}
/*
* @see org.eclipse.jface.action.IAction#run()
*/
@Override
public void run() {
try {
final P proc = getProcedureForSelection();
Predicate<T> filter = new Predicate<T>() {
@Override public boolean test(T o) {
return supergraph.getProcOf(o).equals(proc);
}
};
Graph<T> localGraph = GraphSlicer.prune(supergraph, filter);
// spawn the viewer
System.err.println("Spawn Viewer for " + proc);
DotUtil.dotify(localGraph, labels, dotFile, pdfFile, dotExe);
if (DotUtil.getOutputType() == DotUtil.DotOutputType.PDF) {
PDFViewUtil.launchPDFView(pdfFile, pdfViewExe);
}
} catch (WalaException e) {
e.printStackTrace();
Assertions.UNREACHABLE();
}
}
@SuppressWarnings("unchecked")
protected P getProcedureForSelection() {
// we assume the tree viewer's current selection is a P
IStructuredSelection selection = viewer.getSelection();
if (selection.size() != 1) {
throw new UnsupportedOperationException("did not expect selection of size " + selection.size());
}
P first = (P) selection.getFirstElement();
return first;
}
protected SWTTreeViewer getViewer() {
return viewer;
}
protected ISupergraph<T, P> getSupergraph() {
return supergraph;
}
protected String getDotExe() {
return dotExe;
}
protected String getDotFile() {
return dotFile;
}
protected String getGvExe() {
return pdfViewExe;
}
protected String getPsFile() {
return pdfFile;
}
}