// Tell the rest of soot that this is the interesting main method.
Scene.v().setMainClass(mainClass);
// Reinitialize the hierarchy, since we've added classes.
Scene.v().setActiveHierarchy(new Hierarchy());
Scene.v().setFastHierarchy(new FastHierarchy());
// Optimizations.
// We know that we will never parse classes, so throw away that code.
SootUtilities.assertFinalField(mainClass, mainClass
.getFieldByName("_expectingClass"), IntConstant.v(0));
// We know that we will never be testing, so throw away that code.
SootUtilities.assertFinalField(mainClass, mainClass
.getFieldByName("_test"), IntConstant.v(0));
// We know that we have exactly one model, so create it.
// The final field for the model.
SootField modelField = new SootField("_CGmodel", RefType.v(modelClass),
Modifier.PRIVATE); // | Modifier.FINAL);
mainClass.addField(modelField);
// initialize the field by creating a model
// in all the <init> methods.
for (Iterator methods = mainClass.getMethods().iterator(); methods
.hasNext();) {
SootMethod method = (SootMethod) methods.next();
// ignore things that aren't initializers.
if (!method.getName().equals("<init>")) {
continue;
}
// System.out.println("method = " + method);
JimpleBody body = (JimpleBody) method.retrieveActiveBody();
Chain units = body.getUnits();
Stmt insertPoint = (Stmt) units.getLast();
Local modelLocal = Jimple.v().newLocal(
"_CGTemp" + modelField.getName(), modelField.getType());
body.getLocals().add(modelLocal);
units.insertBefore(Jimple.v().newAssignStmt(modelLocal,
Jimple.v().newNewExpr(RefType.v(modelClass))), insertPoint);
// the arguments
List args = new LinkedList();
SootMethod constructor = SootUtilities.getMatchingMethod(
modelClass, "<init>", args);
units.insertBefore(Jimple.v().newInvokeStmt(
Jimple.v().newSpecialInvokeExpr(modelLocal,
constructor.makeRef(), args)), insertPoint);
FieldRef fieldRef = Jimple.v().newInstanceFieldRef(
body.getThisLocal(), modelField.makeRef());
units.insertBefore(Jimple.v().newAssignStmt(fieldRef, modelLocal),
insertPoint);
// Set the name.
units.insertBefore(Jimple.v().newInvokeStmt(
Jimple.v().newVirtualInvokeExpr(modelLocal,
PtolemyUtilities.setNameMethod.makeRef(),
StringConstant.v(_model.getName()))), insertPoint);
// Set the hardcoded iteration limit, if necessary.
int iterationLimit = PhaseOptions.getInt(options, "iterations");
if (iterationLimit != Integer.MAX_VALUE) {
units.insertBefore(Jimple.v().newAssignStmt(
Jimple.v().newInstanceFieldRef(
body.getThisLocal(),
mainClass.getFieldByName("_iterationLimit")
.makeRef()),
IntConstant.v(iterationLimit)), insertPoint);
}
}
try {
// unroll places where the list of models is used.
// We put this in a try block so that we can exclude it
// if necessary
LinkedList modelList = new LinkedList();
modelList.add(modelField);
SootField modelsField = mainClass.getFieldByName("_models");
if (modelsField != null) {
SootUtilities.unrollIteratorInstances(mainClass, modelsField,
modelList);
}
} catch (RuntimeException ex) {
System.out.println("Warning: did not find _models field: " + ex);
for (Iterator methods = mainClass.getMethods().iterator(); methods
.hasNext();) {
SootMethod method = (SootMethod) methods.next();
JimpleBody body = (JimpleBody) method.retrieveActiveBody();
System.out.println("clt: " + method + " " + body);
}
/*
SootUtilities.createAndSetFieldFromLocal(
body,
modelField,
mainClass,
modelField.getType(),
"_model");
*/
}
// Find calls to Manager.startRun() and replace it with
// iteration code.
// Note: It would be nice if we could inline the manager
// code and optimize it, but in this case, the amount of code
// we would want to throw away is fairly large. This
// just seems simpler here.
//SootClass managerClass = Scene.v()
// .getSootClass("ptolemy.actor.Manager");
//SootMethod managerStartRunMethod = managerClass
// .getMethodByName("startRun");
SootMethod mainStartRunMethod = mainClass.getMethodByName("startRun");
for (Iterator methods = mainClass.getMethods().iterator(); methods
.hasNext();) {
SootMethod method = (SootMethod) methods.next();
JimpleBody body = (JimpleBody) method.retrieveActiveBody();
for (Iterator units = body.getUnits().snapshotIterator(); units
.hasNext();) {
Stmt stmt = (Stmt) units.next();
if (!stmt.containsInvokeExpr()) {
continue;
}
ValueBox box = stmt.getInvokeExprBox();
Value value = box.getValue();
if (value instanceof InstanceInvokeExpr) {
InstanceInvokeExpr expr = (InstanceInvokeExpr) value;
if (expr.getMethod().equals(mainStartRunMethod)) {
// Replace the start run method call
// with code to iterate the model.
// First create a local that refers to the model.
// FIXME This is redundant, since the local
// already exists somewhere...
Local modelLocal = Jimple.v().newLocal(
"_CGTemp" + modelField.getName(),
modelField.getType());
body.getLocals().add(modelLocal);
body.getUnits().insertBefore(
Jimple.v().newAssignStmt(
modelLocal,
Jimple.v().newInstanceFieldRef(
body.getThisLocal(),
modelField.makeRef())), stmt);
_insertIterateCalls(body, stmt, mainClass, modelClass,
modelLocal, options);
body.getUnits().remove(stmt);
}
}
}
}
// inline calls to the startRun and stopRun method.
SootMethod startRunMethod = mainClass.getMethodByName("startRun");
SootUtilities.inlineCallsToMethod(startRunMethod, mainClass);
mainClass.removeMethod(startRunMethod);
SootUtilities.inlineCallsToMethod(mainClass.getMethodByName("stopRun"),
mainClass);
for (Iterator methods = mainClass.getMethods().iterator(); methods
.hasNext();) {
SootMethod method = (SootMethod) methods.next();
JimpleBody body = (JimpleBody) method.retrieveActiveBody();
LocalSplitter.v().transform(body, phaseName + ".lns");
LocalNameStandardizer.v().transform(body, phaseName + ".lns");
TypeResolver.resolve(body, Scene.v());
}
// unroll places where the model itself is looked at.
// SootField modelsField = mainClass.getFieldByName("_models");
// SootUtilities.unrollIteratorInstances(mainClass,
// modelsField, modelList);
// Take the instance of main, and convert it to be a static class.
/*
// FIXME this is currently broken.
{
// First find the constructor statement.
SootMethod mainMethod = mainClass.getMethodByName("main");
JimpleBody body = (JimpleBody)mainMethod.retrieveActiveBody();
Chain units = body.getUnits();
for (Iterator stmts = units.iterator(); stmts.hasNext();) {
Stmt stmt = (Stmt)stmts.next();
// filter out anything that is not a definition.
if (!(stmt instanceof DefinitionStmt)) {
continue;
}
DefinitionStmt newStmt = (DefinitionStmt)stmt;
Value value = (newStmt).getRightOp();
if (!(value instanceof NewExpr)) {
continue;
}
RefType type = ((NewExpr)value).getBaseType();
if (type.getSootClass() != mainClass) {
continue;
}
InvokeStmt constructorStmt = null;
// Now walk forward and find the constructor.
while (stmts.hasNext()) {
stmt = (Stmt)stmts.next();
if (stmt instanceof InvokeStmt &&
((InvokeStmt)stmt).getInvokeExpr()
instanceof SpecialInvokeExpr) {
constructorStmt = (InvokeStmt)stmt;
}
break;
}
// Now we actually have a creation of the main object,
// so create a class just for that instance.
SootClass staticMainClass =
SootUtilities.createStaticClassForInstance(
mainClass, body, newStmt, constructorStmt,
PhaseOptions.getString(options, "targetPackage")
+ ".StaticMain");
// Remove the extra Main method that we created in
// doing this.
SootMethod staticMainMethod =
staticMainClass.getMethodByName("main");
staticMainClass.removeMethod(staticMainMethod);
break;
}
}
*/
// for (Iterator methods = mainClass.getMethods().iterator(); methods
// .hasNext();) {
// SootMethod method = (SootMethod) methods.next();
//
// // System.out.println("method = " + method.toString());
// //SootMethod method2 = Scene.v().getMethod(method.toString());
// }
Scene.v().setActiveHierarchy(new Hierarchy());
Scene.v().setFastHierarchy(new FastHierarchy());
}