package x10.wala.translator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import polyglot.ast.ClassDecl;
import polyglot.ast.MethodDecl;
import polyglot.ast.Node;
import polyglot.ast.SourceFile;
import polyglot.ast.TopLevelDecl;
import polyglot.frontend.ExtensionInfo;
import polyglot.frontend.Job;
import polyglot.frontend.SourceGoal_c;
import polyglot.main.Report;
import polyglot.main.Reporter;
import polyglot.visit.NodeVisitor;
import x10.compiler.ws.util.WSTransformationContent;
import x10.wala.client.X10SourceAnalysisEngine;
import x10.wala.ipa.cha.X10ClassHierarchy;
import x10.wala.loader.X10SourceLoaderImpl;
import com.ibm.wala.cast.tree.CAstEntity;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.callgraph.Entrypoint;
import com.ibm.wala.ipa.callgraph.impl.DefaultEntrypoint;
import com.ibm.wala.types.ClassLoaderReference;
import com.ibm.wala.types.Descriptor;
import com.ibm.wala.types.MethodReference;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.strings.Atom;
public class X102IRGoal extends SourceGoal_c {
// TODO: get rid of static state
// TODO: figure out whether we need multiple loaders
static {
if(Report.verbose)
Report.reporter.report(5,"WALA is invoked!");
}
private static final ClassLoaderReference X10LOADER = X10SourceLoaderImpl.X10SourceLoader;
private static X10IdentityMapper mapper = new X10IdentityMapper(X10LOADER);
private static X10SourceAnalysisEngine engine = new X10SourceAnalysisEngine();
private static final List mainClasses = new ArrayList();
private static final X10SourceLoaderImpl fSourceLoader = (X10SourceLoaderImpl) engine.getClassHierarchy().getLoader(X10LOADER);
public X102IRGoal(Job job) {
super(job);
}
@Override
public boolean runTask() {
ExtensionInfo extInfo = job.extensionInfo();
Reporter reporter = extInfo.getOptions().reporter;
boolean shouldReport = reporter.should_report(Reporter.verbose, 2);
if(shouldReport)
reporter.report(2,"translating " + job.source().name() + " x10 ast to wala ast ...");
X10toCAstTranslator fTranslator = new X10toCAstTranslator(X10LOADER, extInfo.nodeFactory(), extInfo.typeSystem(), mapper);
CAstEntity entity = fTranslator.translate(job.ast(), job.source().name());
if(shouldReport)
reporter.report(2,"translating " + job.source().name() + " wala ast to ir ...");
new X10CAst2IRTranslator(entity, fSourceLoader).translate();
return true;
}
@Override
public String name() {
return "<X10 to IR goal for " + job().source().path() + ">";
}
public static void hasMain(String mainClass) {
mainClasses.add(mainClass);
}
// test method to be called once the IR has been generated for all jo
public static void printCallGraph() {
System.err.println(buildCallGraph());
//GraphUtil.printNumberedGraph(buildCallGraph(), (String)mainClasses.get(mainClasses.size()-1));
}
// A simple method to analyze the call graph and identify transformation taret;
public static WSTransformationContent wsAnalyzeCallGraph(Collection<Job> jobs) {
final WSTransformationContent targets = new X10WSCallGraphAnalyzer(buildCallGraph()).simpleAnalyze();
NodeVisitor deadCodeFinderVisitor = new NodeVisitor(){
public Node leave(Node old, Node n, NodeVisitor v) {
if(n instanceof MethodDecl
// || n instanceof ConstructorDecl
// || (n instanceof Closure && !(n instanceof PlacedClosure))
){ //Note, PlacedClosure are not treated as normal closure, not build node
targets.checkAndMarkDeadMethodDef((MethodDecl)n);
}
return n;
}
};
//it is still in all barrier, so we can visit all the ast, and mark the dead defs
for(Job job : jobs){
if(job == null){
System.err.println("[WALA_WS_ERR] Mark Dead Method: Find one job is empty!");
continue;
}
Node node = job.ast();
if(node != null && node instanceof SourceFile){
for(TopLevelDecl tld : ((SourceFile)node).decls()){
if(tld instanceof ClassDecl){
//visit the class decl
tld.visit(deadCodeFinderVisitor);
}
}
}
else{
if(node == null){
System.err.println("[WALA_WS_ERR] Mark Dead Method: AST node == null for job: " + job.source().toString());
continue;
}
if(! (node instanceof SourceFile)){
System.err.println("[WALA_WS_ERR] Mark Dead Method: AST node is not SourceFile for job: " + job.source().toString());
continue;
}
}
}
return targets;
}
private static CallGraph buildCallGraph(){
try {
engine.buildClassHierarchy();
List<Entrypoint> entrypoints = new ArrayList<Entrypoint>();
for (Iterator it = mainClasses.iterator(); it.hasNext();) {
String mainClass = (String) it.next();
final TypeReference typeRef = TypeReference.findOrCreate(X10LOADER, "L" + mainClass);
final MethodReference mainRef = MethodReference.findOrCreate(
typeRef, Atom.findOrCreateAsciiAtom("main"),
Descriptor.findOrCreateUTF8("(Lx10/array/Array;)V"));
entrypoints.add(new DefaultEntrypoint(mainRef, engine.getClassHierarchy()));
}
if(Report.verbose)
Report.reporter.report(5,"building call graph ...");
return engine.buildCallGraph(entrypoints);
}catch (Throwable t) {
System.err.println(t);
t.printStackTrace();
return null;
}
}
/* FIXME: uncomment after fixing compiler
public static HashMap<CallTableKey, LinkedList<CallTableVal>> analyze() throws Exception {
boolean[] options = {
false, // whether to do fixed-point computation on calltable
false, // whether to print the calltable
true, // whether to expand everthing call in "at"
true,// whether to expand everthing call in "async"
true // whether to expand everthing call in "method"
};
return analyze(options);
}
public static HashMap<CallTableKey, LinkedList<CallTableVal>> analyze(boolean[] options) throws Exception {
boolean ifExpanded = options[0];
boolean ifDump = options[1];
boolean[] mask = { options[2], options[3], options[4] };
HashMap<CallTableKey, LinkedList<CallTableVal>> calltable = new HashMap<CallTableKey, LinkedList<CallTableVal>>();
X10FinishAsyncAnalysis x10fa = new X10FinishAsyncAnalysis();
CallGraph cg = buildCallGraph();
if(Report.verbose)
Report.reporter.report(5,"call graph built!\nanalyzing programs ...");
calltable = x10fa.build(cg,calltable);
calltable = CallTableUtil.findPatterns(calltable);
if (ifDump) {
CallTableUtil.dumpCallTable(calltable);
}
if (ifExpanded) {
if(Report.verbose)
Report.reporter.report(5,"expanding table ...");
CallTableUtil.expandCallTable(calltable, mask);
// CallTableUtil.updateAllArity(calltable);
// CallTableUtil.expandCallTable(calltable, mask);
}
if (ifDump && ifExpanded) {
if(Report.verbose)
Report.reporter.report(5,"New Table:");
CallTableUtil.dumpCallTable(calltable);
}
if(Report.verbose)
Report.reporter.report(5,"done!");
return calltable;
}
*/
}