--- /dev/null
+package Analysis.CallGraph;
+import IR.State;
+import IR.Flat.FlatMethod;
+import IR.Flat.FlatNode;
+import IR.Flat.FlatCall;
+import IR.Flat.FKind;
+import java.util.*;
+import IR.ClassDescriptor;
+import IR.MethodDescriptor;
+
+public class CallGraph {
+ State state;
+ Hashtable methods;
+ Hashtable methodmap;
+
+ public CallGraph(State state) {
+ this.state=state;
+ methods=new Hashtable();
+ methodmap=new Hashtable();
+ buildMethodTable();
+ buildGraph();
+ }
+
+ private void buildMethodTable() {
+ //Iterator through classes
+ Iterator it=state.getClassSymbolTable().getDescriptorsIterator();
+ while(it.hasNext()) {
+ ClassDescriptor cn=(ClassDescriptor)it.next();
+ Iterator methodit=cn.getMethods();
+ //Iterator through methods
+ while(methodit.hasNext()) {
+ MethodDescriptor md=(MethodDescriptor)methodit.next();
+ if (md.isStatic()||md.getReturnType()==null)
+ continue;
+ ClassDescriptor superdesc=cn.getSuperDesc();
+ if (superdesc!=null) {
+ Set possiblematches=superdesc.getMethodTable().getSet(md.getSymbol());
+ boolean foundmatch=false;
+ for(Iterator matchit=possiblematches.iterator();matchit.hasNext();) {
+ MethodDescriptor matchmd=(MethodDescriptor)matchit.next();
+ if (md.matches(matchmd)) {
+ if (!methods.containsKey(matchmd))
+ methods.put(matchmd,new HashSet());
+ ((HashSet)methods.get(matchmd)).add(md);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /** Given a call to MethodDescriptor, lists the methods which
+ could actually be called due to virtual dispatch. */
+ public Set getMethods(MethodDescriptor md) {
+ HashSet ns=new HashSet();
+ ns.add(md);
+ Set s=(Set)methods.get(md);
+ if (s!=null)
+ for(Iterator it=s.iterator();it.hasNext();) {
+ MethodDescriptor md2=(MethodDescriptor)it.next();
+ ns.addAll(getMethods(md2));
+ }
+ return ns;
+ }
+
+ private void buildGraph() {
+ Iterator it=state.getClassSymbolTable().getDescriptorsIterator();
+ while(it.hasNext()) {
+ ClassDescriptor cn=(ClassDescriptor)it.next();
+ Iterator methodit=cn.getMethods();
+ //Iterator through methods
+ while(methodit.hasNext()) {
+ MethodDescriptor md=(MethodDescriptor)methodit.next();
+ analyzeMethod(md);
+ }
+ }
+ }
+
+ private void analyzeMethod(MethodDescriptor md) {
+ FlatMethod fm=state.getMethodFlat(md);
+ HashSet toexplore=new HashSet();
+ toexplore.add(fm);
+ HashSet explored=new HashSet();
+ //look at all the nodes in the flat representation
+ while(!toexplore.isEmpty()) {
+ FlatNode fn=(FlatNode)(toexplore.iterator()).next();
+ toexplore.remove(fn);
+ explored.add(fn);
+ for(int i=0;i<fn.numNext();i++) {
+ FlatNode fnnext=fn.getNext(i);
+ if (!explored.contains(fnnext))
+ toexplore.add(fnnext);
+ }
+ if (fn.kind()==FKind.FlatCall) {
+ FlatCall fc=(FlatCall)fn;
+ MethodDescriptor calledmethod=fc.getMethod();
+ Set methodsthatcouldbecalled=getMethods(calledmethod);
+ if (!methodmap.containsKey(md))
+ methodmap.put(md,new HashSet());
+ ((HashSet)methodmap.get(md)).addAll(methodsthatcouldbecalled);
+ }
+ }
+ }
+}
--- /dev/null
+package Analysis.Flag;
+import java.util.*;
+import IR.FlagDescriptor;
+
+public class FlagState {
+ HashSet flags;
+
+ public FlagState() {
+ flags=new HashSet();
+ }
+
+ public void setFlag(FlagDescriptor fd, boolean status) {
+ if (status)
+ flags.add(fd);
+ else
+ flags.remove(fd);
+ }
+
+ public boolean getFlagState(FlagDescriptor fd) {
+ return flags.contains(fd);
+ }
+
+ public Set getFlags() {
+ return flags;
+ }
+
+ public boolean equals(Object o) {
+ if (!(o instanceof FlagState))
+ return false;
+ FlagState fs=(FlagState)o;
+ return fs.flags.equals(flags);
+ }
+
+ public int hashCode() {
+ return flags.hashCode();
+ }
+}
(an.getDest() instanceof NameNode)))
throw new Error("Bad lside in "+an.printNode(0));
checkExpressionNode(md, nametable, an.getDest(), null);
+
+ /* We want parameter variables to tasks to be immutable */
+ if (md instanceof TaskDescriptor) {
+ if (an.getDest() instanceof NameNode) {
+ NameNode nn=(NameNode)an.getDest();
+ if (nn.getVar()!=null) {
+ if (((TaskDescriptor)md).getParameterTable().contains(nn.getVar().getSymbol()))
+ throw new Error("Can't modify parameter "+nn.getVar()+ " to task "+td.getSymbol());
+ }
+ }
+ }
+
if (!typeutil.isSuperorType(an.getDest().getType(),an.getSrc().getType())) {
throw new Error("Type of rside ("+an.getSrc().getType()+") not compatible with type of lside ("+an.getDest().getType()+")"+an.printNode(0));
}
Lex/Keyword.class Lex/Lexer.class Lex/Literal.class \
Lex/LongLiteral.class Lex/NullLiteral.class Lex/NumericLiteral.class \
Lex/Operator.class Lex/Separator.class Lex/StringLiteral.class \
-Lex/Token.class Lex/TraditionalComment.class Lex/WhiteSpace.class
+Lex/Token.class Lex/TraditionalComment.class Lex/WhiteSpace.class \
+Analysis/Flag/FlagState.class Analysis/CallGraph/CallGraph.class
all: Parse/Sym.class Parse/Parser.class $(CLASSFILES)
javac -cp ../cup:.:$(CLASSPATH) $<
clean:
- rm IR/*.class IR/Tree/*.class Main/*.class Lex/*.class Parse/*.class Parse/Sym.java Parse/Parser.java IR/Flat/*.class classdefs.h methodheaders.h methods.c structdefs.h virtualtable.h
+ rm IR/*.class IR/Tree/*.class Main/*.class Lex/*.class Parse/*.class Parse/Sym.java Parse/Parser.java IR/Flat/*.class classdefs.h methodheaders.h methods.c structdefs.h virtualtable.h Analysis/*.class Analysis/Flag/*.class