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 {
|
class AstCGNode extends ExplicitNode {
|
||||||
private Set callbacks;
|
private Set<Function> callbacks;
|
||||||
|
|
||||||
private AstCGNode(IMethod method, Context context) {
|
private AstCGNode(IMethod method, Context context) {
|
||||||
super(method, context);
|
super(method, context);
|
||||||
|
@ -73,8 +73,8 @@ public class AstCallGraph extends ExplicitCallGraph {
|
||||||
boolean done = false;
|
boolean done = false;
|
||||||
while (!done) {
|
while (!done) {
|
||||||
try {
|
try {
|
||||||
for (Iterator x = callbacks.iterator(); x.hasNext();) {
|
for (Iterator<Function> x = callbacks.iterator(); x.hasNext();) {
|
||||||
((Function) x.next()).apply(null);
|
x.next().apply(null);
|
||||||
}
|
}
|
||||||
} catch (ConcurrentModificationException e) {
|
} catch (ConcurrentModificationException e) {
|
||||||
done = false;
|
done = false;
|
||||||
|
@ -87,12 +87,12 @@ public class AstCallGraph extends ExplicitCallGraph {
|
||||||
|
|
||||||
public void addCallback(Function callback) {
|
public void addCallback(Function callback) {
|
||||||
if (callbacks == null)
|
if (callbacks == null)
|
||||||
callbacks = new HashSet(1);
|
callbacks = new HashSet<Function>(1);
|
||||||
callbacks.add(callback);
|
callbacks.add(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fireCallbacksTransitive() {
|
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(); )
|
nodes.hasNext(); )
|
||||||
{
|
{
|
||||||
((AstCGNode)nodes.next()).fireCallbacks();
|
((AstCGNode)nodes.next()).fireCallbacks();
|
||||||
|
|
|
@ -10,17 +10,20 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
package com.ibm.wala.cast.ipa.callgraph;
|
package com.ibm.wala.cast.ipa.callgraph;
|
||||||
|
|
||||||
import com.ibm.wala.cast.loader.*;
|
import java.util.Iterator;
|
||||||
import com.ibm.wala.classLoader.*;
|
|
||||||
import com.ibm.wala.ipa.callgraph.*;
|
import com.ibm.wala.cast.loader.AstMethod;
|
||||||
import com.ibm.wala.ipa.callgraph.propagation.cfa.*;
|
import com.ibm.wala.classLoader.CallSiteReference;
|
||||||
import com.ibm.wala.ipa.cha.*;
|
import com.ibm.wala.classLoader.IMethod;
|
||||||
import com.ibm.wala.ssa.*;
|
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.collections.EmptyIterator;
|
||||||
import com.ibm.wala.util.warnings.WarningSet;
|
import com.ibm.wala.util.warnings.WarningSet;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class AstContextInsensitiveSSAContextInterpreter
|
public class AstContextInsensitiveSSAContextInterpreter
|
||||||
extends ContextInsensitiveSSAInterpreter
|
extends ContextInsensitiveSSAInterpreter
|
||||||
{
|
{
|
||||||
|
@ -33,7 +36,7 @@ public class AstContextInsensitiveSSAContextInterpreter
|
||||||
return method instanceof AstMethod;
|
return method instanceof AstMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator iterateCallSites(CGNode N, WarningSet warnings) {
|
public Iterator<CallSiteReference> iterateCallSites(CGNode N, WarningSet warnings) {
|
||||||
IR ir = getIR(N, warnings);
|
IR ir = getIR(N, warnings);
|
||||||
if (ir == null) {
|
if (ir == null) {
|
||||||
return EmptyIterator.instance();
|
return EmptyIterator.instance();
|
||||||
|
|
|
@ -16,9 +16,9 @@ import java.util.*;
|
||||||
|
|
||||||
public interface AstPointerKeyFactory extends PointerKeyFactory {
|
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);
|
PointerKey getPointerKeyForObjectCatalog(InstanceKey I);
|
||||||
|
|
||||||
|
|
|
@ -105,14 +105,14 @@ public abstract class AstSSAPropagationCallGraphBuilder
|
||||||
.getPointerKeyForObjectCatalog(I);
|
.getPointerKeyForObjectCatalog(I);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator
|
public Iterator<PointerKey>
|
||||||
getPointerKeysForReflectedFieldRead(InstanceKey I, InstanceKey F)
|
getPointerKeysForReflectedFieldRead(InstanceKey I, InstanceKey F)
|
||||||
{
|
{
|
||||||
return ((AstPointerKeyFactory)pointerKeyFactory)
|
return ((AstPointerKeyFactory)pointerKeyFactory)
|
||||||
.getPointerKeysForReflectedFieldRead(I, F);
|
.getPointerKeysForReflectedFieldRead(I, F);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator
|
public Iterator<PointerKey>
|
||||||
getPointerKeysForReflectedFieldWrite(InstanceKey I, InstanceKey F)
|
getPointerKeysForReflectedFieldWrite(InstanceKey I, InstanceKey F)
|
||||||
{
|
{
|
||||||
return ((AstPointerKeyFactory)pointerKeyFactory)
|
return ((AstPointerKeyFactory)pointerKeyFactory)
|
||||||
|
@ -290,10 +290,10 @@ public abstract class AstSSAPropagationCallGraphBuilder
|
||||||
if (AstTranslator.DEBUG_LEXICAL)
|
if (AstTranslator.DEBUG_LEXICAL)
|
||||||
Trace.println("looking up lexical parent " + definer);
|
Trace.println("looking up lexical parent " + definer);
|
||||||
|
|
||||||
for(Iterator DS = getLexicalDefiners(node, definer).iterator();
|
for(Iterator<CGNode> DS = getLexicalDefiners(node, definer).iterator();
|
||||||
DS.hasNext(); )
|
DS.hasNext(); )
|
||||||
{
|
{
|
||||||
final CGNode D = (CGNode) DS.next();
|
final CGNode D = DS.next();
|
||||||
|
|
||||||
Iterator PS = new NumberedDFSDiscoverTimeIterator(callGraph, node) {
|
Iterator PS = new NumberedDFSDiscoverTimeIterator(callGraph, node) {
|
||||||
/**
|
/**
|
||||||
|
@ -346,12 +346,12 @@ public abstract class AstSSAPropagationCallGraphBuilder
|
||||||
public int hashCode() { return System.identityHashCode(this); }
|
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) {
|
if (definer == null) {
|
||||||
return Collections.singleton(callGraph.getFakeRootNode());
|
return Collections.singleton(callGraph.getFakeRootNode());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
final Set result = new HashSet();
|
final Set<CGNode> result = new HashSet<CGNode>();
|
||||||
PointerKey F = getPointerKeyForLocal(opNode, 1);
|
PointerKey F = getPointerKeyForLocal(opNode, 1);
|
||||||
|
|
||||||
IR ir = getCFAContextInterpreter().getIR(opNode, getWarnings());
|
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);
|
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,
|
private void addUpwardFunargConstraints(PointerKey lhs,
|
||||||
String name,
|
String name,
|
||||||
|
@ -680,21 +680,21 @@ public abstract class AstSSAPropagationCallGraphBuilder
|
||||||
PointerKey objCatalog = getPointerKeyForObjectCatalog(objKeys[o]);
|
PointerKey objCatalog = getPointerKeyForObjectCatalog(objKeys[o]);
|
||||||
for(int f = 0; f < fieldsKeys.length; f++) {
|
for(int f = 0; f < fieldsKeys.length; f++) {
|
||||||
if (isLoadOperation) {
|
if (isLoadOperation) {
|
||||||
for(Iterator keys =
|
for(Iterator<PointerKey> keys =
|
||||||
getPointerKeysForReflectedFieldRead(objKeys[o], fieldsKeys[f]);
|
getPointerKeysForReflectedFieldRead(objKeys[o], fieldsKeys[f]);
|
||||||
keys.hasNext(); )
|
keys.hasNext(); )
|
||||||
{
|
{
|
||||||
PointerKey key = (PointerKey)keys.next();
|
PointerKey key = keys.next();
|
||||||
if (DEBUG_PROPERTIES) action.dump( key, true, true );
|
if (DEBUG_PROPERTIES) action.dump( key, true, true );
|
||||||
action.action( key );
|
action.action( key );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
system.newConstraint(objCatalog, fieldsKeys[f]);
|
system.newConstraint(objCatalog, fieldsKeys[f]);
|
||||||
for(Iterator keys =
|
for(Iterator<PointerKey> keys =
|
||||||
getPointerKeysForReflectedFieldWrite(objKeys[o],fieldsKeys[f]);
|
getPointerKeysForReflectedFieldWrite(objKeys[o],fieldsKeys[f]);
|
||||||
keys.hasNext(); )
|
keys.hasNext(); )
|
||||||
{
|
{
|
||||||
PointerKey key = (PointerKey)keys.next();
|
PointerKey key = keys.next();
|
||||||
if (DEBUG_PROPERTIES) action.dump( key, true, true );
|
if (DEBUG_PROPERTIES) action.dump( key, true, true );
|
||||||
action.action( key );
|
action.action( key );
|
||||||
}
|
}
|
||||||
|
@ -768,21 +768,21 @@ public abstract class AstSSAPropagationCallGraphBuilder
|
||||||
getPointerKeyForObjectCatalog(object);
|
getPointerKeyForObjectCatalog(object);
|
||||||
for(int f = 0; f < fieldsKeys.length; f++) {
|
for(int f = 0; f < fieldsKeys.length; f++) {
|
||||||
if (isLoadOperation) {
|
if (isLoadOperation) {
|
||||||
for(Iterator keys =
|
for(Iterator<PointerKey> keys =
|
||||||
getPointerKeysForReflectedFieldRead(object, fieldsKeys[f]);
|
getPointerKeysForReflectedFieldRead(object, fieldsKeys[f]);
|
||||||
keys.hasNext(); )
|
keys.hasNext(); )
|
||||||
{
|
{
|
||||||
PointerKey key = (PointerKey)keys.next();
|
PointerKey key = keys.next();
|
||||||
if (DEBUG_PROPERTIES) action.dump(key, true, false);
|
if (DEBUG_PROPERTIES) action.dump(key, true, false);
|
||||||
action.action( key );
|
action.action( key );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
system.newConstraint(objCatalog, fieldsKeys[f]);
|
system.newConstraint(objCatalog, fieldsKeys[f]);
|
||||||
for(Iterator keys =
|
for(Iterator<PointerKey> keys =
|
||||||
getPointerKeysForReflectedFieldWrite(object,fieldsKeys[f]);
|
getPointerKeysForReflectedFieldWrite(object,fieldsKeys[f]);
|
||||||
keys.hasNext(); )
|
keys.hasNext(); )
|
||||||
{
|
{
|
||||||
PointerKey key = (PointerKey)keys.next();
|
PointerKey key = keys.next();
|
||||||
if (DEBUG_PROPERTIES) action.dump(key, true, false);
|
if (DEBUG_PROPERTIES) action.dump(key, true, false);
|
||||||
action.action( key );
|
action.action( key );
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,8 +130,8 @@ public class CAstAnalysisScope extends AnalysisScope {
|
||||||
/**
|
/**
|
||||||
* @return an Iterator <ClassLoaderReference>over the loaders.
|
* @return an Iterator <ClassLoaderReference>over the loaders.
|
||||||
*/
|
*/
|
||||||
public Iterator getLoaders() {
|
public Iterator<ClassLoaderReference> getLoaders() {
|
||||||
return new NonNullSingletonIterator( theLoader );
|
return new NonNullSingletonIterator<ClassLoaderReference>( theLoader );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -53,16 +53,17 @@ public class DelegatingAstPointerKeys implements AstPointerKeyFactory {
|
||||||
return new ObjectPropertyCatalogKey(I);
|
return new ObjectPropertyCatalogKey(I);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Map specificStringKeys = new HashMap();
|
private final Map<IField, Set<PointerKey>> specificStringKeys = new HashMap<IField, Set<PointerKey>>();
|
||||||
|
|
||||||
// private final Map specificIndexKeys = new HashMap();
|
// private final Map specificIndexKeys = new HashMap();
|
||||||
|
|
||||||
public PointerKey getPointerKeyForInstanceField(InstanceKey I, IField f) {
|
public PointerKey getPointerKeyForInstanceField(InstanceKey I, IField f) {
|
||||||
PointerKey fk = base.getPointerKeyForInstanceField(I, f);
|
PointerKey fk = base.getPointerKeyForInstanceField(I, f);
|
||||||
if (!specificStringKeys.containsKey(f)) {
|
if (!specificStringKeys.containsKey(f)) {
|
||||||
specificStringKeys.put(f, new HashSet());
|
specificStringKeys.put(f, new HashSet<PointerKey>());
|
||||||
}
|
}
|
||||||
|
|
||||||
((Set)specificStringKeys.get(f)).add(fk);
|
specificStringKeys.get(f).add(fk);
|
||||||
|
|
||||||
return fk;
|
return fk;
|
||||||
}
|
}
|
||||||
|
@ -71,15 +72,14 @@ public class DelegatingAstPointerKeys implements AstPointerKeyFactory {
|
||||||
return base.getPointerKeyForArrayContents(I);
|
return base.getPointerKeyForArrayContents(I);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator getPointerKeysForReflectedFieldRead(InstanceKey I, InstanceKey F) {
|
public Iterator<PointerKey> getPointerKeysForReflectedFieldRead(InstanceKey I, InstanceKey F) {
|
||||||
List result = new LinkedList();
|
List<PointerKey> result = new LinkedList<PointerKey>();
|
||||||
|
|
||||||
// FIXME: current only constant string are handled
|
// FIXME: current only constant string are handled
|
||||||
if (F instanceof ConstantKey) {
|
if (F instanceof ConstantKey) {
|
||||||
Object v = ((ConstantKey) F).getValue();
|
Object v = ((ConstantKey) F).getValue();
|
||||||
if (v instanceof String) {
|
if (v instanceof String) {
|
||||||
IField f =
|
IField f = I.getConcreteType().getField(Atom.findOrCreateUnicodeAtom((String) v));
|
||||||
I.getConcreteType().getField(Atom.findOrCreateUnicodeAtom((String)v));
|
|
||||||
result.add(getPointerKeyForInstanceField(I, f));
|
result.add(getPointerKeyForInstanceField(I, f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,17 +89,16 @@ public class DelegatingAstPointerKeys implements AstPointerKeyFactory {
|
||||||
return result.iterator();
|
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
|
// FIXME: current only constant string are handled
|
||||||
if (F instanceof ConstantKey) {
|
if (F instanceof ConstantKey) {
|
||||||
Object v = ((ConstantKey) F).getValue();
|
Object v = ((ConstantKey) F).getValue();
|
||||||
if (v instanceof String) {
|
if (v instanceof String) {
|
||||||
IField f =
|
IField f = I.getConcreteType().getField(Atom.findOrCreateUnicodeAtom((String) v));
|
||||||
I.getConcreteType().getField(Atom.findOrCreateUnicodeAtom((String)v));
|
return new NonNullSingletonIterator<PointerKey>(getPointerKeyForInstanceField(I, f));
|
||||||
return new NonNullSingletonIterator(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
|
public class MiscellaneousHacksContextSelector implements ContextSelector
|
||||||
{
|
{
|
||||||
|
|
||||||
private final Set methodsToSpecialize;
|
private final Set<MethodReference> methodsToSpecialize;
|
||||||
|
|
||||||
private final ContextSelector specialPolicy;
|
private final ContextSelector specialPolicy;
|
||||||
private final ContextSelector basePolicy;
|
private final ContextSelector basePolicy;
|
||||||
|
@ -42,7 +42,7 @@ public class MiscellaneousHacksContextSelector implements ContextSelector
|
||||||
{
|
{
|
||||||
basePolicy = base;
|
basePolicy = base;
|
||||||
specialPolicy = special;
|
specialPolicy = special;
|
||||||
methodsToSpecialize = new HashSet();
|
methodsToSpecialize = new HashSet<MethodReference>();
|
||||||
for(int i = 0; i < descriptors.length; i++) {
|
for(int i = 0; i < descriptors.length; i++) {
|
||||||
String[] descr = descriptors[i];
|
String[] descr = descriptors[i];
|
||||||
switch (descr.length) {
|
switch (descr.length) {
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
package com.ibm.wala.cast.ipa.callgraph;
|
package com.ibm.wala.cast.ipa.callgraph;
|
||||||
|
|
||||||
|
|
||||||
import com.ibm.wala.cast.ir.translator.*;
|
import com.ibm.wala.cast.ir.translator.*;
|
||||||
import com.ibm.wala.cast.loader.AstMethod.*;
|
import com.ibm.wala.cast.loader.AstMethod.*;
|
||||||
import com.ibm.wala.classLoader.*;
|
import com.ibm.wala.classLoader.*;
|
||||||
|
@ -29,18 +28,21 @@ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory {
|
||||||
protected abstract boolean needsScopeMappingKey(InstanceKey base);
|
protected abstract boolean needsScopeMappingKey(InstanceKey base);
|
||||||
|
|
||||||
private final PropagationCallGraphBuilder builder;
|
private final PropagationCallGraphBuilder builder;
|
||||||
|
|
||||||
private final InstanceKeyFactory basic;
|
private final InstanceKeyFactory basic;
|
||||||
|
|
||||||
public class ScopeMappingInstanceKey implements InstanceKey {
|
public class ScopeMappingInstanceKey implements InstanceKey {
|
||||||
private final InstanceKey base;
|
private final InstanceKey base;
|
||||||
|
|
||||||
private final CGNode creator;
|
private final CGNode creator;
|
||||||
|
|
||||||
private final ScopeMap map;
|
private final ScopeMap map;
|
||||||
|
|
||||||
private class ScopeMap extends HashMap {
|
private class ScopeMap extends HashMap {
|
||||||
|
|
||||||
private static final long serialVersionUID = 3645910671551712906L;
|
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) {
|
if (toDo > 0) {
|
||||||
int restoreIndex = -1;
|
int restoreIndex = -1;
|
||||||
LexicalParent restoreParent = null;
|
LexicalParent restoreParent = null;
|
||||||
|
@ -50,7 +52,8 @@ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory {
|
||||||
|
|
||||||
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)
|
if (AstTranslator.DEBUG_LEXICAL)
|
||||||
Trace.println(level + ": searching " + parents[i]);
|
Trace.println(level + ": searching " + parents[i]);
|
||||||
|
@ -61,7 +64,8 @@ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory {
|
||||||
else {
|
else {
|
||||||
put(parents[i].getName(), node);
|
put(parents[i].getName(), node);
|
||||||
if (AstTranslator.DEBUG_LEXICAL)
|
if (AstTranslator.DEBUG_LEXICAL)
|
||||||
Trace.println(level + ": Adding lexical parent " + parents[i].getName() + " for " + base + " at " + creator + "(toDo is now " + toDo +")");
|
Trace.println(level + ": Adding lexical parent " + parents[i].getName() + " for " + base + " at " + creator
|
||||||
|
+ "(toDo is now " + toDo + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
toDo--;
|
toDo--;
|
||||||
|
@ -96,7 +100,7 @@ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory {
|
||||||
if (AstTranslator.DEBUG_LEXICAL)
|
if (AstTranslator.DEBUG_LEXICAL)
|
||||||
Trace.println("starting search for parents at " + creator);
|
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) {
|
CGNode getDefiningNode(String definer) {
|
||||||
|
@ -123,9 +127,8 @@ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
return (o instanceof ScopeMappingInstanceKey) &&
|
return (o instanceof ScopeMappingInstanceKey) && ((ScopeMappingInstanceKey) o).base.equals(base)
|
||||||
((ScopeMappingInstanceKey)o).base.equals(base) &&
|
&& ((ScopeMappingInstanceKey) o).creator.equals(creator);
|
||||||
((ScopeMappingInstanceKey)o).creator.equals(creator);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
@ -162,10 +165,7 @@ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory {
|
||||||
return basic.getInstanceKeyForClassObject(type);
|
return basic.getInstanceKeyForClassObject(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScopeMappingInstanceKeys(
|
public ScopeMappingInstanceKeys(PropagationCallGraphBuilder builder, InstanceKeyFactory basic) {
|
||||||
PropagationCallGraphBuilder builder,
|
|
||||||
InstanceKeyFactory basic)
|
|
||||||
{
|
|
||||||
this.basic = basic;
|
this.basic = basic;
|
||||||
this.builder = builder;
|
this.builder = builder;
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,8 +66,8 @@ public abstract class ScriptEntryPoints implements Entrypoints {
|
||||||
this.scriptType = scriptType;
|
this.scriptType = scriptType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator iterator() {
|
public Iterator<ScriptEntryPoint> iterator() {
|
||||||
Set ES = new HashSet();
|
Set<ScriptEntryPoint> ES = new HashSet<ScriptEntryPoint>();
|
||||||
Iterator classes = scriptType.getClassLoader().iterateAllClasses();
|
Iterator classes = scriptType.getClassLoader().iterateAllClasses();
|
||||||
while ( classes.hasNext() ) {
|
while ( classes.hasNext() ) {
|
||||||
IClass cls = (IClass)classes.next();
|
IClass cls = (IClass)classes.next();
|
||||||
|
|
|
@ -18,9 +18,7 @@ import com.ibm.wala.util.intset.BitVector;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class DelegatingCFG extends AbstractNumberedGraph<IBasicBlock>
|
public class DelegatingCFG extends AbstractNumberedGraph<IBasicBlock> implements ControlFlowGraph {
|
||||||
implements ControlFlowGraph
|
|
||||||
{
|
|
||||||
|
|
||||||
protected final ControlFlowGraph parent;
|
protected final ControlFlowGraph parent;
|
||||||
|
|
||||||
|
@ -28,45 +26,55 @@ public class DelegatingCFG extends AbstractNumberedGraph<IBasicBlock>
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected NodeManager getNodeManager() {
|
protected NodeManager<IBasicBlock> getNodeManager() {
|
||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected EdgeManager getEdgeManager() {
|
protected EdgeManager<IBasicBlock> getEdgeManager() {
|
||||||
return parent;
|
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) {
|
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) {
|
public int getProgramCounter(int index) {
|
||||||
return parent.getProgramCounter(index);
|
return parent.getProgramCounter(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IMethod getMethod() { return parent.getMethod(); }
|
public IMethod getMethod() {
|
||||||
|
return parent.getMethod();
|
||||||
|
}
|
||||||
|
|
||||||
public Collection getExceptionalSuccessors(IBasicBlock b) {
|
public Collection<IBasicBlock> getExceptionalSuccessors(IBasicBlock b) {
|
||||||
return parent.getExceptionalSuccessors(b);
|
return parent.getExceptionalSuccessors(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getNormalSuccessors(IBasicBlock b) {
|
public Collection<IBasicBlock> getNormalSuccessors(IBasicBlock b) {
|
||||||
return parent.getNormalSuccessors(b);
|
return parent.getNormalSuccessors(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getExceptionalPredecessors(IBasicBlock b) {
|
public Collection<IBasicBlock> getExceptionalPredecessors(IBasicBlock b) {
|
||||||
return parent.getExceptionalPredecessors(b);
|
return parent.getExceptionalPredecessors(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getNormalPredecessors(IBasicBlock b) {
|
public Collection<IBasicBlock> getNormalPredecessors(IBasicBlock b) {
|
||||||
return parent.getNormalPredecessors(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 ControlFlowGraph cfg;
|
||||||
|
|
||||||
private final NumberedNodeManager currentCFGNodes;
|
private final NumberedNodeManager<IBasicBlock> currentCFGNodes;
|
||||||
|
|
||||||
private final EdgeFilter filter;
|
private final EdgeFilter filter;
|
||||||
|
|
||||||
FilteredCFGEdges(ControlFlowGraph cfg, NumberedNodeManager currentCFGNodes, EdgeFilter filter) {
|
FilteredCFGEdges(ControlFlowGraph cfg, NumberedNodeManager<IBasicBlock> currentCFGNodes, EdgeFilter filter) {
|
||||||
this.cfg = cfg;
|
this.cfg = cfg;
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
this.currentCFGNodes = currentCFGNodes;
|
this.currentCFGNodes = currentCFGNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator getExceptionalSuccessors(final IBasicBlock N) {
|
public Iterator<IBasicBlock> getExceptionalSuccessors(final IBasicBlock N) {
|
||||||
return new FilterIterator(cfg.getExceptionalSuccessors(N).iterator(), new Filter() {
|
return new FilterIterator<IBasicBlock>(cfg.getExceptionalSuccessors(N).iterator(), new Filter() {
|
||||||
public boolean accepts(Object o) {
|
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) {
|
public Iterator<IBasicBlock> getNormalSuccessors(final IBasicBlock N) {
|
||||||
return new FilterIterator(cfg.getNormalSuccessors(N).iterator(), new Filter() {
|
return new FilterIterator<IBasicBlock>(cfg.getNormalSuccessors(N).iterator(), new Filter() {
|
||||||
public boolean accepts(Object o) {
|
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) {
|
public Iterator<IBasicBlock> getExceptionalPredecessors(final IBasicBlock N) {
|
||||||
return new FilterIterator(cfg.getExceptionalPredecessors(N).iterator(), new Filter() {
|
return new FilterIterator<IBasicBlock>(cfg.getExceptionalPredecessors(N).iterator(), new Filter() {
|
||||||
public boolean accepts(Object o) {
|
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) {
|
public Iterator<IBasicBlock> getNormalPredecessors(final IBasicBlock N) {
|
||||||
return new FilterIterator(cfg.getNormalPredecessors(N).iterator(), new Filter() {
|
return new FilterIterator<IBasicBlock>(cfg.getNormalPredecessors(N).iterator(), new Filter() {
|
||||||
public boolean accepts(Object o) {
|
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) {
|
public Iterator<IBasicBlock> getSuccNodes(IBasicBlock N) {
|
||||||
return new CompoundIterator(getNormalSuccessors((IBasicBlock) N), getExceptionalSuccessors((IBasicBlock) N));
|
return new CompoundIterator<IBasicBlock>(getNormalSuccessors((IBasicBlock) N), getExceptionalSuccessors((IBasicBlock) N));
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSuccNodeCount(Object N) {
|
public int getSuccNodeCount(IBasicBlock N) {
|
||||||
return new Iterator2Collection(getSuccNodes(N)).size();
|
return new Iterator2Collection<IBasicBlock>(getSuccNodes(N)).size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IntSet getSuccNodeNumbers(Object N) {
|
public IntSet getSuccNodeNumbers(IBasicBlock N) {
|
||||||
MutableIntSet bits = IntSetUtil.make();
|
MutableIntSet bits = IntSetUtil.make();
|
||||||
for (Iterator EE = getSuccNodes(N); EE.hasNext();) {
|
for (Iterator EE = getSuccNodes(N); EE.hasNext();) {
|
||||||
bits.add(((IBasicBlock) EE.next()).getNumber());
|
bits.add(((IBasicBlock) EE.next()).getNumber());
|
||||||
|
@ -109,15 +109,15 @@ public class PrunedCFG extends AbstractNumberedGraph<IBasicBlock> implements Con
|
||||||
return bits;
|
return bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator getPredNodes(Object N) {
|
public Iterator<IBasicBlock> getPredNodes(IBasicBlock N) {
|
||||||
return new CompoundIterator(getNormalPredecessors((IBasicBlock) N), getExceptionalPredecessors((IBasicBlock) N));
|
return new CompoundIterator<IBasicBlock>(getNormalPredecessors((IBasicBlock) N), getExceptionalPredecessors((IBasicBlock) N));
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getPredNodeCount(Object N) {
|
public int getPredNodeCount(IBasicBlock N) {
|
||||||
return new Iterator2Collection(getPredNodes(N)).size();
|
return new Iterator2Collection<IBasicBlock>(getPredNodes(N)).size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IntSet getPredNodeNumbers(Object N) {
|
public IntSet getPredNodeNumbers(IBasicBlock N) {
|
||||||
MutableIntSet bits = IntSetUtil.make();
|
MutableIntSet bits = IntSetUtil.make();
|
||||||
for (Iterator EE = getPredNodes(N); EE.hasNext();) {
|
for (Iterator EE = getPredNodes(N); EE.hasNext();) {
|
||||||
bits.add(((IBasicBlock) EE.next()).getNumber());
|
bits.add(((IBasicBlock) EE.next()).getNumber());
|
||||||
|
@ -126,7 +126,7 @@ public class PrunedCFG extends AbstractNumberedGraph<IBasicBlock> implements Con
|
||||||
return bits;
|
return bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasEdge(Object src, Object dst) {
|
public boolean hasEdge(IBasicBlock src, IBasicBlock dst) {
|
||||||
for (Iterator EE = getSuccNodes(src); EE.hasNext();) {
|
for (Iterator EE = getSuccNodes(src); EE.hasNext();) {
|
||||||
if (EE.next().equals(dst)) {
|
if (EE.next().equals(dst)) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -136,46 +136,46 @@ public class PrunedCFG extends AbstractNumberedGraph<IBasicBlock> implements Con
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addEdge(Object src, Object dst) {
|
public void addEdge(IBasicBlock src, IBasicBlock dst) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeEdge(Object src, Object dst) {
|
public void removeEdge(IBasicBlock src, IBasicBlock dst) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeAllIncidentEdges(Object node) {
|
public void removeAllIncidentEdges(IBasicBlock node) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeIncomingEdges(Object node) {
|
public void removeIncomingEdges(IBasicBlock node) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeOutgoingEdges(Object node) {
|
public void removeOutgoingEdges(IBasicBlock node) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class FilteredNodes implements NumberedNodeManager {
|
private static class FilteredNodes implements NumberedNodeManager<IBasicBlock> {
|
||||||
private final NumberedNodeManager nodes;
|
private final NumberedNodeManager<IBasicBlock> nodes;
|
||||||
|
|
||||||
private final Set subset;
|
private final Set subset;
|
||||||
|
|
||||||
FilteredNodes(NumberedNodeManager nodes, Set subset) {
|
FilteredNodes(NumberedNodeManager<IBasicBlock> nodes, Set subset) {
|
||||||
this.nodes = nodes;
|
this.nodes = nodes;
|
||||||
this.subset = subset;
|
this.subset = subset;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getNumber(Object N) {
|
public int getNumber(IBasicBlock N) {
|
||||||
if (subset.contains(N))
|
if (subset.contains(N))
|
||||||
return nodes.getNumber(N);
|
return nodes.getNumber(N);
|
||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getNode(int number) {
|
public IBasicBlock getNode(int number) {
|
||||||
Object N = nodes.getNode(number);
|
IBasicBlock N = nodes.getNode(number);
|
||||||
if (subset.contains(N))
|
if (subset.contains(N))
|
||||||
return N;
|
return N;
|
||||||
else
|
else
|
||||||
|
@ -184,8 +184,8 @@ public class PrunedCFG extends AbstractNumberedGraph<IBasicBlock> implements Con
|
||||||
|
|
||||||
public int getMaxNumber() {
|
public int getMaxNumber() {
|
||||||
int max = -1;
|
int max = -1;
|
||||||
for (Iterator NS = nodes.iterateNodes(); NS.hasNext();) {
|
for (Iterator<? extends IBasicBlock> NS = nodes.iterateNodes(); NS.hasNext();) {
|
||||||
Object N = NS.next();
|
IBasicBlock N = NS.next();
|
||||||
if (subset.contains(N) && getNumber(N) > max) {
|
if (subset.contains(N) && getNumber(N) > max) {
|
||||||
max = getNumber(N);
|
max = getNumber(N);
|
||||||
}
|
}
|
||||||
|
@ -194,19 +194,19 @@ public class PrunedCFG extends AbstractNumberedGraph<IBasicBlock> implements Con
|
||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Iterator filterNodes(Iterator nodeIterator) {
|
private Iterator<IBasicBlock> filterNodes(Iterator nodeIterator) {
|
||||||
return new FilterIterator(nodeIterator, new Filter() {
|
return new FilterIterator<IBasicBlock>(nodeIterator, new Filter() {
|
||||||
public boolean accepts(Object o) {
|
public boolean accepts(Object o) {
|
||||||
return subset.contains(o);
|
return subset.contains(o);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator iterateNodes(IntSet s) {
|
public Iterator<IBasicBlock> iterateNodes(IntSet s) {
|
||||||
return filterNodes(nodes.iterateNodes(s));
|
return filterNodes(nodes.iterateNodes(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator iterateNodes() {
|
public Iterator<IBasicBlock> iterateNodes() {
|
||||||
return filterNodes(nodes.iterateNodes());
|
return filterNodes(nodes.iterateNodes());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,15 +214,15 @@ public class PrunedCFG extends AbstractNumberedGraph<IBasicBlock> implements Con
|
||||||
return subset.size();
|
return subset.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addNode(Object n) {
|
public void addNode(IBasicBlock n) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeNode(Object n) {
|
public void removeNode(IBasicBlock n) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsNode(Object N) {
|
public boolean containsNode(IBasicBlock N) {
|
||||||
return subset.contains(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) {
|
public PrunedCFG(final ControlFlowGraph cfg, final EdgeFilter filter) {
|
||||||
this.cfg = cfg;
|
this.cfg = cfg;
|
||||||
Graph<IBasicBlock> temp = new AbstractNumberedGraph<IBasicBlock>() {
|
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;
|
return cfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected EdgeManager getEdgeManager() {
|
protected EdgeManager<IBasicBlock> getEdgeManager() {
|
||||||
return edges;
|
return edges;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Set reachable = DFS.getReachableNodes(temp, Collections.singleton(cfg.entry()));
|
Set<IBasicBlock> reachable = DFS.getReachableNodes(temp, Collections.singleton(cfg.entry()));
|
||||||
Set back = DFS.getReachableNodes(GraphInverter.invert(temp), Collections.singleton(cfg.exit()));
|
Set<IBasicBlock> back = DFS.getReachableNodes(GraphInverter.invert(temp), Collections.singleton(cfg.exit()));
|
||||||
reachable.retainAll(back);
|
reachable.retainAll(back);
|
||||||
|
|
||||||
this.nodes = new FilteredNodes(cfg, reachable);
|
this.nodes = new FilteredNodes(cfg, reachable);
|
||||||
this.edges = new FilteredCFGEdges(cfg, nodes, filter);
|
this.edges = new FilteredCFGEdges(cfg, nodes, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected NodeManager getNodeManager() {
|
protected NodeManager<IBasicBlock> getNodeManager() {
|
||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected EdgeManager getEdgeManager() {
|
protected EdgeManager<IBasicBlock> getEdgeManager() {
|
||||||
return edges;
|
return edges;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getExceptionalSuccessors(final IBasicBlock N) {
|
public Collection<IBasicBlock> getExceptionalSuccessors(final IBasicBlock N) {
|
||||||
return new Iterator2Collection(edges.getExceptionalSuccessors(N));
|
return new Iterator2Collection<IBasicBlock>(edges.getExceptionalSuccessors(N));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getNormalSuccessors(final IBasicBlock N) {
|
public Collection<IBasicBlock> getNormalSuccessors(final IBasicBlock N) {
|
||||||
return new Iterator2Collection(edges.getNormalSuccessors(N));
|
return new Iterator2Collection<IBasicBlock>(edges.getNormalSuccessors(N));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getExceptionalPredecessors(final IBasicBlock N) {
|
public Collection<IBasicBlock> getExceptionalPredecessors(final IBasicBlock N) {
|
||||||
return new Iterator2Collection(edges.getExceptionalPredecessors(N));
|
return new Iterator2Collection<IBasicBlock>(edges.getExceptionalPredecessors(N));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getNormalPredecessors(final IBasicBlock N) {
|
public Collection<IBasicBlock> getNormalPredecessors(final IBasicBlock N) {
|
||||||
return new Iterator2Collection(edges.getNormalPredecessors(N));
|
return new Iterator2Collection<IBasicBlock>(edges.getNormalPredecessors(N));
|
||||||
}
|
}
|
||||||
|
|
||||||
public IBasicBlock entry() {
|
public IBasicBlock entry() {
|
||||||
|
|
|
@ -21,20 +21,19 @@ import com.ibm.wala.ssa.SSAInstruction;
|
||||||
import com.ibm.wala.ssa.SSAOptions;
|
import com.ibm.wala.ssa.SSAOptions;
|
||||||
import com.ibm.wala.ssa.SSAPhiInstruction;
|
import com.ibm.wala.ssa.SSAPhiInstruction;
|
||||||
import com.ibm.wala.ssa.SymbolTable;
|
import com.ibm.wala.ssa.SymbolTable;
|
||||||
|
import com.ibm.wala.ssa.SSACFG.BasicBlock;
|
||||||
import com.ibm.wala.ssa.SSAOptions.DefaultValues;
|
import com.ibm.wala.ssa.SSAOptions.DefaultValues;
|
||||||
import com.ibm.wala.util.collections.IntStack;
|
import com.ibm.wala.util.collections.IntStack;
|
||||||
import com.ibm.wala.util.debug.Assertions;
|
import com.ibm.wala.util.debug.Assertions;
|
||||||
import com.ibm.wala.util.graph.DominanceFrontiers;
|
import com.ibm.wala.util.graph.DominanceFrontiers;
|
||||||
import com.ibm.wala.util.graph.Graph;
|
import com.ibm.wala.util.graph.Graph;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract core of traditional SSA conversion (Cytron et al.).
|
* Abstract core of traditional SSA conversion (Cytron et al.).
|
||||||
*
|
*
|
||||||
* This implementation is abstract in the sense that it is designed
|
* This implementation is abstract in the sense that it is designed to work over
|
||||||
* to work over the instrutions and CFG of a Domo IR, but it is
|
* the instrutions and CFG of a Domo IR, but it is abstract with respect to
|
||||||
* abstract with respect to several integral portions of the
|
* several integral portions of the traditional algorithm:
|
||||||
* traditional algorithm:
|
|
||||||
* <UL>
|
* <UL>
|
||||||
* <LI> The notion of uses and defs of a given instruction.
|
* <LI> The notion of uses and defs of a given instruction.
|
||||||
* <LI> Assignments (<def> := <use>) that are be copy-propagated away
|
* <LI> Assignments (<def> := <use>) that are be copy-propagated away
|
||||||
|
@ -56,10 +55,8 @@ public abstract class AbstractSSAConversion {
|
||||||
|
|
||||||
protected abstract int getUse(SSAInstruction inst, int index);
|
protected abstract int getUse(SSAInstruction inst, int index);
|
||||||
|
|
||||||
|
|
||||||
protected abstract boolean isAssignInstruction(SSAInstruction inst);
|
protected abstract boolean isAssignInstruction(SSAInstruction inst);
|
||||||
|
|
||||||
|
|
||||||
protected abstract int getMaxValueNumber();
|
protected abstract int getMaxValueNumber();
|
||||||
|
|
||||||
protected abstract boolean isLive(SSACFG.BasicBlock Y, int V);
|
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 boolean isConstant(int valueNumber);
|
||||||
|
|
||||||
|
|
||||||
protected abstract int getNextNewValueNumber();
|
protected abstract int getNextNewValueNumber();
|
||||||
|
|
||||||
|
|
||||||
protected abstract void initializeVariables();
|
protected abstract void initializeVariables();
|
||||||
|
|
||||||
protected abstract void repairExit();
|
protected abstract void repairExit();
|
||||||
|
|
||||||
|
|
||||||
protected abstract void placeNewPhiAt(int value, SSACFG.BasicBlock Y);
|
protected abstract void placeNewPhiAt(int value, SSACFG.BasicBlock Y);
|
||||||
|
|
||||||
protected abstract SSAPhiInstruction getPhi(SSACFG.BasicBlock B, int index);
|
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 repairPhiUse(SSACFG.BasicBlock BB, int phiIndex, int rvalIndex, int newRval);
|
||||||
|
|
||||||
|
|
||||||
protected abstract void repairInstructionUses(SSAInstruction inst, int index, int[] newUses);
|
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 repairInstructionDefs(SSAInstruction inst, int index, int[] newDefs, int[] newUses);
|
||||||
|
|
||||||
|
|
||||||
protected abstract void pushAssignment(SSAInstruction inst, int index, int newRhs);
|
protected abstract void pushAssignment(SSAInstruction inst, int index, int newRhs);
|
||||||
|
|
||||||
protected abstract void popAssignment(SSAInstruction inst, int index);
|
protected abstract void popAssignment(SSAInstruction inst, int index);
|
||||||
|
|
||||||
|
|
||||||
protected final SSACFG CFG;
|
protected final SSACFG CFG;
|
||||||
|
|
||||||
protected final DominanceFrontiers<IBasicBlock> DF;
|
protected final DominanceFrontiers<IBasicBlock> DF;
|
||||||
|
|
||||||
private final Graph dominatorTree;
|
private final Graph dominatorTree;
|
||||||
|
|
||||||
protected final int[] phiCounts;
|
protected final int[] phiCounts;
|
||||||
|
|
||||||
protected final SSAInstruction[] instructions;
|
protected final SSAInstruction[] instructions;
|
||||||
|
|
||||||
private final int flags[];
|
private final int flags[];
|
||||||
|
|
||||||
protected final SymbolTable symbolTable;
|
protected final SymbolTable symbolTable;
|
||||||
|
|
||||||
protected final DefaultValues defaultValues;
|
protected final DefaultValues defaultValues;
|
||||||
|
|
||||||
protected IntStack S[];
|
protected IntStack S[];
|
||||||
|
|
||||||
protected int C[];
|
protected int C[];
|
||||||
|
|
||||||
protected int valueMap[];
|
protected int valueMap[];
|
||||||
|
|
||||||
private Set[] assignmentMap;
|
private Set[] assignmentMap;
|
||||||
|
|
||||||
protected AbstractSSAConversion(IR ir, SSAOptions options) {
|
protected AbstractSSAConversion(IR ir, SSAOptions options) {
|
||||||
this.CFG = ir.getControlFlowGraph();
|
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.dominatorTree = DF.dominatorTree();
|
||||||
this.flags = new int[2 * ir.getControlFlowGraph().getNumberOfNodes()];
|
this.flags = new int[2 * ir.getControlFlowGraph().getNumberOfNodes()];
|
||||||
this.instructions = ir.getInstructions();
|
this.instructions = ir.getInstructions();
|
||||||
|
@ -123,7 +124,6 @@ public abstract class AbstractSSAConversion {
|
||||||
this.defaultValues = options.getDefaultValues();
|
this.defaultValues = options.getDefaultValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// top-level control
|
// top-level control
|
||||||
//
|
//
|
||||||
|
@ -133,7 +133,6 @@ public abstract class AbstractSSAConversion {
|
||||||
renameVariables();
|
renameVariables();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// initialization
|
// initialization
|
||||||
//
|
//
|
||||||
|
@ -161,10 +160,10 @@ public abstract class AbstractSSAConversion {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addDefiningBlock(Set[] A, SSACFG.BasicBlock BB, int i) {
|
private void addDefiningBlock(Set<SSACFG.BasicBlock>[] A, SSACFG.BasicBlock BB, int i) {
|
||||||
if (!skip(i)) {
|
if (!skip(i)) {
|
||||||
if (A[i] == null) {
|
if (A[i] == null) {
|
||||||
A[i] = new LinkedHashSet(2);
|
A[i] = new LinkedHashSet<SSACFG.BasicBlock>(2);
|
||||||
}
|
}
|
||||||
A[i].add(BB);
|
A[i].add(BB);
|
||||||
}
|
}
|
||||||
|
@ -182,7 +181,7 @@ public abstract class AbstractSSAConversion {
|
||||||
setWork(X, 0);
|
setWork(X, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Set W = new LinkedHashSet();
|
Set<BasicBlock> W = new LinkedHashSet<BasicBlock>();
|
||||||
for (int V = 0; V < assignmentMap.length; V++) {
|
for (int V = 0; V < assignmentMap.length; V++) {
|
||||||
|
|
||||||
// some things (e.g. constants) have no defs at all
|
// some things (e.g. constants) have no defs at all
|
||||||
|
@ -202,7 +201,7 @@ public abstract class AbstractSSAConversion {
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!W.isEmpty()) {
|
while (!W.isEmpty()) {
|
||||||
SSACFG.BasicBlock X = (SSACFG.BasicBlock) W.iterator().next();
|
SSACFG.BasicBlock X = W.iterator().next();
|
||||||
W.remove(X);
|
W.remove(X);
|
||||||
for (Iterator YS = DF.getDominanceFrontier(X); YS.hasNext();) {
|
for (Iterator YS = DF.getDominanceFrontier(X); YS.hasNext();) {
|
||||||
SSACFG.BasicBlock Y = (SSACFG.BasicBlock) YS.next();
|
SSACFG.BasicBlock Y = (SSACFG.BasicBlock) YS.next();
|
||||||
|
@ -238,7 +237,6 @@ public abstract class AbstractSSAConversion {
|
||||||
flags[BB.getGraphNodeId() * 2] = v;
|
flags[BB.getGraphNodeId() * 2] = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// rename variables phase of traditional algorithm
|
// rename variables phase of traditional algorithm
|
||||||
//
|
//
|
||||||
|
@ -332,8 +330,7 @@ public abstract class AbstractSSAConversion {
|
||||||
private int[] makeNewUses(SSAInstruction inst) {
|
private int[] makeNewUses(SSAInstruction inst) {
|
||||||
int[] newUses = new int[getNumberOfUses(inst)];
|
int[] newUses = new int[getNumberOfUses(inst)];
|
||||||
for (int j = 0; j < getNumberOfUses(inst); j++) {
|
for (int j = 0; j < getNumberOfUses(inst); j++) {
|
||||||
newUses[j] =
|
newUses[j] = skip(getUse(inst, j)) ? getUse(inst, j) : top(getUse(inst, j));
|
||||||
skip(getUse(inst, j))? getUse(inst, j): top(getUse(inst, j));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return newUses;
|
return newUses;
|
||||||
|
@ -367,23 +364,20 @@ public abstract class AbstractSSAConversion {
|
||||||
if (inst == null)
|
if (inst == null)
|
||||||
return true;
|
return true;
|
||||||
for (int i = 0; i < getNumberOfDefs(inst); i++)
|
for (int i = 0; i < getNumberOfDefs(inst); i++)
|
||||||
if (! skip(getDef(inst, i))) return false;
|
if (!skip(getDef(inst, i)))
|
||||||
|
return false;
|
||||||
for (int i = 0; i < getNumberOfUses(inst); i++)
|
for (int i = 0; i < getNumberOfUses(inst); i++)
|
||||||
if (! skip(getUse(inst, i))) return false;
|
if (!skip(getUse(inst, i)))
|
||||||
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void fail(int v) {
|
protected void fail(int v) {
|
||||||
Assertions._assert(
|
Assertions._assert(isConstant(v) || !S[v].isEmpty(), "bad stack for " + v + " while SSA converting");
|
||||||
isConstant(v) || !S[v].isEmpty(),
|
|
||||||
"bad stack for " + v + " while SSA converting");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean hasDefaultValue(int valueNumber) {
|
protected boolean hasDefaultValue(int valueNumber) {
|
||||||
return
|
return (defaultValues != null) && (defaultValues.getDefaultValue(symbolTable, valueNumber) != -1);
|
||||||
(defaultValues != null)
|
|
||||||
&&
|
|
||||||
(defaultValues.getDefaultValue(symbolTable, valueNumber) != -1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int getDefaultValue(int valueNumber) {
|
protected int getDefaultValue(int valueNumber) {
|
||||||
|
|
|
@ -15,10 +15,12 @@ import java.util.Collection;
|
||||||
import com.ibm.wala.ssa.SSAInstruction;
|
import com.ibm.wala.ssa.SSAInstruction;
|
||||||
import com.ibm.wala.ssa.SymbolTable;
|
import com.ibm.wala.ssa.SymbolTable;
|
||||||
import com.ibm.wala.ssa.ValueDecorator;
|
import com.ibm.wala.ssa.ValueDecorator;
|
||||||
|
import com.ibm.wala.types.TypeReference;
|
||||||
import com.ibm.wala.util.debug.Assertions;
|
import com.ibm.wala.util.debug.Assertions;
|
||||||
|
|
||||||
public class AstAssertInstruction extends SSAInstruction {
|
public class AstAssertInstruction extends SSAInstruction {
|
||||||
private final int value;
|
private final int value;
|
||||||
|
|
||||||
private final boolean fromSpecification;
|
private final boolean fromSpecification;
|
||||||
|
|
||||||
public AstAssertInstruction(int value, boolean fromSpecification) {
|
public AstAssertInstruction(int value, boolean fromSpecification) {
|
||||||
|
@ -40,8 +42,7 @@ public class AstAssertInstruction extends SSAInstruction {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString(SymbolTable symbolTable, ValueDecorator d) {
|
public String toString(SymbolTable symbolTable, ValueDecorator d) {
|
||||||
return "assert " + getValueString(symbolTable, d, value) +
|
return "assert " + getValueString(symbolTable, d, value) + " (fromSpec: " + fromSpecification + ")";
|
||||||
" (fromSpec: " + fromSpecification + ")";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void visit(IVisitor v) {
|
public void visit(IVisitor v) {
|
||||||
|
@ -52,7 +53,7 @@ public class AstAssertInstruction extends SSAInstruction {
|
||||||
return 2177 * value;
|
return 2177 * value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getExceptionTypes() {
|
public Collection<TypeReference> getExceptionTypes() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,12 @@ package com.ibm.wala.cast.ir.ssa;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import com.ibm.wala.ssa.*;
|
import com.ibm.wala.ssa.SSAGetInstruction;
|
||||||
import com.ibm.wala.types.*;
|
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 {
|
public class AstGlobalRead extends SSAGetInstruction {
|
||||||
|
|
||||||
|
@ -38,7 +42,7 @@ public class AstGlobalRead extends SSAGetInstruction {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getExceptionTypes() {
|
public Collection<TypeReference> getExceptionTypes() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,12 @@ package com.ibm.wala.cast.ir.ssa;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import com.ibm.wala.ssa.*;
|
import com.ibm.wala.ssa.SSAInstruction;
|
||||||
import com.ibm.wala.types.*;
|
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 {
|
public class AstGlobalWrite extends SSAPutInstruction {
|
||||||
|
|
||||||
|
@ -38,7 +42,7 @@ public class AstGlobalWrite extends SSAPutInstruction {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getExceptionTypes() {
|
public Collection<TypeReference> getExceptionTypes() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
package com.ibm.wala.cast.ir.ssa;
|
package com.ibm.wala.cast.ir.ssa;
|
||||||
|
|
||||||
|
|
||||||
import com.ibm.wala.cast.loader.*;
|
import com.ibm.wala.cast.loader.*;
|
||||||
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
|
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
|
||||||
import com.ibm.wala.cfg.*;
|
import com.ibm.wala.cfg.*;
|
||||||
|
@ -27,18 +26,15 @@ import java.util.*;
|
||||||
|
|
||||||
public class AstIRFactory implements IRFactory {
|
public class AstIRFactory implements IRFactory {
|
||||||
private final boolean keepIR;
|
private final boolean keepIR;
|
||||||
private final Map keptIRs;
|
|
||||||
|
private final Map<IMethod, IR> keptIRs;
|
||||||
|
|
||||||
AstIRFactory(boolean keepIR) {
|
AstIRFactory(boolean keepIR) {
|
||||||
this.keepIR = keepIR;
|
this.keepIR = keepIR;
|
||||||
this.keptIRs = (keepIR)? new HashMap(): null;
|
this.keptIRs = (keepIR) ? new HashMap<IMethod, IR>() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ControlFlowGraph makeCFG(final IMethod method,
|
public ControlFlowGraph makeCFG(final IMethod method, final Context context, final ClassHierarchy cha, final WarningSet warnings) {
|
||||||
final Context context,
|
|
||||||
final ClassHierarchy cha,
|
|
||||||
final WarningSet warnings)
|
|
||||||
{
|
|
||||||
return ((AstMethod) method).getControlFlowGraph();
|
return ((AstMethod) method).getControlFlowGraph();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,18 +44,15 @@ public class AstIRFactory implements IRFactory {
|
||||||
private void setCatchInstructions(SSACFG ssacfg, AbstractCFG oldcfg) {
|
private void setCatchInstructions(SSACFG ssacfg, AbstractCFG oldcfg) {
|
||||||
for (int i = 0; i < oldcfg.getNumberOfNodes(); i++)
|
for (int i = 0; i < oldcfg.getNumberOfNodes(); i++)
|
||||||
if (oldcfg.isCatchBlock(i)) {
|
if (oldcfg.isCatchBlock(i)) {
|
||||||
ExceptionHandlerBasicBlock B =
|
ExceptionHandlerBasicBlock B = (ExceptionHandlerBasicBlock) ssacfg.getNode(i);
|
||||||
(ExceptionHandlerBasicBlock) ssacfg.getNode(i);
|
B.setCatchInstruction((SSAGetCaughtExceptionInstruction) getInstructions()[B.getFirstInstructionIndex()]);
|
||||||
B.setCatchInstruction((SSAGetCaughtExceptionInstruction)
|
|
||||||
getInstructions()[B.getFirstInstructionIndex()]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupCatchTypes(SSACFG cfg, TypeReference[][] catchTypes) {
|
private void setupCatchTypes(SSACFG cfg, TypeReference[][] catchTypes) {
|
||||||
for (int i = 0; i < catchTypes.length; i++) {
|
for (int i = 0; i < catchTypes.length; i++) {
|
||||||
if (catchTypes[i] != null) {
|
if (catchTypes[i] != null) {
|
||||||
ExceptionHandlerBasicBlock bb =
|
ExceptionHandlerBasicBlock bb = (ExceptionHandlerBasicBlock) cfg.getNode(i);
|
||||||
(ExceptionHandlerBasicBlock) cfg.getNode(i);
|
|
||||||
for (int j = 0; j < catchTypes[i].length; j++) {
|
for (int j = 0; j < catchTypes[i].length; j++) {
|
||||||
bb.addCaughtExceptionType(catchTypes[i][j]);
|
bb.addCaughtExceptionType(catchTypes[i][j]);
|
||||||
}
|
}
|
||||||
|
@ -72,8 +65,7 @@ public class AstIRFactory implements IRFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String instructionPosition(int instructionIndex) {
|
protected String instructionPosition(int instructionIndex) {
|
||||||
Position pos =
|
Position pos = ((AstMethod) getMethod()).getSourcePosition(instructionIndex);
|
||||||
((AstMethod)getMethod()).getSourcePosition(instructionIndex);
|
|
||||||
if (pos == null) {
|
if (pos == null) {
|
||||||
return "";
|
return "";
|
||||||
} else {
|
} else {
|
||||||
|
@ -81,12 +73,7 @@ public class AstIRFactory implements IRFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private AstIR(AstMethod method,
|
private AstIR(AstMethod method, SSAInstruction[] instructions, SymbolTable symbolTable, SSACFG cfg, SSAOptions options) {
|
||||||
SSAInstruction[] instructions,
|
|
||||||
SymbolTable symbolTable,
|
|
||||||
SSACFG cfg,
|
|
||||||
SSAOptions options)
|
|
||||||
{
|
|
||||||
super(method, instructions, symbolTable, cfg, options);
|
super(method, instructions, symbolTable, cfg, options);
|
||||||
|
|
||||||
setCatchInstructions(getControlFlowGraph(), method.cfg);
|
setCatchInstructions(getControlFlowGraph(), method.cfg);
|
||||||
|
@ -99,27 +86,19 @@ public class AstIRFactory implements IRFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IR makeIR(final IMethod method,
|
public IR makeIR(final IMethod method, final Context context, final ClassHierarchy cha, final SSAOptions options,
|
||||||
final Context context,
|
final WarningSet warnings) {
|
||||||
final ClassHierarchy cha,
|
|
||||||
final SSAOptions options,
|
|
||||||
final WarningSet warnings)
|
|
||||||
{
|
|
||||||
Assertions._assert(method instanceof AstMethod, method.toString());
|
Assertions._assert(method instanceof AstMethod, method.toString());
|
||||||
if (keepIR) {
|
if (keepIR) {
|
||||||
if (keptIRs.containsKey(method)) {
|
if (keptIRs.containsKey(method)) {
|
||||||
return (IR) keptIRs.get(method);
|
return keptIRs.get(method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractCFG oldCfg = ((AstMethod) method).cfg;
|
AbstractCFG oldCfg = ((AstMethod) method).cfg;
|
||||||
SSAInstruction[] instrs = (SSAInstruction[]) oldCfg.getInstructions();
|
SSAInstruction[] instrs = (SSAInstruction[]) oldCfg.getInstructions();
|
||||||
|
|
||||||
IR newIR =
|
IR newIR = new AstIR((AstMethod) method, instrs, ((AstMethod) method).symtab, new SSACFG(method, oldCfg, instrs, warnings),
|
||||||
new AstIR((AstMethod)method,
|
|
||||||
instrs,
|
|
||||||
((AstMethod)method).symtab,
|
|
||||||
new SSACFG(method, oldCfg, instrs, warnings),
|
|
||||||
options);
|
options);
|
||||||
|
|
||||||
if (keepIR) {
|
if (keepIR) {
|
||||||
|
@ -133,12 +112,7 @@ public class AstIRFactory implements IRFactory {
|
||||||
return new DefaultIRFactory() {
|
return new DefaultIRFactory() {
|
||||||
private final AstIRFactory astFactory = new AstIRFactory(keepAstIRs);
|
private final AstIRFactory astFactory = new AstIRFactory(keepAstIRs);
|
||||||
|
|
||||||
public IR makeIR(IMethod method,
|
public IR makeIR(IMethod method, Context context, ClassHierarchy cha, SSAOptions options, WarningSet warnings) {
|
||||||
Context context,
|
|
||||||
ClassHierarchy cha,
|
|
||||||
SSAOptions options,
|
|
||||||
WarningSet warnings)
|
|
||||||
{
|
|
||||||
if (method instanceof AstMethod) {
|
if (method instanceof AstMethod) {
|
||||||
return astFactory.makeIR(method, context, cha, options, warnings);
|
return astFactory.makeIR(method, context, cha, options, warnings);
|
||||||
} else {
|
} else {
|
||||||
|
@ -146,11 +120,7 @@ public class AstIRFactory implements IRFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ControlFlowGraph makeCFG(IMethod method,
|
public ControlFlowGraph makeCFG(IMethod method, Context context, ClassHierarchy cha, WarningSet warnings) {
|
||||||
Context context,
|
|
||||||
ClassHierarchy cha,
|
|
||||||
WarningSet warnings)
|
|
||||||
{
|
|
||||||
if (method instanceof AstMethod) {
|
if (method instanceof AstMethod) {
|
||||||
return astFactory.makeCFG(method, context, cha, warnings);
|
return astFactory.makeCFG(method, context, cha, warnings);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -13,6 +13,7 @@ package com.ibm.wala.cast.ir.ssa;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
import com.ibm.wala.ssa.SSAInstruction;
|
import com.ibm.wala.ssa.SSAInstruction;
|
||||||
|
import com.ibm.wala.types.TypeReference;
|
||||||
|
|
||||||
public abstract class AstLexicalAccess extends SSAInstruction {
|
public abstract class AstLexicalAccess extends SSAInstruction {
|
||||||
|
|
||||||
|
@ -71,7 +72,7 @@ public abstract class AstLexicalAccess extends SSAInstruction {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getExceptionTypes() {
|
public Collection<TypeReference> getExceptionTypes() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,9 +10,14 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
package com.ibm.wala.cast.ir.ssa;
|
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 {
|
public class EachElementGetInstruction extends SSAAbstractUnaryInstruction {
|
||||||
|
|
||||||
|
@ -34,7 +39,7 @@ public class EachElementGetInstruction extends SSAAbstractUnaryInstruction {
|
||||||
((AstInstructionVisitor) v).visitEachElementGet(this);
|
((AstInstructionVisitor) v).visitEachElementGet(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getExceptionTypes() {
|
public Collection<TypeReference> getExceptionTypes() {
|
||||||
return Collections.EMPTY_SET;
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,14 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
package com.ibm.wala.cast.ir.ssa;
|
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 {
|
public class EachElementHasNextInstruction extends SSAAbstractUnaryInstruction {
|
||||||
|
|
||||||
|
@ -34,7 +39,7 @@ public class EachElementHasNextInstruction extends SSAAbstractUnaryInstruction {
|
||||||
((AstInstructionVisitor) v).visitEachElementHasNext(this);
|
((AstInstructionVisitor) v).visitEachElementHasNext(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getExceptionTypes() {
|
public Collection<TypeReference> getExceptionTypes() {
|
||||||
return Collections.EMPTY_SET;
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,12 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
package com.ibm.wala.cast.ir.ssa;
|
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 {
|
public class NonExceptingThrowInstruction extends SSAAbstractThrowInstruction {
|
||||||
|
|
||||||
|
@ -31,8 +34,8 @@ public class NonExceptingThrowInstruction extends SSAAbstractThrowInstruction {
|
||||||
((AstInstructionVisitor)v).visitNonExceptingThrow(this);
|
((AstInstructionVisitor)v).visitNonExceptingThrow(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getExceptionTypes() {
|
public Collection<TypeReference> getExceptionTypes() {
|
||||||
return Collections.EMPTY_SET;
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,8 +44,11 @@ import com.ibm.wala.util.intset.MutableIntSet;
|
||||||
public class SSAConversion extends AbstractSSAConversion {
|
public class SSAConversion extends AbstractSSAConversion {
|
||||||
|
|
||||||
public static boolean DEBUG = false;
|
public static boolean DEBUG = false;
|
||||||
|
|
||||||
public static boolean DEBUG_UNDO = true;
|
public static boolean DEBUG_UNDO = true;
|
||||||
|
|
||||||
public static boolean DEBUG_NAMES = true;
|
public static boolean DEBUG_NAMES = true;
|
||||||
|
|
||||||
public static boolean DUMP = false;
|
public static boolean DUMP = false;
|
||||||
|
|
||||||
private final AstIR ir;
|
private final AstIR ir;
|
||||||
|
@ -66,11 +69,13 @@ public class SSAConversion extends AbstractSSAConversion {
|
||||||
// Copy propagation history
|
// Copy propagation history
|
||||||
//
|
//
|
||||||
|
|
||||||
private final Map copyPropagationMap;
|
private final Map<Object, CopyPropagationRecord> copyPropagationMap;
|
||||||
private final Stack R[];
|
|
||||||
|
private final Stack<CopyPropagationRecord> R[];
|
||||||
|
|
||||||
private static class UseRecord {
|
private static class UseRecord {
|
||||||
final int instructionIndex;
|
final int instructionIndex;
|
||||||
|
|
||||||
final int useNumber;
|
final int useNumber;
|
||||||
|
|
||||||
private UseRecord(int instructionIndex, int useNumber) {
|
private UseRecord(int instructionIndex, int useNumber) {
|
||||||
|
@ -83,15 +88,16 @@ public class SSAConversion extends AbstractSSAConversion {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
return (o instanceof UseRecord) &&
|
return (o instanceof UseRecord) && instructionIndex == ((UseRecord) o).instructionIndex
|
||||||
instructionIndex==((UseRecord)o).instructionIndex &&
|
&& useNumber == ((UseRecord) o).useNumber;
|
||||||
useNumber==((UseRecord)o).useNumber;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class PhiUseRecord {
|
private class PhiUseRecord {
|
||||||
final int BBnumber;
|
final int BBnumber;
|
||||||
|
|
||||||
final int phiNumber;
|
final int phiNumber;
|
||||||
|
|
||||||
final int useNumber;
|
final int useNumber;
|
||||||
|
|
||||||
private PhiUseRecord(int BBnumber, int phiNumber, int useNumber) {
|
private PhiUseRecord(int BBnumber, int phiNumber, int useNumber) {
|
||||||
|
@ -105,43 +111,48 @@ public class SSAConversion extends AbstractSSAConversion {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
return (o instanceof PhiUseRecord) &&
|
return (o instanceof PhiUseRecord) && BBnumber == ((PhiUseRecord) o).BBnumber && phiNumber == ((PhiUseRecord) o).phiNumber
|
||||||
BBnumber==((PhiUseRecord)o).BBnumber &&
|
&& useNumber == ((PhiUseRecord) o).useNumber;
|
||||||
phiNumber==((PhiUseRecord)o).phiNumber &&
|
|
||||||
useNumber==((PhiUseRecord)o).useNumber;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class CopyPropagationRecord {
|
private class CopyPropagationRecord {
|
||||||
final int lhs;
|
final int lhs;
|
||||||
|
|
||||||
final int rhs;
|
final int rhs;
|
||||||
|
|
||||||
final int instructionIndex;
|
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() {
|
public int hashCode() {
|
||||||
return instructionIndex;
|
return instructionIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
return (o instanceof CopyPropagationRecord) &&
|
return (o instanceof CopyPropagationRecord) && instructionIndex == ((CopyPropagationRecord) o).instructionIndex;
|
||||||
instructionIndex==((CopyPropagationRecord)o).instructionIndex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private CopyPropagationRecord(int instructionIndex, int lhs, int rhs) {
|
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.lhs = lhs;
|
||||||
this.rhs = rhs;
|
this.rhs = rhs;
|
||||||
this.instructionIndex = instructionIndex;
|
this.instructionIndex = instructionIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addChild(CopyPropagationRecord rec) {
|
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);
|
childRecords.add(rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addUse(int instructionIndex, int use) {
|
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);
|
UseRecord rec = new UseRecord(instructionIndex, use);
|
||||||
copyPropagationMap.put(rec, this);
|
copyPropagationMap.put(rec, this);
|
||||||
renamedUses.add(rec);
|
renamedUses.add(rec);
|
||||||
|
@ -171,16 +182,18 @@ public class SSAConversion extends AbstractSSAConversion {
|
||||||
|
|
||||||
instructions[instructionIndex] = new AssignInstruction(lhs, rhs);
|
instructions[instructionIndex] = new AssignInstruction(lhs, rhs);
|
||||||
|
|
||||||
if (DEBUG_UNDO) Trace.println("recreating assignment at " + instructionIndex + " as " + lhs + " = " + rhs);
|
if (DEBUG_UNDO)
|
||||||
|
Trace.println("recreating assignment at " + instructionIndex + " as " + lhs + " = " + rhs);
|
||||||
|
|
||||||
for(Iterator uses = renamedUses.iterator(); uses.hasNext(); ) {
|
for (Iterator<Object> uses = renamedUses.iterator(); uses.hasNext();) {
|
||||||
Object x = uses.next();
|
Object x = uses.next();
|
||||||
if (x instanceof UseRecord) {
|
if (x instanceof UseRecord) {
|
||||||
UseRecord use = (UseRecord) x;
|
UseRecord use = (UseRecord) x;
|
||||||
int idx = use.instructionIndex;
|
int idx = use.instructionIndex;
|
||||||
SSAInstruction inst = instructions[idx];
|
SSAInstruction inst = instructions[idx];
|
||||||
|
|
||||||
if (DEBUG_UNDO) Trace.println("Changing use #" + use.useNumber + " of inst #" + idx + " to val " + lhs);
|
if (DEBUG_UNDO)
|
||||||
|
Trace.println("Changing use #" + use.useNumber + " of inst #" + idx + " to val " + lhs);
|
||||||
|
|
||||||
if (use.useNumber >= 0) {
|
if (use.useNumber >= 0) {
|
||||||
instructions[idx] = undo(inst, use.useNumber, lhs);
|
instructions[idx] = undo(inst, use.useNumber, lhs);
|
||||||
|
@ -198,8 +211,8 @@ public class SSAConversion extends AbstractSSAConversion {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(Iterator cs = childRecords.iterator(); cs.hasNext(); ) {
|
for (Iterator<CopyPropagationRecord> cs = childRecords.iterator(); cs.hasNext();) {
|
||||||
((CopyPropagationRecord)cs.next()).undo( lhs );
|
cs.next().undo(lhs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,7 +232,6 @@ public class SSAConversion extends AbstractSSAConversion {
|
||||||
info.copyUse(fromInst, fromUse, toInst, toUse);
|
info.copyUse(fromInst, fromUse, toInst, toUse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// SSA2LocalMap implementation for SSAConversion
|
// SSA2LocalMap implementation for SSAConversion
|
||||||
//
|
//
|
||||||
|
@ -241,18 +253,18 @@ public class SSAConversion extends AbstractSSAConversion {
|
||||||
|
|
||||||
UseRecord use = new UseRecord(instructionIndex, useNumber);
|
UseRecord use = new UseRecord(instructionIndex, useNumber);
|
||||||
if (copyPropagationMap.containsKey(use)) {
|
if (copyPropagationMap.containsKey(use)) {
|
||||||
((CopyPropagationRecord)copyPropagationMap.get(use)).undo();
|
copyPropagationMap.get(use).undo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void copyUse(int fromInst, int fromUse, int toInst, int toUse) {
|
private void copyUse(int fromInst, int fromUse, int toInst, int toUse) {
|
||||||
UseRecord use = new UseRecord(fromInst, fromUse);
|
UseRecord use = new UseRecord(fromInst, fromUse);
|
||||||
if (copyPropagationMap.containsKey(use)) {
|
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;
|
return copyPropagationMap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -268,7 +280,6 @@ public class SSAConversion extends AbstractSSAConversion {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// implementation of AbstractSSAConversion hooks
|
// implementation of AbstractSSAConversion hooks
|
||||||
//
|
//
|
||||||
|
@ -409,7 +420,8 @@ public class SSAConversion extends AbstractSSAConversion {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == -1) return true;
|
if (index == -1)
|
||||||
|
return true;
|
||||||
|
|
||||||
int[] lexicalUses = lexicalInfo.getExposedUses(index);
|
int[] lexicalUses = lexicalInfo.getExposedUses(index);
|
||||||
if (lexicalUses != null) {
|
if (lexicalUses != null) {
|
||||||
|
@ -427,12 +439,11 @@ public class SSAConversion extends AbstractSSAConversion {
|
||||||
* @param ir
|
* @param ir
|
||||||
* @param options
|
* @param options
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
private SSAConversion(AstMethod M, AstIR ir, SSAOptions options) {
|
private SSAConversion(AstMethod M, AstIR ir, SSAOptions options) {
|
||||||
super(ir, options);
|
super(ir, options);
|
||||||
this.copyPropagationMap =
|
this.copyPropagationMap = (ir.getLocalMap() instanceof SSAInformation) ? ((SSAInformation) ir.getLocalMap()).getCopyHistory()
|
||||||
(ir.getLocalMap() instanceof SSAInformation)?
|
: new HashMap<Object,CopyPropagationRecord>();
|
||||||
((SSAInformation)ir.getLocalMap()).getCopyHistory():
|
|
||||||
new HashMap();
|
|
||||||
|
|
||||||
this.ir = ir;
|
this.ir = ir;
|
||||||
this.debugInfo = M.debugInfo;
|
this.debugInfo = M.debugInfo;
|
||||||
|
@ -444,7 +455,8 @@ public class SSAConversion extends AbstractSSAConversion {
|
||||||
SSACFG.BasicBlock bb = (SSACFG.BasicBlock) CFG.getNode(i);
|
SSACFG.BasicBlock bb = (SSACFG.BasicBlock) CFG.getNode(i);
|
||||||
if (bb.hasPhi()) {
|
if (bb.hasPhi()) {
|
||||||
int n = 0;
|
int n = 0;
|
||||||
for(Iterator X = bb.iteratePhis(); X.hasNext(); n++) X.next();
|
for (Iterator X = bb.iteratePhis(); X.hasNext(); n++)
|
||||||
|
X.next();
|
||||||
phiCounts[i] = n;
|
phiCounts[i] = n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -472,10 +484,7 @@ public class SSAConversion extends AbstractSSAConversion {
|
||||||
|
|
||||||
private void copyNames(int to, int from) {
|
private void copyNames(int to, int from) {
|
||||||
String[][] namesData = debugInfo.getSourceNamesForValues();
|
String[][] namesData = debugInfo.getSourceNamesForValues();
|
||||||
if (namesData != null &&
|
if (namesData != null && namesData.length > from && namesData[from] != null) {
|
||||||
namesData.length > from &&
|
|
||||||
namesData[from] != null)
|
|
||||||
{
|
|
||||||
if (namesData[to] == null) {
|
if (namesData[to] == null) {
|
||||||
namesData[to] = namesData[from];
|
namesData[to] = namesData[from];
|
||||||
} else {
|
} else {
|
||||||
|
@ -562,11 +571,8 @@ public class SSAConversion extends AbstractSSAConversion {
|
||||||
for (int j = 0; j < inst.getNumberOfDefs(); j++) {
|
for (int j = 0; j < inst.getNumberOfDefs(); j++) {
|
||||||
int def = inst.getDef(j);
|
int def = inst.getDef(j);
|
||||||
if (def != -1) {
|
if (def != -1) {
|
||||||
if (foundOne.contains(def) ||
|
if (foundOne.contains(def) || ir.getSymbolTable().isConstant(def) || def <= ir.getNumberOfParameters()
|
||||||
ir.getSymbolTable().isConstant(def) ||
|
|| inst instanceof AssignInstruction) {
|
||||||
def <= ir.getNumberOfParameters() ||
|
|
||||||
inst instanceof AssignInstruction)
|
|
||||||
{
|
|
||||||
foundTwo.add(def);
|
foundTwo.add(def);
|
||||||
} else {
|
} else {
|
||||||
foundOne.add(def);
|
foundOne.add(def);
|
||||||
|
@ -583,25 +589,24 @@ public class SSAConversion extends AbstractSSAConversion {
|
||||||
return convert(M, ir, options, valuesToConvert(ir));
|
return convert(M, ir, options, valuesToConvert(ir));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SSA2LocalMap convert(AstMethod M,
|
public static SSA2LocalMap convert(AstMethod M, final AstIR ir, SSAOptions options, final IntSet values) {
|
||||||
final AstIR ir,
|
|
||||||
SSAOptions options,
|
|
||||||
final IntSet values)
|
|
||||||
{
|
|
||||||
try {
|
try {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Trace.println("starting conversion for " + values);
|
Trace.println("starting conversion for " + values);
|
||||||
Trace.println(ir);
|
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) {
|
SSAConversion ssa = new SSAConversion(M, ir, options) {
|
||||||
final int limit = ir.getSymbolTable().getMaxValueNumber();
|
final int limit = ir.getSymbolTable().getMaxValueNumber();
|
||||||
|
|
||||||
protected boolean skip(int i) {
|
protected boolean skip(int i) {
|
||||||
return (i >= 0) && (i <= limit) && (!values.contains(i));
|
return (i >= 0) && (i <= limit) && (!values.contains(i));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
ssa.perform();
|
ssa.perform();
|
||||||
if (DEBUG_UNDO) Trace.println("<<< done " + ir.getMethod());
|
if (DEBUG_UNDO)
|
||||||
|
Trace.println("<<< done " + ir.getMethod());
|
||||||
return ssa.getComputedLocalMap();
|
return ssa.getComputedLocalMap();
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
Trace.println("exception " + e + " while converting:");
|
Trace.println("exception " + e + " while converting:");
|
||||||
|
|
|
@ -13,6 +13,7 @@ package com.ibm.wala.cast.ir.ssa.analysis;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
import com.ibm.wala.cfg.ControlFlowGraph;
|
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.AbstractMeetOperator;
|
||||||
import com.ibm.wala.dataflow.graph.BitVectorSolver;
|
import com.ibm.wala.dataflow.graph.BitVectorSolver;
|
||||||
import com.ibm.wala.dataflow.graph.BitVectorUnion;
|
import com.ibm.wala.dataflow.graph.BitVectorUnion;
|
||||||
|
@ -152,15 +153,15 @@ public class LiveAnalysis {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final BitVectorSolver S = new BitVectorSolver(new IKilldallFramework() {
|
final BitVectorSolver<IBasicBlock> S = new BitVectorSolver<IBasicBlock>(new IKilldallFramework<IBasicBlock>() {
|
||||||
private final Graph G = GraphInverter.invert(cfg);
|
private final Graph<IBasicBlock> G = GraphInverter.invert(cfg);
|
||||||
|
|
||||||
public Graph getFlowGraph() {
|
public Graph<IBasicBlock> getFlowGraph() {
|
||||||
return G;
|
return G;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ITransferFunctionProvider getTransferFunctionProvider() {
|
public ITransferFunctionProvider<IBasicBlock> getTransferFunctionProvider() {
|
||||||
return new ITransferFunctionProvider() {
|
return new ITransferFunctionProvider<IBasicBlock>() {
|
||||||
|
|
||||||
public boolean hasNodeTransferFunctions() {
|
public boolean hasNodeTransferFunctions() {
|
||||||
return true;
|
return true;
|
||||||
|
@ -170,7 +171,7 @@ public class LiveAnalysis {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UnaryOperator getNodeTransferFunction(Object node) {
|
public UnaryOperator getNodeTransferFunction(IBasicBlock node) {
|
||||||
if (((SSACFG.BasicBlock) node).isExitBlock()) {
|
if (((SSACFG.BasicBlock) node).isExitBlock()) {
|
||||||
return new ExitBlockGenKillOperator();
|
return new ExitBlockGenKillOperator();
|
||||||
} else {
|
} else {
|
||||||
|
@ -178,7 +179,7 @@ public class LiveAnalysis {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public UnaryOperator getEdgeTransferFunction(Object s, Object d) {
|
public UnaryOperator getEdgeTransferFunction(IBasicBlock s, IBasicBlock d) {
|
||||||
Assertions.UNREACHABLE();
|
Assertions.UNREACHABLE();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,7 @@ import com.ibm.wala.cast.util.CAstPrinter;
|
||||||
import com.ibm.wala.cfg.AbstractCFG;
|
import com.ibm.wala.cfg.AbstractCFG;
|
||||||
import com.ibm.wala.cfg.IBasicBlock;
|
import com.ibm.wala.cfg.IBasicBlock;
|
||||||
import com.ibm.wala.classLoader.IClassLoader;
|
import com.ibm.wala.classLoader.IClassLoader;
|
||||||
|
import com.ibm.wala.classLoader.IField;
|
||||||
import com.ibm.wala.classLoader.IMethod;
|
import com.ibm.wala.classLoader.IMethod;
|
||||||
import com.ibm.wala.shrikeBT.BinaryOpInstruction;
|
import com.ibm.wala.shrikeBT.BinaryOpInstruction;
|
||||||
import com.ibm.wala.shrikeBT.ConditionalBranchInstruction;
|
import com.ibm.wala.shrikeBT.ConditionalBranchInstruction;
|
||||||
|
@ -331,7 +332,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
|
|
||||||
private int lastIndex = -2;
|
private int lastIndex = -2;
|
||||||
|
|
||||||
private final List instructions = new ArrayList();
|
private final List<SSAInstruction> instructions = new ArrayList<SSAInstruction>();
|
||||||
|
|
||||||
public int getNumber() {
|
public int getNumber() {
|
||||||
return getGraphNodeId();
|
return getGraphNodeId();
|
||||||
|
@ -389,7 +390,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
return "PreBB" + number + ":" + firstIndex + ".." + lastIndex;
|
return "PreBB" + number + ":" + firstIndex + ".." + lastIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
List instructions() {
|
List<SSAInstruction> instructions() {
|
||||||
return instructions;
|
return instructions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,7 +402,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator iterateAllInstructions() {
|
public Iterator<SSAInstruction> iterateAllInstructions() {
|
||||||
return instructions.iterator();
|
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 {
|
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) {
|
void setUnwindState(PreBasicBlock block, UnwindState context) {
|
||||||
unwindData.put(block, context);
|
unwindData.put(block, context);
|
||||||
|
@ -468,7 +469,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreBasicBlock findOrCreateCode(PreBasicBlock source, PreBasicBlock target, boolean exception) {
|
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
|
// no unwinding is needed, so jump to target block directly
|
||||||
if (sourceContext == null)
|
if (sourceContext == null)
|
||||||
|
@ -477,16 +478,17 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
WalkContext astContext = sourceContext.astContext;
|
WalkContext astContext = sourceContext.astContext;
|
||||||
UnwindState targetContext = null;
|
UnwindState targetContext = null;
|
||||||
if (target != null)
|
if (target != null)
|
||||||
targetContext = (UnwindState) unwindData.get(target);
|
targetContext = unwindData.get(target);
|
||||||
|
|
||||||
// in unwind context, but catch in same (or inner) unwind context
|
// in unwind context, but catch in same (or inner) unwind context
|
||||||
if (targetContext != null && targetContext.covers(sourceContext))
|
if (targetContext != null && targetContext.covers(sourceContext))
|
||||||
return target;
|
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)) {
|
if (code.containsKey(key)) {
|
||||||
return (PreBasicBlock) code.get(key);
|
return code.get(key);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
int e = -1;
|
int e = -1;
|
||||||
|
@ -544,19 +546,19 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
|
|
||||||
private Unwind unwind = null;
|
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 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];
|
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) {
|
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))
|
if (delayedEdges.containsKey(dst))
|
||||||
((Set) delayedEdges.get(dst)).add(v);
|
delayedEdges.get(dst).add(v);
|
||||||
else {
|
else {
|
||||||
Set s = new LinkedHashSet();
|
Set<Pair<PreBasicBlock, Boolean>> s = new LinkedHashSet<Pair<PreBasicBlock, Boolean>>();
|
||||||
s.add(v);
|
s.add(v);
|
||||||
delayedEdges.put(dst, s);
|
delayedEdges.put(dst, s);
|
||||||
}
|
}
|
||||||
|
@ -637,7 +639,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
void makeExitBlock(PreBasicBlock bb) {
|
void makeExitBlock(PreBasicBlock bb) {
|
||||||
bb.makeExitBlock();
|
bb.makeExitBlock();
|
||||||
|
|
||||||
for (Iterator ps = getPredNodes(bb); ps.hasNext();)
|
for (Iterator<? extends PreBasicBlock> ps = getPredNodes(bb); ps.hasNext();)
|
||||||
normalToExit.add(ps.next());
|
normalToExit.add(ps.next());
|
||||||
|
|
||||||
checkForRealizedExitEdges(bb);
|
checkForRealizedExitEdges(bb);
|
||||||
|
@ -649,14 +651,14 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
|
|
||||||
private void checkForRealizedEdges(CAstNode n) {
|
private void checkForRealizedEdges(CAstNode n) {
|
||||||
if (delayedEdges.containsKey(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();
|
Pair s = (Pair) ss.next();
|
||||||
PreBasicBlock that = (PreBasicBlock) s.fst;
|
PreBasicBlock that = (PreBasicBlock) s.fst;
|
||||||
boolean exception = ((Boolean) s.snd).booleanValue();
|
boolean exception = ((Boolean) s.snd).booleanValue();
|
||||||
if (unwind == null) {
|
if (unwind == null) {
|
||||||
addEdge(that, nodeToBlock.get(n));
|
addEdge(that, nodeToBlock.get(n));
|
||||||
} else {
|
} else {
|
||||||
PreBasicBlock target = (PreBasicBlock) nodeToBlock.get(n);
|
PreBasicBlock target = nodeToBlock.get(n);
|
||||||
addEdge(that, unwind.findOrCreateCode(that, target, exception));
|
addEdge(that, unwind.findOrCreateCode(that, target, exception));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -667,7 +669,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
|
|
||||||
private void checkForRealizedExitEdges(PreBasicBlock n) {
|
private void checkForRealizedExitEdges(PreBasicBlock n) {
|
||||||
if (delayedEdges.containsKey(exitMarker)) {
|
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();
|
Pair s = (Pair) ss.next();
|
||||||
PreBasicBlock that = (PreBasicBlock) s.fst;
|
PreBasicBlock that = (PreBasicBlock) s.fst;
|
||||||
boolean exception = ((Boolean) s.snd).booleanValue();
|
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) {
|
public void addPreEdge(CAstNode src, CAstNode dst, boolean exception) {
|
||||||
Assertions._assert(nodeToBlock.containsKey(src));
|
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) {
|
public void addPreEdge(PreBasicBlock src, CAstNode dst, boolean exception) {
|
||||||
if (nodeToBlock.containsKey(dst)) {
|
if (nodeToBlock.containsKey(dst)) {
|
||||||
PreBasicBlock target = (PreBasicBlock) nodeToBlock.get(dst);
|
PreBasicBlock target = nodeToBlock.get(dst);
|
||||||
if (DEBUG_CFG)
|
if (DEBUG_CFG)
|
||||||
Trace.println("adding pre-edge " + src + " --> " + dst);
|
Trace.println("adding pre-edge " + src + " --> " + dst);
|
||||||
if (unwind == null) {
|
if (unwind == null) {
|
||||||
|
@ -726,7 +728,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
|
|
||||||
public void addPreEdgeToExit(CAstNode src, boolean exception) {
|
public void addPreEdgeToExit(CAstNode src, boolean exception) {
|
||||||
Assertions._assert(nodeToBlock.containsKey(src));
|
Assertions._assert(nodeToBlock.containsKey(src));
|
||||||
addPreEdgeToExit((PreBasicBlock) nodeToBlock.get(src), exception);
|
addPreEdgeToExit(nodeToBlock.get(src), exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addPreEdgeToExit(PreBasicBlock src, boolean exception) {
|
public void addPreEdgeToExit(PreBasicBlock src, boolean exception) {
|
||||||
|
@ -741,7 +743,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
addDelayedEdge(src, exitMarker, exception);
|
addDelayedEdge(src, exitMarker, exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addEdge(Object src, Object dst) {
|
public void addEdge(PreBasicBlock src, PreBasicBlock dst) {
|
||||||
super.addEdge(src, dst);
|
super.addEdge(src, dst);
|
||||||
deadBlocks.remove(dst);
|
deadBlocks.remove(dst);
|
||||||
}
|
}
|
||||||
|
@ -751,7 +753,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreBasicBlock getBlock(CAstNode n) {
|
public PreBasicBlock getBlock(CAstNode n) {
|
||||||
return (PreBasicBlock) nodeToBlock.get(n);
|
return nodeToBlock.get(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void noteLinePosition(int instruction) {
|
private void noteLinePosition(int instruction) {
|
||||||
|
@ -798,24 +800,24 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
|
|
||||||
AstCFG(CAstEntity n, IncipientCFG icfg, SymbolTable symtab) {
|
AstCFG(CAstEntity n, IncipientCFG icfg, SymbolTable symtab) {
|
||||||
super(null);
|
super(null);
|
||||||
List blocks = icfg.blocks;
|
List<PreBasicBlock> blocks = icfg.blocks;
|
||||||
|
|
||||||
this.symtab = symtab;
|
this.symtab = symtab;
|
||||||
functionName = n.getName();
|
functionName = n.getName();
|
||||||
instructionToBlockMap = new int[blocks.size()];
|
instructionToBlockMap = new int[blocks.size()];
|
||||||
|
|
||||||
for (int i = 0; i < blocks.size(); i++)
|
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++) {
|
for (int i = 0; i < blocks.size(); i++) {
|
||||||
PreBasicBlock block = (PreBasicBlock) blocks.get(i);
|
PreBasicBlock block = blocks.get(i);
|
||||||
this.addNode(block);
|
this.addNode(block);
|
||||||
if (block.isCatchBlock()) {
|
if (block.isCatchBlock()) {
|
||||||
setCatchBlock(i);
|
setCatchBlock(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DEBUG_CFG)
|
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)
|
if (DEBUG_CFG)
|
||||||
Trace.println(getMaxNumber() + " blocks total");
|
Trace.println(getMaxNumber() + " blocks total");
|
||||||
|
@ -823,7 +825,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
init();
|
init();
|
||||||
|
|
||||||
for (int i = 0; i < blocks.size(); i++) {
|
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();) {
|
for (Iterator j = icfg.getSuccNodes(src); j.hasNext();) {
|
||||||
PreBasicBlock dst = (PreBasicBlock) j.next();
|
PreBasicBlock dst = (PreBasicBlock) j.next();
|
||||||
if (isCatchBlock(dst.getNumber()) || (dst.isExitBlock() && icfg.exceptionalToExit.contains(src))) {
|
if (isCatchBlock(dst.getNumber()) || (dst.isExitBlock() && icfg.exceptionalToExit.contains(src))) {
|
||||||
|
@ -843,9 +845,9 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
int x = 0;
|
int x = 0;
|
||||||
instructions = new SSAInstruction[icfg.currentInstruction];
|
instructions = new SSAInstruction[icfg.currentInstruction];
|
||||||
for (int i = 0; i < blocks.size(); i++) {
|
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++) {
|
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);
|
Symbol lookup(String name);
|
||||||
|
|
||||||
Iterator getAllNames();
|
Iterator<String> getAllNames();
|
||||||
|
|
||||||
int size();
|
int size();
|
||||||
|
|
||||||
|
@ -987,9 +989,9 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
private abstract class AbstractScope implements Scope {
|
private abstract class AbstractScope implements Scope {
|
||||||
private final Scope parent;
|
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();
|
protected abstract SymbolTable getUnderlyingSymtab();
|
||||||
|
|
||||||
|
@ -997,7 +999,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
return getUnderlyingSymtab().getMaxValueNumber() + 1;
|
return getUnderlyingSymtab().getMaxValueNumber() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator getAllNames() {
|
public Iterator<String> getAllNames() {
|
||||||
return values.keySet().iterator();
|
return values.keySet().iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1061,7 +1063,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
private final String mapName(String nm) {
|
private final String mapName(String nm) {
|
||||||
String mappedName = (String) caseInsensitiveNames.get(nm.toLowerCase());
|
String mappedName = caseInsensitiveNames.get(nm.toLowerCase());
|
||||||
return (mappedName == null) ? nm : mappedName;
|
return (mappedName == null) ? nm : mappedName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1081,7 +1083,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
|
|
||||||
public Symbol lookup(String nm) {
|
public Symbol lookup(String nm) {
|
||||||
if (contains(nm)) {
|
if (contains(nm)) {
|
||||||
return (Symbol) values.get(mapName(nm));
|
return values.get(mapName(nm));
|
||||||
} else {
|
} else {
|
||||||
Symbol scoped = parent.lookup(nm);
|
Symbol scoped = parent.lookup(nm);
|
||||||
if (scoped != null && getEntityScope() == this && (isGlobal(scoped) || isLexicallyScoped(scoped))) {
|
if (scoped != null && getEntityScope() == this && (isGlobal(scoped) || isLexicallyScoped(scoped))) {
|
||||||
|
@ -1089,7 +1091,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
if (scoped.getDefiningScope().isCaseInsensitive(nm)) {
|
if (scoped.getDefiningScope().isCaseInsensitive(nm)) {
|
||||||
caseInsensitiveNames.put(nm.toLowerCase(), nm);
|
caseInsensitiveNames.put(nm.toLowerCase(), nm);
|
||||||
}
|
}
|
||||||
return (Symbol) values.get(nm);
|
return values.get(nm);
|
||||||
} else {
|
} else {
|
||||||
return scoped;
|
return scoped;
|
||||||
}
|
}
|
||||||
|
@ -1097,7 +1099,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean contains(String nm) {
|
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);
|
return values.containsKey(mappedName == null ? nm : mappedName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1277,11 +1279,11 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Scope makeGlobalScope() {
|
private Scope makeGlobalScope() {
|
||||||
final Map globalSymbols = new LinkedHashMap();
|
final Map<String, AbstractSymbol> globalSymbols = new LinkedHashMap<String, AbstractSymbol>();
|
||||||
final Map caseInsensitiveNames = new LinkedHashMap();
|
final Map<String, String> caseInsensitiveNames = new LinkedHashMap<String, String>();
|
||||||
return new Scope() {
|
return new Scope() {
|
||||||
private final String mapName(String nm) {
|
private final String mapName(String nm) {
|
||||||
String mappedName = (String) caseInsensitiveNames.get(nm.toLowerCase());
|
String mappedName = caseInsensitiveNames.get(nm.toLowerCase());
|
||||||
return (mappedName == null) ? nm : mappedName;
|
return (mappedName == null) ? nm : mappedName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1301,7 +1303,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
return globalSymbols.size();
|
return globalSymbols.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator getAllNames() {
|
public Iterator<String> getAllNames() {
|
||||||
return globalSymbols.keySet().iterator();
|
return globalSymbols.keySet().iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1343,7 +1345,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
throw new Error("cannot find " + name);
|
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) {
|
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) {
|
protected Scope makeTypeScope(final CAstEntity type, final Scope parent) {
|
||||||
final Map typeSymbols = new LinkedHashMap();
|
final Map<String, AbstractSymbol> typeSymbols = new LinkedHashMap<String, AbstractSymbol>();
|
||||||
final Map caseInsensitiveNames = new LinkedHashMap();
|
final Map<String, String> caseInsensitiveNames = new LinkedHashMap<String, String>();
|
||||||
return new Scope() {
|
return new Scope() {
|
||||||
private final String mapName(String nm) {
|
private final String mapName(String nm) {
|
||||||
String mappedName = (String) caseInsensitiveNames.get(nm.toLowerCase());
|
String mappedName = caseInsensitiveNames.get(nm.toLowerCase());
|
||||||
return (mappedName == null) ? nm : mappedName;
|
return (mappedName == null) ? nm : mappedName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1397,7 +1399,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
return typeSymbols.size();
|
return typeSymbols.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator getAllNames() {
|
public Iterator<String> getAllNames() {
|
||||||
return typeSymbols.keySet().iterator();
|
return typeSymbols.keySet().iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1431,7 +1433,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
|
|
||||||
public Symbol lookup(String nm) {
|
public Symbol lookup(String nm) {
|
||||||
if (typeSymbols.containsKey(mapName(nm)))
|
if (typeSymbols.containsKey(mapName(nm)))
|
||||||
return (Symbol) typeSymbols.get(mapName(nm));
|
return typeSymbols.get(mapName(nm));
|
||||||
else {
|
else {
|
||||||
return parent.lookup(nm);
|
return parent.lookup(nm);
|
||||||
}
|
}
|
||||||
|
@ -1475,7 +1477,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
|
|
||||||
Scope currentScope();
|
Scope currentScope();
|
||||||
|
|
||||||
Set entityScopes();
|
Set<Scope> entityScopes();
|
||||||
|
|
||||||
IncipientCFG cfg();
|
IncipientCFG cfg();
|
||||||
|
|
||||||
|
@ -1520,7 +1522,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
return parent.currentScope();
|
return parent.currentScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set entityScopes() {
|
public Set<Scope> entityScopes() {
|
||||||
return parent.entityScopes();
|
return parent.entityScopes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1601,7 +1603,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
private class CodeEntityContext extends EntityContext {
|
private class CodeEntityContext extends EntityContext {
|
||||||
private final Scope topEntityScope;
|
private final Scope topEntityScope;
|
||||||
|
|
||||||
private final Set allEntityScopes;
|
private final Set<Scope> allEntityScopes;
|
||||||
|
|
||||||
private final IncipientCFG cfg;
|
private final IncipientCFG cfg;
|
||||||
|
|
||||||
|
@ -1612,7 +1614,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
|
|
||||||
this.topEntityScope = entityScope;
|
this.topEntityScope = entityScope;
|
||||||
|
|
||||||
this.allEntityScopes = new HashSet();
|
this.allEntityScopes = new HashSet<Scope>();
|
||||||
this.allEntityScopes.add(entityScope);
|
this.allEntityScopes.add(entityScope);
|
||||||
|
|
||||||
cfg = new IncipientCFG();
|
cfg = new IncipientCFG();
|
||||||
|
@ -1630,7 +1632,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
return topEntityScope;
|
return topEntityScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set entityScopes() {
|
public Set<Scope> entityScopes() {
|
||||||
return allEntityScopes;
|
return allEntityScopes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1762,14 +1764,14 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (accesses != null) {
|
if (accesses != null) {
|
||||||
Set parents = new LinkedHashSet();
|
Set<String> parents = new LinkedHashSet<String>();
|
||||||
for (Iterator ACS = accesses.iterator(); ACS.hasNext();) {
|
for (Iterator ACS = accesses.iterator(); ACS.hasNext();) {
|
||||||
Access AC = (Access) ACS.next();
|
Access AC = (Access) ACS.next();
|
||||||
if (AC.variableDefiner != null) {
|
if (AC.variableDefiner != null) {
|
||||||
parents.add(AC.variableDefiner);
|
parents.add(AC.variableDefiner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scopingParents = (String[]) parents.toArray(new String[parents.size()]);
|
scopingParents = parents.toArray(new String[parents.size()]);
|
||||||
|
|
||||||
if (DEBUG_LEXICAL) {
|
if (DEBUG_LEXICAL) {
|
||||||
Trace.println("scoping parents of " + scope.getEntity());
|
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) {
|
protected boolean hasValue(CAstNode n) {
|
||||||
return results.containsKey(n);
|
return results.containsKey(n);
|
||||||
|
@ -1823,18 +1825,18 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
|
|
||||||
public final int getValue(CAstNode n) {
|
public final int getValue(CAstNode n) {
|
||||||
if (results.containsKey(n))
|
if (results.containsKey(n))
|
||||||
return ((Integer) results.get(n)).intValue();
|
return results.get(n).intValue();
|
||||||
else {
|
else {
|
||||||
Trace.println("no value for " + n.getKind());
|
Trace.println("no value for " + n.getKind());
|
||||||
return -1;
|
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) {
|
private void addEntityName(CAstEntity e, String name) {
|
||||||
entityNames.put(e, name);
|
entityNames.put(e, name);
|
||||||
|
@ -1842,15 +1844,17 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
|
|
||||||
private void addAccess(CAstEntity e, Access access) {
|
private void addAccess(CAstEntity e, Access access) {
|
||||||
if (!accesses.containsKey(e))
|
if (!accesses.containsKey(e))
|
||||||
accesses.put(e, new LinkedHashSet());
|
accesses.put(e, new LinkedHashSet<Access>());
|
||||||
((Set) accesses.get(e)).add(access);
|
accesses.get(e).add(access);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addExposedName(CAstEntity entity, CAstEntity declaration, String name, int valueNumber) {
|
private void addExposedName(CAstEntity entity, CAstEntity declaration, String name, int valueNumber) {
|
||||||
if (!exposedNames.containsKey(entity))
|
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) {
|
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
|
// all scopes share the same underlying symtab, which is what
|
||||||
// size really refers to.
|
// 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) {
|
if (DEBUG_NAMES) {
|
||||||
Trace.println("names array of size " + map.length);
|
Trace.println("names array of size " + map.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Iterator S = scopes.iterator(); S.hasNext();) {
|
for (Iterator<Scope> S = scopes.iterator(); S.hasNext();) {
|
||||||
Scope scope = (Scope) S.next();
|
Scope scope = S.next();
|
||||||
for (Iterator I = scope.getAllNames(); I.hasNext();) {
|
for (Iterator<String> I = scope.getAllNames(); I.hasNext();) {
|
||||||
String nm = (String) I.next();
|
String nm = I.next();
|
||||||
Symbol v = (Symbol) scope.lookup(nm);
|
Symbol v = (Symbol) scope.lookup(nm);
|
||||||
|
|
||||||
// hack for new expression idiom in the Java translator
|
// hack for new expression idiom in the Java translator
|
||||||
|
@ -2088,20 +2092,19 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
String[] nms = makeNameMap(functionContext.entityScopes());
|
String[] nms = makeNameMap(functionContext.entityScopes());
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Set reachableBlocks =
|
* Set reachableBlocks = DFS.getReachableNodes(cfg,
|
||||||
DFS.getReachableNodes(cfg, Collections.singleton(cfg.entry()));
|
* Collections.singleton(cfg.entry()));
|
||||||
Assertions._assert(reachableBlocks.size() == cfg.getNumberOfNodes(),
|
* Assertions._assert(reachableBlocks.size() == cfg.getNumberOfNodes(),
|
||||||
cfg.toString());
|
* cfg.toString());
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// (put here to allow subclasses to handle stuff in scoped entities)
|
// (put here to allow subclasses to handle stuff in scoped entities)
|
||||||
|
|
||||||
// assemble lexical information
|
// assemble lexical information
|
||||||
patchLexicalAccesses(cfg.getInstructions(), (Set) accesses.get(n));
|
patchLexicalAccesses(cfg.getInstructions(), accesses.get(n));
|
||||||
LexicalInformation LI =
|
LexicalInformation LI =
|
||||||
// TODO: Ask Julian if the below change is always correct
|
// TODO: Ask Julian if the below change is always correct
|
||||||
new AstLexicalInformation((AbstractScope) functionContext.currentScope(), cfg.getInstructions(), (Set) exposedNames.get(n),
|
new AstLexicalInformation((AbstractScope) functionContext.currentScope(), cfg.getInstructions(), exposedNames.get(n), accesses
|
||||||
(Set) accesses.get(n));
|
.get(n));
|
||||||
|
|
||||||
DebuggingInformation DBG = new AstDebuggingInformation(line, nms);
|
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);
|
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) {
|
protected Context makeLocalContext(Context context, CAstNode n) {
|
||||||
return new LocalContext((WalkContext) context, makeLocalScope(n, ((WalkContext) context).currentScope()));
|
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
|
// FIXME: should it be possible to override visit() instead to do the below
|
||||||
// and then call super.visit?
|
// 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) {
|
protected boolean enterNode(CAstNode n, Context c, CAstVisitor visitor) {
|
||||||
WalkContext context = (WalkContext) c;
|
WalkContext context = (WalkContext) c;
|
||||||
|
@ -2146,7 +2149,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
protected void postProcessNode(CAstNode n, Context c, CAstVisitor visitor) {
|
protected void postProcessNode(CAstNode n, Context c, CAstVisitor visitor) {
|
||||||
WalkContext context = (WalkContext) c;
|
WalkContext context = (WalkContext) c;
|
||||||
if (popPositionM.get(n) != null) {
|
if (popPositionM.get(n) != null) {
|
||||||
context.cfg().setCurrentPosition((Position) positions.pop());
|
context.cfg().setCurrentPosition(positions.pop());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2729,8 +2732,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
else if (context.currentScope().isLexicallyScoped(ls)) {
|
else if (context.currentScope().isLexicallyScoped(ls)) {
|
||||||
doLexicallyScopedWrite(context, nm, rval);
|
doLexicallyScopedWrite(context, nm, rval);
|
||||||
} else {
|
} else {
|
||||||
Assertions._assert(rval != -1,
|
Assertions._assert(rval != -1, CAstPrinter.print(n, c.top().getSourceMap()));
|
||||||
CAstPrinter.print(n, c.top().getSourceMap()));
|
|
||||||
doLocalWrite(context, nm, rval);
|
doLocalWrite(context, nm, rval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2776,8 +2778,8 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
|
|
||||||
private boolean isSimpleSwitch(CAstNode n, WalkContext context, CAstVisitor visitor) {
|
private boolean isSimpleSwitch(CAstNode n, WalkContext context, CAstVisitor visitor) {
|
||||||
CAstControlFlowMap ctrl = context.getControlFlow();
|
CAstControlFlowMap ctrl = context.getControlFlow();
|
||||||
Collection caseLabels = ctrl.getTargetLabels(n);
|
Collection<IField> caseLabels = ctrl.getTargetLabels(n);
|
||||||
for (Iterator kases = caseLabels.iterator(); kases.hasNext();) {
|
for (Iterator<IField> kases = caseLabels.iterator(); kases.hasNext();) {
|
||||||
Object x = kases.next();
|
Object x = kases.next();
|
||||||
|
|
||||||
if (x == CAstControlFlowMap.SWITCH_DEFAULT)
|
if (x == CAstControlFlowMap.SWITCH_DEFAULT)
|
||||||
|
@ -2816,7 +2818,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
|
|
||||||
boolean hasExplicitDefault = ctrl.getTarget(n, CAstControlFlowMap.SWITCH_DEFAULT) != null;
|
boolean hasExplicitDefault = ctrl.getTarget(n, CAstControlFlowMap.SWITCH_DEFAULT) != null;
|
||||||
|
|
||||||
Collection caseLabels = ctrl.getTargetLabels(n);
|
Collection<IField> caseLabels = ctrl.getTargetLabels(n);
|
||||||
int cases = caseLabels.size();
|
int cases = caseLabels.size();
|
||||||
if (hasExplicitDefault)
|
if (hasExplicitDefault)
|
||||||
cases--;
|
cases--;
|
||||||
|
@ -2839,7 +2841,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
context.cfg().newBlock(true);
|
context.cfg().newBlock(true);
|
||||||
|
|
||||||
int cn = 0;
|
int cn = 0;
|
||||||
for (Iterator kases = caseLabels.iterator(); kases.hasNext();) {
|
for (Iterator<IField> kases = caseLabels.iterator(); kases.hasNext();) {
|
||||||
Object x = kases.next();
|
Object x = kases.next();
|
||||||
CAstNode target = ctrl.getTarget(n, x);
|
CAstNode target = ctrl.getTarget(n, x);
|
||||||
if (x == CAstControlFlowMap.SWITCH_DEFAULT) {
|
if (x == CAstControlFlowMap.SWITCH_DEFAULT) {
|
||||||
|
@ -2863,9 +2865,9 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
visitor.visit(switchValue, context, visitor);
|
visitor.visit(switchValue, context, visitor);
|
||||||
int v = getValue(switchValue);
|
int v = getValue(switchValue);
|
||||||
|
|
||||||
Collection caseLabels = ctrl.getTargetLabels(n);
|
Collection<IField> caseLabels = ctrl.getTargetLabels(n);
|
||||||
Map labelToBlock = new LinkedHashMap();
|
Map<Object, PreBasicBlock> labelToBlock = new LinkedHashMap<Object, PreBasicBlock>();
|
||||||
for (Iterator kases = caseLabels.iterator(); kases.hasNext();) {
|
for (Iterator<IField> kases = caseLabels.iterator(); kases.hasNext();) {
|
||||||
Object x = kases.next();
|
Object x = kases.next();
|
||||||
if (x != CAstControlFlowMap.SWITCH_DEFAULT) {
|
if (x != CAstControlFlowMap.SWITCH_DEFAULT) {
|
||||||
walkNodes((CAstNode) x, context);
|
walkNodes((CAstNode) x, context);
|
||||||
|
@ -2885,8 +2887,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
visitor.visit(switchBody, context, visitor);
|
visitor.visit(switchBody, context, visitor);
|
||||||
context.cfg().newBlock(true);
|
context.cfg().newBlock(true);
|
||||||
|
|
||||||
PreBasicBlock nextBlock = context.cfg().getCurrentBlock();
|
for (Iterator<IField> kases = caseLabels.iterator(); kases.hasNext();) {
|
||||||
for (Iterator kases = caseLabels.iterator(); kases.hasNext();) {
|
|
||||||
Object x = kases.next();
|
Object x = kases.next();
|
||||||
if (x != CAstControlFlowMap.SWITCH_DEFAULT) {
|
if (x != CAstControlFlowMap.SWITCH_DEFAULT) {
|
||||||
CAstNode target = ctrl.getTarget(n, x);
|
CAstNode target = ctrl.getTarget(n, x);
|
||||||
|
@ -2930,8 +2931,8 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
context.cfg().addPreNode(n, context.getUnwindState());
|
context.cfg().addPreNode(n, context.getUnwindState());
|
||||||
context.cfg().newBlock(false);
|
context.cfg().newBlock(false);
|
||||||
|
|
||||||
Collection labels = context.getControlFlow().getTargetLabels(n);
|
Collection<IField> labels = context.getControlFlow().getTargetLabels(n);
|
||||||
for (Iterator iter = labels.iterator(); iter.hasNext();) {
|
for (Iterator<IField> iter = labels.iterator(); iter.hasNext();) {
|
||||||
Object label = iter.next();
|
Object label = iter.next();
|
||||||
CAstNode target = context.getControlFlow().getTarget(n, label);
|
CAstNode target = context.getControlFlow().getTarget(n, label);
|
||||||
if (target == CAstControlFlowMap.EXCEPTION_TO_EXIT)
|
if (target == CAstControlFlowMap.EXCEPTION_TO_EXIT)
|
||||||
|
@ -3089,8 +3090,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
Assertions._assert(n.getChild(0).getKind() == CAstNode.CONSTANT);
|
Assertions._assert(n.getChild(0).getKind() == CAstNode.CONSTANT);
|
||||||
String typeNameStr = (String) n.getChild(0).getValue();
|
String typeNameStr = (String) n.getChild(0).getValue();
|
||||||
TypeName typeName = TypeName.string2TypeName(typeNameStr);
|
TypeName typeName = TypeName.string2TypeName(typeNameStr);
|
||||||
TypeReference typeRef =
|
TypeReference typeRef = TypeReference.findOrCreate(loader.getReference(), typeName);
|
||||||
TypeReference.findOrCreate(loader.getReference(), typeName);
|
|
||||||
|
|
||||||
int result = wc.currentScope().allocateTempValue();
|
int result = wc.currentScope().allocateTempValue();
|
||||||
setValue(n, result);
|
setValue(n, result);
|
||||||
|
@ -3131,7 +3131,7 @@ public abstract class AstTranslator extends CAstVisitor {
|
||||||
return t.globalScope;
|
return t.globalScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set entityScopes() {
|
public Set<Scope> entityScopes() {
|
||||||
return Collections.singleton(t.globalScope);
|
return Collections.singleton(t.globalScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,31 +11,41 @@
|
||||||
package com.ibm.wala.cast.loader;
|
package com.ibm.wala.cast.loader;
|
||||||
|
|
||||||
|
|
||||||
import com.ibm.wala.cast.tree.*;
|
import java.net.URL;
|
||||||
import com.ibm.wala.classLoader.*;
|
import java.util.Collection;
|
||||||
import com.ibm.wala.ipa.cha.*;
|
import java.util.HashSet;
|
||||||
import com.ibm.wala.shrikeCT.*;
|
import java.util.Iterator;
|
||||||
import com.ibm.wala.types.*;
|
import java.util.Map;
|
||||||
import com.ibm.wala.util.*;
|
import java.util.Set;
|
||||||
import com.ibm.wala.util.debug.Assertions;
|
|
||||||
|
|
||||||
import java.net.*;
|
import com.ibm.wala.cast.tree.CAstSourcePositionMap;
|
||||||
import java.util.*;
|
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 {
|
abstract public class AstClass implements IClass, ClassConstants {
|
||||||
private final CAstSourcePositionMap.Position sourcePosition;
|
private final CAstSourcePositionMap.Position sourcePosition;
|
||||||
private final TypeName typeName;
|
private final TypeName typeName;
|
||||||
private final IClassLoader loader;
|
private final IClassLoader loader;
|
||||||
private final short modifiers;
|
private final short modifiers;
|
||||||
protected final Map declaredFields;
|
protected final Map<Atom, IField> declaredFields;
|
||||||
protected final Map declaredMethods;
|
protected final Map<Selector,IMethod> declaredMethods;
|
||||||
|
|
||||||
protected AstClass(CAstSourcePositionMap.Position sourcePosition,
|
protected AstClass(CAstSourcePositionMap.Position sourcePosition,
|
||||||
TypeName typeName,
|
TypeName typeName,
|
||||||
IClassLoader loader,
|
IClassLoader loader,
|
||||||
short modifiers,
|
short modifiers,
|
||||||
Map declaredFields,
|
Map<Atom, IField> declaredFields,
|
||||||
Map declaredMethods)
|
Map<Selector,IMethod> declaredMethods)
|
||||||
{
|
{
|
||||||
this.sourcePosition = sourcePosition;
|
this.sourcePosition = sourcePosition;
|
||||||
this.typeName = typeName;
|
this.typeName = typeName;
|
||||||
|
@ -95,22 +105,22 @@ abstract public class AstClass implements IClass, ClassConstants {
|
||||||
|
|
||||||
public abstract IClass getSuperclass() throws ClassHierarchyException;
|
public abstract IClass getSuperclass() throws ClassHierarchyException;
|
||||||
|
|
||||||
private Collection gatherInterfaces() throws ClassHierarchyException {
|
private Collection<IClass> gatherInterfaces() throws ClassHierarchyException {
|
||||||
Set result = new HashSet();
|
Set<IClass> result = new HashSet<IClass>();
|
||||||
result.addAll( getDirectInterfaces() );
|
result.addAll( getDirectInterfaces() );
|
||||||
if (getSuperclass() != null)
|
if (getSuperclass() != null)
|
||||||
result.addAll( getSuperclass().getAllImplementedInterfaces() );
|
result.addAll( getSuperclass().getAllImplementedInterfaces() );
|
||||||
return result;
|
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());
|
Assertions._assert(! isInterface());
|
||||||
return gatherInterfaces();
|
return gatherInterfaces();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getAllAncestorInterfaces() throws ClassHierarchyException {
|
public Collection<IClass> getAllAncestorInterfaces() throws ClassHierarchyException {
|
||||||
Assertions._assert(isInterface());
|
Assertions._assert(isInterface());
|
||||||
return gatherInterfaces();
|
return gatherInterfaces();
|
||||||
}
|
}
|
||||||
|
@ -122,7 +132,7 @@ abstract public class AstClass implements IClass, ClassConstants {
|
||||||
public IMethod getMethod(Selector selector) {
|
public IMethod getMethod(Selector selector) {
|
||||||
try {
|
try {
|
||||||
if (declaredMethods.containsKey(selector)) {
|
if (declaredMethods.containsKey(selector)) {
|
||||||
return (IMethod)declaredMethods.get(selector);
|
return declaredMethods.get(selector);
|
||||||
} else if (getSuperclass() != null) {
|
} else if (getSuperclass() != null) {
|
||||||
return getSuperclass().getMethod(selector);
|
return getSuperclass().getMethod(selector);
|
||||||
} else {
|
} else {
|
||||||
|
@ -137,7 +147,7 @@ abstract public class AstClass implements IClass, ClassConstants {
|
||||||
public IField getField(Atom name) {
|
public IField getField(Atom name) {
|
||||||
try {
|
try {
|
||||||
if (declaredFields.containsKey(name)) {
|
if (declaredFields.containsKey(name)) {
|
||||||
return (IField)declaredFields.get(name);
|
return declaredFields.get(name);
|
||||||
} else if (getSuperclass() != null) {
|
} else if (getSuperclass() != null) {
|
||||||
return getSuperclass().getField(name);
|
return getSuperclass().getField(name);
|
||||||
} else {
|
} else {
|
||||||
|
@ -153,10 +163,10 @@ abstract public class AstClass implements IClass, ClassConstants {
|
||||||
return declaredMethods.values();
|
return declaredMethods.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getDeclaredInstanceFields() {
|
public Collection<IField> getDeclaredInstanceFields() {
|
||||||
Set result = new HashSet();
|
Set<IField> result = new HashSet<IField>();
|
||||||
for(Iterator FS = declaredFields.values().iterator(); FS.hasNext();) {
|
for(Iterator<IField> FS = declaredFields.values().iterator(); FS.hasNext();) {
|
||||||
IField F = (IField) FS.next();
|
IField F = FS.next();
|
||||||
if (! F.isStatic()) {
|
if (! F.isStatic()) {
|
||||||
result.add( F );
|
result.add( F );
|
||||||
}
|
}
|
||||||
|
@ -165,10 +175,10 @@ abstract public class AstClass implements IClass, ClassConstants {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getDeclaredStaticFields() {
|
public Collection<IField> getDeclaredStaticFields() {
|
||||||
Set result = new HashSet();
|
Set<IField> result = new HashSet<IField>();
|
||||||
for(Iterator FS = declaredFields.values().iterator(); FS.hasNext();) {
|
for(Iterator<IField> FS = declaredFields.values().iterator(); FS.hasNext();) {
|
||||||
IField F = (IField) FS.next();
|
IField F = FS.next();
|
||||||
if (F.isStatic()) {
|
if (F.isStatic()) {
|
||||||
result.add( F );
|
result.add( F );
|
||||||
}
|
}
|
||||||
|
@ -177,8 +187,8 @@ abstract public class AstClass implements IClass, ClassConstants {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getAllInstanceFields() throws ClassHierarchyException {
|
public Collection<IField> getAllInstanceFields() throws ClassHierarchyException {
|
||||||
Collection result = new HashSet();
|
Collection<IField> result = new HashSet<IField>();
|
||||||
result.addAll( getDeclaredInstanceFields() );
|
result.addAll( getDeclaredInstanceFields() );
|
||||||
if (getSuperclass() != null) {
|
if (getSuperclass() != null) {
|
||||||
result.addAll( getSuperclass().getAllInstanceFields() );
|
result.addAll( getSuperclass().getAllInstanceFields() );
|
||||||
|
@ -187,8 +197,8 @@ abstract public class AstClass implements IClass, ClassConstants {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getAllStaticFields() throws ClassHierarchyException {
|
public Collection<IField> getAllStaticFields() throws ClassHierarchyException {
|
||||||
Collection result = new HashSet();
|
Collection<IField> result = new HashSet<IField>();
|
||||||
result.addAll( getDeclaredStaticFields() );
|
result.addAll( getDeclaredStaticFields() );
|
||||||
if (getSuperclass() != null) {
|
if (getSuperclass() != null) {
|
||||||
result.addAll( getSuperclass().getAllStaticFields() );
|
result.addAll( getSuperclass().getAllStaticFields() );
|
||||||
|
@ -197,16 +207,16 @@ abstract public class AstClass implements IClass, ClassConstants {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getAllFields() throws ClassHierarchyException {
|
public Collection<IField> getAllFields() throws ClassHierarchyException {
|
||||||
Collection result = new HashSet();
|
Collection<IField> result = new HashSet<IField>();
|
||||||
result.addAll( getAllInstanceFields() );
|
result.addAll( getAllInstanceFields() );
|
||||||
result.addAll( getAllStaticFields() );
|
result.addAll( getAllStaticFields() );
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getAllMethods() throws ClassHierarchyException {
|
public Collection<IMethod> getAllMethods() throws ClassHierarchyException {
|
||||||
Collection result = new HashSet();
|
Collection<IMethod> result = new HashSet<IMethod>();
|
||||||
for(Iterator ms = getDeclaredMethods().iterator(); ms.hasNext(); ) {
|
for(Iterator<IMethod> ms = getDeclaredMethods().iterator(); ms.hasNext(); ) {
|
||||||
result.add( ms.next() );
|
result.add( ms.next() );
|
||||||
}
|
}
|
||||||
if (getSuperclass() != null) {
|
if (getSuperclass() != null) {
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
package com.ibm.wala.cast.loader;
|
package com.ibm.wala.cast.loader;
|
||||||
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
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.IClass;
|
||||||
import com.ibm.wala.classLoader.IClassLoader;
|
import com.ibm.wala.classLoader.IClassLoader;
|
||||||
import com.ibm.wala.classLoader.IField;
|
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.ClassHierarchy;
|
||||||
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
||||||
import com.ibm.wala.types.FieldReference;
|
import com.ibm.wala.types.FieldReference;
|
||||||
|
import com.ibm.wala.types.Selector;
|
||||||
import com.ibm.wala.types.TypeName;
|
import com.ibm.wala.types.TypeName;
|
||||||
import com.ibm.wala.types.TypeReference;
|
import com.ibm.wala.types.TypeReference;
|
||||||
import com.ibm.wala.util.Atom;
|
import com.ibm.wala.util.Atom;
|
||||||
|
@ -29,15 +30,16 @@ import com.ibm.wala.util.debug.Assertions;
|
||||||
public abstract class AstDynamicPropertyClass extends AstClass {
|
public abstract class AstDynamicPropertyClass extends AstClass {
|
||||||
private final TypeReference defaultDescriptor;
|
private final TypeReference defaultDescriptor;
|
||||||
|
|
||||||
protected AstDynamicPropertyClass(CAstSourcePositionMap.Position sourcePosition, TypeName typeName, IClassLoader loader, short modifiers, Map declaredMethods, TypeReference defaultDescriptor) {
|
protected AstDynamicPropertyClass(CAstSourcePositionMap.Position sourcePosition, TypeName typeName, IClassLoader loader,
|
||||||
super(sourcePosition, typeName, loader, modifiers, new HashMap(), declaredMethods);
|
short modifiers, Map<Selector, IMethod> declaredMethods, TypeReference defaultDescriptor) {
|
||||||
|
super(sourcePosition, typeName, loader, modifiers, new HashMap<Atom, IField>(), declaredMethods);
|
||||||
this.defaultDescriptor = defaultDescriptor;
|
this.defaultDescriptor = defaultDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IField getField(final Atom name) {
|
public IField getField(final Atom name) {
|
||||||
try {
|
try {
|
||||||
if (declaredFields.containsKey(name)) {
|
if (declaredFields.containsKey(name)) {
|
||||||
return (IField) declaredFields.get(name);
|
return declaredFields.get(name);
|
||||||
} else if (getSuperclass() != null) {
|
} else if (getSuperclass() != null) {
|
||||||
return getSuperclass().getField(name);
|
return getSuperclass().getField(name);
|
||||||
} else {
|
} else {
|
||||||
|
@ -92,7 +94,7 @@ public abstract class AstDynamicPropertyClass extends AstClass {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return (IField) declaredFields.get(name);
|
return declaredFields.get(name);
|
||||||
}
|
}
|
||||||
} catch (ClassHierarchyException e) {
|
} catch (ClassHierarchyException e) {
|
||||||
Assertions.UNREACHABLE();
|
Assertions.UNREACHABLE();
|
||||||
|
|
|
@ -81,16 +81,16 @@ abstract public class AstFunctionClass implements IClass, ClassConstants {
|
||||||
return loader.lookupClass(superReference.getName(), getClassHierarchy());
|
return loader.lookupClass(superReference.getName(), getClassHierarchy());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getDirectInterfaces() {
|
public Collection<IClass> getDirectInterfaces() {
|
||||||
return Collections.EMPTY_SET;
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getAllImplementedInterfaces() {
|
public Collection<IClass> getAllImplementedInterfaces() {
|
||||||
return Collections.EMPTY_SET;
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getAllAncestorInterfaces() {
|
public Collection<IClass> getAllAncestorInterfaces() {
|
||||||
return Collections.EMPTY_SET;
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IMethod getMethod(Selector selector) {
|
public IMethod getMethod(Selector selector) {
|
||||||
|
@ -137,27 +137,27 @@ abstract public class AstFunctionClass implements IClass, ClassConstants {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getDeclaredInstanceFields() {
|
public Collection<IField> getDeclaredInstanceFields() {
|
||||||
return Collections.EMPTY_SET;
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getDeclaredStaticFields() {
|
public Collection<IField> getDeclaredStaticFields() {
|
||||||
return Collections.EMPTY_SET;
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getAllInstanceFields() {
|
public Collection<IField> getAllInstanceFields() {
|
||||||
return Collections.EMPTY_SET;
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getAllStaticFields() {
|
public Collection<IField> getAllStaticFields() {
|
||||||
return Collections.EMPTY_SET;
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getAllFields() {
|
public Collection<IField> getAllFields() {
|
||||||
return Collections.EMPTY_SET;
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection getAllMethods() {
|
public Collection<IMethod> getAllMethods() {
|
||||||
return Collections.singleton(functionBody);
|
return Collections.singleton(functionBody);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,5 +72,5 @@ public interface CAstControlFlowMap {
|
||||||
* Returns an iterator of all CAstNodes for which this map contains
|
* Returns an iterator of all CAstNodes for which this map contains
|
||||||
* control flow mapping information.
|
* control flow mapping information.
|
||||||
*/
|
*/
|
||||||
Collection getMappedNodes();
|
Collection<CAstNode> getMappedNodes();
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ package com.ibm.wala.cast.tree;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class CAstQualifier {
|
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 CONST = new CAstQualifier("const");
|
||||||
public static final CAstQualifier STRICTFP = new CAstQualifier("strictfp");
|
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
|
* Returns an iterator of all CAstNodes for which this map contains
|
||||||
* source mapping information.
|
* source mapping information.
|
||||||
*/
|
*/
|
||||||
Iterator getMappedNodes();
|
Iterator<CAstNode> getMappedNodes();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
package com.ibm.wala.cast.tree.impl;
|
package com.ibm.wala.cast.tree.impl;
|
||||||
|
|
||||||
import com.ibm.wala.cast.tree.*;
|
import com.ibm.wala.cast.tree.*;
|
||||||
|
import com.ibm.wala.classLoader.IField;
|
||||||
|
|
||||||
import java.util.*;
|
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) {
|
if (root instanceof CAstOperator) {
|
||||||
nodeMap.put(root, root);
|
nodeMap.put(root, root);
|
||||||
return root;
|
return root;
|
||||||
|
@ -53,12 +54,12 @@ public class CAstCloner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private CAstControlFlowMap copyFlow(Map nodeMap, CAstControlFlowMap orig) {
|
private CAstControlFlowMap copyFlow(Map<CAstNode, CAstNode> nodeMap, CAstControlFlowMap orig) {
|
||||||
Collection oldSources = orig.getMappedNodes();
|
Collection<CAstNode> oldSources = orig.getMappedNodes();
|
||||||
CAstControlFlowRecorder newMap = new CAstControlFlowRecorder();
|
CAstControlFlowRecorder newMap = new CAstControlFlowRecorder();
|
||||||
for(Iterator NS = nodeMap.keySet().iterator(); NS.hasNext(); ) {
|
for(Iterator<CAstNode> NS = nodeMap.keySet().iterator(); NS.hasNext(); ) {
|
||||||
CAstNode old = (CAstNode) NS.next();
|
CAstNode old = NS.next();
|
||||||
CAstNode newNode = (CAstNode) nodeMap.get(old);
|
CAstNode newNode = nodeMap.get(old);
|
||||||
newMap.map(newNode, newNode);
|
newMap.map(newNode, newNode);
|
||||||
if (oldSources.contains(old)) {
|
if (oldSources.contains(old)) {
|
||||||
if (orig.getTarget(old, null) != null) {
|
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();
|
Object label = LS.next();
|
||||||
CAstNode oldTarget = orig.getTarget(old, label);
|
CAstNode oldTarget = orig.getTarget(old, label);
|
||||||
if (nodeMap.containsKey(oldTarget)) {
|
if (nodeMap.containsKey(oldTarget)) {
|
||||||
|
@ -86,15 +87,15 @@ public class CAstCloner {
|
||||||
}
|
}
|
||||||
|
|
||||||
private CAstSourcePositionMap
|
private CAstSourcePositionMap
|
||||||
copySource(Map nodeMap, CAstSourcePositionMap orig)
|
copySource(Map<CAstNode, CAstNode> nodeMap, CAstSourcePositionMap orig)
|
||||||
{
|
{
|
||||||
if (orig == null) {
|
if (orig == null) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
CAstSourcePositionRecorder newMap = new CAstSourcePositionRecorder();
|
CAstSourcePositionRecorder newMap = new CAstSourcePositionRecorder();
|
||||||
for(Iterator NS = nodeMap.keySet().iterator(); NS.hasNext(); ) {
|
for(Iterator<CAstNode> NS = nodeMap.keySet().iterator(); NS.hasNext(); ) {
|
||||||
CAstNode old = (CAstNode) NS.next();
|
CAstNode old = NS.next();
|
||||||
CAstNode newNode = (CAstNode) nodeMap.get(old);
|
CAstNode newNode = nodeMap.get(old);
|
||||||
|
|
||||||
if (orig.getPosition(old) != null) {
|
if (orig.getPosition(old) != null) {
|
||||||
newMap.setPosition(newNode, orig.getPosition(old));
|
newMap.setPosition(newNode, orig.getPosition(old));
|
||||||
|
@ -109,7 +110,7 @@ public class CAstCloner {
|
||||||
final CAstControlFlowMap cfg,
|
final CAstControlFlowMap cfg,
|
||||||
final CAstSourcePositionMap pos)
|
final CAstSourcePositionMap pos)
|
||||||
{
|
{
|
||||||
final Map nodes = new HashMap();
|
final Map<CAstNode, CAstNode> nodes = new HashMap<CAstNode, CAstNode>();
|
||||||
final CAstNode newRoot = copyNodes(root, nodes);
|
final CAstNode newRoot = copyNodes(root, nodes);
|
||||||
return new Clone() {
|
return new Clone() {
|
||||||
private CAstControlFlowMap theCfg = null;
|
private CAstControlFlowMap theCfg = null;
|
||||||
|
|
|
@ -10,21 +10,25 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
package com.ibm.wala.cast.tree.impl;
|
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 com.ibm.wala.cast.tree.CAstNode;
|
||||||
import java.net.*;
|
import com.ibm.wala.cast.tree.CAstSourcePositionMap;
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class CAstSourcePositionRecorder implements 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) {
|
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();
|
return positions.keySet().iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,8 +83,8 @@ public class CAstSourcePositionRecorder implements CAstSourcePositionMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAll(CAstSourcePositionMap other) {
|
public void addAll(CAstSourcePositionMap other) {
|
||||||
for(Iterator nodes = other.getMappedNodes(); nodes.hasNext(); ) {
|
for(Iterator<CAstNode> nodes = other.getMappedNodes(); nodes.hasNext(); ) {
|
||||||
CAstNode node = (CAstNode) nodes.next();
|
CAstNode node = nodes.next();
|
||||||
setPosition(node, other.getPosition(node));
|
setPosition(node, other.getPosition(node));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,10 +18,10 @@ import com.ibm.wala.cast.tree.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class CAstTypeDictionaryImpl implements CAstTypeDictionary {
|
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) {
|
public CAstType getCAstTypeFor(Object/*ASTType*/ astType) {
|
||||||
return (CAstType) fMap.get(astType);
|
return fMap.get(astType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void map(Object/*ASTType*/ astType, CAstType castType) {
|
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; }
|
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.
|
* Get the parent entity for a given entity.
|
||||||
|
@ -76,7 +76,7 @@ public abstract class CAstVisitor {
|
||||||
* @return the parent entity for the given entity
|
* @return the parent entity for the given entity
|
||||||
*/
|
*/
|
||||||
protected CAstEntity getParent(CAstEntity entity) {
|
protected CAstEntity getParent(CAstEntity entity) {
|
||||||
return (CAstEntity) entityParents.get(entity);
|
return entityParents.get(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -36,10 +36,10 @@ public class CAstFunctions {
|
||||||
public static Iterator iterateNodes(final CAstNode tree) {
|
public static Iterator iterateNodes(final CAstNode tree) {
|
||||||
return new DFSDiscoverTimeIterator() {
|
return new DFSDiscoverTimeIterator() {
|
||||||
|
|
||||||
private final Map pendingChildren = new HashMap();
|
private final Map<Object, Iterator> pendingChildren = new HashMap<Object, Iterator>();
|
||||||
|
|
||||||
protected Iterator getPendingChildren(Object n) {
|
protected Iterator getPendingChildren(Object n) {
|
||||||
return (Iterator) pendingChildren.get(n);
|
return pendingChildren.get(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setPendingChildren(Object v, Iterator iterator) {
|
protected void setPendingChildren(Object v, Iterator iterator) {
|
||||||
|
|
|
@ -25,13 +25,19 @@ import com.ibm.wala.util.debug.Trace;
|
||||||
|
|
||||||
public class CAstPattern {
|
public class CAstPattern {
|
||||||
private static boolean DEBUG_PARSER = false;
|
private static boolean DEBUG_PARSER = false;
|
||||||
|
|
||||||
private static boolean DEBUG_MATCH = false;
|
private static boolean DEBUG_MATCH = false;
|
||||||
|
|
||||||
private final static int CHILD_KIND = -1;
|
private final static int CHILD_KIND = -1;
|
||||||
|
|
||||||
private final static int CHILDREN_KIND = -2;
|
private final static int CHILDREN_KIND = -2;
|
||||||
|
|
||||||
private final static int REPEATED_PATTERN_KIND = -3;
|
private final static int REPEATED_PATTERN_KIND = -3;
|
||||||
|
|
||||||
private final static int ALTERNATIVE_PATTERN_KIND = -4;
|
private final static int ALTERNATIVE_PATTERN_KIND = -4;
|
||||||
|
|
||||||
private final static int OPTIONAL_PATTERN_KIND = -5;
|
private final static int OPTIONAL_PATTERN_KIND = -5;
|
||||||
|
|
||||||
private final static int REFERENCE_PATTERN_KIND = -6;
|
private final static int REFERENCE_PATTERN_KIND = -6;
|
||||||
|
|
||||||
private final static int IGNORE_KIND = -99;
|
private final static int IGNORE_KIND = -99;
|
||||||
|
@ -39,27 +45,30 @@ public class CAstPattern {
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
private final int kind;
|
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) {
|
public CAstNode getSingle(String name) {
|
||||||
Assertions._assert(containsKey(name), name);
|
Assertions._assert(containsKey(name), name);
|
||||||
return (CAstNode) get(name);
|
return (CAstNode) get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List getMultiple(String name) {
|
public List<Object> getMultiple(String name) {
|
||||||
if (!containsKey(name)) {
|
if (!containsKey(name)) {
|
||||||
return Collections.EMPTY_LIST;
|
return Collections.emptyList();
|
||||||
} else {
|
} else {
|
||||||
Object o = get(name);
|
Object o = get(name);
|
||||||
if (o instanceof CAstNode) {
|
if (o instanceof CAstNode) {
|
||||||
return Collections.singletonList(o);
|
return Collections.singletonList(o);
|
||||||
} else {
|
} else {
|
||||||
Assertions._assert(o instanceof List);
|
Assertions._assert(o instanceof List);
|
||||||
return (List)o;
|
return (List<Object>) o;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,9 +80,7 @@ public class CAstPattern {
|
||||||
if (e.getValue() instanceof CAstNode) {
|
if (e.getValue() instanceof CAstNode) {
|
||||||
add(name, (CAstNode) e.getValue());
|
add(name, (CAstNode) e.getValue());
|
||||||
} else {
|
} else {
|
||||||
for(Iterator vs = ((List)e.getValue()).iterator();
|
for (Iterator vs = ((List) e.getValue()).iterator(); vs.hasNext();) {
|
||||||
vs.hasNext(); )
|
|
||||||
{
|
|
||||||
add(name, (CAstNode) vs.next());
|
add(name, (CAstNode) vs.next());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,10 +91,10 @@ public class CAstPattern {
|
||||||
if (containsKey(name)) {
|
if (containsKey(name)) {
|
||||||
Object o = get(name);
|
Object o = get(name);
|
||||||
if (o instanceof List) {
|
if (o instanceof List) {
|
||||||
((List)o).add(result);
|
((List<CAstNode>) o).add(result);
|
||||||
} else {
|
} else {
|
||||||
Assertions._assert(o instanceof CAstNode);
|
Assertions._assert(o instanceof CAstNode);
|
||||||
List x = new ArrayList();
|
List<Object> x = new ArrayList<Object>();
|
||||||
x.add(o);
|
x.add(o);
|
||||||
x.add(result);
|
x.add(result);
|
||||||
put(name, x);
|
put(name, x);
|
||||||
|
@ -114,7 +121,7 @@ public class CAstPattern {
|
||||||
this.references = null;
|
this.references = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CAstPattern(String patternName, Map references) {
|
public CAstPattern(String patternName, Map<String, CAstPattern> references) {
|
||||||
this.name = null;
|
this.name = null;
|
||||||
this.kind = REFERENCE_PATTERN_KIND;
|
this.kind = REFERENCE_PATTERN_KIND;
|
||||||
this.value = patternName;
|
this.value = patternName;
|
||||||
|
@ -164,9 +171,7 @@ public class CAstPattern {
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean
|
private static boolean matchChildren(CAstNode tree, int i, CAstPattern[] cs, int j, Segments s) {
|
||||||
matchChildren(CAstNode tree, int i, CAstPattern[] cs, int j, Segments s)
|
|
||||||
{
|
|
||||||
if (i >= tree.getChildCount() && j >= cs.length) {
|
if (i >= tree.getChildCount() && j >= cs.length) {
|
||||||
return true;
|
return true;
|
||||||
} else if (i < tree.getChildCount() && j >= cs.length) {
|
} else if (i < tree.getChildCount() && j >= cs.length) {
|
||||||
|
@ -205,8 +210,7 @@ public class CAstPattern {
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (DEBUG_MATCH) {
|
if (DEBUG_MATCH) {
|
||||||
Trace.println(
|
Trace.println("** matches " + CAstPrinter.print(tree.getChild(i)));
|
||||||
"** matches " + CAstPrinter.print(tree.getChild(i)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s != null && cs[j].name != null) {
|
if (s != null && cs[j].name != null) {
|
||||||
|
@ -224,8 +228,7 @@ public class CAstPattern {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DEBUG_MATCH) {
|
if (DEBUG_MATCH) {
|
||||||
Trace.println(
|
Trace.println(cs[j] + " matches " + CAstPrinter.print(tree.getChild(i)));
|
||||||
cs[j] + " matches " + CAstPrinter.print(tree.getChild(i)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return matchChildren(tree, i + 1, cs, j, s);
|
return matchChildren(tree, i + 1, cs, j, s);
|
||||||
|
@ -252,8 +255,7 @@ public class CAstPattern {
|
||||||
if (optionalPattern.tryMatch(tree.getChild(i), s)) {
|
if (optionalPattern.tryMatch(tree.getChild(i), s)) {
|
||||||
|
|
||||||
if (DEBUG_MATCH) {
|
if (DEBUG_MATCH) {
|
||||||
Trace.println(
|
Trace.println(cs[j] + " matches " + CAstPrinter.print(tree.getChild(i)));
|
||||||
cs[j] + " matches " + CAstPrinter.print(tree.getChild(i)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return matchChildren(tree, i + 1, cs, j + 1, s);
|
return matchChildren(tree, i + 1, cs, j + 1, s);
|
||||||
|
@ -263,10 +265,7 @@ public class CAstPattern {
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return
|
return cs[j].match(tree.getChild(i), s) && matchChildren(tree, i + 1, cs, j + 1, s);
|
||||||
cs[j].match(tree.getChild(i), s)
|
|
||||||
&&
|
|
||||||
matchChildren(tree, i+1, cs, j+1, s);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -277,13 +276,14 @@ public class CAstPattern {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kind == REFERENCE_PATTERN_KIND) {
|
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) {
|
} else if (kind == ALTERNATIVE_PATTERN_KIND) {
|
||||||
for (int i = 0; i < children.length; i++) {
|
for (int i = 0; i < children.length; i++) {
|
||||||
if (children[i].tryMatch(tree, s)) {
|
if (children[i].tryMatch(tree, s)) {
|
||||||
|
|
||||||
if (s != null && name != null) s.add(name, tree);
|
if (s != null && name != null)
|
||||||
|
s.add(name, tree);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -295,12 +295,8 @@ public class CAstPattern {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if ( (value == null)?
|
if ((value == null) ? tree.getKind() != kind : (tree.getKind() != CAstNode.CONSTANT || !value.equals(tree.getValue()
|
||||||
tree.getKind() != kind:
|
.toString()))) {
|
||||||
( tree.getKind()!=CAstNode.CONSTANT
|
|
||||||
||
|
|
||||||
!value.equals(tree.getValue().toString()) ) )
|
|
||||||
{
|
|
||||||
if (DEBUG_MATCH) {
|
if (DEBUG_MATCH) {
|
||||||
Trace.println("match failed (b)");
|
Trace.println("match failed (b)");
|
||||||
}
|
}
|
||||||
|
@ -308,7 +304,8 @@ public class CAstPattern {
|
||||||
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 (children == null || children.length == 0) {
|
||||||
if (DEBUG_MATCH && tree.getChildCount() != 0) {
|
if (DEBUG_MATCH && tree.getChildCount() != 0) {
|
||||||
|
@ -321,15 +318,14 @@ public class CAstPattern {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean
|
private static boolean tryMatchChildren(CAstNode tree, int i, CAstPattern[] cs, int j, Segments s) {
|
||||||
tryMatchChildren(CAstNode tree, int i, CAstPattern[] cs, int j, Segments s)
|
|
||||||
{
|
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
return matchChildren(tree, i, cs, j, s);
|
return matchChildren(tree, i, cs, j, s);
|
||||||
} else {
|
} else {
|
||||||
Segments ss = new Segments();
|
Segments ss = new Segments();
|
||||||
boolean result = matchChildren(tree, i, cs, j, ss);
|
boolean result = matchChildren(tree, i, cs, j, ss);
|
||||||
if (result) s.addAll(ss);
|
if (result)
|
||||||
|
s.addAll(ss);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -340,7 +336,8 @@ public class CAstPattern {
|
||||||
} else {
|
} else {
|
||||||
Segments ss = new Segments();
|
Segments ss = new Segments();
|
||||||
boolean result = match(tree, ss);
|
boolean result = match(tree, ss);
|
||||||
if (result) s.addAll(ss);
|
if (result)
|
||||||
|
s.addAll(ss);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -367,9 +364,12 @@ public class CAstPattern {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Parser {
|
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 final String patternString;
|
||||||
|
|
||||||
private int start;
|
private int start;
|
||||||
|
|
||||||
private int end;
|
private int end;
|
||||||
|
|
||||||
private Parser(String patternString) {
|
private Parser(String patternString) {
|
||||||
|
@ -392,9 +392,7 @@ public class CAstPattern {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public CAstPattern parse()
|
public CAstPattern parse() throws NoSuchFieldException, IllegalAccessException {
|
||||||
throws NoSuchFieldException, IllegalAccessException
|
|
||||||
{
|
|
||||||
if (DEBUG_PARSER) {
|
if (DEBUG_PARSER) {
|
||||||
Trace.println("parsing " + patternString.substring(start));
|
Trace.println("parsing " + patternString.substring(start));
|
||||||
}
|
}
|
||||||
|
@ -413,10 +411,7 @@ public class CAstPattern {
|
||||||
} else if (patternString.charAt(start) == '"') {
|
} else if (patternString.charAt(start) == '"') {
|
||||||
int strEnd = patternString.indexOf('"', start + 1);
|
int strEnd = patternString.indexOf('"', start + 1);
|
||||||
end = strEnd + 1;
|
end = strEnd + 1;
|
||||||
result =
|
result = new CAstPattern(name, patternString.substring(start + 1, strEnd));
|
||||||
new CAstPattern(
|
|
||||||
name,
|
|
||||||
patternString.substring(start+1, strEnd));
|
|
||||||
|
|
||||||
} else if (patternString.startsWith("**", start)) {
|
} else if (patternString.startsWith("**", start)) {
|
||||||
end = start + 2;
|
end = start + 2;
|
||||||
|
@ -427,7 +422,7 @@ public class CAstPattern {
|
||||||
result = new CAstPattern(name, CHILD_KIND, null);
|
result = new CAstPattern(name, CHILD_KIND, null);
|
||||||
|
|
||||||
} else if (patternString.startsWith("|(", start)) {
|
} else if (patternString.startsWith("|(", start)) {
|
||||||
List alternatives = new ArrayList();
|
List<CAstPattern> alternatives = new ArrayList<CAstPattern>();
|
||||||
start += 2;
|
start += 2;
|
||||||
do {
|
do {
|
||||||
alternatives.add(parse());
|
alternatives.add(parse());
|
||||||
|
@ -435,10 +430,7 @@ public class CAstPattern {
|
||||||
} while (patternString.startsWith("||", end));
|
} while (patternString.startsWith("||", end));
|
||||||
Assertions._assert(patternString.startsWith(")|", end), patternString);
|
Assertions._assert(patternString.startsWith(")|", end), patternString);
|
||||||
end += 2;
|
end += 2;
|
||||||
result = new CAstPattern(name,
|
result = new CAstPattern(name, ALTERNATIVE_PATTERN_KIND, alternatives.toArray(new CAstPattern[alternatives.size()]));
|
||||||
ALTERNATIVE_PATTERN_KIND,
|
|
||||||
(CAstPattern[])
|
|
||||||
alternatives.toArray(new CAstPattern[alternatives.size()]));
|
|
||||||
|
|
||||||
} else if (patternString.startsWith("@(", start)) {
|
} else if (patternString.startsWith("@(", start)) {
|
||||||
start += 2;
|
start += 2;
|
||||||
|
@ -475,15 +467,14 @@ public class CAstPattern {
|
||||||
result = new CAstPattern(name, kind, null);
|
result = new CAstPattern(name, kind, null);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
List children = new ArrayList();
|
List<CAstPattern> children = new ArrayList<CAstPattern>();
|
||||||
start = patternString.indexOf('(', start) + 1;
|
start = patternString.indexOf('(', start) + 1;
|
||||||
do {
|
do {
|
||||||
children.add(parse());
|
children.add(parse());
|
||||||
start = end + 1;
|
start = end + 1;
|
||||||
|
|
||||||
if (DEBUG_PARSER) {
|
if (DEBUG_PARSER) {
|
||||||
Trace.println(
|
Trace.println("parsing children: " + patternString.substring(end));
|
||||||
"parsing children: " + patternString.substring(end));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} while (patternString.charAt(end) == ',');
|
} while (patternString.charAt(end) == ',');
|
||||||
|
@ -491,11 +482,7 @@ public class CAstPattern {
|
||||||
Assertions._assert(patternString.charAt(end) == ')');
|
Assertions._assert(patternString.charAt(end) == ')');
|
||||||
end++;
|
end++;
|
||||||
|
|
||||||
result = new CAstPattern(
|
result = new CAstPattern(name, kind, children.toArray(new CAstPattern[children.size()]));
|
||||||
name,
|
|
||||||
kind,
|
|
||||||
(CAstPattern[])
|
|
||||||
children.toArray(new CAstPattern[children.size()]));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue