7c49c405c0062de85a352dc2e360bd9171d32879
[org.ibex.arenaj.git] / src / edu / berkeley / cs / megacz / Transformer.java
1 package edu.berkeley.cs.megacz;
2 import soot.*;
3 import soot.jimple.*;
4 import soot.util.*;
5 import java.io.*;
6 import java.util.*;
7
8 public class Transformer extends BodyTransformer {    
9
10     private static Transformer instance = new Transformer();
11     private Transformer() {}
12     public static Transformer v() { return instance; }
13
14     public static void main(String[] args)  {
15         if(args.length == 0) {
16             System.out.println("Syntax: java " + v().getClass().getName() + " [soot options]");
17             System.exit(0);
18         }
19         PackManager.v().getPack("jtp").add(new Transform("jtp.instrumenter", Transformer.v()));
20         // Just in case, resolve the PrintStream SootClass.
21         Scene.v().addBasicClass("java.io.PrintStream",SootClass.SIGNATURES);
22         soot.Main.main(args);
23     }
24
25     static int tfr = 0;
26     public static Local viaLocal(Value v, Body b, Unit u) {
27         Local l = Jimple.v().newLocal("tmpRef" + (tfr++), v.getType());
28         b.getLocals().add(l);
29         b.getUnits().insertBefore(Jimple.v().newAssignStmt(l, v), u);
30         return l;
31     }
32
33     HashMap map = new HashMap();
34     HashSet size_added = new HashSet();
35
36     public boolean isGladiator(SootClass c) { return c.implementsInterface("edu.berkeley.cs.megacz.Gladiator"); }
37     public boolean isGladiatorField(SootField f)
38         { return isGladiator(f.getDeclaringClass()) && !f.getName().equals("this") && f.getName().indexOf('$')==-1; }
39     public SootField getGladiatorField(SootField f) {
40         SootClass c  = f.getDeclaringClass();
41         SootClass oc = Scene.v().getSootClass(c.getName().substring(0, c.getName().lastIndexOf('$')));
42         if (map.get(f) != null) return (SootField)map.get(f);
43         SootField nf = new SootField(c.getShortName().substring(c.getShortName().lastIndexOf('$')+1) + "$" + f.getName(),
44                                      f.getType().makeArrayType(),
45                                      f.getModifiers());
46         oc.addField(nf);
47         Body body = oc.getMethod("<init>", new LinkedList()).getActiveBody();
48         Expr newArr = Jimple.v().newNewArrayExpr(f.getType(), IntConstant.v(1000));
49         Local newArrLocal = Jimple.v().newLocal("tmpRef" + (tfr++), f.getType().makeArrayType());
50         body.getLocals().add(newArrLocal);
51         InstanceFieldRef ifr = Jimple.v().newInstanceFieldRef(body.getThisLocal(), nf.makeRef());
52         body.getUnits().addFirst(Jimple.v().newAssignStmt(ifr, newArrLocal));
53         body.getUnits().addFirst(Jimple.v().newAssignStmt(newArrLocal, newArr));
54         map.put(f, nf);
55         return nf;
56     }
57
58     private Body body;
59     public SootFieldRef getGladiatorFieldSizeRef(SootClass c) {
60         SootClass mc = Scene.v().getMainClass();
61         String name = c.getShortName().substring(c.getShortName().lastIndexOf('$')+1) + "_size";
62         if (map.get(c) == null) {
63             SootField f = new SootField(name, IntType.v());
64             mc.addField(f);
65         Body body = mc.getMethod("<init>", new LinkedList()).getActiveBody();
66         InstanceFieldRef ifr = Jimple.v().newInstanceFieldRef(body.getThisLocal(), f.makeRef());
67         body.getUnits().addFirst(Jimple.v().newAssignStmt(ifr, IntConstant.v(0)));
68
69             map.put(c, f);
70         }
71         return Scene.v().makeFieldRef(mc, name, IntType.v(), false);
72     }
73
74     public boolean isGladiatorType(Type t) {
75         return (t instanceof RefType) && isGladiator(((RefType)t).getSootClass());
76     }
77
78     public SootMethodRef convert(SootMethodRef mr) {
79         List l = mr.parameterTypes();
80         List l2 = new LinkedList();
81         for(Iterator it2 = l.iterator(); it2.hasNext();) {
82             Type t = (Type)it2.next();
83             l2.add(isGladiatorType(t) ? IntType.v() : t);
84         }
85         return Scene.v().makeMethodRef(mr.declaringClass(),
86                                        mr.name(),
87                                        l2,
88                                        isGladiatorType(mr.returnType()) ? IntType.v() : mr.returnType(),
89                                        mr.isStatic());
90     }
91
92     boolean done = false;
93     public void internalTransform(Body bz, String phaseName, Map options) {
94         System.out.println("============= " + phaseName);
95         if (done) return;
96         done = true;
97         nuke(Scene.v().getSootClass("edu.berkeley.cs.megacz.Test$Inner"));
98         nuke(Scene.v().getSootClass("edu.berkeley.cs.megacz.Test"));
99     }
100     public void nuke(SootClass c) {
101         for(Iterator it = c.getFields().iterator(); it.hasNext();) {
102             SootField f = (SootField)it.next();
103             Type t = f.getType();
104             if (!(t instanceof RefType)) continue;
105             if (isGladiator(((RefType)t).getSootClass())) f.setType(IntType.v());
106         }
107
108         List list = new LinkedList(); list.addAll(c.getMethods());
109         for(Iterator it = list.iterator(); it.hasNext();) {
110             SootMethod m = (SootMethod)it.next();
111             if (m.hasActiveBody()) m.setActiveBody(fixBody(m.getActiveBody()));
112             if (m.getName().equals("<init>")) continue;
113             if (m.getName().equals("<clinit>")) continue;
114             //if (map.get(m) != null) continue;
115             //map.put(m, Boolean.TRUE);
116             System.out.println(m.getName() + " -- " + m.getActiveBody());
117             List l2 = new LinkedList();
118             List l = m.getParameterTypes();
119             for(Iterator it2 = l.iterator(); it2.hasNext();) {
120                 Type t = (Type)it2.next();
121                 //l2.add(t);
122                 l2.add(isGladiatorType(t) ? IntType.v() : t);
123                 //if (isGladiatorType(t)) System.out.println("ought to swap " + t);
124             }
125             Type t = m.getReturnType();
126             c.removeMethod(m);
127             SootMethod meth = new SootMethod(m.getName(), l2, isGladiatorType(t) ? IntType.v() : t, m.getModifiers());
128             meth.setActiveBody(m.getActiveBody());
129             c.addMethod(meth);
130         }
131
132     }
133
134     protected Body fixBody(Body body) {
135         this.body = body;
136         Chain units = body.getUnits();
137         Iterator stmtIt = units.snapshotIterator();
138         for(Iterator it = body.getLocals().snapshotIterator(); it.hasNext();) {
139             Local l = (Local)it.next();
140             if (isGladiatorType(l.getType())) l.setType(IntType.v());
141         }
142         while(stmtIt.hasNext()) {
143             Stmt s = (Stmt) stmtIt.next();
144             List l = s.getUseAndDefBoxes();
145             for(Iterator it = l.iterator(); it.hasNext();) {
146                 Object o = it.next();
147                 if (o instanceof ValueBox) {
148                     ValueBox vb = (ValueBox)o;
149                     Value v = vb.getValue();
150
151                     if (v instanceof InvokeExpr) {
152                         InvokeExpr ie = (InvokeExpr)v;
153                         SootMethodRef mr = ie.getMethodRef();
154                         if (isGladiator(mr.declaringClass())) {
155                             body.getUnits().remove(s);
156                             break;
157                         }
158                         ie.setMethodRef(convert(mr));
159
160                     } else if (v instanceof NewExpr) {
161                         NewExpr ne = (NewExpr)v;
162                         if (isGladiatorType(ne.getBaseType())) {
163                             System.out.println("******");
164                             SootClass mc = Scene.v().getMainClass();
165                             SootClass sc = ((RefType)ne.getBaseType()).getSootClass();
166                             System.out.println(sc);
167                             InstanceFieldRef sfr = Jimple.v().newInstanceFieldRef(body.getThisLocal(),
168                                                                                   getGladiatorFieldSizeRef(sc));
169                             Local ll = viaLocal(sfr, body, s);
170                             Local ll2 = Jimple.v().newLocal("tmpRef" + (tfr++), IntType.v());
171                             body.getLocals().add(ll2);
172                             Stmt stmt = Jimple.v().newAssignStmt(ll2, Jimple.v().newAddExpr(ll, IntConstant.v(1)));
173                             units.insertBefore(stmt, s);
174                             units.insertAfter(Jimple.v().newAssignStmt(sfr, ll2), stmt);
175                             vb.setValue(ll);
176                         }
177
178                     } else if (v instanceof InstanceFieldRef) {
179                         InstanceFieldRef ifr = (InstanceFieldRef)v;
180                         Type t = ifr.getType();
181                         if ((t instanceof RefType) && isGladiator(((RefType)t).getSootClass())) {
182                             SootClass tc = ((RefType)t).getSootClass();
183                             SootClass mc = Scene.v().getMainClass();
184                             SootFieldRef fr = Scene.v().makeFieldRef(mc, "z", IntType.v(), false);
185                             ifr.setFieldRef(fr);
186                         }
187                         SootField f = ifr.getField();
188                         if (isGladiatorField(f)) {
189                             f = getGladiatorField(f);
190                             SootClass mc = Scene.v().getMainClass();
191                             SootField sf = mc.getField(f.getName(), f.getType());
192                             InstanceFieldRef sfr = Jimple.v().newInstanceFieldRef(body.getThisLocal(), sf.makeRef());
193                             ArrayRef ar = Jimple.v().newArrayRef(viaLocal(sfr, body, s), ifr.getBase());
194                             vb.setValue(ar);
195                         }
196                     }
197                 }
198             }
199         }
200         return body;
201     }
202 }