some generics
git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@692 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
parent
e89006e2c9
commit
a92bff31bb
|
@ -62,7 +62,7 @@ public class AstCallGraph extends ExplicitCallGraph {
|
|||
}
|
||||
|
||||
class AstCGNode extends ExplicitNode {
|
||||
private Set callbacks;
|
||||
private Set<Function> callbacks;
|
||||
|
||||
private AstCGNode(IMethod method, Context context) {
|
||||
super(method, context);
|
||||
|
@ -73,8 +73,8 @@ public class AstCallGraph extends ExplicitCallGraph {
|
|||
boolean done = false;
|
||||
while (!done) {
|
||||
try {
|
||||
for (Iterator x = callbacks.iterator(); x.hasNext();) {
|
||||
((Function) x.next()).apply(null);
|
||||
for (Iterator<Function> x = callbacks.iterator(); x.hasNext();) {
|
||||
x.next().apply(null);
|
||||
}
|
||||
} catch (ConcurrentModificationException e) {
|
||||
done = false;
|
||||
|
@ -87,12 +87,12 @@ public class AstCallGraph extends ExplicitCallGraph {
|
|||
|
||||
public void addCallback(Function callback) {
|
||||
if (callbacks == null)
|
||||
callbacks = new HashSet(1);
|
||||
callbacks = new HashSet<Function>(1);
|
||||
callbacks.add(callback);
|
||||
}
|
||||
|
||||
private void fireCallbacksTransitive() {
|
||||
for(Iterator nodes = DFS.iterateFinishTime(AstCallGraph.this, new NonNullSingletonIterator<CGNode>(this));
|
||||
for(Iterator<CGNode> nodes = DFS.iterateFinishTime(AstCallGraph.this, new NonNullSingletonIterator<CGNode>(this));
|
||||
nodes.hasNext(); )
|
||||
{
|
||||
((AstCGNode)nodes.next()).fireCallbacks();
|
||||
|
|
|
@ -10,17 +10,20 @@
|
|||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.ipa.callgraph;
|
||||
|
||||
import com.ibm.wala.cast.loader.*;
|
||||
import com.ibm.wala.classLoader.*;
|
||||
import com.ibm.wala.ipa.callgraph.*;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.cfa.*;
|
||||
import com.ibm.wala.ipa.cha.*;
|
||||
import com.ibm.wala.ssa.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.ibm.wala.cast.loader.AstMethod;
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisOptions;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.Context;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.cfa.ContextInsensitiveSSAInterpreter;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.util.collections.EmptyIterator;
|
||||
import com.ibm.wala.util.warnings.WarningSet;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class AstContextInsensitiveSSAContextInterpreter
|
||||
extends ContextInsensitiveSSAInterpreter
|
||||
{
|
||||
|
@ -33,7 +36,7 @@ public class AstContextInsensitiveSSAContextInterpreter
|
|||
return method instanceof AstMethod;
|
||||
}
|
||||
|
||||
public Iterator iterateCallSites(CGNode N, WarningSet warnings) {
|
||||
public Iterator<CallSiteReference> iterateCallSites(CGNode N, WarningSet warnings) {
|
||||
IR ir = getIR(N, warnings);
|
||||
if (ir == null) {
|
||||
return EmptyIterator.instance();
|
||||
|
|
|
@ -16,9 +16,9 @@ import java.util.*;
|
|||
|
||||
public interface AstPointerKeyFactory extends PointerKeyFactory {
|
||||
|
||||
Iterator getPointerKeysForReflectedFieldRead(InstanceKey I, InstanceKey F);
|
||||
Iterator<PointerKey> getPointerKeysForReflectedFieldRead(InstanceKey I, InstanceKey F);
|
||||
|
||||
Iterator getPointerKeysForReflectedFieldWrite(InstanceKey I, InstanceKey F);
|
||||
Iterator<PointerKey> getPointerKeysForReflectedFieldWrite(InstanceKey I, InstanceKey F);
|
||||
|
||||
PointerKey getPointerKeyForObjectCatalog(InstanceKey I);
|
||||
|
||||
|
|
|
@ -105,14 +105,14 @@ public abstract class AstSSAPropagationCallGraphBuilder
|
|||
.getPointerKeyForObjectCatalog(I);
|
||||
}
|
||||
|
||||
public Iterator
|
||||
public Iterator<PointerKey>
|
||||
getPointerKeysForReflectedFieldRead(InstanceKey I, InstanceKey F)
|
||||
{
|
||||
return ((AstPointerKeyFactory)pointerKeyFactory)
|
||||
.getPointerKeysForReflectedFieldRead(I, F);
|
||||
}
|
||||
|
||||
public Iterator
|
||||
public Iterator<PointerKey>
|
||||
getPointerKeysForReflectedFieldWrite(InstanceKey I, InstanceKey F)
|
||||
{
|
||||
return ((AstPointerKeyFactory)pointerKeyFactory)
|
||||
|
@ -290,10 +290,10 @@ public abstract class AstSSAPropagationCallGraphBuilder
|
|||
if (AstTranslator.DEBUG_LEXICAL)
|
||||
Trace.println("looking up lexical parent " + definer);
|
||||
|
||||
for(Iterator DS = getLexicalDefiners(node, definer).iterator();
|
||||
for(Iterator<CGNode> DS = getLexicalDefiners(node, definer).iterator();
|
||||
DS.hasNext(); )
|
||||
{
|
||||
final CGNode D = (CGNode) DS.next();
|
||||
final CGNode D = DS.next();
|
||||
|
||||
Iterator PS = new NumberedDFSDiscoverTimeIterator(callGraph, node) {
|
||||
/**
|
||||
|
@ -346,12 +346,12 @@ public abstract class AstSSAPropagationCallGraphBuilder
|
|||
public int hashCode() { return System.identityHashCode(this); }
|
||||
}
|
||||
|
||||
private Set getLexicalDefiners(final CGNode opNode, final String definer) {
|
||||
private Set<CGNode> getLexicalDefiners(final CGNode opNode, final String definer) {
|
||||
if (definer == null) {
|
||||
return Collections.singleton(callGraph.getFakeRootNode());
|
||||
|
||||
} else {
|
||||
final Set result = new HashSet();
|
||||
final Set<CGNode> result = new HashSet<CGNode>();
|
||||
PointerKey F = getPointerKeyForLocal(opNode, 1);
|
||||
|
||||
IR ir = getCFAContextInterpreter().getIR(opNode, getWarnings());
|
||||
|
@ -391,7 +391,7 @@ public abstract class AstSSAPropagationCallGraphBuilder
|
|||
if (a == null) return b==null; else return a.equals(b);
|
||||
}
|
||||
|
||||
private Set discoveredUpwardFunargs = new HashSet();
|
||||
private Set<PointerKey> discoveredUpwardFunargs = new HashSet<PointerKey>();
|
||||
|
||||
private void addUpwardFunargConstraints(PointerKey lhs,
|
||||
String name,
|
||||
|
@ -680,21 +680,21 @@ public abstract class AstSSAPropagationCallGraphBuilder
|
|||
PointerKey objCatalog = getPointerKeyForObjectCatalog(objKeys[o]);
|
||||
for(int f = 0; f < fieldsKeys.length; f++) {
|
||||
if (isLoadOperation) {
|
||||
for(Iterator keys =
|
||||
for(Iterator<PointerKey> keys =
|
||||
getPointerKeysForReflectedFieldRead(objKeys[o], fieldsKeys[f]);
|
||||
keys.hasNext(); )
|
||||
{
|
||||
PointerKey key = (PointerKey)keys.next();
|
||||
PointerKey key = keys.next();
|
||||
if (DEBUG_PROPERTIES) action.dump( key, true, true );
|
||||
action.action( key );
|
||||
}
|
||||
} else {
|
||||
system.newConstraint(objCatalog, fieldsKeys[f]);
|
||||
for(Iterator keys =
|
||||
for(Iterator<PointerKey> keys =
|
||||
getPointerKeysForReflectedFieldWrite(objKeys[o],fieldsKeys[f]);
|
||||
keys.hasNext(); )
|
||||
{
|
||||
PointerKey key = (PointerKey)keys.next();
|
||||
PointerKey key = keys.next();
|
||||
if (DEBUG_PROPERTIES) action.dump( key, true, true );
|
||||
action.action( key );
|
||||
}
|
||||
|
@ -768,21 +768,21 @@ public abstract class AstSSAPropagationCallGraphBuilder
|
|||
getPointerKeyForObjectCatalog(object);
|
||||
for(int f = 0; f < fieldsKeys.length; f++) {
|
||||
if (isLoadOperation) {
|
||||
for(Iterator keys =
|
||||
for(Iterator<PointerKey> keys =
|
||||
getPointerKeysForReflectedFieldRead(object, fieldsKeys[f]);
|
||||
keys.hasNext(); )
|
||||
{
|
||||
PointerKey key = (PointerKey)keys.next();
|
||||
PointerKey key = keys.next();
|
||||
if (DEBUG_PROPERTIES) action.dump(key, true, false);
|
||||
action.action( key );
|
||||
}
|
||||
} else {
|
||||
system.newConstraint(objCatalog, fieldsKeys[f]);
|
||||
for(Iterator keys =
|
||||
for(Iterator<PointerKey> keys =
|
||||
getPointerKeysForReflectedFieldWrite(object,fieldsKeys[f]);
|
||||
keys.hasNext(); )
|
||||
{
|
||||
PointerKey key = (PointerKey)keys.next();
|
||||
PointerKey key = keys.next();
|
||||
if (DEBUG_PROPERTIES) action.dump(key, true, false);
|
||||
action.action( key );
|
||||
}
|
||||
|
|
|
@ -130,8 +130,8 @@ public class CAstAnalysisScope extends AnalysisScope {
|
|||
/**
|
||||
* @return an Iterator <ClassLoaderReference>over the loaders.
|
||||
*/
|
||||
public Iterator getLoaders() {
|
||||
return new NonNullSingletonIterator( theLoader );
|
||||
public Iterator<ClassLoaderReference> getLoaders() {
|
||||
return new NonNullSingletonIterator<ClassLoaderReference>( theLoader );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -37,7 +37,7 @@ public class DelegatingAstPointerKeys implements AstPointerKeyFactory {
|
|||
return base.getFilteredPointerKeyForLocal(node, valueNumber, filter);
|
||||
}
|
||||
|
||||
public PointerKey getPointerKeyForReturnValue(CGNode node){
|
||||
public PointerKey getPointerKeyForReturnValue(CGNode node) {
|
||||
return base.getPointerKeyForReturnValue(node);
|
||||
}
|
||||
|
||||
|
@ -53,16 +53,17 @@ public class DelegatingAstPointerKeys implements AstPointerKeyFactory {
|
|||
return new ObjectPropertyCatalogKey(I);
|
||||
}
|
||||
|
||||
private final Map specificStringKeys = new HashMap();
|
||||
// private final Map specificIndexKeys = new HashMap();
|
||||
|
||||
private final Map<IField, Set<PointerKey>> specificStringKeys = new HashMap<IField, Set<PointerKey>>();
|
||||
|
||||
// private final Map specificIndexKeys = new HashMap();
|
||||
|
||||
public PointerKey getPointerKeyForInstanceField(InstanceKey I, IField f) {
|
||||
PointerKey fk = base.getPointerKeyForInstanceField(I, f);
|
||||
if (! specificStringKeys.containsKey(f)) {
|
||||
specificStringKeys.put(f, new HashSet());
|
||||
if (!specificStringKeys.containsKey(f)) {
|
||||
specificStringKeys.put(f, new HashSet<PointerKey>());
|
||||
}
|
||||
|
||||
((Set)specificStringKeys.get(f)).add(fk);
|
||||
specificStringKeys.get(f).add(fk);
|
||||
|
||||
return fk;
|
||||
}
|
||||
|
@ -71,35 +72,33 @@ public class DelegatingAstPointerKeys implements AstPointerKeyFactory {
|
|||
return base.getPointerKeyForArrayContents(I);
|
||||
}
|
||||
|
||||
public Iterator getPointerKeysForReflectedFieldRead(InstanceKey I, InstanceKey F) {
|
||||
List result = new LinkedList();
|
||||
public Iterator<PointerKey> getPointerKeysForReflectedFieldRead(InstanceKey I, InstanceKey F) {
|
||||
List<PointerKey> result = new LinkedList<PointerKey>();
|
||||
|
||||
// FIXME: current only constant string are handled
|
||||
if (F instanceof ConstantKey) {
|
||||
Object v = ((ConstantKey)F).getValue();
|
||||
Object v = ((ConstantKey) F).getValue();
|
||||
if (v instanceof String) {
|
||||
IField f =
|
||||
I.getConcreteType().getField(Atom.findOrCreateUnicodeAtom((String)v));
|
||||
result.add( getPointerKeyForInstanceField(I, f) );
|
||||
IField f = I.getConcreteType().getField(Atom.findOrCreateUnicodeAtom((String) v));
|
||||
result.add(getPointerKeyForInstanceField(I, f));
|
||||
}
|
||||
}
|
||||
|
||||
result.add(ReflectedFieldPointerKey.mapped(new ConcreteTypeKey(F.getConcreteType()), I));
|
||||
|
||||
|
||||
return result.iterator();
|
||||
}
|
||||
|
||||
public Iterator getPointerKeysForReflectedFieldWrite(InstanceKey I, InstanceKey F) {
|
||||
public Iterator<PointerKey> getPointerKeysForReflectedFieldWrite(InstanceKey I, InstanceKey F) {
|
||||
// FIXME: current only constant string are handled
|
||||
if (F instanceof ConstantKey) {
|
||||
Object v = ((ConstantKey)F).getValue();
|
||||
Object v = ((ConstantKey) F).getValue();
|
||||
if (v instanceof String) {
|
||||
IField f =
|
||||
I.getConcreteType().getField(Atom.findOrCreateUnicodeAtom((String)v));
|
||||
return new NonNullSingletonIterator(getPointerKeyForInstanceField(I, f));
|
||||
IField f = I.getConcreteType().getField(Atom.findOrCreateUnicodeAtom((String) v));
|
||||
return new NonNullSingletonIterator<PointerKey>(getPointerKeyForInstanceField(I, f));
|
||||
}
|
||||
}
|
||||
|
||||
return new NonNullSingletonIterator(ReflectedFieldPointerKey.mapped(new ConcreteTypeKey(F.getConcreteType()), I));
|
||||
return new NonNullSingletonIterator<PointerKey>(ReflectedFieldPointerKey.mapped(new ConcreteTypeKey(F.getConcreteType()), I));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ import com.ibm.wala.util.warnings.WarningSet;
|
|||
public class MiscellaneousHacksContextSelector implements ContextSelector
|
||||
{
|
||||
|
||||
private final Set methodsToSpecialize;
|
||||
private final Set<MethodReference> methodsToSpecialize;
|
||||
|
||||
private final ContextSelector specialPolicy;
|
||||
private final ContextSelector basePolicy;
|
||||
|
@ -42,7 +42,7 @@ public class MiscellaneousHacksContextSelector implements ContextSelector
|
|||
{
|
||||
basePolicy = base;
|
||||
specialPolicy = special;
|
||||
methodsToSpecialize = new HashSet();
|
||||
methodsToSpecialize = new HashSet<MethodReference>();
|
||||
for(int i = 0; i < descriptors.length; i++) {
|
||||
String[] descr = descriptors[i];
|
||||
switch (descr.length) {
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.ipa.callgraph;
|
||||
|
||||
|
||||
import com.ibm.wala.cast.ir.translator.*;
|
||||
import com.ibm.wala.cast.loader.AstMethod.*;
|
||||
import com.ibm.wala.classLoader.*;
|
||||
|
@ -29,78 +28,83 @@ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory {
|
|||
protected abstract boolean needsScopeMappingKey(InstanceKey base);
|
||||
|
||||
private final PropagationCallGraphBuilder builder;
|
||||
|
||||
private final InstanceKeyFactory basic;
|
||||
|
||||
public class ScopeMappingInstanceKey implements InstanceKey {
|
||||
private final InstanceKey base;
|
||||
|
||||
private final CGNode creator;
|
||||
|
||||
private final ScopeMap map;
|
||||
|
||||
private class ScopeMap extends HashMap {
|
||||
|
||||
private static final long serialVersionUID = 3645910671551712906L;
|
||||
|
||||
private void scan(int level, int toDo, LexicalParent parents[], CGNode node, Set parentNodes) {
|
||||
private void scan(int level, int toDo, LexicalParent parents[], CGNode node, Set<CGNode> parentNodes) {
|
||||
if (toDo > 0) {
|
||||
int restoreIndex = -1;
|
||||
LexicalParent restoreParent = null;
|
||||
int restoreIndex = -1;
|
||||
LexicalParent restoreParent = null;
|
||||
|
||||
if (AstTranslator.DEBUG_LEXICAL)
|
||||
Trace.println(level + ": searching " + node + " for parents");
|
||||
if (AstTranslator.DEBUG_LEXICAL)
|
||||
Trace.println(level + ": searching " + node + " for parents");
|
||||
|
||||
for(int i = 0; i < parents.length; i++) {
|
||||
for (int i = 0; i < parents.length; i++) {
|
||||
|
||||
if (parents[i] == null) continue;
|
||||
if (parents[i] == null)
|
||||
continue;
|
||||
|
||||
if (AstTranslator.DEBUG_LEXICAL)
|
||||
Trace.println(level + ": searching " + parents[i]);
|
||||
|
||||
if (node.getMethod() == parents[i].getMethod()) {
|
||||
if (containsKey(parents[i].getName()))
|
||||
Assertions._assert(get(parents[i].getName()) == node);
|
||||
else {
|
||||
put( parents[i].getName(), node );
|
||||
if (AstTranslator.DEBUG_LEXICAL)
|
||||
Trace.println(level + ": Adding lexical parent " + parents[i].getName() + " for " + base + " at " + creator + "(toDo is now " + toDo +")");
|
||||
}
|
||||
if (AstTranslator.DEBUG_LEXICAL)
|
||||
Trace.println(level + ": searching " + parents[i]);
|
||||
|
||||
toDo--;
|
||||
restoreIndex = i;
|
||||
restoreParent = parents[i];
|
||||
parents[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
CallGraph CG = builder.getCallGraph();
|
||||
|
||||
Assertions._assert(CG.getPredNodes(node).hasNext() || toDo==0);
|
||||
if (node.getMethod() == parents[i].getMethod()) {
|
||||
if (containsKey(parents[i].getName()))
|
||||
Assertions._assert(get(parents[i].getName()) == node);
|
||||
else {
|
||||
put(parents[i].getName(), node);
|
||||
if (AstTranslator.DEBUG_LEXICAL)
|
||||
Trace.println(level + ": Adding lexical parent " + parents[i].getName() + " for " + base + " at " + creator
|
||||
+ "(toDo is now " + toDo + ")");
|
||||
}
|
||||
|
||||
for(Iterator PS = CG.getPredNodes(node); PS.hasNext(); ) {
|
||||
CGNode pred = (CGNode) PS.next();
|
||||
if (pred != creator && !parentNodes.contains(pred)) {
|
||||
parentNodes.add( pred );
|
||||
scan(level+1, toDo, parents, pred, parentNodes);
|
||||
parentNodes.remove(pred);
|
||||
}
|
||||
}
|
||||
toDo--;
|
||||
restoreIndex = i;
|
||||
restoreParent = parents[i];
|
||||
parents[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (restoreIndex != -1) {
|
||||
parents[restoreIndex] = restoreParent;
|
||||
}
|
||||
}
|
||||
CallGraph CG = builder.getCallGraph();
|
||||
|
||||
Assertions._assert(CG.getPredNodes(node).hasNext() || toDo == 0);
|
||||
|
||||
for (Iterator PS = CG.getPredNodes(node); PS.hasNext();) {
|
||||
CGNode pred = (CGNode) PS.next();
|
||||
if (pred != creator && !parentNodes.contains(pred)) {
|
||||
parentNodes.add(pred);
|
||||
scan(level + 1, toDo, parents, pred, parentNodes);
|
||||
parentNodes.remove(pred);
|
||||
}
|
||||
}
|
||||
|
||||
if (restoreIndex != -1) {
|
||||
parents[restoreIndex] = restoreParent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private ScopeMap() {
|
||||
LexicalParent[] parents = getParents(base);
|
||||
|
||||
if (AstTranslator.DEBUG_LEXICAL)
|
||||
Trace.println("starting search for parents at " + creator);
|
||||
if (AstTranslator.DEBUG_LEXICAL)
|
||||
Trace.println("starting search for parents at " + creator);
|
||||
|
||||
scan( 0, parents.length, parents, creator, new HashSet(5));
|
||||
scan(0, parents.length, parents, creator, new HashSet<CGNode>(5));
|
||||
}
|
||||
|
||||
|
||||
CGNode getDefiningNode(String definer) {
|
||||
return (CGNode) get(definer);
|
||||
return (CGNode) get(definer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,21 +119,20 @@ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory {
|
|||
}
|
||||
|
||||
CGNode getDefiningNode(String definer) {
|
||||
return map.getDefiningNode( definer );
|
||||
return map.getDefiningNode(definer);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return base.hashCode()*creator.hashCode();
|
||||
public int hashCode() {
|
||||
return base.hashCode() * creator.hashCode();
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
return (o instanceof ScopeMappingInstanceKey) &&
|
||||
((ScopeMappingInstanceKey)o).base.equals(base) &&
|
||||
((ScopeMappingInstanceKey)o).creator.equals(creator);
|
||||
return (o instanceof ScopeMappingInstanceKey) && ((ScopeMappingInstanceKey) o).base.equals(base)
|
||||
&& ((ScopeMappingInstanceKey) o).creator.equals(creator);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "SMIK:"+base+"@"+creator;
|
||||
return "SMIK:" + base + "@" + creator;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -162,10 +165,7 @@ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory {
|
|||
return basic.getInstanceKeyForClassObject(type);
|
||||
}
|
||||
|
||||
public ScopeMappingInstanceKeys(
|
||||
PropagationCallGraphBuilder builder,
|
||||
InstanceKeyFactory basic)
|
||||
{
|
||||
public ScopeMappingInstanceKeys(PropagationCallGraphBuilder builder, InstanceKeyFactory basic) {
|
||||
this.basic = basic;
|
||||
this.builder = builder;
|
||||
}
|
||||
|
|
|
@ -66,8 +66,8 @@ public abstract class ScriptEntryPoints implements Entrypoints {
|
|||
this.scriptType = scriptType;
|
||||
}
|
||||
|
||||
public Iterator iterator() {
|
||||
Set ES = new HashSet();
|
||||
public Iterator<ScriptEntryPoint> iterator() {
|
||||
Set<ScriptEntryPoint> ES = new HashSet<ScriptEntryPoint>();
|
||||
Iterator classes = scriptType.getClassLoader().iterateAllClasses();
|
||||
while ( classes.hasNext() ) {
|
||||
IClass cls = (IClass)classes.next();
|
||||
|
|
|
@ -18,9 +18,7 @@ import com.ibm.wala.util.intset.BitVector;
|
|||
|
||||
import java.util.*;
|
||||
|
||||
public class DelegatingCFG extends AbstractNumberedGraph<IBasicBlock>
|
||||
implements ControlFlowGraph
|
||||
{
|
||||
public class DelegatingCFG extends AbstractNumberedGraph<IBasicBlock> implements ControlFlowGraph {
|
||||
|
||||
protected final ControlFlowGraph parent;
|
||||
|
||||
|
@ -28,46 +26,56 @@ public class DelegatingCFG extends AbstractNumberedGraph<IBasicBlock>
|
|||
this.parent = parent;
|
||||
}
|
||||
|
||||
protected NodeManager getNodeManager() {
|
||||
protected NodeManager<IBasicBlock> getNodeManager() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
protected EdgeManager getEdgeManager() {
|
||||
protected EdgeManager<IBasicBlock> getEdgeManager() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public IBasicBlock entry() { return parent.entry(); }
|
||||
public IBasicBlock entry() {
|
||||
return parent.entry();
|
||||
}
|
||||
|
||||
public IBasicBlock exit() { return parent.exit(); }
|
||||
public IBasicBlock exit() {
|
||||
return parent.exit();
|
||||
}
|
||||
|
||||
public BitVector getCatchBlocks() { return parent.getCatchBlocks(); }
|
||||
public BitVector getCatchBlocks() {
|
||||
return parent.getCatchBlocks();
|
||||
}
|
||||
|
||||
public IBasicBlock getBlockForInstruction(int index) {
|
||||
return parent.getBlockForInstruction( index );
|
||||
return parent.getBlockForInstruction(index);
|
||||
}
|
||||
|
||||
public IInstruction[] getInstructions() { return parent.getInstructions(); }
|
||||
public IInstruction[] getInstructions() {
|
||||
return parent.getInstructions();
|
||||
}
|
||||
|
||||
public int getProgramCounter(int index) {
|
||||
return parent.getProgramCounter( index );
|
||||
return parent.getProgramCounter(index);
|
||||
}
|
||||
|
||||
public IMethod getMethod() { return parent.getMethod(); }
|
||||
|
||||
public Collection getExceptionalSuccessors(IBasicBlock b) {
|
||||
return parent.getExceptionalSuccessors( b );
|
||||
public IMethod getMethod() {
|
||||
return parent.getMethod();
|
||||
}
|
||||
|
||||
public Collection getNormalSuccessors(IBasicBlock b) {
|
||||
return parent.getNormalSuccessors( b );
|
||||
}
|
||||
|
||||
public Collection getExceptionalPredecessors(IBasicBlock b) {
|
||||
return parent.getExceptionalPredecessors( b );
|
||||
public Collection<IBasicBlock> getExceptionalSuccessors(IBasicBlock b) {
|
||||
return parent.getExceptionalSuccessors(b);
|
||||
}
|
||||
|
||||
public Collection getNormalPredecessors(IBasicBlock b) {
|
||||
return parent.getNormalPredecessors( b );
|
||||
public Collection<IBasicBlock> getNormalSuccessors(IBasicBlock b) {
|
||||
return parent.getNormalSuccessors(b);
|
||||
}
|
||||
|
||||
public Collection<IBasicBlock> getExceptionalPredecessors(IBasicBlock b) {
|
||||
return parent.getExceptionalPredecessors(b);
|
||||
}
|
||||
|
||||
public Collection<IBasicBlock> getNormalPredecessors(IBasicBlock b) {
|
||||
return parent.getNormalPredecessors(b);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -47,60 +47,60 @@ public class PrunedCFG extends AbstractNumberedGraph<IBasicBlock> implements Con
|
|||
|
||||
}
|
||||
|
||||
private static class FilteredCFGEdges implements NumberedEdgeManager {
|
||||
private static class FilteredCFGEdges implements NumberedEdgeManager<IBasicBlock> {
|
||||
private final ControlFlowGraph cfg;
|
||||
|
||||
private final NumberedNodeManager currentCFGNodes;
|
||||
private final NumberedNodeManager<IBasicBlock> currentCFGNodes;
|
||||
|
||||
private final EdgeFilter filter;
|
||||
|
||||
FilteredCFGEdges(ControlFlowGraph cfg, NumberedNodeManager currentCFGNodes, EdgeFilter filter) {
|
||||
FilteredCFGEdges(ControlFlowGraph cfg, NumberedNodeManager<IBasicBlock> currentCFGNodes, EdgeFilter filter) {
|
||||
this.cfg = cfg;
|
||||
this.filter = filter;
|
||||
this.currentCFGNodes = currentCFGNodes;
|
||||
}
|
||||
|
||||
public Iterator getExceptionalSuccessors(final IBasicBlock N) {
|
||||
return new FilterIterator(cfg.getExceptionalSuccessors(N).iterator(), new Filter() {
|
||||
public Iterator<IBasicBlock> getExceptionalSuccessors(final IBasicBlock N) {
|
||||
return new FilterIterator<IBasicBlock>(cfg.getExceptionalSuccessors(N).iterator(), new Filter() {
|
||||
public boolean accepts(Object o) {
|
||||
return currentCFGNodes.containsNode(o) && filter.hasExceptionalEdge((IBasicBlock) N, (IBasicBlock) o);
|
||||
return currentCFGNodes.containsNode((IBasicBlock) o) && filter.hasExceptionalEdge((IBasicBlock) N, (IBasicBlock) o);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Iterator getNormalSuccessors(final IBasicBlock N) {
|
||||
return new FilterIterator(cfg.getNormalSuccessors(N).iterator(), new Filter() {
|
||||
public Iterator<IBasicBlock> getNormalSuccessors(final IBasicBlock N) {
|
||||
return new FilterIterator<IBasicBlock>(cfg.getNormalSuccessors(N).iterator(), new Filter() {
|
||||
public boolean accepts(Object o) {
|
||||
return currentCFGNodes.containsNode(o) && filter.hasNormalEdge((IBasicBlock) N, (IBasicBlock) o);
|
||||
return currentCFGNodes.containsNode((IBasicBlock)o) && filter.hasNormalEdge((IBasicBlock) N, (IBasicBlock) o);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Iterator getExceptionalPredecessors(final IBasicBlock N) {
|
||||
return new FilterIterator(cfg.getExceptionalPredecessors(N).iterator(), new Filter() {
|
||||
public Iterator<IBasicBlock> getExceptionalPredecessors(final IBasicBlock N) {
|
||||
return new FilterIterator<IBasicBlock>(cfg.getExceptionalPredecessors(N).iterator(), new Filter() {
|
||||
public boolean accepts(Object o) {
|
||||
return currentCFGNodes.containsNode(o) && filter.hasExceptionalEdge((IBasicBlock) o, (IBasicBlock) N);
|
||||
return currentCFGNodes.containsNode((IBasicBlock)o) && filter.hasExceptionalEdge((IBasicBlock) o, (IBasicBlock) N);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Iterator getNormalPredecessors(final IBasicBlock N) {
|
||||
return new FilterIterator(cfg.getNormalPredecessors(N).iterator(), new Filter() {
|
||||
public Iterator<IBasicBlock> getNormalPredecessors(final IBasicBlock N) {
|
||||
return new FilterIterator<IBasicBlock>(cfg.getNormalPredecessors(N).iterator(), new Filter() {
|
||||
public boolean accepts(Object o) {
|
||||
return currentCFGNodes.containsNode(o) && filter.hasNormalEdge((IBasicBlock) o, (IBasicBlock) N);
|
||||
return currentCFGNodes.containsNode((IBasicBlock)o) && filter.hasNormalEdge((IBasicBlock) o, (IBasicBlock) N);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Iterator getSuccNodes(Object N) {
|
||||
return new CompoundIterator(getNormalSuccessors((IBasicBlock) N), getExceptionalSuccessors((IBasicBlock) N));
|
||||
public Iterator<IBasicBlock> getSuccNodes(IBasicBlock N) {
|
||||
return new CompoundIterator<IBasicBlock>(getNormalSuccessors((IBasicBlock) N), getExceptionalSuccessors((IBasicBlock) N));
|
||||
}
|
||||
|
||||
public int getSuccNodeCount(Object N) {
|
||||
return new Iterator2Collection(getSuccNodes(N)).size();
|
||||
public int getSuccNodeCount(IBasicBlock N) {
|
||||
return new Iterator2Collection<IBasicBlock>(getSuccNodes(N)).size();
|
||||
}
|
||||
|
||||
public IntSet getSuccNodeNumbers(Object N) {
|
||||
public IntSet getSuccNodeNumbers(IBasicBlock N) {
|
||||
MutableIntSet bits = IntSetUtil.make();
|
||||
for (Iterator EE = getSuccNodes(N); EE.hasNext();) {
|
||||
bits.add(((IBasicBlock) EE.next()).getNumber());
|
||||
|
@ -109,15 +109,15 @@ public class PrunedCFG extends AbstractNumberedGraph<IBasicBlock> implements Con
|
|||
return bits;
|
||||
}
|
||||
|
||||
public Iterator getPredNodes(Object N) {
|
||||
return new CompoundIterator(getNormalPredecessors((IBasicBlock) N), getExceptionalPredecessors((IBasicBlock) N));
|
||||
public Iterator<IBasicBlock> getPredNodes(IBasicBlock N) {
|
||||
return new CompoundIterator<IBasicBlock>(getNormalPredecessors((IBasicBlock) N), getExceptionalPredecessors((IBasicBlock) N));
|
||||
}
|
||||
|
||||
public int getPredNodeCount(Object N) {
|
||||
return new Iterator2Collection(getPredNodes(N)).size();
|
||||
public int getPredNodeCount(IBasicBlock N) {
|
||||
return new Iterator2Collection<IBasicBlock>(getPredNodes(N)).size();
|
||||
}
|
||||
|
||||
public IntSet getPredNodeNumbers(Object N) {
|
||||
public IntSet getPredNodeNumbers(IBasicBlock N) {
|
||||
MutableIntSet bits = IntSetUtil.make();
|
||||
for (Iterator EE = getPredNodes(N); EE.hasNext();) {
|
||||
bits.add(((IBasicBlock) EE.next()).getNumber());
|
||||
|
@ -126,7 +126,7 @@ public class PrunedCFG extends AbstractNumberedGraph<IBasicBlock> implements Con
|
|||
return bits;
|
||||
}
|
||||
|
||||
public boolean hasEdge(Object src, Object dst) {
|
||||
public boolean hasEdge(IBasicBlock src, IBasicBlock dst) {
|
||||
for (Iterator EE = getSuccNodes(src); EE.hasNext();) {
|
||||
if (EE.next().equals(dst)) {
|
||||
return true;
|
||||
|
@ -136,46 +136,46 @@ public class PrunedCFG extends AbstractNumberedGraph<IBasicBlock> implements Con
|
|||
return false;
|
||||
}
|
||||
|
||||
public void addEdge(Object src, Object dst) {
|
||||
public void addEdge(IBasicBlock src, IBasicBlock dst) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void removeEdge(Object src, Object dst) {
|
||||
public void removeEdge(IBasicBlock src, IBasicBlock dst) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void removeAllIncidentEdges(Object node) {
|
||||
public void removeAllIncidentEdges(IBasicBlock node) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void removeIncomingEdges(Object node) {
|
||||
public void removeIncomingEdges(IBasicBlock node) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void removeOutgoingEdges(Object node) {
|
||||
public void removeOutgoingEdges(IBasicBlock node) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
private static class FilteredNodes implements NumberedNodeManager {
|
||||
private final NumberedNodeManager nodes;
|
||||
private static class FilteredNodes implements NumberedNodeManager<IBasicBlock> {
|
||||
private final NumberedNodeManager<IBasicBlock> nodes;
|
||||
|
||||
private final Set subset;
|
||||
|
||||
FilteredNodes(NumberedNodeManager nodes, Set subset) {
|
||||
FilteredNodes(NumberedNodeManager<IBasicBlock> nodes, Set subset) {
|
||||
this.nodes = nodes;
|
||||
this.subset = subset;
|
||||
}
|
||||
|
||||
public int getNumber(Object N) {
|
||||
public int getNumber(IBasicBlock N) {
|
||||
if (subset.contains(N))
|
||||
return nodes.getNumber(N);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
public Object getNode(int number) {
|
||||
Object N = nodes.getNode(number);
|
||||
public IBasicBlock getNode(int number) {
|
||||
IBasicBlock N = nodes.getNode(number);
|
||||
if (subset.contains(N))
|
||||
return N;
|
||||
else
|
||||
|
@ -184,8 +184,8 @@ public class PrunedCFG extends AbstractNumberedGraph<IBasicBlock> implements Con
|
|||
|
||||
public int getMaxNumber() {
|
||||
int max = -1;
|
||||
for (Iterator NS = nodes.iterateNodes(); NS.hasNext();) {
|
||||
Object N = NS.next();
|
||||
for (Iterator<? extends IBasicBlock> NS = nodes.iterateNodes(); NS.hasNext();) {
|
||||
IBasicBlock N = NS.next();
|
||||
if (subset.contains(N) && getNumber(N) > max) {
|
||||
max = getNumber(N);
|
||||
}
|
||||
|
@ -194,19 +194,19 @@ public class PrunedCFG extends AbstractNumberedGraph<IBasicBlock> implements Con
|
|||
return max;
|
||||
}
|
||||
|
||||
private Iterator filterNodes(Iterator nodeIterator) {
|
||||
return new FilterIterator(nodeIterator, new Filter() {
|
||||
private Iterator<IBasicBlock> filterNodes(Iterator nodeIterator) {
|
||||
return new FilterIterator<IBasicBlock>(nodeIterator, new Filter() {
|
||||
public boolean accepts(Object o) {
|
||||
return subset.contains(o);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Iterator iterateNodes(IntSet s) {
|
||||
public Iterator<IBasicBlock> iterateNodes(IntSet s) {
|
||||
return filterNodes(nodes.iterateNodes(s));
|
||||
}
|
||||
|
||||
public Iterator iterateNodes() {
|
||||
public Iterator<IBasicBlock> iterateNodes() {
|
||||
return filterNodes(nodes.iterateNodes());
|
||||
}
|
||||
|
||||
|
@ -214,15 +214,15 @@ public class PrunedCFG extends AbstractNumberedGraph<IBasicBlock> implements Con
|
|||
return subset.size();
|
||||
}
|
||||
|
||||
public void addNode(Object n) {
|
||||
public void addNode(IBasicBlock n) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void removeNode(Object n) {
|
||||
public void removeNode(IBasicBlock n) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public boolean containsNode(Object N) {
|
||||
public boolean containsNode(IBasicBlock N) {
|
||||
return subset.contains(N);
|
||||
}
|
||||
}
|
||||
|
@ -236,47 +236,47 @@ public class PrunedCFG extends AbstractNumberedGraph<IBasicBlock> implements Con
|
|||
public PrunedCFG(final ControlFlowGraph cfg, final EdgeFilter filter) {
|
||||
this.cfg = cfg;
|
||||
Graph<IBasicBlock> temp = new AbstractNumberedGraph<IBasicBlock>() {
|
||||
private final EdgeManager edges = new FilteredCFGEdges(cfg, cfg, filter);
|
||||
private final EdgeManager<IBasicBlock> edges = new FilteredCFGEdges(cfg, cfg, filter);
|
||||
|
||||
protected NodeManager getNodeManager() {
|
||||
protected NodeManager<IBasicBlock> getNodeManager() {
|
||||
return cfg;
|
||||
}
|
||||
|
||||
protected EdgeManager getEdgeManager() {
|
||||
protected EdgeManager<IBasicBlock> getEdgeManager() {
|
||||
return edges;
|
||||
}
|
||||
};
|
||||
|
||||
Set reachable = DFS.getReachableNodes(temp, Collections.singleton(cfg.entry()));
|
||||
Set back = DFS.getReachableNodes(GraphInverter.invert(temp), Collections.singleton(cfg.exit()));
|
||||
Set<IBasicBlock> reachable = DFS.getReachableNodes(temp, Collections.singleton(cfg.entry()));
|
||||
Set<IBasicBlock> back = DFS.getReachableNodes(GraphInverter.invert(temp), Collections.singleton(cfg.exit()));
|
||||
reachable.retainAll(back);
|
||||
|
||||
this.nodes = new FilteredNodes(cfg, reachable);
|
||||
this.edges = new FilteredCFGEdges(cfg, nodes, filter);
|
||||
}
|
||||
|
||||
protected NodeManager getNodeManager() {
|
||||
protected NodeManager<IBasicBlock> getNodeManager() {
|
||||
return nodes;
|
||||
}
|
||||
|
||||
protected EdgeManager getEdgeManager() {
|
||||
protected EdgeManager<IBasicBlock> getEdgeManager() {
|
||||
return edges;
|
||||
}
|
||||
|
||||
public Collection getExceptionalSuccessors(final IBasicBlock N) {
|
||||
return new Iterator2Collection(edges.getExceptionalSuccessors(N));
|
||||
public Collection<IBasicBlock> getExceptionalSuccessors(final IBasicBlock N) {
|
||||
return new Iterator2Collection<IBasicBlock>(edges.getExceptionalSuccessors(N));
|
||||
}
|
||||
|
||||
public Collection getNormalSuccessors(final IBasicBlock N) {
|
||||
return new Iterator2Collection(edges.getNormalSuccessors(N));
|
||||
public Collection<IBasicBlock> getNormalSuccessors(final IBasicBlock N) {
|
||||
return new Iterator2Collection<IBasicBlock>(edges.getNormalSuccessors(N));
|
||||
}
|
||||
|
||||
public Collection getExceptionalPredecessors(final IBasicBlock N) {
|
||||
return new Iterator2Collection(edges.getExceptionalPredecessors(N));
|
||||
public Collection<IBasicBlock> getExceptionalPredecessors(final IBasicBlock N) {
|
||||
return new Iterator2Collection<IBasicBlock>(edges.getExceptionalPredecessors(N));
|
||||
}
|
||||
|
||||
public Collection getNormalPredecessors(final IBasicBlock N) {
|
||||
return new Iterator2Collection(edges.getNormalPredecessors(N));
|
||||
public Collection<IBasicBlock> getNormalPredecessors(final IBasicBlock N) {
|
||||
return new Iterator2Collection<IBasicBlock>(edges.getNormalPredecessors(N));
|
||||
}
|
||||
|
||||
public IBasicBlock entry() {
|
||||
|
|
|
@ -21,30 +21,29 @@ import com.ibm.wala.ssa.SSAInstruction;
|
|||
import com.ibm.wala.ssa.SSAOptions;
|
||||
import com.ibm.wala.ssa.SSAPhiInstruction;
|
||||
import com.ibm.wala.ssa.SymbolTable;
|
||||
import com.ibm.wala.ssa.SSACFG.BasicBlock;
|
||||
import com.ibm.wala.ssa.SSAOptions.DefaultValues;
|
||||
import com.ibm.wala.util.collections.IntStack;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.graph.DominanceFrontiers;
|
||||
import com.ibm.wala.util.graph.Graph;
|
||||
|
||||
|
||||
/**
|
||||
* Abstract core of traditional SSA conversion (Cytron et al.).
|
||||
*
|
||||
* This implementation is abstract in the sense that it is designed
|
||||
* to work over the instrutions and CFG of a Domo IR, but it is
|
||||
* abstract with respect to several integral portions of the
|
||||
* traditional algorithm:
|
||||
*
|
||||
* This implementation is abstract in the sense that it is designed to work over
|
||||
* the instrutions and CFG of a Domo IR, but it is abstract with respect to
|
||||
* several integral portions of the traditional algorithm:
|
||||
* <UL>
|
||||
* <LI> The notion of uses and defs of a given instruction.
|
||||
* <LI> Assignments (<def> := <use>) that are be copy-propagated away
|
||||
* <LI> Which values are constants---i.e. have no definition.
|
||||
* <LI> Any value numbers to be skipped during SSA construction
|
||||
* <LI> Special initialization and exit block processing.
|
||||
* <LI> The notion of uses and defs of a given instruction.
|
||||
* <LI> Assignments (<def> := <use>) that are be copy-propagated away
|
||||
* <LI> Which values are constants---i.e. have no definition.
|
||||
* <LI> Any value numbers to be skipped during SSA construction
|
||||
* <LI> Special initialization and exit block processing.
|
||||
* </UL>
|
||||
*
|
||||
*
|
||||
* @author Julian dolby (dolby@us.ibm.com)
|
||||
*
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractSSAConversion {
|
||||
|
||||
|
@ -56,10 +55,8 @@ public abstract class AbstractSSAConversion {
|
|||
|
||||
protected abstract int getUse(SSAInstruction inst, int index);
|
||||
|
||||
|
||||
protected abstract boolean isAssignInstruction(SSAInstruction inst);
|
||||
|
||||
|
||||
protected abstract int getMaxValueNumber();
|
||||
|
||||
protected abstract boolean isLive(SSACFG.BasicBlock Y, int V);
|
||||
|
@ -68,15 +65,12 @@ public abstract class AbstractSSAConversion {
|
|||
|
||||
protected abstract boolean isConstant(int valueNumber);
|
||||
|
||||
|
||||
protected abstract int getNextNewValueNumber();
|
||||
|
||||
|
||||
protected abstract void initializeVariables();
|
||||
|
||||
protected abstract void repairExit();
|
||||
|
||||
|
||||
protected abstract void placeNewPhiAt(int value, SSACFG.BasicBlock Y);
|
||||
|
||||
protected abstract SSAPhiInstruction getPhi(SSACFG.BasicBlock B, int index);
|
||||
|
@ -87,34 +81,41 @@ public abstract class AbstractSSAConversion {
|
|||
|
||||
protected abstract void repairPhiUse(SSACFG.BasicBlock BB, int phiIndex, int rvalIndex, int newRval);
|
||||
|
||||
|
||||
protected abstract void repairInstructionUses(SSAInstruction inst, int index, int[] newUses);
|
||||
|
||||
protected abstract void repairInstructionDefs(SSAInstruction inst, int index, int[] newDefs, int[] newUses);
|
||||
|
||||
|
||||
protected abstract void pushAssignment(SSAInstruction inst, int index, int newRhs);
|
||||
|
||||
protected abstract void popAssignment(SSAInstruction inst, int index);
|
||||
|
||||
|
||||
protected final SSACFG CFG;
|
||||
|
||||
protected final DominanceFrontiers<IBasicBlock> DF;
|
||||
|
||||
private final Graph dominatorTree;
|
||||
|
||||
protected final int[] phiCounts;
|
||||
|
||||
protected final SSAInstruction[] instructions;
|
||||
|
||||
private final int flags[];
|
||||
|
||||
protected final SymbolTable symbolTable;
|
||||
|
||||
protected final DefaultValues defaultValues;
|
||||
|
||||
protected IntStack S[];
|
||||
|
||||
protected int C[];
|
||||
|
||||
protected int valueMap[];
|
||||
|
||||
private Set[] assignmentMap;
|
||||
|
||||
protected AbstractSSAConversion(IR ir, SSAOptions options) {
|
||||
this.CFG = ir.getControlFlowGraph();
|
||||
this.DF = new DominanceFrontiers(ir.getControlFlowGraph(), ir.getControlFlowGraph().entry());
|
||||
this.DF = new DominanceFrontiers<IBasicBlock>(ir.getControlFlowGraph(), ir.getControlFlowGraph().entry());
|
||||
this.dominatorTree = DF.dominatorTree();
|
||||
this.flags = new int[2 * ir.getControlFlowGraph().getNumberOfNodes()];
|
||||
this.instructions = ir.getInstructions();
|
||||
|
@ -123,7 +124,6 @@ public abstract class AbstractSSAConversion {
|
|||
this.defaultValues = options.getDefaultValues();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// top-level control
|
||||
//
|
||||
|
@ -133,7 +133,6 @@ public abstract class AbstractSSAConversion {
|
|||
renameVariables();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// initialization
|
||||
//
|
||||
|
@ -149,22 +148,22 @@ public abstract class AbstractSSAConversion {
|
|||
for (Iterator BBs = CFG.iterateNodes(); BBs.hasNext();) {
|
||||
SSACFG.BasicBlock BB = (SSACFG.BasicBlock) BBs.next();
|
||||
if (BB.getFirstInstructionIndex() >= 0) {
|
||||
for(Iterator IS = BB.iterateAllInstructions(); IS.hasNext(); ) {
|
||||
SSAInstruction inst = (SSAInstruction)IS.next();
|
||||
if (inst != null) {
|
||||
for (int j = 0; j < getNumberOfDefs(inst); j++) {
|
||||
for (Iterator IS = BB.iterateAllInstructions(); IS.hasNext();) {
|
||||
SSAInstruction inst = (SSAInstruction) IS.next();
|
||||
if (inst != null) {
|
||||
for (int j = 0; j < getNumberOfDefs(inst); j++) {
|
||||
addDefiningBlock(assignmentMap, BB, getDef(inst, j));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addDefiningBlock(Set[] A, SSACFG.BasicBlock BB, int i) {
|
||||
if (! skip(i)) {
|
||||
private void addDefiningBlock(Set<SSACFG.BasicBlock>[] A, SSACFG.BasicBlock BB, int i) {
|
||||
if (!skip(i)) {
|
||||
if (A[i] == null) {
|
||||
A[i] = new LinkedHashSet(2);
|
||||
A[i] = new LinkedHashSet<SSACFG.BasicBlock>(2);
|
||||
}
|
||||
A[i].add(BB);
|
||||
}
|
||||
|
@ -182,7 +181,7 @@ public abstract class AbstractSSAConversion {
|
|||
setWork(X, 0);
|
||||
}
|
||||
|
||||
Set W = new LinkedHashSet();
|
||||
Set<BasicBlock> W = new LinkedHashSet<BasicBlock>();
|
||||
for (int V = 0; V < assignmentMap.length; V++) {
|
||||
|
||||
// some things (e.g. constants) have no defs at all
|
||||
|
@ -191,7 +190,7 @@ public abstract class AbstractSSAConversion {
|
|||
|
||||
// ignore values as requested
|
||||
if (skip(V))
|
||||
continue;
|
||||
continue;
|
||||
|
||||
IterCount++;
|
||||
|
||||
|
@ -202,15 +201,15 @@ public abstract class AbstractSSAConversion {
|
|||
}
|
||||
|
||||
while (!W.isEmpty()) {
|
||||
SSACFG.BasicBlock X = (SSACFG.BasicBlock) W.iterator().next();
|
||||
SSACFG.BasicBlock X = W.iterator().next();
|
||||
W.remove(X);
|
||||
for (Iterator YS = DF.getDominanceFrontier(X); YS.hasNext();) {
|
||||
SSACFG.BasicBlock Y = (SSACFG.BasicBlock) YS.next();
|
||||
if (getHasAlready(Y) < IterCount) {
|
||||
if (isLive(Y, V)) {
|
||||
if (isLive(Y, V)) {
|
||||
placeNewPhiAt(V, Y);
|
||||
phiCounts[Y.getGraphNodeId()]++;
|
||||
}
|
||||
phiCounts[Y.getGraphNodeId()]++;
|
||||
}
|
||||
setHasAlready(Y, IterCount);
|
||||
if (getWork(Y) < IterCount) {
|
||||
setWork(Y, IterCount);
|
||||
|
@ -238,15 +237,14 @@ public abstract class AbstractSSAConversion {
|
|||
flags[BB.getGraphNodeId() * 2] = v;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// rename variables phase of traditional algorithm
|
||||
//
|
||||
private void renameVariables() {
|
||||
for (int V = 1; V <= getMaxValueNumber(); V++) {
|
||||
if (! skip(V)) {
|
||||
C[V] = 0;
|
||||
S[V] = new IntStack();
|
||||
if (!skip(V)) {
|
||||
C[V] = 0;
|
||||
S[V] = new IntStack();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -262,27 +260,27 @@ public abstract class AbstractSSAConversion {
|
|||
// first loop
|
||||
for (int i = 0; i < phiCounts[id]; i++) {
|
||||
SSAPhiInstruction phi = getPhi(X, i);
|
||||
if (! skipRepair(phi, -1)) {
|
||||
setPhi(X, i, repairPhiDefs(phi, makeNewDefs(phi)));
|
||||
if (!skipRepair(phi, -1)) {
|
||||
setPhi(X, i, repairPhiDefs(phi, makeNewDefs(phi)));
|
||||
}
|
||||
}
|
||||
for (int i = Xf; i <= X.getLastInstructionIndex(); i++) {
|
||||
SSAInstruction inst = instructions[i];
|
||||
if (isAssignInstruction(inst)) {
|
||||
int lhs = getDef(inst, 0);
|
||||
int rhs = getUse(inst, 0);
|
||||
int newRhs = skip(rhs)? rhs: top(rhs);
|
||||
S[lhs].push( newRhs );
|
||||
int lhs = getDef(inst, 0);
|
||||
int rhs = getUse(inst, 0);
|
||||
int newRhs = skip(rhs) ? rhs : top(rhs);
|
||||
S[lhs].push(newRhs);
|
||||
|
||||
pushAssignment(inst, i, newRhs);
|
||||
pushAssignment(inst, i, newRhs);
|
||||
|
||||
} else {
|
||||
if (! skipRepair(inst, i)) {
|
||||
int[] newUses = makeNewUses(inst);
|
||||
repairInstructionUses(inst, i, newUses);
|
||||
int[] newDefs = makeNewDefs(inst);
|
||||
repairInstructionDefs(inst, i, newDefs, newUses);
|
||||
}
|
||||
if (!skipRepair(inst, i)) {
|
||||
int[] newUses = makeNewUses(inst);
|
||||
repairInstructionUses(inst, i, newUses);
|
||||
int[] newDefs = makeNewDefs(inst);
|
||||
repairInstructionDefs(inst, i, newDefs, newUses);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -295,10 +293,10 @@ public abstract class AbstractSSAConversion {
|
|||
int Y_id = Y.getGraphNodeId();
|
||||
int j = com.ibm.wala.cast.ir.cfg.Util.whichPred(CFG, Y, X);
|
||||
for (int i = 0; i < phiCounts[Y_id]; i++) {
|
||||
SSAPhiInstruction phi = getPhi(Y, i);
|
||||
int oldUse = getUse(phi, j);
|
||||
int newUse = skip(oldUse) ? oldUse: top(oldUse);
|
||||
repairPhiUse(Y, i, j, newUse);
|
||||
SSAPhiInstruction phi = getPhi(Y, i);
|
||||
int oldUse = getUse(phi, j);
|
||||
int newUse = skip(oldUse) ? oldUse : top(oldUse);
|
||||
repairPhiUse(Y, i, j, newUse);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -309,31 +307,30 @@ public abstract class AbstractSSAConversion {
|
|||
for (int i = 0; i < phiCounts[id]; i++) {
|
||||
SSAInstruction A = getPhi(X, i);
|
||||
for (int j = 0; j < getNumberOfDefs(A); j++) {
|
||||
if (! skip(getDef(A, j))) {
|
||||
S[valueMap[getDef(A, j)]].pop();
|
||||
}
|
||||
if (!skip(getDef(A, j))) {
|
||||
S[valueMap[getDef(A, j)]].pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = Xf; i <= X.getLastInstructionIndex(); i++) {
|
||||
SSAInstruction A = instructions[i];
|
||||
if (isAssignInstruction(A)) {
|
||||
S[ getDef(A, 0) ].pop();
|
||||
popAssignment(A, i);
|
||||
S[getDef(A, 0)].pop();
|
||||
popAssignment(A, i);
|
||||
} else if (A != null) {
|
||||
for (int j = 0; j < getNumberOfDefs(A); j++) {
|
||||
if (! skip(getDef(A, j))) {
|
||||
S[valueMap[getDef(A, j)]].pop();
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < getNumberOfDefs(A); j++) {
|
||||
if (!skip(getDef(A, j))) {
|
||||
S[valueMap[getDef(A, j)]].pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private int[] makeNewUses(SSAInstruction inst) {
|
||||
int[] newUses = new int[getNumberOfUses(inst)];
|
||||
for (int j = 0; j < getNumberOfUses(inst); j++) {
|
||||
newUses[j] =
|
||||
skip(getUse(inst, j))? getUse(inst, j): top(getUse(inst, j));
|
||||
newUses[j] = skip(getUse(inst, j)) ? getUse(inst, j) : top(getUse(inst, j));
|
||||
}
|
||||
|
||||
return newUses;
|
||||
|
@ -344,19 +341,19 @@ public abstract class AbstractSSAConversion {
|
|||
|
||||
for (int j = 0; j < getNumberOfDefs(inst); j++) {
|
||||
if (skip(getDef(inst, j))) {
|
||||
newDefs[j] = getDef(inst, j);
|
||||
newDefs[j] = getDef(inst, j);
|
||||
} else {
|
||||
int ii = getNextNewValueNumber();
|
||||
int ii = getNextNewValueNumber();
|
||||
|
||||
if (valueMap.length <= ii) {
|
||||
int[] nvm = new int[valueMap.length * 2 + ii + 1];
|
||||
System.arraycopy(valueMap, 0, nvm, 0, valueMap.length);
|
||||
valueMap = nvm;
|
||||
}
|
||||
if (valueMap.length <= ii) {
|
||||
int[] nvm = new int[valueMap.length * 2 + ii + 1];
|
||||
System.arraycopy(valueMap, 0, nvm, 0, valueMap.length);
|
||||
valueMap = nvm;
|
||||
}
|
||||
|
||||
valueMap[ii] = getDef(inst, j);
|
||||
S[getDef(inst, j)].push(ii);
|
||||
newDefs[j] = ii;
|
||||
valueMap[ii] = getDef(inst, j);
|
||||
S[getDef(inst, j)].push(ii);
|
||||
newDefs[j] = ii;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -366,24 +363,21 @@ public abstract class AbstractSSAConversion {
|
|||
protected boolean skipRepair(SSAInstruction inst, int index) {
|
||||
if (inst == null)
|
||||
return true;
|
||||
for(int i = 0; i < getNumberOfDefs(inst); i++)
|
||||
if (! skip(getDef(inst, i))) return false;
|
||||
for(int i = 0; i < getNumberOfUses(inst); i++)
|
||||
if (! skip(getUse(inst, i))) return false;
|
||||
for (int i = 0; i < getNumberOfDefs(inst); i++)
|
||||
if (!skip(getDef(inst, i)))
|
||||
return false;
|
||||
for (int i = 0; i < getNumberOfUses(inst); i++)
|
||||
if (!skip(getUse(inst, i)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void fail(int v) {
|
||||
Assertions._assert(
|
||||
isConstant(v) || !S[v].isEmpty(),
|
||||
"bad stack for " + v + " while SSA converting");
|
||||
Assertions._assert(isConstant(v) || !S[v].isEmpty(), "bad stack for " + v + " while SSA converting");
|
||||
}
|
||||
|
||||
protected boolean hasDefaultValue(int valueNumber) {
|
||||
return
|
||||
(defaultValues != null)
|
||||
&&
|
||||
(defaultValues.getDefaultValue(symbolTable, valueNumber) != -1);
|
||||
return (defaultValues != null) && (defaultValues.getDefaultValue(symbolTable, valueNumber) != -1);
|
||||
}
|
||||
|
||||
protected int getDefaultValue(int valueNumber) {
|
||||
|
@ -391,11 +385,11 @@ public abstract class AbstractSSAConversion {
|
|||
}
|
||||
|
||||
protected int top(int v) {
|
||||
if (! (isConstant(v) || !S[v].isEmpty())) {
|
||||
if (!(isConstant(v) || !S[v].isEmpty())) {
|
||||
if (hasDefaultValue(v)) {
|
||||
return getDefaultValue(v);
|
||||
return getDefaultValue(v);
|
||||
} else {
|
||||
fail(v);
|
||||
fail(v);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,52 +15,53 @@ import java.util.Collection;
|
|||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SymbolTable;
|
||||
import com.ibm.wala.ssa.ValueDecorator;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
public class AstAssertInstruction extends SSAInstruction {
|
||||
private final int value;
|
||||
private final boolean fromSpecification;
|
||||
|
||||
public AstAssertInstruction(int value, boolean fromSpecification) {
|
||||
this.value = value;
|
||||
this.fromSpecification = fromSpecification;
|
||||
}
|
||||
|
||||
public int getNumberOfUses() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public int getUse(int i) {
|
||||
Assertions._assert(i == 0);
|
||||
return value;
|
||||
}
|
||||
|
||||
public SSAInstruction copyForSSA(int[] defs, int[] uses) {
|
||||
return new AstAssertInstruction(uses==null? value: uses[0], fromSpecification);
|
||||
}
|
||||
private final int value;
|
||||
|
||||
public String toString(SymbolTable symbolTable, ValueDecorator d) {
|
||||
return "assert " + getValueString(symbolTable, d, value) +
|
||||
" (fromSpec: " + fromSpecification + ")";
|
||||
}
|
||||
private final boolean fromSpecification;
|
||||
|
||||
public void visit(IVisitor v) {
|
||||
((AstInstructionVisitor)v).visitAssert(this);
|
||||
}
|
||||
public AstAssertInstruction(int value, boolean fromSpecification) {
|
||||
this.value = value;
|
||||
this.fromSpecification = fromSpecification;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return 2177*value;
|
||||
}
|
||||
public int getNumberOfUses() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public Collection getExceptionTypes() {
|
||||
return null;
|
||||
}
|
||||
public int getUse(int i) {
|
||||
Assertions._assert(i == 0);
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean isFallThrough() {
|
||||
return true;
|
||||
}
|
||||
public SSAInstruction copyForSSA(int[] defs, int[] uses) {
|
||||
return new AstAssertInstruction(uses == null ? value : uses[0], fromSpecification);
|
||||
}
|
||||
|
||||
public boolean isFromSpecification() {
|
||||
return fromSpecification;
|
||||
}
|
||||
public String toString(SymbolTable symbolTable, ValueDecorator d) {
|
||||
return "assert " + getValueString(symbolTable, d, value) + " (fromSpec: " + fromSpecification + ")";
|
||||
}
|
||||
|
||||
public void visit(IVisitor v) {
|
||||
((AstInstructionVisitor) v).visitAssert(this);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return 2177 * value;
|
||||
}
|
||||
|
||||
public Collection<TypeReference> getExceptionTypes() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isFallThrough() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isFromSpecification() {
|
||||
return fromSpecification;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,8 +12,12 @@ package com.ibm.wala.cast.ir.ssa;
|
|||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.ibm.wala.ssa.*;
|
||||
import com.ibm.wala.types.*;
|
||||
import com.ibm.wala.ssa.SSAGetInstruction;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SymbolTable;
|
||||
import com.ibm.wala.ssa.ValueDecorator;
|
||||
import com.ibm.wala.types.FieldReference;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
|
||||
public class AstGlobalRead extends SSAGetInstruction {
|
||||
|
||||
|
@ -38,7 +42,7 @@ public class AstGlobalRead extends SSAGetInstruction {
|
|||
return true;
|
||||
}
|
||||
|
||||
public Collection getExceptionTypes() {
|
||||
public Collection<TypeReference> getExceptionTypes() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,8 +12,12 @@ package com.ibm.wala.cast.ir.ssa;
|
|||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.ibm.wala.ssa.*;
|
||||
import com.ibm.wala.types.*;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SSAPutInstruction;
|
||||
import com.ibm.wala.ssa.SymbolTable;
|
||||
import com.ibm.wala.ssa.ValueDecorator;
|
||||
import com.ibm.wala.types.FieldReference;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
|
||||
public class AstGlobalWrite extends SSAPutInstruction {
|
||||
|
||||
|
@ -38,7 +42,7 @@ public class AstGlobalWrite extends SSAPutInstruction {
|
|||
return true;
|
||||
}
|
||||
|
||||
public Collection getExceptionTypes() {
|
||||
public Collection<TypeReference> getExceptionTypes() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.ir.ssa;
|
||||
|
||||
|
||||
import com.ibm.wala.cast.loader.*;
|
||||
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
|
||||
import com.ibm.wala.cfg.*;
|
||||
|
@ -27,19 +26,16 @@ import java.util.*;
|
|||
|
||||
public class AstIRFactory implements IRFactory {
|
||||
private final boolean keepIR;
|
||||
private final Map keptIRs;
|
||||
|
||||
private final Map<IMethod, IR> keptIRs;
|
||||
|
||||
AstIRFactory(boolean keepIR) {
|
||||
this.keepIR = keepIR;
|
||||
this.keptIRs = (keepIR)? new HashMap(): null;
|
||||
this.keptIRs = (keepIR) ? new HashMap<IMethod, IR>() : null;
|
||||
}
|
||||
|
||||
public ControlFlowGraph makeCFG(final IMethod method,
|
||||
final Context context,
|
||||
final ClassHierarchy cha,
|
||||
final WarningSet warnings)
|
||||
{
|
||||
return ((AstMethod)method).getControlFlowGraph();
|
||||
public ControlFlowGraph makeCFG(final IMethod method, final Context context, final ClassHierarchy cha, final WarningSet warnings) {
|
||||
return ((AstMethod) method).getControlFlowGraph();
|
||||
}
|
||||
|
||||
public class AstIR extends IR {
|
||||
|
@ -47,80 +43,63 @@ public class AstIRFactory implements IRFactory {
|
|||
|
||||
private void setCatchInstructions(SSACFG ssacfg, AbstractCFG oldcfg) {
|
||||
for (int i = 0; i < oldcfg.getNumberOfNodes(); i++)
|
||||
if (oldcfg.isCatchBlock(i)) {
|
||||
ExceptionHandlerBasicBlock B =
|
||||
(ExceptionHandlerBasicBlock) ssacfg.getNode(i);
|
||||
B.setCatchInstruction((SSAGetCaughtExceptionInstruction)
|
||||
getInstructions()[B.getFirstInstructionIndex()]);
|
||||
}
|
||||
if (oldcfg.isCatchBlock(i)) {
|
||||
ExceptionHandlerBasicBlock B = (ExceptionHandlerBasicBlock) ssacfg.getNode(i);
|
||||
B.setCatchInstruction((SSAGetCaughtExceptionInstruction) getInstructions()[B.getFirstInstructionIndex()]);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupCatchTypes(SSACFG cfg, TypeReference[][] catchTypes) {
|
||||
for (int i = 0; i < catchTypes.length; i++) {
|
||||
if (catchTypes[i] != null) {
|
||||
ExceptionHandlerBasicBlock bb =
|
||||
(ExceptionHandlerBasicBlock) cfg.getNode(i);
|
||||
for (int j = 0; j < catchTypes[i].length; j++) {
|
||||
bb.addCaughtExceptionType(catchTypes[i][j]);
|
||||
}
|
||||
}
|
||||
if (catchTypes[i] != null) {
|
||||
ExceptionHandlerBasicBlock bb = (ExceptionHandlerBasicBlock) cfg.getNode(i);
|
||||
for (int j = 0; j < catchTypes[i].length; j++) {
|
||||
bb.addCaughtExceptionType(catchTypes[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected SSA2LocalMap getLocalMap() {
|
||||
return localMap;
|
||||
}
|
||||
|
||||
|
||||
protected String instructionPosition(int instructionIndex) {
|
||||
Position pos =
|
||||
((AstMethod)getMethod()).getSourcePosition(instructionIndex);
|
||||
Position pos = ((AstMethod) getMethod()).getSourcePosition(instructionIndex);
|
||||
if (pos == null) {
|
||||
return "";
|
||||
} else {
|
||||
return pos.toString();
|
||||
return pos.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private AstIR(AstMethod method,
|
||||
SSAInstruction[] instructions,
|
||||
SymbolTable symbolTable,
|
||||
SSACFG cfg,
|
||||
SSAOptions options)
|
||||
{
|
||||
private AstIR(AstMethod method, SSAInstruction[] instructions, SymbolTable symbolTable, SSACFG cfg, SSAOptions options) {
|
||||
super(method, instructions, symbolTable, cfg, options);
|
||||
|
||||
|
||||
setCatchInstructions(getControlFlowGraph(), method.cfg);
|
||||
|
||||
localMap = SSAConversion.convert(method, this, options);
|
||||
|
||||
|
||||
setupCatchTypes(getControlFlowGraph(), method.catchTypes);
|
||||
|
||||
setupLocationMap();
|
||||
}
|
||||
}
|
||||
|
||||
public IR makeIR(final IMethod method,
|
||||
final Context context,
|
||||
final ClassHierarchy cha,
|
||||
final SSAOptions options,
|
||||
final WarningSet warnings)
|
||||
{
|
||||
|
||||
public IR makeIR(final IMethod method, final Context context, final ClassHierarchy cha, final SSAOptions options,
|
||||
final WarningSet warnings) {
|
||||
Assertions._assert(method instanceof AstMethod, method.toString());
|
||||
if (keepIR) {
|
||||
if (keptIRs.containsKey(method)) {
|
||||
return (IR) keptIRs.get(method);
|
||||
return keptIRs.get(method);
|
||||
}
|
||||
}
|
||||
|
||||
AbstractCFG oldCfg = ((AstMethod)method).cfg;
|
||||
SSAInstruction[] instrs = (SSAInstruction[])oldCfg.getInstructions();
|
||||
AbstractCFG oldCfg = ((AstMethod) method).cfg;
|
||||
SSAInstruction[] instrs = (SSAInstruction[]) oldCfg.getInstructions();
|
||||
|
||||
IR newIR =
|
||||
new AstIR((AstMethod)method,
|
||||
instrs,
|
||||
((AstMethod)method).symtab,
|
||||
new SSACFG(method, oldCfg, instrs, warnings),
|
||||
options);
|
||||
IR newIR = new AstIR((AstMethod) method, instrs, ((AstMethod) method).symtab, new SSACFG(method, oldCfg, instrs, warnings),
|
||||
options);
|
||||
|
||||
if (keepIR) {
|
||||
keptIRs.put(method, newIR);
|
||||
|
@ -128,34 +107,25 @@ public class AstIRFactory implements IRFactory {
|
|||
|
||||
return newIR;
|
||||
}
|
||||
|
||||
|
||||
public static IRFactory makeDefaultFactory(final boolean keepAstIRs) {
|
||||
return new DefaultIRFactory() {
|
||||
private final AstIRFactory astFactory = new AstIRFactory(keepAstIRs);
|
||||
|
||||
public IR makeIR(IMethod method,
|
||||
Context context,
|
||||
ClassHierarchy cha,
|
||||
SSAOptions options,
|
||||
WarningSet warnings)
|
||||
{
|
||||
if (method instanceof AstMethod) {
|
||||
return astFactory.makeIR(method, context, cha, options, warnings);
|
||||
} else {
|
||||
return super.makeIR(method, context, cha, options, warnings);
|
||||
}
|
||||
public IR makeIR(IMethod method, Context context, ClassHierarchy cha, SSAOptions options, WarningSet warnings) {
|
||||
if (method instanceof AstMethod) {
|
||||
return astFactory.makeIR(method, context, cha, options, warnings);
|
||||
} else {
|
||||
return super.makeIR(method, context, cha, options, warnings);
|
||||
}
|
||||
}
|
||||
|
||||
public ControlFlowGraph makeCFG(IMethod method,
|
||||
Context context,
|
||||
ClassHierarchy cha,
|
||||
WarningSet warnings)
|
||||
{
|
||||
if (method instanceof AstMethod) {
|
||||
return astFactory.makeCFG(method, context, cha, warnings);
|
||||
} else {
|
||||
return super.makeCFG(method, context, cha, warnings);
|
||||
}
|
||||
public ControlFlowGraph makeCFG(IMethod method, Context context, ClassHierarchy cha, WarningSet warnings) {
|
||||
if (method instanceof AstMethod) {
|
||||
return astFactory.makeCFG(method, context, cha, warnings);
|
||||
} else {
|
||||
return super.makeCFG(method, context, cha, warnings);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ package com.ibm.wala.cast.ir.ssa;
|
|||
import java.util.Collection;
|
||||
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
|
||||
public abstract class AstLexicalAccess extends SSAInstruction {
|
||||
|
||||
|
@ -71,7 +72,7 @@ public abstract class AstLexicalAccess extends SSAInstruction {
|
|||
return true;
|
||||
}
|
||||
|
||||
public Collection getExceptionTypes() {
|
||||
public Collection<TypeReference> getExceptionTypes() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,9 +10,14 @@
|
|||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.ir.ssa;
|
||||
|
||||
import com.ibm.wala.ssa.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import java.util.*;
|
||||
import com.ibm.wala.ssa.SSAAbstractUnaryInstruction;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SymbolTable;
|
||||
import com.ibm.wala.ssa.ValueDecorator;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
|
||||
public class EachElementGetInstruction extends SSAAbstractUnaryInstruction {
|
||||
|
||||
|
@ -34,7 +39,7 @@ public class EachElementGetInstruction extends SSAAbstractUnaryInstruction {
|
|||
((AstInstructionVisitor) v).visitEachElementGet(this);
|
||||
}
|
||||
|
||||
public Collection getExceptionTypes() {
|
||||
return Collections.EMPTY_SET;
|
||||
public Collection<TypeReference> getExceptionTypes() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,14 @@
|
|||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.ir.ssa;
|
||||
|
||||
import com.ibm.wala.ssa.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import java.util.*;
|
||||
import com.ibm.wala.ssa.SSAAbstractUnaryInstruction;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SymbolTable;
|
||||
import com.ibm.wala.ssa.ValueDecorator;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
|
||||
public class EachElementHasNextInstruction extends SSAAbstractUnaryInstruction {
|
||||
|
||||
|
@ -34,7 +39,7 @@ public class EachElementHasNextInstruction extends SSAAbstractUnaryInstruction {
|
|||
((AstInstructionVisitor) v).visitEachElementHasNext(this);
|
||||
}
|
||||
|
||||
public Collection getExceptionTypes() {
|
||||
return Collections.EMPTY_SET;
|
||||
public Collection<TypeReference> getExceptionTypes() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,12 @@
|
|||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.ir.ssa;
|
||||
|
||||
import com.ibm.wala.ssa.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import java.util.*;
|
||||
import com.ibm.wala.ssa.SSAAbstractThrowInstruction;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
|
||||
public class NonExceptingThrowInstruction extends SSAAbstractThrowInstruction {
|
||||
|
||||
|
@ -31,8 +34,8 @@ public class NonExceptingThrowInstruction extends SSAAbstractThrowInstruction {
|
|||
((AstInstructionVisitor)v).visitNonExceptingThrow(this);
|
||||
}
|
||||
|
||||
public Collection getExceptionTypes() {
|
||||
return Collections.EMPTY_SET;
|
||||
public Collection<TypeReference> getExceptionTypes() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -38,14 +38,17 @@ import com.ibm.wala.util.intset.MutableIntSet;
|
|||
|
||||
/**
|
||||
* @author Julian Dolby
|
||||
*
|
||||
* Standard SSA conversion for local value numbers.
|
||||
*
|
||||
* Standard SSA conversion for local value numbers.
|
||||
*/
|
||||
public class SSAConversion extends AbstractSSAConversion {
|
||||
|
||||
public static boolean DEBUG = false;
|
||||
|
||||
public static boolean DEBUG_UNDO = true;
|
||||
|
||||
public static boolean DEBUG_NAMES = true;
|
||||
|
||||
public static boolean DUMP = false;
|
||||
|
||||
private final AstIR ir;
|
||||
|
@ -66,32 +69,35 @@ public class SSAConversion extends AbstractSSAConversion {
|
|||
// Copy propagation history
|
||||
//
|
||||
|
||||
private final Map copyPropagationMap;
|
||||
private final Stack R[];
|
||||
private final Map<Object, CopyPropagationRecord> copyPropagationMap;
|
||||
|
||||
private final Stack<CopyPropagationRecord> R[];
|
||||
|
||||
private static class UseRecord {
|
||||
final int instructionIndex;
|
||||
|
||||
final int useNumber;
|
||||
|
||||
private UseRecord(int instructionIndex, int useNumber) {
|
||||
this.useNumber = useNumber;
|
||||
this.instructionIndex = instructionIndex;
|
||||
}
|
||||
|
||||
|
||||
public int hashCode() {
|
||||
return useNumber*instructionIndex;
|
||||
return useNumber * instructionIndex;
|
||||
}
|
||||
|
||||
|
||||
public boolean equals(Object o) {
|
||||
return (o instanceof UseRecord) &&
|
||||
instructionIndex==((UseRecord)o).instructionIndex &&
|
||||
useNumber==((UseRecord)o).useNumber;
|
||||
return (o instanceof UseRecord) && instructionIndex == ((UseRecord) o).instructionIndex
|
||||
&& useNumber == ((UseRecord) o).useNumber;
|
||||
}
|
||||
}
|
||||
|
||||
private class PhiUseRecord {
|
||||
final int BBnumber;
|
||||
|
||||
final int phiNumber;
|
||||
|
||||
final int useNumber;
|
||||
|
||||
private PhiUseRecord(int BBnumber, int phiNumber, int useNumber) {
|
||||
|
@ -99,68 +105,73 @@ public class SSAConversion extends AbstractSSAConversion {
|
|||
this.phiNumber = phiNumber;
|
||||
this.useNumber = useNumber;
|
||||
}
|
||||
|
||||
|
||||
public int hashCode() {
|
||||
return phiNumber*BBnumber*useNumber;
|
||||
return phiNumber * BBnumber * useNumber;
|
||||
}
|
||||
|
||||
|
||||
public boolean equals(Object o) {
|
||||
return (o instanceof PhiUseRecord) &&
|
||||
BBnumber==((PhiUseRecord)o).BBnumber &&
|
||||
phiNumber==((PhiUseRecord)o).phiNumber &&
|
||||
useNumber==((PhiUseRecord)o).useNumber;
|
||||
return (o instanceof PhiUseRecord) && BBnumber == ((PhiUseRecord) o).BBnumber && phiNumber == ((PhiUseRecord) o).phiNumber
|
||||
&& useNumber == ((PhiUseRecord) o).useNumber;
|
||||
}
|
||||
}
|
||||
|
||||
private class CopyPropagationRecord {
|
||||
final int lhs;
|
||||
|
||||
final int rhs;
|
||||
|
||||
final int instructionIndex;
|
||||
final Set renamedUses = new HashSet(2);
|
||||
private final Set childRecords = new HashSet(1);
|
||||
|
||||
final Set<Object> renamedUses = new HashSet<Object>(2);
|
||||
|
||||
private final Set<CopyPropagationRecord> childRecords = new HashSet<CopyPropagationRecord>(1);
|
||||
|
||||
public int hashCode() {
|
||||
return instructionIndex;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
return (o instanceof CopyPropagationRecord) &&
|
||||
instructionIndex==((CopyPropagationRecord)o).instructionIndex;
|
||||
return (o instanceof CopyPropagationRecord) && instructionIndex == ((CopyPropagationRecord) o).instructionIndex;
|
||||
}
|
||||
|
||||
private CopyPropagationRecord(int instructionIndex, int lhs, int rhs) {
|
||||
if (DEBUG_UNDO) Trace.println("new copy record for instruction #" + instructionIndex + ", rhs value is " + rhs);
|
||||
if (DEBUG_UNDO)
|
||||
Trace.println("new copy record for instruction #" + instructionIndex + ", rhs value is " + rhs);
|
||||
this.lhs = lhs;
|
||||
this.rhs = rhs;
|
||||
this.instructionIndex = instructionIndex;
|
||||
}
|
||||
|
||||
private void addChild(CopyPropagationRecord rec) {
|
||||
if (DEBUG_UNDO) Trace.println("("+rec.instructionIndex+","+rec.rhs+") is a child of ("+instructionIndex+","+rhs+")");
|
||||
if (DEBUG_UNDO)
|
||||
Trace.println("(" + rec.instructionIndex + "," + rec.rhs + ") is a child of (" + instructionIndex + "," + rhs + ")");
|
||||
childRecords.add(rec);
|
||||
}
|
||||
|
||||
private void addUse(int instructionIndex, int use) {
|
||||
if (DEBUG_UNDO) Trace.println("propagated use of (" + this.instructionIndex + "," + this.rhs + ") at use #" + use + " of instruction #" + instructionIndex);
|
||||
if (DEBUG_UNDO)
|
||||
Trace.println("propagated use of (" + this.instructionIndex + "," + this.rhs + ") at use #" + use + " of instruction #"
|
||||
+ instructionIndex);
|
||||
UseRecord rec = new UseRecord(instructionIndex, use);
|
||||
copyPropagationMap.put(rec, this);
|
||||
renamedUses.add( rec );
|
||||
renamedUses.add(rec);
|
||||
}
|
||||
|
||||
private void addUse(int BB, int phiNumber, int use) {
|
||||
PhiUseRecord rec = new PhiUseRecord(BB, phiNumber, use);
|
||||
copyPropagationMap.put(rec, this);
|
||||
renamedUses.add( rec );
|
||||
renamedUses.add(rec);
|
||||
}
|
||||
|
||||
private SSAInstruction undo(SSAInstruction inst, int use, int val) {
|
||||
int c = getNumberOfUses(inst);
|
||||
int[] newUses = new int[ c ];
|
||||
for(int i = 0; i < c; i++) {
|
||||
if (i == use)
|
||||
newUses[i] = val;
|
||||
else
|
||||
newUses[i] = getUse(inst, i);
|
||||
int[] newUses = new int[c];
|
||||
for (int i = 0; i < c; i++) {
|
||||
if (i == use)
|
||||
newUses[i] = val;
|
||||
else
|
||||
newUses[i] = getUse(inst, i);
|
||||
}
|
||||
|
||||
return inst.copyForSSA(null, newUses);
|
||||
|
@ -169,43 +180,45 @@ public class SSAConversion extends AbstractSSAConversion {
|
|||
private void undo(int rhs) {
|
||||
int lhs = symtab.newSymbol();
|
||||
|
||||
instructions[ instructionIndex ] = new AssignInstruction(lhs, rhs);
|
||||
|
||||
if (DEBUG_UNDO) Trace.println("recreating assignment at " + instructionIndex + " as " + lhs + " = " + rhs);
|
||||
instructions[instructionIndex] = new AssignInstruction(lhs, rhs);
|
||||
|
||||
for(Iterator uses = renamedUses.iterator(); uses.hasNext(); ) {
|
||||
Object x = uses.next();
|
||||
if (x instanceof UseRecord) {
|
||||
UseRecord use = (UseRecord)x;
|
||||
int idx = use.instructionIndex;
|
||||
SSAInstruction inst = instructions[ idx ];
|
||||
if (DEBUG_UNDO)
|
||||
Trace.println("recreating assignment at " + instructionIndex + " as " + lhs + " = " + rhs);
|
||||
|
||||
if (DEBUG_UNDO) Trace.println("Changing use #" + use.useNumber + " of inst #" + idx + " to val " + lhs);
|
||||
for (Iterator<Object> uses = renamedUses.iterator(); uses.hasNext();) {
|
||||
Object x = uses.next();
|
||||
if (x instanceof UseRecord) {
|
||||
UseRecord use = (UseRecord) x;
|
||||
int idx = use.instructionIndex;
|
||||
SSAInstruction inst = instructions[idx];
|
||||
|
||||
if (use.useNumber >= 0) {
|
||||
instructions[idx] = undo(inst, use.useNumber, lhs);
|
||||
} else {
|
||||
lexicalInfo.getExposedUses(idx)[-use.useNumber - 1] = lhs;
|
||||
}
|
||||
copyPropagationMap.remove( use );
|
||||
} else {
|
||||
PhiUseRecord use = (PhiUseRecord)x;
|
||||
int bb = use.BBnumber;
|
||||
int phi = use.phiNumber;
|
||||
SSACFG.BasicBlock BB = (SSACFG.BasicBlock)CFG.getNode(bb);
|
||||
BB.addPhiForLocal(phi, (SSAPhiInstruction)undo(BB.getPhiForLocal(phi), use.useNumber, lhs));
|
||||
copyPropagationMap.remove( use );
|
||||
}
|
||||
if (DEBUG_UNDO)
|
||||
Trace.println("Changing use #" + use.useNumber + " of inst #" + idx + " to val " + lhs);
|
||||
|
||||
if (use.useNumber >= 0) {
|
||||
instructions[idx] = undo(inst, use.useNumber, lhs);
|
||||
} else {
|
||||
lexicalInfo.getExposedUses(idx)[-use.useNumber - 1] = lhs;
|
||||
}
|
||||
copyPropagationMap.remove(use);
|
||||
} else {
|
||||
PhiUseRecord use = (PhiUseRecord) x;
|
||||
int bb = use.BBnumber;
|
||||
int phi = use.phiNumber;
|
||||
SSACFG.BasicBlock BB = (SSACFG.BasicBlock) CFG.getNode(bb);
|
||||
BB.addPhiForLocal(phi, (SSAPhiInstruction) undo(BB.getPhiForLocal(phi), use.useNumber, lhs));
|
||||
copyPropagationMap.remove(use);
|
||||
}
|
||||
}
|
||||
|
||||
for(Iterator cs = childRecords.iterator(); cs.hasNext(); ) {
|
||||
((CopyPropagationRecord)cs.next()).undo( lhs );
|
||||
for (Iterator<CopyPropagationRecord> cs = childRecords.iterator(); cs.hasNext();) {
|
||||
cs.next().undo(lhs);
|
||||
}
|
||||
}
|
||||
|
||||
public void undo() {
|
||||
undo( this.rhs );
|
||||
copyPropagationMap.remove( new UseRecord(instructionIndex, rhs) );
|
||||
undo(this.rhs);
|
||||
copyPropagationMap.remove(new UseRecord(instructionIndex, rhs));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -218,57 +231,55 @@ public class SSAConversion extends AbstractSSAConversion {
|
|||
SSAInformation info = (SSAInformation) ir.getLocalMap();
|
||||
info.copyUse(fromInst, fromUse, toInst, toUse);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// SSA2LocalMap implementation for SSAConversion
|
||||
//
|
||||
private class SSAInformation implements com.ibm.wala.ssa.IR.SSA2LocalMap {
|
||||
|
||||
|
||||
public String[] getLocalNames(int pc, int vn) {
|
||||
int v = skip(vn)||vn>=valueMap.length? vn: valueMap[vn];
|
||||
int v = skip(vn) || vn >= valueMap.length ? vn : valueMap[vn];
|
||||
String[][] namesData = debugInfo.getSourceNamesForValues();
|
||||
if (namesData == null || namesData.length <= v)
|
||||
return new String[0];
|
||||
else
|
||||
return namesData[v];
|
||||
return new String[0];
|
||||
else
|
||||
return namesData[v];
|
||||
}
|
||||
|
||||
private void undoCopyPropagation(int instructionIndex, int useNumber) {
|
||||
|
||||
if (DEBUG_UNDO)
|
||||
Trace.println("undoing for use #" + useNumber + " of inst #" + instructionIndex);
|
||||
Trace.println("undoing for use #" + useNumber + " of inst #" + instructionIndex);
|
||||
|
||||
UseRecord use = new UseRecord(instructionIndex, useNumber);
|
||||
if (copyPropagationMap.containsKey(use)) {
|
||||
((CopyPropagationRecord)copyPropagationMap.get(use)).undo();
|
||||
copyPropagationMap.get(use).undo();
|
||||
}
|
||||
}
|
||||
|
||||
private void copyUse(int fromInst, int fromUse, int toInst, int toUse) {
|
||||
UseRecord use = new UseRecord(fromInst, fromUse);
|
||||
if (copyPropagationMap.containsKey(use)) {
|
||||
((CopyPropagationRecord)copyPropagationMap.get(use)).addUse(toInst, toUse);
|
||||
copyPropagationMap.get(use).addUse(toInst, toUse);
|
||||
}
|
||||
}
|
||||
|
||||
private Map getCopyHistory() {
|
||||
private Map<Object, CopyPropagationRecord> getCopyHistory() {
|
||||
return copyPropagationMap;
|
||||
}
|
||||
}
|
||||
|
||||
private CopyPropagationRecord topR(int v) {
|
||||
if (R[v] != null && !R[v].isEmpty()) {
|
||||
CopyPropagationRecord rec = (CopyPropagationRecord)R[v].peek();
|
||||
CopyPropagationRecord rec = (CopyPropagationRecord) R[v].peek();
|
||||
if (top(v) == rec.rhs) {
|
||||
return rec;
|
||||
return rec;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// implementation of AbstractSSAConversion hooks
|
||||
//
|
||||
|
@ -331,7 +342,7 @@ public class SSAConversion extends AbstractSSAConversion {
|
|||
}
|
||||
|
||||
protected SSAPhiInstruction repairPhiDefs(SSAPhiInstruction phi, int[] newDefs) {
|
||||
return (SSAPhiInstruction)phi.copyForSSA(newDefs, null);
|
||||
return (SSAPhiInstruction) phi.copyForSSA(newDefs, null);
|
||||
}
|
||||
|
||||
protected void repairPhiUse(SSACFG.BasicBlock BB, int phiIndex, int rvalIndex, int newRval) {
|
||||
|
@ -340,11 +351,11 @@ public class SSAConversion extends AbstractSSAConversion {
|
|||
int[] newUses = new int[getNumberOfUses(phi)];
|
||||
for (int v = 0; v < newUses.length; v++) {
|
||||
int oldUse = getUse(phi, v);
|
||||
int newUse = (v==rvalIndex)? newRval: oldUse;
|
||||
int newUse = (v == rvalIndex) ? newRval : oldUse;
|
||||
newUses[v] = newUse;
|
||||
|
||||
if (v==rvalIndex && topR(oldUse) != null) {
|
||||
topR(oldUse).addUse(BB.getGraphNodeId(), phiIndex, v);
|
||||
if (v == rvalIndex && topR(oldUse) != null) {
|
||||
topR(oldUse).addUse(BB.getGraphNodeId(), phiIndex, v);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -358,36 +369,36 @@ public class SSAConversion extends AbstractSSAConversion {
|
|||
copyNames(rhs, lhs);
|
||||
|
||||
CopyPropagationRecord rec = new CopyPropagationRecord(index, lhs, newRhs);
|
||||
R[lhs].push( rec );
|
||||
R[lhs].push(rec);
|
||||
if (topR(rhs) != null) {
|
||||
topR(rhs).addChild( rec );
|
||||
topR(rhs).addChild(rec);
|
||||
}
|
||||
}
|
||||
|
||||
protected void repairInstructionUses(SSAInstruction inst, int index, int[] newUses){
|
||||
protected void repairInstructionUses(SSAInstruction inst, int index, int[] newUses) {
|
||||
for (int j = 0; j < getNumberOfUses(inst); j++) {
|
||||
if (topR(getUse(inst, j)) != null) {
|
||||
topR(getUse(inst, j)).addUse(index, j);
|
||||
topR(getUse(inst, j)).addUse(index, j);
|
||||
}
|
||||
}
|
||||
|
||||
int[] lexicalUses = lexicalInfo.getExposedUses(index);
|
||||
if (lexicalUses != null) {
|
||||
for(int j = 0; j < lexicalUses.length; j++) {
|
||||
int lexicalUse = lexicalUses[j];
|
||||
if (lexicalUse != -1 && !skip(lexicalUse)) {
|
||||
if (S[lexicalUse].isEmpty()) {
|
||||
lexicalUses[j] = -1;
|
||||
} else {
|
||||
int newUse = top(lexicalUse);
|
||||
|
||||
lexicalUses[j] = newUse;
|
||||
for (int j = 0; j < lexicalUses.length; j++) {
|
||||
int lexicalUse = lexicalUses[j];
|
||||
if (lexicalUse != -1 && !skip(lexicalUse)) {
|
||||
if (S[lexicalUse].isEmpty()) {
|
||||
lexicalUses[j] = -1;
|
||||
} else {
|
||||
int newUse = top(lexicalUse);
|
||||
|
||||
if (topR(lexicalUse) != null) {
|
||||
topR(lexicalUse).addUse(index, -j - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
lexicalUses[j] = newUse;
|
||||
|
||||
if (topR(lexicalUse) != null) {
|
||||
topR(lexicalUse).addUse(index, -j - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -405,18 +416,19 @@ public class SSAConversion extends AbstractSSAConversion {
|
|||
}
|
||||
|
||||
protected boolean skipRepair(SSAInstruction inst, int index) {
|
||||
if (! super.skipRepair(inst, index)) {
|
||||
if (!super.skipRepair(inst, index)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (index == -1) return true;
|
||||
if (index == -1)
|
||||
return true;
|
||||
|
||||
int[] lexicalUses = lexicalInfo.getExposedUses(index);
|
||||
if (lexicalUses != null) {
|
||||
for(int j = 0; j < lexicalUses.length; j++) {
|
||||
if (! skip(lexicalUses[j])) {
|
||||
return false;
|
||||
}
|
||||
for (int j = 0; j < lexicalUses.length; j++) {
|
||||
if (!skip(lexicalUses[j])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -427,12 +439,11 @@ public class SSAConversion extends AbstractSSAConversion {
|
|||
* @param ir
|
||||
* @param options
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private SSAConversion(AstMethod M, AstIR ir, SSAOptions options) {
|
||||
super(ir, options);
|
||||
this.copyPropagationMap =
|
||||
(ir.getLocalMap() instanceof SSAInformation)?
|
||||
((SSAInformation)ir.getLocalMap()).getCopyHistory():
|
||||
new HashMap();
|
||||
this.copyPropagationMap = (ir.getLocalMap() instanceof SSAInformation) ? ((SSAInformation) ir.getLocalMap()).getCopyHistory()
|
||||
: new HashMap<Object,CopyPropagationRecord>();
|
||||
|
||||
this.ir = ir;
|
||||
this.debugInfo = M.debugInfo;
|
||||
|
@ -440,24 +451,25 @@ public class SSAConversion extends AbstractSSAConversion {
|
|||
this.symtab = ir.getSymbolTable();
|
||||
this.R = new Stack[ir.getSymbolTable().getMaxValueNumber() + 1];
|
||||
|
||||
for(int i = 0; i < CFG.getNumberOfNodes(); i++) {
|
||||
for (int i = 0; i < CFG.getNumberOfNodes(); i++) {
|
||||
SSACFG.BasicBlock bb = (SSACFG.BasicBlock) CFG.getNode(i);
|
||||
if (bb.hasPhi()) {
|
||||
int n = 0;
|
||||
for(Iterator X = bb.iteratePhis(); X.hasNext(); n++) X.next();
|
||||
phiCounts[i] = n;
|
||||
int n = 0;
|
||||
for (Iterator X = bb.iteratePhis(); X.hasNext(); n++)
|
||||
X.next();
|
||||
phiCounts[i] = n;
|
||||
}
|
||||
}
|
||||
|
||||
this.nextSSAValue = ir.getNumberOfParameters()+1;
|
||||
this.nextSSAValue = ir.getNumberOfParameters() + 1;
|
||||
|
||||
int[] exitLive = lexicalInfo.getExitExposedUses();
|
||||
BitVector v = new BitVector();
|
||||
if (exitLive != null)
|
||||
for(int i = 0; i < exitLive.length; i++)
|
||||
v.set( exitLive[i] );
|
||||
if (exitLive != null)
|
||||
for (int i = 0; i < exitLive.length; i++)
|
||||
v.set(exitLive[i]);
|
||||
this.liveness = LiveAnalysis.perform(CFG, symtab, v);
|
||||
|
||||
|
||||
if (DEBUG) {
|
||||
Trace.println(liveness);
|
||||
}
|
||||
|
@ -466,39 +478,36 @@ public class SSAConversion extends AbstractSSAConversion {
|
|||
protected int getNextNewValueNumber() {
|
||||
while (symtab.isConstant(nextSSAValue) || skip(nextSSAValue))
|
||||
++nextSSAValue;
|
||||
symtab.ensureSymbol( nextSSAValue );
|
||||
symtab.ensureSymbol(nextSSAValue);
|
||||
return nextSSAValue++;
|
||||
}
|
||||
|
||||
private void copyNames(int to, int from) {
|
||||
String[][] namesData = debugInfo.getSourceNamesForValues();
|
||||
if (namesData != null &&
|
||||
namesData.length > from &&
|
||||
namesData[from] != null)
|
||||
{
|
||||
if (namesData != null && namesData.length > from && namesData[from] != null) {
|
||||
if (namesData[to] == null) {
|
||||
namesData[to] = namesData[from];
|
||||
namesData[to] = namesData[from];
|
||||
} else {
|
||||
String[] newNames = new String[ namesData[from].length+namesData[to].length ];
|
||||
System.arraycopy(namesData[from], 0, newNames, 0, namesData[from].length);
|
||||
System.arraycopy(namesData[to], 0, newNames, namesData[from].length, namesData[to].length);
|
||||
namesData[to] = newNames;
|
||||
String[] newNames = new String[namesData[from].length + namesData[to].length];
|
||||
System.arraycopy(namesData[from], 0, newNames, 0, namesData[from].length);
|
||||
System.arraycopy(namesData[to], 0, newNames, namesData[from].length, namesData[to].length);
|
||||
namesData[to] = newNames;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void initializeVariables() {
|
||||
for (int V = 1; V <= getMaxValueNumber(); V++) {
|
||||
if (! skip(V)) {
|
||||
R[V] = new Stack();
|
||||
if (!skip(V)) {
|
||||
R[V] = new Stack();
|
||||
}
|
||||
}
|
||||
|
||||
int[] params = symtab.getParameterValueNumbers();
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
if (! skip( params[i] )) {
|
||||
S[params[i]].push( params[i] );
|
||||
valueMap[ params[i] ] = params[i];
|
||||
if (!skip(params[i])) {
|
||||
S[params[i]].push(params[i]);
|
||||
valueMap[params[i]] = params[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -507,11 +516,11 @@ public class SSAConversion extends AbstractSSAConversion {
|
|||
protected void repairExit() {
|
||||
int[] exitLives = lexicalInfo.getExitExposedUses();
|
||||
if (exitLives != null) {
|
||||
for(int i = 0; i < exitLives.length; i++) {
|
||||
if (! skip(exitLives[i])) {
|
||||
Assertions._assert(! S[exitLives[i]].isEmpty());
|
||||
exitLives[i] = top(exitLives[i]);
|
||||
}
|
||||
for (int i = 0; i < exitLives.length; i++) {
|
||||
if (!skip(exitLives[i])) {
|
||||
Assertions._assert(!S[exitLives[i]].isEmpty());
|
||||
exitLives[i] = top(exitLives[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -521,8 +530,8 @@ public class SSAConversion extends AbstractSSAConversion {
|
|||
//
|
||||
|
||||
protected void fail(int v) {
|
||||
System.err.println( "during SSA conversion of the following IR:" );
|
||||
System.err.println( ir );
|
||||
System.err.println("during SSA conversion of the following IR:");
|
||||
System.err.println(ir);
|
||||
super.fail(v);
|
||||
}
|
||||
|
||||
|
@ -534,18 +543,18 @@ public class SSAConversion extends AbstractSSAConversion {
|
|||
super.perform();
|
||||
|
||||
if (DUMP) {
|
||||
Trace.println( ir );
|
||||
Trace.println(ir);
|
||||
if (lexicalInfo != null) {
|
||||
for(int i = 0; i < instructions.length; i++) {
|
||||
int[] lexicalUses = lexicalInfo.getExposedUses(i);
|
||||
if (lexicalUses != null) {
|
||||
Trace.print("extra uses for " + instructions[i] + ": ");
|
||||
for(int j = 0; j < lexicalUses.length; j++) {
|
||||
Trace.print( new Integer(lexicalUses[j]).toString() + " " );
|
||||
}
|
||||
Trace.println("");
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < instructions.length; i++) {
|
||||
int[] lexicalUses = lexicalInfo.getExposedUses(i);
|
||||
if (lexicalUses != null) {
|
||||
Trace.print("extra uses for " + instructions[i] + ": ");
|
||||
for (int j = 0; j < lexicalUses.length; j++) {
|
||||
Trace.print(new Integer(lexicalUses[j]).toString() + " ");
|
||||
}
|
||||
Trace.println("");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -556,23 +565,20 @@ public class SSAConversion extends AbstractSSAConversion {
|
|||
IInstruction[] insts = ir.getInstructions();
|
||||
MutableIntSet foundOne = new BitVectorIntSet();
|
||||
MutableIntSet foundTwo = new BitVectorIntSet();
|
||||
for(int i = 0; i < insts.length; i++) {
|
||||
for (int i = 0; i < insts.length; i++) {
|
||||
SSAInstruction inst = (SSAInstruction) insts[i];
|
||||
if (inst != null) {
|
||||
for(int j = 0; j < inst.getNumberOfDefs(); j++) {
|
||||
int def = inst.getDef(j);
|
||||
if (def != -1) {
|
||||
if (foundOne.contains(def) ||
|
||||
ir.getSymbolTable().isConstant(def) ||
|
||||
def <= ir.getNumberOfParameters() ||
|
||||
inst instanceof AssignInstruction)
|
||||
{
|
||||
foundTwo.add(def);
|
||||
} else {
|
||||
foundOne.add(def);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < inst.getNumberOfDefs(); j++) {
|
||||
int def = inst.getDef(j);
|
||||
if (def != -1) {
|
||||
if (foundOne.contains(def) || ir.getSymbolTable().isConstant(def) || def <= ir.getNumberOfParameters()
|
||||
|| inst instanceof AssignInstruction) {
|
||||
foundTwo.add(def);
|
||||
} else {
|
||||
foundOne.add(def);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -583,25 +589,24 @@ public class SSAConversion extends AbstractSSAConversion {
|
|||
return convert(M, ir, options, valuesToConvert(ir));
|
||||
}
|
||||
|
||||
public static SSA2LocalMap convert(AstMethod M,
|
||||
final AstIR ir,
|
||||
SSAOptions options,
|
||||
final IntSet values)
|
||||
{
|
||||
public static SSA2LocalMap convert(AstMethod M, final AstIR ir, SSAOptions options, final IntSet values) {
|
||||
try {
|
||||
if (DEBUG) {
|
||||
Trace.println("starting conversion for " + values);
|
||||
Trace.println( ir );
|
||||
Trace.println("starting conversion for " + values);
|
||||
Trace.println(ir);
|
||||
}
|
||||
if (DEBUG_UNDO) Trace.println(">>> starting " + ir.getMethod());
|
||||
if (DEBUG_UNDO)
|
||||
Trace.println(">>> starting " + ir.getMethod());
|
||||
SSAConversion ssa = new SSAConversion(M, ir, options) {
|
||||
final int limit = ir.getSymbolTable().getMaxValueNumber();
|
||||
protected boolean skip(int i) {
|
||||
return (i >= 0) && (i <= limit) && (!values.contains(i));
|
||||
}
|
||||
final int limit = ir.getSymbolTable().getMaxValueNumber();
|
||||
|
||||
protected boolean skip(int i) {
|
||||
return (i >= 0) && (i <= limit) && (!values.contains(i));
|
||||
}
|
||||
};
|
||||
ssa.perform();
|
||||
if (DEBUG_UNDO) Trace.println("<<< done " + ir.getMethod());
|
||||
if (DEBUG_UNDO)
|
||||
Trace.println("<<< done " + ir.getMethod());
|
||||
return ssa.getComputedLocalMap();
|
||||
} catch (RuntimeException e) {
|
||||
Trace.println("exception " + e + " while converting:");
|
||||
|
|
|
@ -13,6 +13,7 @@ package com.ibm.wala.cast.ir.ssa.analysis;
|
|||
import java.util.Iterator;
|
||||
|
||||
import com.ibm.wala.cfg.ControlFlowGraph;
|
||||
import com.ibm.wala.cfg.IBasicBlock;
|
||||
import com.ibm.wala.dataflow.graph.AbstractMeetOperator;
|
||||
import com.ibm.wala.dataflow.graph.BitVectorSolver;
|
||||
import com.ibm.wala.dataflow.graph.BitVectorUnion;
|
||||
|
@ -152,15 +153,15 @@ public class LiveAnalysis {
|
|||
}
|
||||
}
|
||||
|
||||
final BitVectorSolver S = new BitVectorSolver(new IKilldallFramework() {
|
||||
private final Graph G = GraphInverter.invert(cfg);
|
||||
final BitVectorSolver<IBasicBlock> S = new BitVectorSolver<IBasicBlock>(new IKilldallFramework<IBasicBlock>() {
|
||||
private final Graph<IBasicBlock> G = GraphInverter.invert(cfg);
|
||||
|
||||
public Graph getFlowGraph() {
|
||||
public Graph<IBasicBlock> getFlowGraph() {
|
||||
return G;
|
||||
}
|
||||
|
||||
public ITransferFunctionProvider getTransferFunctionProvider() {
|
||||
return new ITransferFunctionProvider() {
|
||||
public ITransferFunctionProvider<IBasicBlock> getTransferFunctionProvider() {
|
||||
return new ITransferFunctionProvider<IBasicBlock>() {
|
||||
|
||||
public boolean hasNodeTransferFunctions() {
|
||||
return true;
|
||||
|
@ -170,7 +171,7 @@ public class LiveAnalysis {
|
|||
return false;
|
||||
}
|
||||
|
||||
public UnaryOperator getNodeTransferFunction(Object node) {
|
||||
public UnaryOperator getNodeTransferFunction(IBasicBlock node) {
|
||||
if (((SSACFG.BasicBlock) node).isExitBlock()) {
|
||||
return new ExitBlockGenKillOperator();
|
||||
} else {
|
||||
|
@ -178,7 +179,7 @@ public class LiveAnalysis {
|
|||
}
|
||||
}
|
||||
|
||||
public UnaryOperator getEdgeTransferFunction(Object s, Object d) {
|
||||
public UnaryOperator getEdgeTransferFunction(IBasicBlock s, IBasicBlock d) {
|
||||
Assertions.UNREACHABLE();
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ import com.ibm.wala.cast.util.CAstPrinter;
|
|||
import com.ibm.wala.cfg.AbstractCFG;
|
||||
import com.ibm.wala.cfg.IBasicBlock;
|
||||
import com.ibm.wala.classLoader.IClassLoader;
|
||||
import com.ibm.wala.classLoader.IField;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.shrikeBT.BinaryOpInstruction;
|
||||
import com.ibm.wala.shrikeBT.ConditionalBranchInstruction;
|
||||
|
@ -331,7 +332,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
|
||||
private int lastIndex = -2;
|
||||
|
||||
private final List instructions = new ArrayList();
|
||||
private final List<SSAInstruction> instructions = new ArrayList<SSAInstruction>();
|
||||
|
||||
public int getNumber() {
|
||||
return getGraphNodeId();
|
||||
|
@ -389,7 +390,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
return "PreBB" + number + ":" + firstIndex + ".." + lastIndex;
|
||||
}
|
||||
|
||||
List instructions() {
|
||||
List<SSAInstruction> instructions() {
|
||||
return instructions;
|
||||
}
|
||||
|
||||
|
@ -401,7 +402,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
return null;
|
||||
}
|
||||
|
||||
public Iterator iterateAllInstructions() {
|
||||
public Iterator<SSAInstruction> iterateAllInstructions() {
|
||||
return instructions.iterator();
|
||||
}
|
||||
}
|
||||
|
@ -452,12 +453,12 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
public final class IncipientCFG extends SparseNumberedGraph {
|
||||
public final class IncipientCFG extends SparseNumberedGraph<PreBasicBlock> {
|
||||
|
||||
protected class Unwind {
|
||||
private final Map unwindData = new LinkedHashMap();
|
||||
private final Map<PreBasicBlock, UnwindState> unwindData = new LinkedHashMap<PreBasicBlock, UnwindState>();
|
||||
|
||||
private final Map code = new LinkedHashMap();
|
||||
private final Map<Pair<UnwindState, Pair<PreBasicBlock, Boolean>>, PreBasicBlock> code = new LinkedHashMap<Pair<UnwindState, Pair<PreBasicBlock, Boolean>>, PreBasicBlock>();
|
||||
|
||||
void setUnwindState(PreBasicBlock block, UnwindState context) {
|
||||
unwindData.put(block, context);
|
||||
|
@ -468,7 +469,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
}
|
||||
|
||||
public PreBasicBlock findOrCreateCode(PreBasicBlock source, PreBasicBlock target, boolean exception) {
|
||||
UnwindState sourceContext = (UnwindState) unwindData.get(source);
|
||||
UnwindState sourceContext = unwindData.get(source);
|
||||
|
||||
// no unwinding is needed, so jump to target block directly
|
||||
if (sourceContext == null)
|
||||
|
@ -477,16 +478,17 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
WalkContext astContext = sourceContext.astContext;
|
||||
UnwindState targetContext = null;
|
||||
if (target != null)
|
||||
targetContext = (UnwindState) unwindData.get(target);
|
||||
targetContext = unwindData.get(target);
|
||||
|
||||
// in unwind context, but catch in same (or inner) unwind context
|
||||
if (targetContext != null && targetContext.covers(sourceContext))
|
||||
return target;
|
||||
|
||||
Pair key = new Pair(sourceContext, new Pair(target, exception ? Boolean.TRUE : Boolean.FALSE));
|
||||
Pair<UnwindState, Pair<PreBasicBlock, Boolean>> key = new Pair<UnwindState, Pair<PreBasicBlock, Boolean>>(sourceContext,
|
||||
new Pair<PreBasicBlock, Boolean>(target, exception ? Boolean.TRUE : Boolean.FALSE));
|
||||
|
||||
if (code.containsKey(key)) {
|
||||
return (PreBasicBlock) code.get(key);
|
||||
return code.get(key);
|
||||
|
||||
} else {
|
||||
int e = -1;
|
||||
|
@ -544,19 +546,19 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
|
||||
private Unwind unwind = null;
|
||||
|
||||
private final List blocks = new ArrayList();
|
||||
private final List<PreBasicBlock> blocks = new ArrayList<PreBasicBlock>();
|
||||
|
||||
private final Map nodeToBlock = new LinkedHashMap();
|
||||
private final Map<CAstNode, PreBasicBlock> nodeToBlock = new LinkedHashMap<CAstNode, PreBasicBlock>();
|
||||
|
||||
private final Map delayedEdges = new LinkedHashMap();
|
||||
private final Map<Object, Set<Pair<PreBasicBlock, Boolean>>> delayedEdges = new LinkedHashMap<Object, Set<Pair<PreBasicBlock, Boolean>>>();
|
||||
|
||||
private final Object exitMarker = new Object();
|
||||
|
||||
private final Set deadBlocks = new LinkedHashSet();
|
||||
private final Set<PreBasicBlock> deadBlocks = new LinkedHashSet<PreBasicBlock>();
|
||||
|
||||
private final Set normalToExit = new LinkedHashSet();
|
||||
private final Set<PreBasicBlock> normalToExit = new LinkedHashSet<PreBasicBlock>();
|
||||
|
||||
private final Set exceptionalToExit = new LinkedHashSet();
|
||||
private final Set<PreBasicBlock> exceptionalToExit = new LinkedHashSet<PreBasicBlock>();
|
||||
|
||||
private Position[] linePositions = new Position[10];
|
||||
|
||||
|
@ -620,11 +622,11 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
}
|
||||
|
||||
private void addDelayedEdge(PreBasicBlock src, Object dst, boolean exception) {
|
||||
Pair v = new Pair(src, exception ? Boolean.TRUE : Boolean.FALSE);
|
||||
Pair<PreBasicBlock, Boolean> v = new Pair<PreBasicBlock, Boolean>(src, exception ? Boolean.TRUE : Boolean.FALSE);
|
||||
if (delayedEdges.containsKey(dst))
|
||||
((Set) delayedEdges.get(dst)).add(v);
|
||||
delayedEdges.get(dst).add(v);
|
||||
else {
|
||||
Set s = new LinkedHashSet();
|
||||
Set<Pair<PreBasicBlock, Boolean>> s = new LinkedHashSet<Pair<PreBasicBlock, Boolean>>();
|
||||
s.add(v);
|
||||
delayedEdges.put(dst, s);
|
||||
}
|
||||
|
@ -637,7 +639,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
void makeExitBlock(PreBasicBlock bb) {
|
||||
bb.makeExitBlock();
|
||||
|
||||
for (Iterator ps = getPredNodes(bb); ps.hasNext();)
|
||||
for (Iterator<? extends PreBasicBlock> ps = getPredNodes(bb); ps.hasNext();)
|
||||
normalToExit.add(ps.next());
|
||||
|
||||
checkForRealizedExitEdges(bb);
|
||||
|
@ -649,14 +651,14 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
|
||||
private void checkForRealizedEdges(CAstNode n) {
|
||||
if (delayedEdges.containsKey(n)) {
|
||||
for (Iterator ss = ((Set) delayedEdges.get(n)).iterator(); ss.hasNext();) {
|
||||
for (Iterator ss = delayedEdges.get(n).iterator(); ss.hasNext();) {
|
||||
Pair s = (Pair) ss.next();
|
||||
PreBasicBlock that = (PreBasicBlock) s.fst;
|
||||
boolean exception = ((Boolean) s.snd).booleanValue();
|
||||
if (unwind == null) {
|
||||
addEdge(that, nodeToBlock.get(n));
|
||||
} else {
|
||||
PreBasicBlock target = (PreBasicBlock) nodeToBlock.get(n);
|
||||
PreBasicBlock target = nodeToBlock.get(n);
|
||||
addEdge(that, unwind.findOrCreateCode(that, target, exception));
|
||||
}
|
||||
}
|
||||
|
@ -667,7 +669,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
|
||||
private void checkForRealizedExitEdges(PreBasicBlock n) {
|
||||
if (delayedEdges.containsKey(exitMarker)) {
|
||||
for (Iterator ss = ((Set) delayedEdges.get(exitMarker)).iterator(); ss.hasNext();) {
|
||||
for (Iterator ss = delayedEdges.get(exitMarker).iterator(); ss.hasNext();) {
|
||||
Pair s = (Pair) ss.next();
|
||||
PreBasicBlock that = (PreBasicBlock) s.fst;
|
||||
boolean exception = ((Boolean) s.snd).booleanValue();
|
||||
|
@ -704,12 +706,12 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
|
||||
public void addPreEdge(CAstNode src, CAstNode dst, boolean exception) {
|
||||
Assertions._assert(nodeToBlock.containsKey(src));
|
||||
addPreEdge((PreBasicBlock) nodeToBlock.get(src), dst, exception);
|
||||
addPreEdge(nodeToBlock.get(src), dst, exception);
|
||||
}
|
||||
|
||||
public void addPreEdge(PreBasicBlock src, CAstNode dst, boolean exception) {
|
||||
if (nodeToBlock.containsKey(dst)) {
|
||||
PreBasicBlock target = (PreBasicBlock) nodeToBlock.get(dst);
|
||||
PreBasicBlock target = nodeToBlock.get(dst);
|
||||
if (DEBUG_CFG)
|
||||
Trace.println("adding pre-edge " + src + " --> " + dst);
|
||||
if (unwind == null) {
|
||||
|
@ -726,7 +728,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
|
||||
public void addPreEdgeToExit(CAstNode src, boolean exception) {
|
||||
Assertions._assert(nodeToBlock.containsKey(src));
|
||||
addPreEdgeToExit((PreBasicBlock) nodeToBlock.get(src), exception);
|
||||
addPreEdgeToExit(nodeToBlock.get(src), exception);
|
||||
}
|
||||
|
||||
public void addPreEdgeToExit(PreBasicBlock src, boolean exception) {
|
||||
|
@ -741,7 +743,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
addDelayedEdge(src, exitMarker, exception);
|
||||
}
|
||||
|
||||
public void addEdge(Object src, Object dst) {
|
||||
public void addEdge(PreBasicBlock src, PreBasicBlock dst) {
|
||||
super.addEdge(src, dst);
|
||||
deadBlocks.remove(dst);
|
||||
}
|
||||
|
@ -751,7 +753,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
}
|
||||
|
||||
public PreBasicBlock getBlock(CAstNode n) {
|
||||
return (PreBasicBlock) nodeToBlock.get(n);
|
||||
return nodeToBlock.get(n);
|
||||
}
|
||||
|
||||
private void noteLinePosition(int instruction) {
|
||||
|
@ -798,24 +800,24 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
|
||||
AstCFG(CAstEntity n, IncipientCFG icfg, SymbolTable symtab) {
|
||||
super(null);
|
||||
List blocks = icfg.blocks;
|
||||
List<PreBasicBlock> blocks = icfg.blocks;
|
||||
|
||||
this.symtab = symtab;
|
||||
functionName = n.getName();
|
||||
instructionToBlockMap = new int[blocks.size()];
|
||||
|
||||
for (int i = 0; i < blocks.size(); i++)
|
||||
instructionToBlockMap[i] = ((PreBasicBlock) blocks.get(i)).getLastInstructionIndex();
|
||||
instructionToBlockMap[i] = blocks.get(i).getLastInstructionIndex();
|
||||
|
||||
for (int i = 0; i < blocks.size(); i++) {
|
||||
PreBasicBlock block = (PreBasicBlock) blocks.get(i);
|
||||
PreBasicBlock block = blocks.get(i);
|
||||
this.addNode(block);
|
||||
if (block.isCatchBlock()) {
|
||||
setCatchBlock(i);
|
||||
}
|
||||
|
||||
if (DEBUG_CFG)
|
||||
Trace.println("added " + blocks.get(i) + " to final CFG as " + getNumber((IBasicBlock) blocks.get(i)));
|
||||
Trace.println("added " + blocks.get(i) + " to final CFG as " + getNumber(blocks.get(i)));
|
||||
}
|
||||
if (DEBUG_CFG)
|
||||
Trace.println(getMaxNumber() + " blocks total");
|
||||
|
@ -823,7 +825,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
init();
|
||||
|
||||
for (int i = 0; i < blocks.size(); i++) {
|
||||
PreBasicBlock src = (PreBasicBlock) blocks.get(i);
|
||||
PreBasicBlock src = blocks.get(i);
|
||||
for (Iterator j = icfg.getSuccNodes(src); j.hasNext();) {
|
||||
PreBasicBlock dst = (PreBasicBlock) j.next();
|
||||
if (isCatchBlock(dst.getNumber()) || (dst.isExitBlock() && icfg.exceptionalToExit.contains(src))) {
|
||||
|
@ -843,9 +845,9 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
int x = 0;
|
||||
instructions = new SSAInstruction[icfg.currentInstruction];
|
||||
for (int i = 0; i < blocks.size(); i++) {
|
||||
List bi = ((PreBasicBlock) blocks.get(i)).instructions();
|
||||
List<SSAInstruction> bi = blocks.get(i).instructions();
|
||||
for (int j = 0; j < bi.size(); j++) {
|
||||
instructions[x++] = (SSAInstruction) bi.get(j);
|
||||
instructions[x++] = bi.get(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -944,7 +946,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
|
||||
Symbol lookup(String name);
|
||||
|
||||
Iterator getAllNames();
|
||||
Iterator<String> getAllNames();
|
||||
|
||||
int size();
|
||||
|
||||
|
@ -987,9 +989,9 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
private abstract class AbstractScope implements Scope {
|
||||
private final Scope parent;
|
||||
|
||||
private final Map values = new LinkedHashMap();
|
||||
private final Map<String, Symbol> values = new LinkedHashMap<String, Symbol>();
|
||||
|
||||
private final Map caseInsensitiveNames = new LinkedHashMap();
|
||||
private final Map<String, String> caseInsensitiveNames = new LinkedHashMap<String, String>();
|
||||
|
||||
protected abstract SymbolTable getUnderlyingSymtab();
|
||||
|
||||
|
@ -997,7 +999,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
return getUnderlyingSymtab().getMaxValueNumber() + 1;
|
||||
}
|
||||
|
||||
public Iterator getAllNames() {
|
||||
public Iterator<String> getAllNames() {
|
||||
return values.keySet().iterator();
|
||||
}
|
||||
|
||||
|
@ -1061,7 +1063,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
}
|
||||
|
||||
private final String mapName(String nm) {
|
||||
String mappedName = (String) caseInsensitiveNames.get(nm.toLowerCase());
|
||||
String mappedName = caseInsensitiveNames.get(nm.toLowerCase());
|
||||
return (mappedName == null) ? nm : mappedName;
|
||||
}
|
||||
|
||||
|
@ -1081,7 +1083,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
|
||||
public Symbol lookup(String nm) {
|
||||
if (contains(nm)) {
|
||||
return (Symbol) values.get(mapName(nm));
|
||||
return values.get(mapName(nm));
|
||||
} else {
|
||||
Symbol scoped = parent.lookup(nm);
|
||||
if (scoped != null && getEntityScope() == this && (isGlobal(scoped) || isLexicallyScoped(scoped))) {
|
||||
|
@ -1089,7 +1091,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
if (scoped.getDefiningScope().isCaseInsensitive(nm)) {
|
||||
caseInsensitiveNames.put(nm.toLowerCase(), nm);
|
||||
}
|
||||
return (Symbol) values.get(nm);
|
||||
return values.get(nm);
|
||||
} else {
|
||||
return scoped;
|
||||
}
|
||||
|
@ -1097,7 +1099,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
}
|
||||
|
||||
public boolean contains(String nm) {
|
||||
String mappedName = (String) caseInsensitiveNames.get(nm.toLowerCase());
|
||||
String mappedName = caseInsensitiveNames.get(nm.toLowerCase());
|
||||
return values.containsKey(mappedName == null ? nm : mappedName);
|
||||
}
|
||||
|
||||
|
@ -1277,11 +1279,11 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
}
|
||||
|
||||
private Scope makeGlobalScope() {
|
||||
final Map globalSymbols = new LinkedHashMap();
|
||||
final Map caseInsensitiveNames = new LinkedHashMap();
|
||||
final Map<String, AbstractSymbol> globalSymbols = new LinkedHashMap<String, AbstractSymbol>();
|
||||
final Map<String, String> caseInsensitiveNames = new LinkedHashMap<String, String>();
|
||||
return new Scope() {
|
||||
private final String mapName(String nm) {
|
||||
String mappedName = (String) caseInsensitiveNames.get(nm.toLowerCase());
|
||||
String mappedName = caseInsensitiveNames.get(nm.toLowerCase());
|
||||
return (mappedName == null) ? nm : mappedName;
|
||||
}
|
||||
|
||||
|
@ -1301,7 +1303,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
return globalSymbols.size();
|
||||
}
|
||||
|
||||
public Iterator getAllNames() {
|
||||
public Iterator<String> getAllNames() {
|
||||
return globalSymbols.keySet().iterator();
|
||||
}
|
||||
|
||||
|
@ -1343,7 +1345,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
throw new Error("cannot find " + name);
|
||||
}
|
||||
|
||||
return (Symbol) globalSymbols.get(mapName(name));
|
||||
return globalSymbols.get(mapName(name));
|
||||
}
|
||||
|
||||
public void declare(final String name, boolean isFinal, boolean isCaseInsensitive, int vn) {
|
||||
|
@ -1373,11 +1375,11 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
}
|
||||
|
||||
protected Scope makeTypeScope(final CAstEntity type, final Scope parent) {
|
||||
final Map typeSymbols = new LinkedHashMap();
|
||||
final Map caseInsensitiveNames = new LinkedHashMap();
|
||||
final Map<String, AbstractSymbol> typeSymbols = new LinkedHashMap<String, AbstractSymbol>();
|
||||
final Map<String, String> caseInsensitiveNames = new LinkedHashMap<String, String>();
|
||||
return new Scope() {
|
||||
private final String mapName(String nm) {
|
||||
String mappedName = (String) caseInsensitiveNames.get(nm.toLowerCase());
|
||||
String mappedName = caseInsensitiveNames.get(nm.toLowerCase());
|
||||
return (mappedName == null) ? nm : mappedName;
|
||||
}
|
||||
|
||||
|
@ -1397,7 +1399,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
return typeSymbols.size();
|
||||
}
|
||||
|
||||
public Iterator getAllNames() {
|
||||
public Iterator<String> getAllNames() {
|
||||
return typeSymbols.keySet().iterator();
|
||||
}
|
||||
|
||||
|
@ -1431,7 +1433,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
|
||||
public Symbol lookup(String nm) {
|
||||
if (typeSymbols.containsKey(mapName(nm)))
|
||||
return (Symbol) typeSymbols.get(mapName(nm));
|
||||
return typeSymbols.get(mapName(nm));
|
||||
else {
|
||||
return parent.lookup(nm);
|
||||
}
|
||||
|
@ -1475,7 +1477,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
|
||||
Scope currentScope();
|
||||
|
||||
Set entityScopes();
|
||||
Set<Scope> entityScopes();
|
||||
|
||||
IncipientCFG cfg();
|
||||
|
||||
|
@ -1520,7 +1522,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
return parent.currentScope();
|
||||
}
|
||||
|
||||
public Set entityScopes() {
|
||||
public Set<Scope> entityScopes() {
|
||||
return parent.entityScopes();
|
||||
}
|
||||
|
||||
|
@ -1601,7 +1603,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
private class CodeEntityContext extends EntityContext {
|
||||
private final Scope topEntityScope;
|
||||
|
||||
private final Set allEntityScopes;
|
||||
private final Set<Scope> allEntityScopes;
|
||||
|
||||
private final IncipientCFG cfg;
|
||||
|
||||
|
@ -1612,7 +1614,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
|
||||
this.topEntityScope = entityScope;
|
||||
|
||||
this.allEntityScopes = new HashSet();
|
||||
this.allEntityScopes = new HashSet<Scope>();
|
||||
this.allEntityScopes.add(entityScope);
|
||||
|
||||
cfg = new IncipientCFG();
|
||||
|
@ -1630,7 +1632,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
return topEntityScope;
|
||||
}
|
||||
|
||||
public Set entityScopes() {
|
||||
public Set<Scope> entityScopes() {
|
||||
return allEntityScopes;
|
||||
}
|
||||
|
||||
|
@ -1762,14 +1764,14 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
}
|
||||
|
||||
if (accesses != null) {
|
||||
Set parents = new LinkedHashSet();
|
||||
Set<String> parents = new LinkedHashSet<String>();
|
||||
for (Iterator ACS = accesses.iterator(); ACS.hasNext();) {
|
||||
Access AC = (Access) ACS.next();
|
||||
if (AC.variableDefiner != null) {
|
||||
parents.add(AC.variableDefiner);
|
||||
}
|
||||
}
|
||||
scopingParents = (String[]) parents.toArray(new String[parents.size()]);
|
||||
scopingParents = parents.toArray(new String[parents.size()]);
|
||||
|
||||
if (DEBUG_LEXICAL) {
|
||||
Trace.println("scoping parents of " + scope.getEntity());
|
||||
|
@ -1810,7 +1812,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
}
|
||||
};
|
||||
|
||||
private final Map results = new LinkedHashMap();
|
||||
private final Map<CAstNode, Integer> results = new LinkedHashMap<CAstNode, Integer>();
|
||||
|
||||
protected boolean hasValue(CAstNode n) {
|
||||
return results.containsKey(n);
|
||||
|
@ -1823,18 +1825,18 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
|
||||
public final int getValue(CAstNode n) {
|
||||
if (results.containsKey(n))
|
||||
return ((Integer) results.get(n)).intValue();
|
||||
return results.get(n).intValue();
|
||||
else {
|
||||
Trace.println("no value for " + n.getKind());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private final Map entityNames = new LinkedHashMap();
|
||||
private final Map<CAstEntity, String> entityNames = new LinkedHashMap<CAstEntity, String>();
|
||||
|
||||
private final Map exposedNames = new LinkedHashMap();
|
||||
private final Map<CAstEntity, LinkedHashSet<Pair<Pair<String, String>, Integer>>> exposedNames = new LinkedHashMap<CAstEntity, LinkedHashSet<Pair<Pair<String, String>, Integer>>>();
|
||||
|
||||
private final Map accesses = new LinkedHashMap();
|
||||
private final Map<CAstEntity, LinkedHashSet<Access>> accesses = new LinkedHashMap<CAstEntity, LinkedHashSet<Access>>();
|
||||
|
||||
private void addEntityName(CAstEntity e, String name) {
|
||||
entityNames.put(e, name);
|
||||
|
@ -1842,15 +1844,17 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
|
||||
private void addAccess(CAstEntity e, Access access) {
|
||||
if (!accesses.containsKey(e))
|
||||
accesses.put(e, new LinkedHashSet());
|
||||
((Set) accesses.get(e)).add(access);
|
||||
accesses.put(e, new LinkedHashSet<Access>());
|
||||
accesses.get(e).add(access);
|
||||
}
|
||||
|
||||
private void addExposedName(CAstEntity entity, CAstEntity declaration, String name, int valueNumber) {
|
||||
if (!exposedNames.containsKey(entity))
|
||||
exposedNames.put(entity, new LinkedHashSet());
|
||||
exposedNames.put(entity, new LinkedHashSet<Pair<Pair<String, String>, Integer>>());
|
||||
|
||||
((Set) exposedNames.get(entity)).add(new Pair(new Pair(name, getEntityName(declaration)), new Integer(valueNumber)));
|
||||
exposedNames.get(entity).add(
|
||||
new Pair<Pair<String, String>, Integer>(new Pair<String, String>(name, getEntityName(declaration)),
|
||||
new Integer(valueNumber)));
|
||||
}
|
||||
|
||||
private String getEntityName(CAstEntity e) {
|
||||
|
@ -1938,19 +1942,19 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
private String[] makeNameMap(Set scopes) {
|
||||
private String[] makeNameMap(Set<Scope> scopes) {
|
||||
// all scopes share the same underlying symtab, which is what
|
||||
// size really refers to.
|
||||
String[] map = new String[((Scope) scopes.iterator().next()).size() + 1];
|
||||
String[] map = new String[scopes.iterator().next().size() + 1];
|
||||
|
||||
if (DEBUG_NAMES) {
|
||||
Trace.println("names array of size " + map.length);
|
||||
}
|
||||
|
||||
for (Iterator S = scopes.iterator(); S.hasNext();) {
|
||||
Scope scope = (Scope) S.next();
|
||||
for (Iterator I = scope.getAllNames(); I.hasNext();) {
|
||||
String nm = (String) I.next();
|
||||
for (Iterator<Scope> S = scopes.iterator(); S.hasNext();) {
|
||||
Scope scope = S.next();
|
||||
for (Iterator<String> I = scope.getAllNames(); I.hasNext();) {
|
||||
String nm = I.next();
|
||||
Symbol v = (Symbol) scope.lookup(nm);
|
||||
|
||||
// hack for new expression idiom in the Java translator
|
||||
|
@ -2088,20 +2092,19 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
String[] nms = makeNameMap(functionContext.entityScopes());
|
||||
|
||||
/*
|
||||
Set reachableBlocks =
|
||||
DFS.getReachableNodes(cfg, Collections.singleton(cfg.entry()));
|
||||
Assertions._assert(reachableBlocks.size() == cfg.getNumberOfNodes(),
|
||||
cfg.toString());
|
||||
*/
|
||||
* Set reachableBlocks = DFS.getReachableNodes(cfg,
|
||||
* Collections.singleton(cfg.entry()));
|
||||
* Assertions._assert(reachableBlocks.size() == cfg.getNumberOfNodes(),
|
||||
* cfg.toString());
|
||||
*/
|
||||
|
||||
// (put here to allow subclasses to handle stuff in scoped entities)
|
||||
|
||||
// assemble lexical information
|
||||
patchLexicalAccesses(cfg.getInstructions(), (Set) accesses.get(n));
|
||||
patchLexicalAccesses(cfg.getInstructions(), accesses.get(n));
|
||||
LexicalInformation LI =
|
||||
// TODO: Ask Julian if the below change is always correct
|
||||
new AstLexicalInformation((AbstractScope) functionContext.currentScope(), cfg.getInstructions(), (Set) exposedNames.get(n),
|
||||
(Set) accesses.get(n));
|
||||
new AstLexicalInformation((AbstractScope) functionContext.currentScope(), cfg.getInstructions(), exposedNames.get(n), accesses
|
||||
.get(n));
|
||||
|
||||
DebuggingInformation DBG = new AstDebuggingInformation(line, nms);
|
||||
|
||||
|
@ -2109,7 +2112,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
defineFunction(n, parentContext, cfg, symtab, katch, catchTypes, LI, DBG);
|
||||
}
|
||||
|
||||
private final Stack positions = new Stack();
|
||||
private final Stack<Position> positions = new Stack<Position>();
|
||||
|
||||
protected Context makeLocalContext(Context context, CAstNode n) {
|
||||
return new LocalContext((WalkContext) context, makeLocalScope(n, ((WalkContext) context).currentScope()));
|
||||
|
@ -2121,7 +2124,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
|
||||
// FIXME: should it be possible to override visit() instead to do the below
|
||||
// and then call super.visit?
|
||||
private Map popPositionM = new LinkedHashMap();
|
||||
private Map<CAstNode, Boolean> popPositionM = new LinkedHashMap<CAstNode, Boolean>();
|
||||
|
||||
protected boolean enterNode(CAstNode n, Context c, CAstVisitor visitor) {
|
||||
WalkContext context = (WalkContext) c;
|
||||
|
@ -2146,7 +2149,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
protected void postProcessNode(CAstNode n, Context c, CAstVisitor visitor) {
|
||||
WalkContext context = (WalkContext) c;
|
||||
if (popPositionM.get(n) != null) {
|
||||
context.cfg().setCurrentPosition((Position) positions.pop());
|
||||
context.cfg().setCurrentPosition(positions.pop());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2178,7 +2181,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
int result = processFunctionExpr(n, c);
|
||||
CAstEntity fn = (CAstEntity) n.getChild(0).getValue();
|
||||
// FIXME: handle redefinitions of functions
|
||||
if (! context.currentScope().contains(fn.getName())) {
|
||||
if (!context.currentScope().contains(fn.getName())) {
|
||||
context.currentScope().declare(fn.getName(), true, false, result);
|
||||
}
|
||||
}
|
||||
|
@ -2667,7 +2670,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
int[] dims = gatherArrayDims(n);
|
||||
doArrayRead(context, temp, getValue(n.getChild(0)), n, dims);
|
||||
int rval = processAssignOp(n, v, a, temp, !pre, c);
|
||||
setValue(n, pre? rval: temp);
|
||||
setValue(n, pre ? rval : temp);
|
||||
doArrayWrite(context, getValue(n.getChild(0)), n, dims, rval);
|
||||
}
|
||||
|
||||
|
@ -2694,7 +2697,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
int temp = context.currentScope().allocateTempValue();
|
||||
doFieldRead(context, temp, getValue(n.getChild(0)), n.getChild(1), n);
|
||||
int rval = processAssignOp(n, v, a, temp, !pre, c);
|
||||
setValue(n, pre? rval: temp);
|
||||
setValue(n, pre ? rval : temp);
|
||||
doFieldWrite(context, getValue(n.getChild(0)), n.getChild(1), n, rval);
|
||||
}
|
||||
|
||||
|
@ -2729,8 +2732,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
else if (context.currentScope().isLexicallyScoped(ls)) {
|
||||
doLexicallyScopedWrite(context, nm, rval);
|
||||
} else {
|
||||
Assertions._assert(rval != -1,
|
||||
CAstPrinter.print(n, c.top().getSourceMap()));
|
||||
Assertions._assert(rval != -1, CAstPrinter.print(n, c.top().getSourceMap()));
|
||||
doLocalWrite(context, nm, rval);
|
||||
}
|
||||
}
|
||||
|
@ -2776,8 +2778,8 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
|
||||
private boolean isSimpleSwitch(CAstNode n, WalkContext context, CAstVisitor visitor) {
|
||||
CAstControlFlowMap ctrl = context.getControlFlow();
|
||||
Collection caseLabels = ctrl.getTargetLabels(n);
|
||||
for (Iterator kases = caseLabels.iterator(); kases.hasNext();) {
|
||||
Collection<IField> caseLabels = ctrl.getTargetLabels(n);
|
||||
for (Iterator<IField> kases = caseLabels.iterator(); kases.hasNext();) {
|
||||
Object x = kases.next();
|
||||
|
||||
if (x == CAstControlFlowMap.SWITCH_DEFAULT)
|
||||
|
@ -2816,7 +2818,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
|
||||
boolean hasExplicitDefault = ctrl.getTarget(n, CAstControlFlowMap.SWITCH_DEFAULT) != null;
|
||||
|
||||
Collection caseLabels = ctrl.getTargetLabels(n);
|
||||
Collection<IField> caseLabels = ctrl.getTargetLabels(n);
|
||||
int cases = caseLabels.size();
|
||||
if (hasExplicitDefault)
|
||||
cases--;
|
||||
|
@ -2839,7 +2841,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
context.cfg().newBlock(true);
|
||||
|
||||
int cn = 0;
|
||||
for (Iterator kases = caseLabels.iterator(); kases.hasNext();) {
|
||||
for (Iterator<IField> kases = caseLabels.iterator(); kases.hasNext();) {
|
||||
Object x = kases.next();
|
||||
CAstNode target = ctrl.getTarget(n, x);
|
||||
if (x == CAstControlFlowMap.SWITCH_DEFAULT) {
|
||||
|
@ -2863,9 +2865,9 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
visitor.visit(switchValue, context, visitor);
|
||||
int v = getValue(switchValue);
|
||||
|
||||
Collection caseLabels = ctrl.getTargetLabels(n);
|
||||
Map labelToBlock = new LinkedHashMap();
|
||||
for (Iterator kases = caseLabels.iterator(); kases.hasNext();) {
|
||||
Collection<IField> caseLabels = ctrl.getTargetLabels(n);
|
||||
Map<Object, PreBasicBlock> labelToBlock = new LinkedHashMap<Object, PreBasicBlock>();
|
||||
for (Iterator<IField> kases = caseLabels.iterator(); kases.hasNext();) {
|
||||
Object x = kases.next();
|
||||
if (x != CAstControlFlowMap.SWITCH_DEFAULT) {
|
||||
walkNodes((CAstNode) x, context);
|
||||
|
@ -2885,8 +2887,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
visitor.visit(switchBody, context, visitor);
|
||||
context.cfg().newBlock(true);
|
||||
|
||||
PreBasicBlock nextBlock = context.cfg().getCurrentBlock();
|
||||
for (Iterator kases = caseLabels.iterator(); kases.hasNext();) {
|
||||
for (Iterator<IField> kases = caseLabels.iterator(); kases.hasNext();) {
|
||||
Object x = kases.next();
|
||||
if (x != CAstControlFlowMap.SWITCH_DEFAULT) {
|
||||
CAstNode target = ctrl.getTarget(n, x);
|
||||
|
@ -2930,8 +2931,8 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
context.cfg().addPreNode(n, context.getUnwindState());
|
||||
context.cfg().newBlock(false);
|
||||
|
||||
Collection labels = context.getControlFlow().getTargetLabels(n);
|
||||
for (Iterator iter = labels.iterator(); iter.hasNext();) {
|
||||
Collection<IField> labels = context.getControlFlow().getTargetLabels(n);
|
||||
for (Iterator<IField> iter = labels.iterator(); iter.hasNext();) {
|
||||
Object label = iter.next();
|
||||
CAstNode target = context.getControlFlow().getTarget(n, label);
|
||||
if (target == CAstControlFlowMap.EXCEPTION_TO_EXIT)
|
||||
|
@ -3080,17 +3081,16 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
((WalkContext) c).cfg().addInstruction(new EachElementHasNextInstruction(result, getValue(n.getChild(0))));
|
||||
}
|
||||
|
||||
protected boolean visitTypeLiteralExpr(CAstNode n, Context c, CAstVisitor visitor) {
|
||||
protected boolean visitTypeLiteralExpr(CAstNode n, Context c, CAstVisitor visitor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void leaveTypeLiteralExpr(CAstNode n, Context c, CAstVisitor visitor) {
|
||||
WalkContext wc = (WalkContext)c;
|
||||
WalkContext wc = (WalkContext) c;
|
||||
Assertions._assert(n.getChild(0).getKind() == CAstNode.CONSTANT);
|
||||
String typeNameStr = (String) n.getChild(0).getValue();
|
||||
TypeName typeName = TypeName.string2TypeName(typeNameStr);
|
||||
TypeReference typeRef =
|
||||
TypeReference.findOrCreate(loader.getReference(), typeName);
|
||||
TypeReference typeRef = TypeReference.findOrCreate(loader.getReference(), typeName);
|
||||
|
||||
int result = wc.currentScope().allocateTempValue();
|
||||
setValue(n, result);
|
||||
|
@ -3131,7 +3131,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
|||
return t.globalScope;
|
||||
}
|
||||
|
||||
public Set entityScopes() {
|
||||
public Set<Scope> entityScopes() {
|
||||
return Collections.singleton(t.globalScope);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,31 +11,41 @@
|
|||
package com.ibm.wala.cast.loader;
|
||||
|
||||
|
||||
import com.ibm.wala.cast.tree.*;
|
||||
import com.ibm.wala.classLoader.*;
|
||||
import com.ibm.wala.ipa.cha.*;
|
||||
import com.ibm.wala.shrikeCT.*;
|
||||
import com.ibm.wala.types.*;
|
||||
import com.ibm.wala.util.*;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import java.net.URL;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import com.ibm.wala.cast.tree.CAstSourcePositionMap;
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.IClassLoader;
|
||||
import com.ibm.wala.classLoader.IField;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
||||
import com.ibm.wala.shrikeCT.ClassConstants;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.types.Selector;
|
||||
import com.ibm.wala.types.TypeName;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.Atom;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
abstract public class AstClass implements IClass, ClassConstants {
|
||||
private final CAstSourcePositionMap.Position sourcePosition;
|
||||
private final TypeName typeName;
|
||||
private final IClassLoader loader;
|
||||
private final short modifiers;
|
||||
protected final Map declaredFields;
|
||||
protected final Map declaredMethods;
|
||||
protected final Map<Atom, IField> declaredFields;
|
||||
protected final Map<Selector,IMethod> declaredMethods;
|
||||
|
||||
protected AstClass(CAstSourcePositionMap.Position sourcePosition,
|
||||
TypeName typeName,
|
||||
IClassLoader loader,
|
||||
short modifiers,
|
||||
Map declaredFields,
|
||||
Map declaredMethods)
|
||||
Map<Atom, IField> declaredFields,
|
||||
Map<Selector,IMethod> declaredMethods)
|
||||
{
|
||||
this.sourcePosition = sourcePosition;
|
||||
this.typeName = typeName;
|
||||
|
@ -95,22 +105,22 @@ abstract public class AstClass implements IClass, ClassConstants {
|
|||
|
||||
public abstract IClass getSuperclass() throws ClassHierarchyException;
|
||||
|
||||
private Collection gatherInterfaces() throws ClassHierarchyException {
|
||||
Set result = new HashSet();
|
||||
private Collection<IClass> gatherInterfaces() throws ClassHierarchyException {
|
||||
Set<IClass> result = new HashSet<IClass>();
|
||||
result.addAll( getDirectInterfaces() );
|
||||
if (getSuperclass() != null)
|
||||
result.addAll( getSuperclass().getAllImplementedInterfaces() );
|
||||
return result;
|
||||
}
|
||||
|
||||
public abstract Collection getDirectInterfaces() throws ClassHierarchyException;
|
||||
public abstract Collection<IClass> getDirectInterfaces() throws ClassHierarchyException;
|
||||
|
||||
public Collection getAllImplementedInterfaces() throws ClassHierarchyException {
|
||||
public Collection<IClass> getAllImplementedInterfaces() throws ClassHierarchyException {
|
||||
Assertions._assert(! isInterface());
|
||||
return gatherInterfaces();
|
||||
}
|
||||
|
||||
public Collection getAllAncestorInterfaces() throws ClassHierarchyException {
|
||||
public Collection<IClass> getAllAncestorInterfaces() throws ClassHierarchyException {
|
||||
Assertions._assert(isInterface());
|
||||
return gatherInterfaces();
|
||||
}
|
||||
|
@ -122,7 +132,7 @@ abstract public class AstClass implements IClass, ClassConstants {
|
|||
public IMethod getMethod(Selector selector) {
|
||||
try {
|
||||
if (declaredMethods.containsKey(selector)) {
|
||||
return (IMethod)declaredMethods.get(selector);
|
||||
return declaredMethods.get(selector);
|
||||
} else if (getSuperclass() != null) {
|
||||
return getSuperclass().getMethod(selector);
|
||||
} else {
|
||||
|
@ -137,7 +147,7 @@ abstract public class AstClass implements IClass, ClassConstants {
|
|||
public IField getField(Atom name) {
|
||||
try {
|
||||
if (declaredFields.containsKey(name)) {
|
||||
return (IField)declaredFields.get(name);
|
||||
return declaredFields.get(name);
|
||||
} else if (getSuperclass() != null) {
|
||||
return getSuperclass().getField(name);
|
||||
} else {
|
||||
|
@ -153,10 +163,10 @@ abstract public class AstClass implements IClass, ClassConstants {
|
|||
return declaredMethods.values();
|
||||
}
|
||||
|
||||
public Collection getDeclaredInstanceFields() {
|
||||
Set result = new HashSet();
|
||||
for(Iterator FS = declaredFields.values().iterator(); FS.hasNext();) {
|
||||
IField F = (IField) FS.next();
|
||||
public Collection<IField> getDeclaredInstanceFields() {
|
||||
Set<IField> result = new HashSet<IField>();
|
||||
for(Iterator<IField> FS = declaredFields.values().iterator(); FS.hasNext();) {
|
||||
IField F = FS.next();
|
||||
if (! F.isStatic()) {
|
||||
result.add( F );
|
||||
}
|
||||
|
@ -165,10 +175,10 @@ abstract public class AstClass implements IClass, ClassConstants {
|
|||
return result;
|
||||
}
|
||||
|
||||
public Collection getDeclaredStaticFields() {
|
||||
Set result = new HashSet();
|
||||
for(Iterator FS = declaredFields.values().iterator(); FS.hasNext();) {
|
||||
IField F = (IField) FS.next();
|
||||
public Collection<IField> getDeclaredStaticFields() {
|
||||
Set<IField> result = new HashSet<IField>();
|
||||
for(Iterator<IField> FS = declaredFields.values().iterator(); FS.hasNext();) {
|
||||
IField F = FS.next();
|
||||
if (F.isStatic()) {
|
||||
result.add( F );
|
||||
}
|
||||
|
@ -177,8 +187,8 @@ abstract public class AstClass implements IClass, ClassConstants {
|
|||
return result;
|
||||
}
|
||||
|
||||
public Collection getAllInstanceFields() throws ClassHierarchyException {
|
||||
Collection result = new HashSet();
|
||||
public Collection<IField> getAllInstanceFields() throws ClassHierarchyException {
|
||||
Collection<IField> result = new HashSet<IField>();
|
||||
result.addAll( getDeclaredInstanceFields() );
|
||||
if (getSuperclass() != null) {
|
||||
result.addAll( getSuperclass().getAllInstanceFields() );
|
||||
|
@ -187,8 +197,8 @@ abstract public class AstClass implements IClass, ClassConstants {
|
|||
return result;
|
||||
}
|
||||
|
||||
public Collection getAllStaticFields() throws ClassHierarchyException {
|
||||
Collection result = new HashSet();
|
||||
public Collection<IField> getAllStaticFields() throws ClassHierarchyException {
|
||||
Collection<IField> result = new HashSet<IField>();
|
||||
result.addAll( getDeclaredStaticFields() );
|
||||
if (getSuperclass() != null) {
|
||||
result.addAll( getSuperclass().getAllStaticFields() );
|
||||
|
@ -197,16 +207,16 @@ abstract public class AstClass implements IClass, ClassConstants {
|
|||
return result;
|
||||
}
|
||||
|
||||
public Collection getAllFields() throws ClassHierarchyException {
|
||||
Collection result = new HashSet();
|
||||
public Collection<IField> getAllFields() throws ClassHierarchyException {
|
||||
Collection<IField> result = new HashSet<IField>();
|
||||
result.addAll( getAllInstanceFields() );
|
||||
result.addAll( getAllStaticFields() );
|
||||
return result;
|
||||
}
|
||||
|
||||
public Collection getAllMethods() throws ClassHierarchyException {
|
||||
Collection result = new HashSet();
|
||||
for(Iterator ms = getDeclaredMethods().iterator(); ms.hasNext(); ) {
|
||||
public Collection<IMethod> getAllMethods() throws ClassHierarchyException {
|
||||
Collection<IMethod> result = new HashSet<IMethod>();
|
||||
for(Iterator<IMethod> ms = getDeclaredMethods().iterator(); ms.hasNext(); ) {
|
||||
result.add( ms.next() );
|
||||
}
|
||||
if (getSuperclass() != null) {
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.loader;
|
||||
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -18,9 +17,11 @@ import com.ibm.wala.cast.tree.CAstSourcePositionMap;
|
|||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.IClassLoader;
|
||||
import com.ibm.wala.classLoader.IField;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
||||
import com.ibm.wala.types.FieldReference;
|
||||
import com.ibm.wala.types.Selector;
|
||||
import com.ibm.wala.types.TypeName;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.Atom;
|
||||
|
@ -29,15 +30,16 @@ import com.ibm.wala.util.debug.Assertions;
|
|||
public abstract class AstDynamicPropertyClass extends AstClass {
|
||||
private final TypeReference defaultDescriptor;
|
||||
|
||||
protected AstDynamicPropertyClass(CAstSourcePositionMap.Position sourcePosition, TypeName typeName, IClassLoader loader, short modifiers, Map declaredMethods, TypeReference defaultDescriptor) {
|
||||
super(sourcePosition, typeName, loader, modifiers, new HashMap(), declaredMethods);
|
||||
protected AstDynamicPropertyClass(CAstSourcePositionMap.Position sourcePosition, TypeName typeName, IClassLoader loader,
|
||||
short modifiers, Map<Selector, IMethod> declaredMethods, TypeReference defaultDescriptor) {
|
||||
super(sourcePosition, typeName, loader, modifiers, new HashMap<Atom, IField>(), declaredMethods);
|
||||
this.defaultDescriptor = defaultDescriptor;
|
||||
}
|
||||
|
||||
public IField getField(final Atom name) {
|
||||
try {
|
||||
if (declaredFields.containsKey(name)) {
|
||||
return (IField) declaredFields.get(name);
|
||||
return declaredFields.get(name);
|
||||
} else if (getSuperclass() != null) {
|
||||
return getSuperclass().getField(name);
|
||||
} else {
|
||||
|
@ -88,11 +90,11 @@ public abstract class AstDynamicPropertyClass extends AstClass {
|
|||
}
|
||||
|
||||
public ClassHierarchy getClassHierarchy() {
|
||||
return AstDynamicPropertyClass.this.getClassHierarchy();
|
||||
return AstDynamicPropertyClass.this.getClassHierarchy();
|
||||
}
|
||||
});
|
||||
|
||||
return (IField) declaredFields.get(name);
|
||||
return declaredFields.get(name);
|
||||
}
|
||||
} catch (ClassHierarchyException e) {
|
||||
Assertions.UNREACHABLE();
|
||||
|
|
|
@ -81,16 +81,16 @@ abstract public class AstFunctionClass implements IClass, ClassConstants {
|
|||
return loader.lookupClass(superReference.getName(), getClassHierarchy());
|
||||
}
|
||||
|
||||
public Collection getDirectInterfaces() {
|
||||
return Collections.EMPTY_SET;
|
||||
public Collection<IClass> getDirectInterfaces() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
public Collection getAllImplementedInterfaces() {
|
||||
return Collections.EMPTY_SET;
|
||||
public Collection<IClass> getAllImplementedInterfaces() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
public Collection getAllAncestorInterfaces() {
|
||||
return Collections.EMPTY_SET;
|
||||
public Collection<IClass> getAllAncestorInterfaces() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
public IMethod getMethod(Selector selector) {
|
||||
|
@ -137,27 +137,27 @@ abstract public class AstFunctionClass implements IClass, ClassConstants {
|
|||
}
|
||||
}
|
||||
|
||||
public Collection getDeclaredInstanceFields() {
|
||||
return Collections.EMPTY_SET;
|
||||
public Collection<IField> getDeclaredInstanceFields() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
public Collection getDeclaredStaticFields() {
|
||||
return Collections.EMPTY_SET;
|
||||
public Collection<IField> getDeclaredStaticFields() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
public Collection getAllInstanceFields() {
|
||||
return Collections.EMPTY_SET;
|
||||
public Collection<IField> getAllInstanceFields() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
public Collection getAllStaticFields() {
|
||||
return Collections.EMPTY_SET;
|
||||
public Collection<IField> getAllStaticFields() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
public Collection getAllFields() {
|
||||
return Collections.EMPTY_SET;
|
||||
public Collection<IField> getAllFields() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
public Collection getAllMethods() {
|
||||
public Collection<IMethod> getAllMethods() {
|
||||
return Collections.singleton(functionBody);
|
||||
}
|
||||
|
||||
|
|
|
@ -72,5 +72,5 @@ public interface CAstControlFlowMap {
|
|||
* Returns an iterator of all CAstNodes for which this map contains
|
||||
* control flow mapping information.
|
||||
*/
|
||||
Collection getMappedNodes();
|
||||
Collection<CAstNode> getMappedNodes();
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ package com.ibm.wala.cast.tree;
|
|||
import java.util.*;
|
||||
|
||||
public class CAstQualifier {
|
||||
public static final Set/* <CAstQualifier> */sQualifiers = new HashSet();
|
||||
public static final Set/* <CAstQualifier> */<CAstQualifier>sQualifiers = new HashSet<CAstQualifier>();
|
||||
|
||||
public static final CAstQualifier CONST = new CAstQualifier("const");
|
||||
public static final CAstQualifier STRICTFP = new CAstQualifier("strictfp");
|
||||
|
|
|
@ -53,6 +53,6 @@ public interface CAstSourcePositionMap {
|
|||
* Returns an iterator of all CAstNodes for which this map contains
|
||||
* source mapping information.
|
||||
*/
|
||||
Iterator getMappedNodes();
|
||||
Iterator<CAstNode> getMappedNodes();
|
||||
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
package com.ibm.wala.cast.tree.impl;
|
||||
|
||||
import com.ibm.wala.cast.tree.*;
|
||||
import com.ibm.wala.classLoader.IField;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
@ -32,7 +33,7 @@ public class CAstCloner {
|
|||
|
||||
}
|
||||
|
||||
private CAstNode copyNodes(CAstNode root, Map nodeMap) {
|
||||
private CAstNode copyNodes(CAstNode root, Map<CAstNode, CAstNode> nodeMap) {
|
||||
if (root instanceof CAstOperator) {
|
||||
nodeMap.put(root, root);
|
||||
return root;
|
||||
|
@ -53,12 +54,12 @@ public class CAstCloner {
|
|||
}
|
||||
}
|
||||
|
||||
private CAstControlFlowMap copyFlow(Map nodeMap, CAstControlFlowMap orig) {
|
||||
Collection oldSources = orig.getMappedNodes();
|
||||
private CAstControlFlowMap copyFlow(Map<CAstNode, CAstNode> nodeMap, CAstControlFlowMap orig) {
|
||||
Collection<CAstNode> oldSources = orig.getMappedNodes();
|
||||
CAstControlFlowRecorder newMap = new CAstControlFlowRecorder();
|
||||
for(Iterator NS = nodeMap.keySet().iterator(); NS.hasNext(); ) {
|
||||
CAstNode old = (CAstNode) NS.next();
|
||||
CAstNode newNode = (CAstNode) nodeMap.get(old);
|
||||
for(Iterator<CAstNode> NS = nodeMap.keySet().iterator(); NS.hasNext(); ) {
|
||||
CAstNode old = NS.next();
|
||||
CAstNode newNode = nodeMap.get(old);
|
||||
newMap.map(newNode, newNode);
|
||||
if (oldSources.contains(old)) {
|
||||
if (orig.getTarget(old, null) != null) {
|
||||
|
@ -70,7 +71,7 @@ public class CAstCloner {
|
|||
}
|
||||
}
|
||||
|
||||
for(Iterator LS = orig.getTargetLabels(old).iterator(); LS.hasNext(); ) {
|
||||
for(Iterator<IField> LS = orig.getTargetLabels(old).iterator(); LS.hasNext(); ) {
|
||||
Object label = LS.next();
|
||||
CAstNode oldTarget = orig.getTarget(old, label);
|
||||
if (nodeMap.containsKey(oldTarget)) {
|
||||
|
@ -86,15 +87,15 @@ public class CAstCloner {
|
|||
}
|
||||
|
||||
private CAstSourcePositionMap
|
||||
copySource(Map nodeMap, CAstSourcePositionMap orig)
|
||||
copySource(Map<CAstNode, CAstNode> nodeMap, CAstSourcePositionMap orig)
|
||||
{
|
||||
if (orig == null) {
|
||||
return null;
|
||||
} else {
|
||||
CAstSourcePositionRecorder newMap = new CAstSourcePositionRecorder();
|
||||
for(Iterator NS = nodeMap.keySet().iterator(); NS.hasNext(); ) {
|
||||
CAstNode old = (CAstNode) NS.next();
|
||||
CAstNode newNode = (CAstNode) nodeMap.get(old);
|
||||
for(Iterator<CAstNode> NS = nodeMap.keySet().iterator(); NS.hasNext(); ) {
|
||||
CAstNode old = NS.next();
|
||||
CAstNode newNode = nodeMap.get(old);
|
||||
|
||||
if (orig.getPosition(old) != null) {
|
||||
newMap.setPosition(newNode, orig.getPosition(old));
|
||||
|
@ -109,7 +110,7 @@ public class CAstCloner {
|
|||
final CAstControlFlowMap cfg,
|
||||
final CAstSourcePositionMap pos)
|
||||
{
|
||||
final Map nodes = new HashMap();
|
||||
final Map<CAstNode, CAstNode> nodes = new HashMap<CAstNode, CAstNode>();
|
||||
final CAstNode newRoot = copyNodes(root, nodes);
|
||||
return new Clone() {
|
||||
private CAstControlFlowMap theCfg = null;
|
||||
|
|
|
@ -10,21 +10,25 @@
|
|||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.tree.impl;
|
||||
|
||||
import com.ibm.wala.cast.tree.*;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import com.ibm.wala.cast.tree.CAstNode;
|
||||
import com.ibm.wala.cast.tree.CAstSourcePositionMap;
|
||||
|
||||
public class CAstSourcePositionRecorder implements CAstSourcePositionMap {
|
||||
|
||||
private final HashMap positions = new HashMap();
|
||||
private final HashMap<CAstNode, Position> positions = new HashMap<CAstNode, Position>();
|
||||
|
||||
public Position getPosition(CAstNode n) {
|
||||
return (Position) positions.get(n);
|
||||
return positions.get(n);
|
||||
}
|
||||
|
||||
public Iterator getMappedNodes() {
|
||||
public Iterator<CAstNode> getMappedNodes() {
|
||||
return positions.keySet().iterator();
|
||||
}
|
||||
|
||||
|
@ -79,8 +83,8 @@ public class CAstSourcePositionRecorder implements CAstSourcePositionMap {
|
|||
}
|
||||
|
||||
public void addAll(CAstSourcePositionMap other) {
|
||||
for(Iterator nodes = other.getMappedNodes(); nodes.hasNext(); ) {
|
||||
CAstNode node = (CAstNode) nodes.next();
|
||||
for(Iterator<CAstNode> nodes = other.getMappedNodes(); nodes.hasNext(); ) {
|
||||
CAstNode node = nodes.next();
|
||||
setPosition(node, other.getPosition(node));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,10 +18,10 @@ import com.ibm.wala.cast.tree.*;
|
|||
import java.util.*;
|
||||
|
||||
public class CAstTypeDictionaryImpl implements CAstTypeDictionary {
|
||||
private final Map/*<ASTType,CAstType>*/ fMap= new HashMap();
|
||||
private final Map/*<ASTType,CAstType>*/<Object, CAstType> fMap= new HashMap<Object, CAstType>();
|
||||
|
||||
public CAstType getCAstTypeFor(Object/*ASTType*/ astType) {
|
||||
return (CAstType) fMap.get(astType);
|
||||
return fMap.get(astType);
|
||||
}
|
||||
|
||||
public void map(Object/*ASTType*/ astType, CAstType castType) {
|
||||
|
|
|
@ -68,7 +68,7 @@ public abstract class CAstVisitor {
|
|||
*/
|
||||
protected Context makeUnwindContext(Context context, CAstNode n, CAstVisitor visitor) { return context; }
|
||||
|
||||
private final Map entityParents = new HashMap();
|
||||
private final Map<CAstEntity, CAstEntity> entityParents = new HashMap<CAstEntity, CAstEntity>();
|
||||
|
||||
/**
|
||||
* Get the parent entity for a given entity.
|
||||
|
@ -76,7 +76,7 @@ public abstract class CAstVisitor {
|
|||
* @return the parent entity for the given entity
|
||||
*/
|
||||
protected CAstEntity getParent(CAstEntity entity) {
|
||||
return (CAstEntity) entityParents.get(entity);
|
||||
return entityParents.get(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,11 +22,11 @@ public class CAstFunctions {
|
|||
if (f.accepts(tree)) {
|
||||
return tree;
|
||||
} else {
|
||||
for(int i = 0; i < tree.getChildCount(); i++) {
|
||||
CAstNode result = findIf(tree.getChild(i), f);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
for (int i = 0; i < tree.getChildCount(); i++) {
|
||||
CAstNode result = findIf(tree.getChild(i), f);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,36 +36,36 @@ public class CAstFunctions {
|
|||
public static Iterator iterateNodes(final CAstNode tree) {
|
||||
return new DFSDiscoverTimeIterator() {
|
||||
|
||||
private final Map pendingChildren = new HashMap();
|
||||
private final Map<Object, Iterator> pendingChildren = new HashMap<Object, Iterator>();
|
||||
|
||||
protected Iterator getPendingChildren(Object n) {
|
||||
return (Iterator) pendingChildren.get(n);
|
||||
return pendingChildren.get(n);
|
||||
}
|
||||
|
||||
protected void setPendingChildren(Object v, Iterator iterator) {
|
||||
pendingChildren.put(v, iterator);
|
||||
pendingChildren.put(v, iterator);
|
||||
}
|
||||
|
||||
protected Iterator getConnected(final Object n) {
|
||||
return new Iterator() {
|
||||
private int i = 0;
|
||||
return new Iterator() {
|
||||
private int i = 0;
|
||||
|
||||
public boolean hasNext() {
|
||||
return i < ((CAstNode)n).getChildCount();
|
||||
}
|
||||
public boolean hasNext() {
|
||||
return i < ((CAstNode) n).getChildCount();
|
||||
}
|
||||
|
||||
public Object next() {
|
||||
return ((CAstNode)n).getChild(i++);
|
||||
}
|
||||
public Object next() {
|
||||
return ((CAstNode) n).getChild(i++);
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
{
|
||||
init(tree);
|
||||
init(tree);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -73,5 +73,5 @@ public class CAstFunctions {
|
|||
public static Iterator findAll(CAstNode tree, Filter f) {
|
||||
return new FilterIterator(iterateNodes(tree), f);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -25,13 +25,19 @@ import com.ibm.wala.util.debug.Trace;
|
|||
|
||||
public class CAstPattern {
|
||||
private static boolean DEBUG_PARSER = false;
|
||||
|
||||
private static boolean DEBUG_MATCH = false;
|
||||
|
||||
private final static int CHILD_KIND = -1;
|
||||
|
||||
private final static int CHILDREN_KIND = -2;
|
||||
|
||||
private final static int REPEATED_PATTERN_KIND = -3;
|
||||
|
||||
private final static int ALTERNATIVE_PATTERN_KIND = -4;
|
||||
|
||||
private final static int OPTIONAL_PATTERN_KIND = -5;
|
||||
|
||||
private final static int REFERENCE_PATTERN_KIND = -6;
|
||||
|
||||
private final static int IGNORE_KIND = -99;
|
||||
|
@ -39,61 +45,62 @@ public class CAstPattern {
|
|||
private final String name;
|
||||
|
||||
private final int kind;
|
||||
private final String value;
|
||||
private final CAstPattern[] children;
|
||||
private final Map references;
|
||||
|
||||
public static class Segments extends TreeMap {
|
||||
|
||||
private final String value;
|
||||
|
||||
private final CAstPattern[] children;
|
||||
|
||||
private final Map<String, CAstPattern> references;
|
||||
|
||||
public static class Segments extends TreeMap<String,Object> {
|
||||
|
||||
public CAstNode getSingle(String name) {
|
||||
Assertions._assert(containsKey(name), name);
|
||||
return (CAstNode) get(name);
|
||||
}
|
||||
|
||||
public List getMultiple(String name) {
|
||||
if (! containsKey(name)) {
|
||||
return Collections.EMPTY_LIST;
|
||||
public List<Object> getMultiple(String name) {
|
||||
if (!containsKey(name)) {
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
Object o = get(name);
|
||||
if (o instanceof CAstNode) {
|
||||
return Collections.singletonList(o);
|
||||
} else {
|
||||
Assertions._assert(o instanceof List);
|
||||
return (List)o;
|
||||
}
|
||||
Object o = get(name);
|
||||
if (o instanceof CAstNode) {
|
||||
return Collections.singletonList(o);
|
||||
} else {
|
||||
Assertions._assert(o instanceof List);
|
||||
return (List<Object>) o;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addAll(Segments other) {
|
||||
for(Iterator xs = other.entrySet().iterator(); xs.hasNext(); ) {
|
||||
Map.Entry e = (Map.Entry) xs.next();
|
||||
String name = (String)e.getKey();
|
||||
if (e.getValue() instanceof CAstNode) {
|
||||
add(name, (CAstNode) e.getValue());
|
||||
} else {
|
||||
for(Iterator vs = ((List)e.getValue()).iterator();
|
||||
vs.hasNext(); )
|
||||
{
|
||||
add(name, (CAstNode) vs.next());
|
||||
}
|
||||
}
|
||||
for (Iterator xs = other.entrySet().iterator(); xs.hasNext();) {
|
||||
Map.Entry e = (Map.Entry) xs.next();
|
||||
String name = (String) e.getKey();
|
||||
if (e.getValue() instanceof CAstNode) {
|
||||
add(name, (CAstNode) e.getValue());
|
||||
} else {
|
||||
for (Iterator vs = ((List) e.getValue()).iterator(); vs.hasNext();) {
|
||||
add(name, (CAstNode) vs.next());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void add(String name, CAstNode result) {
|
||||
if (containsKey(name)) {
|
||||
Object o = get(name);
|
||||
if (o instanceof List) {
|
||||
((List)o).add(result);
|
||||
} else {
|
||||
Assertions._assert(o instanceof CAstNode);
|
||||
List x = new ArrayList();
|
||||
x.add(o);
|
||||
x.add(result);
|
||||
put(name, x);
|
||||
}
|
||||
Object o = get(name);
|
||||
if (o instanceof List) {
|
||||
((List<CAstNode>) o).add(result);
|
||||
} else {
|
||||
Assertions._assert(o instanceof CAstNode);
|
||||
List<Object> x = new ArrayList<Object>();
|
||||
x.add(o);
|
||||
x.add(result);
|
||||
put(name, x);
|
||||
}
|
||||
} else {
|
||||
put(name, result);
|
||||
put(name, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -114,7 +121,7 @@ public class CAstPattern {
|
|||
this.references = null;
|
||||
}
|
||||
|
||||
public CAstPattern(String patternName, Map references) {
|
||||
public CAstPattern(String patternName, Map<String, CAstPattern> references) {
|
||||
this.name = null;
|
||||
this.kind = REFERENCE_PATTERN_KIND;
|
||||
this.value = patternName;
|
||||
|
@ -133,7 +140,7 @@ public class CAstPattern {
|
|||
if (kind == REFERENCE_PATTERN_KIND) {
|
||||
sb.append("ref:").append(value);
|
||||
} else {
|
||||
sb.append("literal:").append(value);
|
||||
sb.append("literal:").append(value);
|
||||
}
|
||||
} else if (kind == CHILD_KIND) {
|
||||
sb.append("*");
|
||||
|
@ -151,22 +158,20 @@ public class CAstPattern {
|
|||
|
||||
if (children != null) {
|
||||
sb.append("(");
|
||||
for(int i = 0; i < children.length; i++) {
|
||||
sb.append( children[i].toString() );
|
||||
if (i == children.length-1) {
|
||||
sb.append(")");
|
||||
} else {
|
||||
sb.append(",");
|
||||
}
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
sb.append(children[i].toString());
|
||||
if (i == children.length - 1) {
|
||||
sb.append(")");
|
||||
} else {
|
||||
sb.append(",");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static boolean
|
||||
matchChildren(CAstNode tree, int i, CAstPattern[] cs, int j, Segments s)
|
||||
{
|
||||
private static boolean matchChildren(CAstNode tree, int i, CAstPattern[] cs, int j, Segments s) {
|
||||
if (i >= tree.getChildCount() && j >= cs.length) {
|
||||
return true;
|
||||
} else if (i < tree.getChildCount() && j >= cs.length) {
|
||||
|
@ -176,160 +181,151 @@ public class CAstPattern {
|
|||
case CHILDREN_KIND:
|
||||
case OPTIONAL_PATTERN_KIND:
|
||||
case REPEATED_PATTERN_KIND:
|
||||
return matchChildren(tree, i, cs, j+1, s);
|
||||
return matchChildren(tree, i, cs, j + 1, s);
|
||||
|
||||
default:
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (cs[j].kind == CHILD_KIND) {
|
||||
|
||||
if (DEBUG_MATCH) {
|
||||
Trace.println("* matches "+CAstPrinter.print(tree.getChild(i)));
|
||||
}
|
||||
if (DEBUG_MATCH) {
|
||||
Trace.println("* matches " + CAstPrinter.print(tree.getChild(i)));
|
||||
}
|
||||
|
||||
if (s != null && cs[j].name != null) {
|
||||
s.add(cs[j].name, tree.getChild(i));
|
||||
}
|
||||
return matchChildren(tree, i+1, cs, j+1, s);
|
||||
if (s != null && cs[j].name != null) {
|
||||
s.add(cs[j].name, tree.getChild(i));
|
||||
}
|
||||
return matchChildren(tree, i + 1, cs, j + 1, s);
|
||||
|
||||
} else if (cs[j].kind == CHILDREN_KIND) {
|
||||
if (tryMatchChildren(tree, i, cs, j+1, s)) {
|
||||
if (tryMatchChildren(tree, i, cs, j + 1, s)) {
|
||||
|
||||
if (DEBUG_MATCH) {
|
||||
Trace.println("** matches nothing");
|
||||
}
|
||||
if (DEBUG_MATCH) {
|
||||
Trace.println("** matches nothing");
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
|
||||
} else {
|
||||
} else {
|
||||
|
||||
if (DEBUG_MATCH) {
|
||||
Trace.println(
|
||||
"** matches " + CAstPrinter.print(tree.getChild(i)));
|
||||
}
|
||||
if (DEBUG_MATCH) {
|
||||
Trace.println("** matches " + CAstPrinter.print(tree.getChild(i)));
|
||||
}
|
||||
|
||||
if (s != null && cs[j].name != null) {
|
||||
s.add(cs[j].name, tree.getChild(i) );
|
||||
}
|
||||
if (s != null && cs[j].name != null) {
|
||||
s.add(cs[j].name, tree.getChild(i));
|
||||
}
|
||||
|
||||
return matchChildren(tree, i+1, cs, j, s);
|
||||
}
|
||||
return matchChildren(tree, i + 1, cs, j, s);
|
||||
}
|
||||
|
||||
} else if (cs[j].kind == REPEATED_PATTERN_KIND) {
|
||||
CAstPattern repeatedPattern = cs[j].children[0];
|
||||
if (repeatedPattern.tryMatch(tree.getChild(i), s)) {
|
||||
if (s != null && cs[j].name != null) {
|
||||
s.add(cs[j].name, tree.getChild(i) );
|
||||
}
|
||||
CAstPattern repeatedPattern = cs[j].children[0];
|
||||
if (repeatedPattern.tryMatch(tree.getChild(i), s)) {
|
||||
if (s != null && cs[j].name != null) {
|
||||
s.add(cs[j].name, tree.getChild(i));
|
||||
}
|
||||
|
||||
if (DEBUG_MATCH) {
|
||||
Trace.println(
|
||||
cs[j] + " matches " + CAstPrinter.print(tree.getChild(i)));
|
||||
}
|
||||
if (DEBUG_MATCH) {
|
||||
Trace.println(cs[j] + " matches " + CAstPrinter.print(tree.getChild(i)));
|
||||
}
|
||||
|
||||
return matchChildren(tree, i+1, cs, j, s);
|
||||
return matchChildren(tree, i + 1, cs, j, s);
|
||||
|
||||
} else {
|
||||
} else {
|
||||
|
||||
if (DEBUG_MATCH) {
|
||||
Trace.println(cs[j] + " matches nothing");
|
||||
}
|
||||
if (DEBUG_MATCH) {
|
||||
Trace.println(cs[j] + " matches nothing");
|
||||
}
|
||||
|
||||
return matchChildren(tree, i, cs, j+1, s);
|
||||
}
|
||||
return matchChildren(tree, i, cs, j + 1, s);
|
||||
}
|
||||
|
||||
} else if (cs[j].kind == OPTIONAL_PATTERN_KIND) {
|
||||
if (tryMatchChildren(tree, i, cs, j+1, s)) {
|
||||
if (tryMatchChildren(tree, i, cs, j + 1, s)) {
|
||||
|
||||
if (DEBUG_MATCH) {
|
||||
Trace.println(cs[j] + " matches nothing");
|
||||
}
|
||||
if (DEBUG_MATCH) {
|
||||
Trace.println(cs[j] + " matches nothing");
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
CAstPattern optionalPattern = cs[j].children[0];
|
||||
if (optionalPattern.tryMatch(tree.getChild(i), s)) {
|
||||
return true;
|
||||
} else {
|
||||
CAstPattern optionalPattern = cs[j].children[0];
|
||||
if (optionalPattern.tryMatch(tree.getChild(i), s)) {
|
||||
|
||||
if (DEBUG_MATCH) {
|
||||
Trace.println(
|
||||
cs[j] + " matches " + CAstPrinter.print(tree.getChild(i)));
|
||||
}
|
||||
if (DEBUG_MATCH) {
|
||||
Trace.println(cs[j] + " matches " + CAstPrinter.print(tree.getChild(i)));
|
||||
}
|
||||
|
||||
return matchChildren(tree, i+1, cs, j+1, s);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return matchChildren(tree, i + 1, cs, j + 1, s);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
return
|
||||
cs[j].match(tree.getChild(i), s)
|
||||
&&
|
||||
matchChildren(tree, i+1, cs, j+1, s);
|
||||
return cs[j].match(tree.getChild(i), s) && matchChildren(tree, i + 1, cs, j + 1, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean match(CAstNode tree, Segments s) {
|
||||
if (DEBUG_MATCH) {
|
||||
Trace.println("matching "+this+" against "+CAstPrinter.print(tree));
|
||||
Trace.println("matching " + this + " against " + CAstPrinter.print(tree));
|
||||
}
|
||||
|
||||
if (kind == REFERENCE_PATTERN_KIND) {
|
||||
return ((CAstPattern)references.get(value)).match(tree, s);
|
||||
return references.get(value).match(tree, s);
|
||||
|
||||
} else if (kind == ALTERNATIVE_PATTERN_KIND) {
|
||||
for(int i = 0; i < children.length; i++) {
|
||||
if (children[i].tryMatch(tree, s)) {
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
if (children[i].tryMatch(tree, s)) {
|
||||
|
||||
if (s != null && name != null) s.add(name, tree);
|
||||
|
||||
return true;
|
||||
}
|
||||
if (s != null && name != null)
|
||||
s.add(name, tree);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG_MATCH) {
|
||||
Trace.println("match failed (a)");
|
||||
Trace.println("match failed (a)");
|
||||
}
|
||||
return false;
|
||||
|
||||
} else {
|
||||
if ( (value == null)?
|
||||
tree.getKind() != kind:
|
||||
( tree.getKind()!=CAstNode.CONSTANT
|
||||
||
|
||||
!value.equals(tree.getValue().toString()) ) )
|
||||
{
|
||||
if (DEBUG_MATCH) {
|
||||
Trace.println("match failed (b)");
|
||||
}
|
||||
if ((value == null) ? tree.getKind() != kind : (tree.getKind() != CAstNode.CONSTANT || !value.equals(tree.getValue()
|
||||
.toString()))) {
|
||||
if (DEBUG_MATCH) {
|
||||
Trace.println("match failed (b)");
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (s != null && name != null) s.add(name, tree);
|
||||
|
||||
if (s != null && name != null)
|
||||
s.add(name, tree);
|
||||
|
||||
if (children == null || children.length == 0) {
|
||||
if (DEBUG_MATCH && tree.getChildCount() != 0) {
|
||||
Trace.println("match failed (c)");
|
||||
}
|
||||
return tree.getChildCount() == 0;
|
||||
if (DEBUG_MATCH && tree.getChildCount() != 0) {
|
||||
Trace.println("match failed (c)");
|
||||
}
|
||||
return tree.getChildCount() == 0;
|
||||
} else {
|
||||
return matchChildren(tree, 0, children, 0, s);
|
||||
return matchChildren(tree, 0, children, 0, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean
|
||||
tryMatchChildren(CAstNode tree, int i, CAstPattern[] cs, int j, Segments s)
|
||||
{
|
||||
private static boolean tryMatchChildren(CAstNode tree, int i, CAstPattern[] cs, int j, Segments s) {
|
||||
if (s == null) {
|
||||
return matchChildren(tree, i, cs, j, s);
|
||||
} else {
|
||||
Segments ss = new Segments();
|
||||
boolean result = matchChildren(tree, i, cs, j, ss);
|
||||
if (result) s.addAll(ss);
|
||||
if (result)
|
||||
s.addAll(ss);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -340,7 +336,8 @@ public class CAstPattern {
|
|||
} else {
|
||||
Segments ss = new Segments();
|
||||
boolean result = match(tree, ss);
|
||||
if (result) s.addAll(ss);
|
||||
if (result)
|
||||
s.addAll(ss);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -367,36 +364,37 @@ public class CAstPattern {
|
|||
}
|
||||
|
||||
private static class Parser {
|
||||
private final Map namedPatterns = new HashMap();
|
||||
private final Map<String, CAstPattern> namedPatterns = new HashMap<String, CAstPattern>();
|
||||
|
||||
private final String patternString;
|
||||
|
||||
private int start;
|
||||
|
||||
private int end;
|
||||
|
||||
private Parser(String patternString) {
|
||||
this.patternString = patternString;
|
||||
}
|
||||
|
||||
// private Parser(String patternString, int start) {
|
||||
// this(patternString);
|
||||
// this.start = start;
|
||||
// }
|
||||
// private Parser(String patternString, int start) {
|
||||
// this(patternString);
|
||||
// this.start = start;
|
||||
// }
|
||||
|
||||
private String parseName(boolean internal) {
|
||||
if (patternString.charAt(start) == (internal?'{':'<')) {
|
||||
int nameStart = start+1;
|
||||
int nameEnd = patternString.indexOf(internal?'}':'>', nameStart);
|
||||
start = nameEnd + 1;
|
||||
return patternString.substring(nameStart, nameEnd);
|
||||
if (patternString.charAt(start) == (internal ? '{' : '<')) {
|
||||
int nameStart = start + 1;
|
||||
int nameEnd = patternString.indexOf(internal ? '}' : '>', nameStart);
|
||||
start = nameEnd + 1;
|
||||
return patternString.substring(nameStart, nameEnd);
|
||||
} else {
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public CAstPattern parse()
|
||||
throws NoSuchFieldException, IllegalAccessException
|
||||
{
|
||||
public CAstPattern parse() throws NoSuchFieldException, IllegalAccessException {
|
||||
if (DEBUG_PARSER) {
|
||||
Trace.println("parsing " + patternString.substring(start));
|
||||
Trace.println("parsing " + patternString.substring(start));
|
||||
}
|
||||
|
||||
String internalName = parseName(true);
|
||||
|
@ -404,103 +402,92 @@ public class CAstPattern {
|
|||
|
||||
CAstPattern result;
|
||||
if (patternString.charAt(start) == '`') {
|
||||
int strEnd = patternString.indexOf('`', start+1);
|
||||
end = strEnd+1;
|
||||
String patternName = patternString.substring(start+1, strEnd);
|
||||
Assertions._assert(internalName == null);
|
||||
result = new CAstPattern(patternName, namedPatterns);
|
||||
int strEnd = patternString.indexOf('`', start + 1);
|
||||
end = strEnd + 1;
|
||||
String patternName = patternString.substring(start + 1, strEnd);
|
||||
Assertions._assert(internalName == null);
|
||||
result = new CAstPattern(patternName, namedPatterns);
|
||||
|
||||
} else if (patternString.charAt(start) == '"') {
|
||||
int strEnd = patternString.indexOf('"', start+1);
|
||||
end = strEnd+1;
|
||||
result =
|
||||
new CAstPattern(
|
||||
name,
|
||||
patternString.substring(start+1, strEnd));
|
||||
int strEnd = patternString.indexOf('"', start + 1);
|
||||
end = strEnd + 1;
|
||||
result = new CAstPattern(name, patternString.substring(start + 1, strEnd));
|
||||
|
||||
} else if (patternString.startsWith("**", start)) {
|
||||
end = start+2;
|
||||
result = new CAstPattern(name, CHILDREN_KIND, null);
|
||||
end = start + 2;
|
||||
result = new CAstPattern(name, CHILDREN_KIND, null);
|
||||
|
||||
} else if (patternString.startsWith("*", start)) {
|
||||
end = start+1;
|
||||
result = new CAstPattern(name, CHILD_KIND, null);
|
||||
|
||||
end = start + 1;
|
||||
result = new CAstPattern(name, CHILD_KIND, null);
|
||||
|
||||
} else if (patternString.startsWith("|(", start)) {
|
||||
List alternatives = new ArrayList();
|
||||
start += 2;
|
||||
do {
|
||||
alternatives.add( parse() );
|
||||
start = end+2;
|
||||
} while (patternString.startsWith("||", end));
|
||||
Assertions._assert(patternString.startsWith(")|", end), patternString);
|
||||
end += 2;
|
||||
result = new CAstPattern(name,
|
||||
ALTERNATIVE_PATTERN_KIND,
|
||||
(CAstPattern[])
|
||||
alternatives.toArray(new CAstPattern[alternatives.size()]));
|
||||
|
||||
List<CAstPattern> alternatives = new ArrayList<CAstPattern>();
|
||||
start += 2;
|
||||
do {
|
||||
alternatives.add(parse());
|
||||
start = end + 2;
|
||||
} while (patternString.startsWith("||", end));
|
||||
Assertions._assert(patternString.startsWith(")|", end), patternString);
|
||||
end += 2;
|
||||
result = new CAstPattern(name, ALTERNATIVE_PATTERN_KIND, alternatives.toArray(new CAstPattern[alternatives.size()]));
|
||||
|
||||
} else if (patternString.startsWith("@(", start)) {
|
||||
start += 2;
|
||||
CAstPattern children[] = new CAstPattern[]{ parse() };
|
||||
Assertions._assert( patternString.startsWith(")@", end) );
|
||||
end += 2;
|
||||
start += 2;
|
||||
CAstPattern children[] = new CAstPattern[] { parse() };
|
||||
Assertions._assert(patternString.startsWith(")@", end));
|
||||
end += 2;
|
||||
|
||||
if (DEBUG_PARSER) {
|
||||
Trace.println("repeated pattern: " + children[0]);
|
||||
}
|
||||
if (DEBUG_PARSER) {
|
||||
Trace.println("repeated pattern: " + children[0]);
|
||||
}
|
||||
|
||||
result = new CAstPattern(name, REPEATED_PATTERN_KIND, children);
|
||||
|
||||
result = new CAstPattern(name, REPEATED_PATTERN_KIND, children);
|
||||
|
||||
} else if (patternString.startsWith("?(", start)) {
|
||||
start += 2;
|
||||
CAstPattern children[] = new CAstPattern[]{ parse() };
|
||||
Assertions._assert( patternString.startsWith(")?", end) );
|
||||
end += 2;
|
||||
start += 2;
|
||||
CAstPattern children[] = new CAstPattern[] { parse() };
|
||||
Assertions._assert(patternString.startsWith(")?", end));
|
||||
end += 2;
|
||||
|
||||
if (DEBUG_PARSER) {
|
||||
Trace.println("optional pattern: " + children[0]);
|
||||
}
|
||||
if (DEBUG_PARSER) {
|
||||
Trace.println("optional pattern: " + children[0]);
|
||||
}
|
||||
|
||||
result = new CAstPattern(name, OPTIONAL_PATTERN_KIND, children);
|
||||
|
||||
result = new CAstPattern(name, OPTIONAL_PATTERN_KIND, children);
|
||||
|
||||
} else {
|
||||
int kindEnd = patternString.indexOf('(', start);
|
||||
String kindStr = patternString.substring(start, kindEnd);
|
||||
Field kindField = CAstNode.class.getField(kindStr);
|
||||
int kind = kindField.getInt(null);
|
||||
int kindEnd = patternString.indexOf('(', start);
|
||||
String kindStr = patternString.substring(start, kindEnd);
|
||||
Field kindField = CAstNode.class.getField(kindStr);
|
||||
int kind = kindField.getInt(null);
|
||||
|
||||
if (patternString.charAt(kindEnd+1) == ')') {
|
||||
end = kindEnd+2;
|
||||
result = new CAstPattern(name, kind, null);
|
||||
|
||||
} else {
|
||||
List children = new ArrayList();
|
||||
start = patternString.indexOf('(', start) + 1;
|
||||
do {
|
||||
children.add( parse() );
|
||||
start = end+1;
|
||||
|
||||
if (DEBUG_PARSER) {
|
||||
Trace.println(
|
||||
"parsing children: " + patternString.substring(end));
|
||||
}
|
||||
|
||||
} while (patternString.charAt(end) == ',');
|
||||
|
||||
Assertions._assert(patternString.charAt(end) == ')');
|
||||
end++;
|
||||
if (patternString.charAt(kindEnd + 1) == ')') {
|
||||
end = kindEnd + 2;
|
||||
result = new CAstPattern(name, kind, null);
|
||||
|
||||
result = new CAstPattern(
|
||||
name,
|
||||
kind,
|
||||
(CAstPattern[])
|
||||
children.toArray(new CAstPattern[children.size()]));
|
||||
}
|
||||
} else {
|
||||
List<CAstPattern> children = new ArrayList<CAstPattern>();
|
||||
start = patternString.indexOf('(', start) + 1;
|
||||
do {
|
||||
children.add(parse());
|
||||
start = end + 1;
|
||||
|
||||
if (DEBUG_PARSER) {
|
||||
Trace.println("parsing children: " + patternString.substring(end));
|
||||
}
|
||||
|
||||
} while (patternString.charAt(end) == ',');
|
||||
|
||||
Assertions._assert(patternString.charAt(end) == ')');
|
||||
end++;
|
||||
|
||||
result = new CAstPattern(name, kind, children.toArray(new CAstPattern[children.size()]));
|
||||
}
|
||||
}
|
||||
|
||||
if (internalName != null) {
|
||||
namedPatterns.put(internalName, result);
|
||||
namedPatterns.put(internalName, result);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
Loading…
Reference in New Issue