0001: /* Soot - a J*va Optimization Framework
0002: * Copyright (C) 1997 Clark Verbrugge
0003: *
0004: * This library is free software; you can redistribute it and/or
0005: * modify it under the terms of the GNU Lesser General Public
0006: * License as published by the Free Software Foundation; either
0007: * version 2.1 of the License, or (at your option) any later version.
0008: *
0009: * This library is distributed in the hope that it will be useful,
0010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0012: * Lesser General Public License for more details.
0013: *
0014: * You should have received a copy of the GNU Lesser General Public
0015: * License along with this library; if not, write to the
0016: * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
0017: * Boston, MA 02111-1307, USA.
0018: */
0019:
0020: /*
0021: * Modified by the Sable Research Group and others 1997-1999.
0022: * See the 'credits' file distributed with Soot for the complete list of
0023: * contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot)
0024: */
0025:
0026: package soot.coffi;
0027:
0028: import soot.options.*;
0029:
0030: import java.util.*;
0031:
0032: import soot.*;
0033: import soot.jimple.*;
0034: import soot.util.*;
0035: import soot.tagkit.*;
0036:
0037: /** A Control Flow Graph.
0038: * @author Clark Verbrugge
0039: */
0040: public class CFG {
0041:
0042: /** Method for which this is a control flow graph.
0043: * @see method_info
0044: */
0045: private method_info method;
0046: /** Ordered list of BasicBlocks comprising the code of this CFG.
0047: */
0048: BasicBlock cfg;
0049:
0050: Chain units;
0051: JimpleBody listBody;
0052:
0053: Map<Instruction, Stmt> instructionToFirstStmt;
0054: Map<Instruction, Stmt> instructionToLastStmt;
0055: SootMethod jmethod;
0056: Scene cm;
0057:
0058: Instruction firstInstruction;
0059: Instruction lastInstruction;
0060:
0061: private Instruction sentinel;
0062: private Hashtable<Instruction, BasicBlock> h2bb, t2bb;
0063:
0064: /** Constructs a new control flow graph for the given method.
0065: * @param m the method in question.
0066: * @see method_info
0067: */
0068: public CFG(method_info m) {
0069: this .method = m;
0070:
0071: this .sentinel = new Instruction_Nop();
0072: this .sentinel.next = m.instructions;
0073: m.instructions.prev = this .sentinel;
0074:
0075: // printInstructions();
0076: // printExceptionTable();
0077:
0078: eliminateJsrRets();
0079:
0080: // printInstructions();
0081: // printExceptionTable();
0082:
0083: buildBBCFG();
0084:
0085: // printBBs();
0086: // printBBCFGSucc();
0087:
0088: cfg.beginCode = true;
0089:
0090: m.cfg = this ;
0091:
0092: if (cfg != null)
0093: firstInstruction = cfg.head;
0094: else
0095: firstInstruction = null;
0096:
0097: // calculate complexity metrics
0098: if (soot.jbco.Main.metrics)
0099: complexity();
0100:
0101: /*
0102: if (m.code_attr != null)
0103: {
0104: for (int i=0; i<m.code_attr.attributes.length; i++)
0105: {
0106: if (m.code_attr.attributes[i]
0107: instanceof LineNumberTable_attribute)
0108: {
0109: G.v().out.print(m.code_attr.attributes[i]);
0110: }
0111: }
0112: }
0113: */
0114: }
0115:
0116: public static HashMap<SootMethod, int[]> methodsToVEM = new HashMap<SootMethod, int[]>();
0117:
0118: private void complexity() {
0119: // ignore all non-app classes
0120: if (!method.jmethod.getDeclaringClass().isApplicationClass())
0121: return;
0122:
0123: BasicBlock b = this .cfg;
0124: HashMap<BasicBlock, Integer> block2exc = new HashMap<BasicBlock, Integer>();
0125: int tmp, nodes = 0, edges = 0, highest = 0;
0126:
0127: while (b != null) {
0128: tmp = 0;
0129: for (exception_table_entry element : method.code_attr.exception_table) {
0130: Instruction start = element.start_inst;
0131: Instruction end = element.start_inst;
0132: if ((start.label >= b.head.label && start.label <= b.tail.label)
0133: || (end.label > b.head.label && (b.tail.next == null || end.label <= b.tail.next.label)))
0134: tmp++;
0135: }
0136: block2exc.put(b, new Integer(tmp));
0137: b = b.next;
0138: }
0139:
0140: b = this .cfg;
0141: while (b != null) {
0142: nodes++;
0143: tmp = b.succ.size() + block2exc.get(b).intValue();
0144:
0145: // exceptions are not counted in succs and preds so we need to do so manually
0146: int deg = b.pred.size() + tmp + (b.beginException ? 1 : 0);
0147: if (deg > highest)
0148: highest = deg;
0149: edges += tmp;
0150: b = b.next;
0151: }
0152: methodsToVEM.put(method.jmethod, new int[] { nodes, edges,
0153: highest });
0154: }
0155:
0156: // Constructs the actual control flow graph. Assumes the hash table
0157: // currently associates leaders with BasicBlocks, this function
0158: // builds the next[] and prev[] pointer arrays.
0159: private void buildBBCFG() {
0160: Object branches[];
0161: Code_attribute ca = method.locate_code_attribute();
0162:
0163: {
0164: h2bb = new Hashtable<Instruction, BasicBlock>(100, 25);
0165: t2bb = new Hashtable<Instruction, BasicBlock>(100, 25);
0166:
0167: Instruction insn = this .sentinel.next;
0168: BasicBlock blast = null;
0169: if (insn != null) {
0170: Instruction tail = buildBasicBlock(insn);
0171: cfg = new BasicBlock(insn, tail);
0172: h2bb.put(insn, cfg);
0173: t2bb.put(tail, cfg);
0174: insn = tail.next;
0175: blast = cfg;
0176: }
0177:
0178: while (insn != null) {
0179: Instruction tail = buildBasicBlock(insn);
0180: BasicBlock block = new BasicBlock(insn, tail);
0181: blast.next = block;
0182: blast = block;
0183: h2bb.put(insn, block);
0184: t2bb.put(tail, block);
0185: insn = tail.next;
0186: }
0187: }
0188:
0189: BasicBlock block = cfg;
0190:
0191: while (block != null) {
0192: Instruction insn = block.tail;
0193:
0194: if (insn.branches) {
0195: if (insn instanceof Instruction_Athrow) {
0196: // see how many targets it can reach. Note that this is a
0197: // subset of the exception_table.
0198: HashSet<Instruction> ethandlers = new HashSet<Instruction>();
0199:
0200: // not quite a subset---could also be that control
0201: // exits this method, so start icount at 1
0202: for (int i = 0; i < ca.exception_table_length; i++) {
0203: exception_table_entry etentry = ca.exception_table[i];
0204:
0205: if (insn.label >= etentry.start_inst.label
0206: && (etentry.end_inst == null || insn.label < etentry.end_inst.label)) {
0207: ethandlers.add(etentry.handler_inst);
0208: }
0209: }
0210:
0211: branches = ethandlers.toArray();
0212: } else {
0213: branches = insn.branchpoints(insn.next);
0214: }
0215:
0216: if (branches != null) {
0217: block.succ.ensureCapacity(block.succ.size()
0218: + branches.length);
0219:
0220: for (Object element : branches) {
0221: if (element != null) {
0222: BasicBlock bb = h2bb.get(element);
0223:
0224: if (bb == null) {
0225: G.v().out.println("Warning: "
0226: + "target of a branch is null");
0227: G.v().out.println(insn);
0228: } else {
0229: block.succ.addElement(bb);
0230: bb.pred.addElement(block);
0231: }
0232: }
0233: }
0234: }
0235: } else if (block.next != null) { // BB ended not with a branch, so just go to next
0236: block.succ.addElement(block.next);
0237: block.next.pred.addElement(block);
0238: }
0239: block = block.next;
0240: }
0241:
0242: // One final step, run through exception handlers and mark which
0243: // basic blocks begin their code
0244: for (int i = 0; i < ca.exception_table_length; i++) {
0245: BasicBlock bb = h2bb
0246: .get(ca.exception_table[i].handler_inst);
0247: if (bb == null) {
0248: G.v().out.println("Warning: No basic block found for"
0249: + " start of exception handler code.");
0250: } else {
0251: bb.beginException = true;
0252: ca.exception_table[i].b = bb;
0253: }
0254: }
0255: }
0256:
0257: /* given the list of instructions head, this pulls off the front
0258: * basic block, terminates it with a null, and returns the next
0259: * instruction after.
0260: */
0261: private static Instruction buildBasicBlock(Instruction head) {
0262: Instruction insn, next;
0263: insn = head;
0264: next = insn.next;
0265:
0266: if (next == null)
0267: return insn;
0268:
0269: do {
0270: if (insn.branches || next.labelled)
0271: break;
0272: else {
0273: insn = next;
0274: next = insn.next;
0275: }
0276: } while (next != null);
0277:
0278: return insn;
0279: }
0280:
0281: /* We only handle simple cases. */
0282: Map<Instruction, Instruction> jsr2astore = new HashMap<Instruction, Instruction>();
0283: Map<Instruction, Instruction> astore2ret = new HashMap<Instruction, Instruction>();
0284:
0285: LinkedList<Instruction> jsrorder = new LinkedList<Instruction>();
0286:
0287: /* Eliminate subroutines ( JSR/RET instructions ) by inlining the
0288: routine bodies. */
0289: private boolean eliminateJsrRets() {
0290: Instruction insn = this .sentinel;
0291:
0292: // find the last instruction, for copying blocks.
0293: while (insn.next != null) {
0294: insn = insn.next;
0295: }
0296: this .lastInstruction = insn;
0297:
0298: HashMap<Instruction, Instruction> todoBlocks = new HashMap<Instruction, Instruction>();
0299: todoBlocks.put(this .sentinel.next, this .lastInstruction);
0300: LinkedList<Instruction> todoList = new LinkedList<Instruction>();
0301: todoList.add(this .sentinel.next);
0302:
0303: while (!todoList.isEmpty()) {
0304: Instruction firstInsn = todoList.removeFirst();
0305: Instruction lastInsn = todoBlocks.get(firstInsn);
0306:
0307: jsrorder.clear();
0308: jsr2astore.clear();
0309: astore2ret.clear();
0310:
0311: if (findOutmostJsrs(firstInsn, lastInsn)) {
0312: HashMap<Instruction, Instruction> newblocks = inliningJsrTargets();
0313: todoBlocks.putAll(newblocks);
0314: todoList.addAll(newblocks.keySet());
0315: }
0316: }
0317:
0318: /* patch exception table and others.*/
0319: {
0320: method.instructions = this .sentinel.next;
0321:
0322: adjustExceptionTable();
0323: adjustLineNumberTable();
0324: adjustBranchTargets();
0325: }
0326:
0327: // we should prune the code and exception table here.
0328: // remove any exception handler whose region is in a jsr/ret block.
0329: // pruneExceptionTable();
0330:
0331: return true;
0332: }
0333:
0334: // find outmost jsr/ret pairs in a code area, all information is
0335: // saved in jsr2astore, and astore2ret
0336: // start : start instruction, inclusively.
0337: // end : the last instruction, inclusively.
0338: // return the last instruction encounted ( before end )
0339: // the caller cleans jsr2astore, astore2ret
0340: private boolean findOutmostJsrs(Instruction start, Instruction end) {
0341: // use to put innerJsrs.
0342: HashSet<Instruction> innerJsrs = new HashSet<Instruction>();
0343: boolean unusual = false;
0344:
0345: Instruction insn = start;
0346: do {
0347: if (insn instanceof Instruction_Jsr
0348: || insn instanceof Instruction_Jsr_w) {
0349: if (innerJsrs.contains(insn)) {
0350: // skip it
0351: insn = insn.next;
0352: continue;
0353: }
0354:
0355: Instruction astore = ((Instruction_branch) insn).target;
0356: if (!(astore instanceof Interface_Astore)) {
0357: unusual = true;
0358: break;
0359: }
0360:
0361: Instruction ret = findMatchingRet(astore, insn,
0362: innerJsrs);
0363:
0364: /*
0365: if (ret == null)
0366: {
0367: unusual = true;
0368: break;
0369: }
0370: */
0371:
0372: jsrorder.addLast(insn);
0373: jsr2astore.put(insn, astore);
0374: astore2ret.put(astore, ret);
0375: }
0376:
0377: insn = insn.next;
0378:
0379: } while (insn != end.next);
0380:
0381: if (unusual) {
0382: G.v().out.println("Sorry, I cannot handle this method.");
0383: return false;
0384: }
0385:
0386: return true;
0387: }
0388:
0389: private Instruction findMatchingRet(Instruction astore,
0390: Instruction jsr, HashSet<Instruction> innerJsrs) {
0391: int astorenum = ((Interface_Astore) astore).getLocalNumber();
0392:
0393: Instruction insn = astore.next;
0394: while (insn != null) {
0395: if (insn instanceof Instruction_Ret
0396: || insn instanceof Instruction_Ret_w) {
0397: int retnum = ((Interface_OneIntArg) insn).getIntArg();
0398: if (astorenum == retnum)
0399: return insn;
0400: } else
0401: /* adjust the jsr inlining order. */
0402: if (insn instanceof Instruction_Jsr
0403: || insn instanceof Instruction_Jsr_w) {
0404: innerJsrs.add(insn);
0405: }
0406:
0407: insn = insn.next;
0408: }
0409:
0410: return null;
0411: }
0412:
0413: // make copies of jsr/ret blocks
0414: // return new blocks
0415: private HashMap<Instruction, Instruction> inliningJsrTargets() {
0416: /*
0417: for (int i=0, n=jsrorder.size(); i<n; i++) {
0418: Instruction jsr = (Instruction)jsrorder.get(i);
0419: Instruction astore = (Instruction)jsr2astore.get(jsr);
0420: Instruction ret = (Instruction)astore2ret.get(astore);
0421: G.v().out.println("jsr"+jsr.label+"\t"
0422: +"as"+astore.label+"\t"
0423: +"ret"+ret.label);
0424: }
0425: */
0426: HashMap<Instruction, Instruction> newblocks = new HashMap<Instruction, Instruction>();
0427:
0428: while (!jsrorder.isEmpty()) {
0429: Instruction jsr = jsrorder.removeFirst();
0430: Instruction astore = jsr2astore.get(jsr);
0431:
0432: Instruction ret = astore2ret.get(astore);
0433:
0434: // make a copy of the code, append to the last instruction.
0435: Instruction newhead = makeCopyOf(astore, ret, jsr.next);
0436:
0437: // jsr is replaced by goto newhead
0438: // astore has been removed
0439: // ret is replaced by goto jsr.next
0440: Instruction_Goto togo = new Instruction_Goto();
0441: togo.target = newhead;
0442: newhead.labelled = true;
0443: togo.label = jsr.label;
0444: togo.labelled = jsr.labelled;
0445: togo.prev = jsr.prev;
0446: togo.next = jsr.next;
0447: togo.prev.next = togo;
0448: togo.next.prev = togo;
0449:
0450: replacedInsns.put(jsr, togo);
0451:
0452: // just quick hack
0453: if (ret != null) {
0454: newblocks.put(newhead, this .lastInstruction);
0455: }
0456: }
0457:
0458: return newblocks;
0459: }
0460:
0461: /* make a copy of code between from and to exclusively,
0462: * fixup targets of branch instructions in the code.
0463: */
0464: private Instruction makeCopyOf(Instruction astore, Instruction ret,
0465: Instruction target) {
0466: // do a quick hacker for ret == null
0467: if (ret == null) {
0468: return astore.next;
0469: }
0470:
0471: Instruction last = this .lastInstruction;
0472: Instruction headbefore = last;
0473:
0474: int curlabel = this .lastInstruction.label;
0475:
0476: // mapping from original instructions to new instructions.
0477: HashMap<Instruction, Instruction> insnmap = new HashMap<Instruction, Instruction>();
0478: Instruction insn = astore.next;
0479:
0480: while (insn != ret && insn != null) {
0481: try {
0482: Instruction newone = (Instruction) insn.clone();
0483:
0484: newone.label = ++curlabel;
0485: newone.prev = last;
0486: last.next = newone;
0487: last = newone;
0488:
0489: insnmap.put(insn, newone);
0490: } catch (CloneNotSupportedException e) {
0491: G.v().out.println("Error !");
0492: }
0493: insn = insn.next;
0494: }
0495:
0496: // replace ret by a goto
0497: Instruction_Goto togo = new Instruction_Goto();
0498: togo.target = target;
0499: target.labelled = true;
0500: togo.label = ++curlabel;
0501: last.next = togo;
0502: togo.prev = last;
0503: last = togo;
0504:
0505: this .lastInstruction = last;
0506:
0507: // The ret instruction is removed,
0508: insnmap.put(astore, headbefore.next);
0509: insnmap.put(ret, togo);
0510:
0511: // fixup targets in new instruction (only in the scope of
0512: // new instructions).
0513: // do not forget set target labelled as TRUE
0514: insn = headbefore.next;
0515: while (insn != last) {
0516: if (insn instanceof Instruction_branch) {
0517: Instruction oldtgt = ((Instruction_branch) insn).target;
0518: Instruction newtgt = insnmap.get(oldtgt);
0519: if (newtgt != null) {
0520: ((Instruction_branch) insn).target = newtgt;
0521: newtgt.labelled = true;
0522: }
0523: } else if (insn instanceof Instruction_Lookupswitch) {
0524: Instruction_Lookupswitch switchinsn = (Instruction_Lookupswitch) insn;
0525:
0526: Instruction newdefault = insnmap
0527: .get(switchinsn.default_inst);
0528: if (newdefault != null) {
0529: switchinsn.default_inst = newdefault;
0530: newdefault.labelled = true;
0531: }
0532:
0533: for (int i = 0; i < switchinsn.match_insts.length; i++) {
0534: Instruction newtgt = insnmap
0535: .get(switchinsn.match_insts[i]);
0536: if (newtgt != null) {
0537: switchinsn.match_insts[i] = newtgt;
0538: newtgt.labelled = true;
0539: }
0540: }
0541: } else if (insn instanceof Instruction_Tableswitch) {
0542: Instruction_Tableswitch switchinsn = (Instruction_Tableswitch) insn;
0543:
0544: Instruction newdefault = insnmap
0545: .get(switchinsn.default_inst);
0546: if (newdefault != null) {
0547: switchinsn.default_inst = newdefault;
0548: newdefault.labelled = true;
0549: }
0550:
0551: for (int i = 0; i < switchinsn.jump_insts.length; i++) {
0552: Instruction newtgt = insnmap
0553: .get(switchinsn.jump_insts[i]);
0554: if (newtgt != null) {
0555: switchinsn.jump_insts[i] = newtgt;
0556: newtgt.labelled = true;
0557: }
0558: }
0559: }
0560:
0561: insn = insn.next;
0562: }
0563:
0564: // do we need to copy a new exception table entry?
0565: // new exception table has new exception range,
0566: // and the new exception handler.
0567: {
0568: Code_attribute ca = method.locate_code_attribute();
0569:
0570: LinkedList<exception_table_entry> newentries = new LinkedList<exception_table_entry>();
0571:
0572: int orig_start_of_subr = astore.next.originalIndex; // inclusive
0573: int orig_end_of_subr = ret.originalIndex; // again, inclusive
0574:
0575: for (int i = 0; i < ca.exception_table_length; i++) {
0576: exception_table_entry etentry = ca.exception_table[i];
0577:
0578: int orig_start_of_trap = etentry.start_pc; // inclusive
0579: int orig_end_of_trap = etentry.end_pc; // exclusive
0580: if (orig_start_of_trap < orig_end_of_subr
0581: && orig_end_of_trap > orig_start_of_subr) {
0582: // At least a portion of the cloned subroutine is trapped.
0583: exception_table_entry newone = new exception_table_entry();
0584: if (orig_start_of_trap <= orig_start_of_subr) {
0585: newone.start_inst = headbefore.next;
0586: } else {
0587: newone.start_inst = insnmap
0588: .get(etentry.start_inst);
0589: }
0590: if (orig_end_of_trap > orig_end_of_subr) {
0591: newone.end_inst = null; // Representing the insn after
0592: // the last instruction in the
0593: // subr; we need to fix it if
0594: // we inline another subr.
0595: } else {
0596: newone.end_inst = insnmap.get(etentry.end_inst);
0597: }
0598:
0599: newone.handler_inst = insnmap
0600: .get(etentry.handler_inst);
0601: if (newone.handler_inst == null)
0602: newone.handler_inst = etentry.handler_inst;
0603:
0604: // We can leave newone.start_pc == 0 and newone.end_pc == 0.
0605: // since that cannot overlap the range of any other
0606: // subroutines that get inlined later.
0607:
0608: newentries.add(newone);
0609: }
0610: // Finally, fix up the old entry if its protected area
0611: // ran to the end of the method we have just lengthened:
0612: // patch its end marker to be the first
0613: // instruction in the subroutine we've just inlined.
0614: if (etentry.end_inst == null) {
0615: etentry.end_inst = headbefore.next;
0616: }
0617: }
0618:
0619: if (newentries.size() > 0) {
0620: ca.exception_table_length += newentries.size();
0621: exception_table_entry[] newtable = new exception_table_entry[ca.exception_table_length];
0622: System.arraycopy(ca.exception_table, 0, newtable, 0,
0623: ca.exception_table.length);
0624: for (int i = 0, j = ca.exception_table.length; i < newentries
0625: .size(); i++, j++) {
0626: newtable[j] = newentries.get(i);
0627: }
0628:
0629: ca.exception_table = newtable;
0630: }
0631: }
0632:
0633: return headbefore.next;
0634: }
0635:
0636: /* if a jsr/astore/ret is replaced by some other instruction, it will be put on this table. */
0637: private final Hashtable<Instruction, Instruction_Goto> replacedInsns = new Hashtable<Instruction, Instruction_Goto>();
0638:
0639: /* do not forget set the target labelled as TRUE.*/
0640: private void adjustBranchTargets() {
0641: Instruction insn = this .sentinel.next;
0642: while (insn != null) {
0643: if (insn instanceof Instruction_branch) {
0644: Instruction_branch binsn = (Instruction_branch) insn;
0645: Instruction newtgt = replacedInsns.get(binsn.target);
0646: if (newtgt != null) {
0647: binsn.target = newtgt;
0648: newtgt.labelled = true;
0649: }
0650: } else if (insn instanceof Instruction_Lookupswitch) {
0651: Instruction_Lookupswitch switchinsn = (Instruction_Lookupswitch) insn;
0652:
0653: Instruction newdefault = replacedInsns
0654: .get(switchinsn.default_inst);
0655: if (newdefault != null) {
0656: switchinsn.default_inst = newdefault;
0657: newdefault.labelled = true;
0658: }
0659:
0660: for (int i = 0; i < switchinsn.npairs; i++) {
0661: Instruction newtgt = replacedInsns
0662: .get(switchinsn.match_insts[i]);
0663: if (newtgt != null) {
0664: switchinsn.match_insts[i] = newtgt;
0665: newtgt.labelled = true;
0666: }
0667: }
0668: } else if (insn instanceof Instruction_Tableswitch) {
0669: Instruction_Tableswitch switchinsn = (Instruction_Tableswitch) insn;
0670:
0671: Instruction newdefault = replacedInsns
0672: .get(switchinsn.default_inst);
0673: if (newdefault != null) {
0674: switchinsn.default_inst = newdefault;
0675: newdefault.labelled = true;
0676: }
0677:
0678: for (int i = 0; i <= switchinsn.high - switchinsn.low; i++) {
0679: Instruction newtgt = replacedInsns
0680: .get(switchinsn.jump_insts[i]);
0681: if (newtgt != null) {
0682: switchinsn.jump_insts[i] = newtgt;
0683: newtgt.labelled = true;
0684: }
0685: }
0686: }
0687:
0688: insn = insn.next;
0689: }
0690: }
0691:
0692: private void adjustExceptionTable() {
0693: Code_attribute codeAttribute = method.locate_code_attribute();
0694:
0695: for (int i = 0; i < codeAttribute.exception_table_length; i++) {
0696: exception_table_entry entry = codeAttribute.exception_table[i];
0697:
0698: Instruction oldinsn = entry.start_inst;
0699: Instruction newinsn = replacedInsns.get(oldinsn);
0700: if (newinsn != null)
0701: entry.start_inst = newinsn;
0702:
0703: oldinsn = entry.end_inst;
0704: if (entry.end_inst != null) {
0705: newinsn = replacedInsns.get(oldinsn);
0706: if (newinsn != null)
0707: entry.end_inst = newinsn;
0708: }
0709:
0710: oldinsn = entry.handler_inst;
0711: newinsn = replacedInsns.get(oldinsn);
0712: if (newinsn != null)
0713: entry.handler_inst = newinsn;
0714: }
0715: }
0716:
0717: private void adjustLineNumberTable() {
0718: if (!Options.v().keep_line_number())
0719: return;
0720: if (method.code_attr == null)
0721: return;
0722:
0723: attribute_info[] attributes = method.code_attr.attributes;
0724:
0725: for (attribute_info element : attributes) {
0726: if (element instanceof LineNumberTable_attribute) {
0727: LineNumberTable_attribute lntattr = (LineNumberTable_attribute) element;
0728: for (line_number_table_entry element0 : lntattr.line_number_table) {
0729: Instruction oldinst = element0.start_inst;
0730: Instruction newinst = replacedInsns.get(oldinst);
0731: if (newinst != null)
0732: element0.start_inst = newinst;
0733: }
0734: }
0735: }
0736: }
0737:
0738: /** Reconstructs the instruction stream by appending the Instruction
0739: * lists associated with each basic block.
0740: * <p>
0741: * Note that this joins up the basic block Instruction lists, and so
0742: * they will no longer end with <i>null</i> after this.
0743: * @return the head of the list of instructions.
0744: */
0745: public Instruction reconstructInstructions() {
0746: if (cfg != null)
0747: return cfg.head;
0748: else
0749: return null;
0750: }
0751:
0752: /** Main.v() entry point for converting list of Instructions to Jimple statements;
0753: * performs flow analysis, constructs Jimple statements, and fixes jumps.
0754: * @param constant_pool constant pool of ClassFile.
0755: * @param this_class constant pool index of the CONSTANT_Class_info object for
0756: * this' class.
0757: * @return <i>true</i> if all ok, <i>false</i> if there was an error.
0758: * @see Stmt
0759: */
0760: public boolean jimplify(cp_info constant_pool[], int this _class,
0761: JimpleBody listBody) {
0762: Util.v().setClassNameToAbbreviation(new HashMap());
0763:
0764: Chain units = listBody.getUnits();
0765:
0766: this .listBody = listBody;
0767: this .units = units;
0768: instructionToFirstStmt = new HashMap<Instruction, Stmt>();
0769: instructionToLastStmt = new HashMap<Instruction, Stmt>();
0770:
0771: jmethod = listBody.getMethod();
0772: cm = Scene.v();
0773:
0774: //TypeArray.setClassManager(cm);
0775: //TypeStack.setClassManager(cm);
0776:
0777: Set initialLocals = new ArraySet();
0778:
0779: List parameterTypes = jmethod.getParameterTypes();
0780:
0781: // Initialize nameToLocal which is an index*Type->Local map, which is used
0782: // to determine local in bytecode references.
0783: {
0784: Code_attribute ca = method.locate_code_attribute();
0785: LocalVariableTable_attribute la = ca
0786: .findLocalVariableTable();
0787: LocalVariableTypeTable_attribute lt = ca
0788: .findLocalVariableTypeTable();
0789:
0790: Util.v().activeVariableTable = la;
0791: Util.v().activeVariableTypeTable = lt;
0792:
0793: Util.v().activeConstantPool = constant_pool;
0794:
0795: Type this Type = RefType.v(jmethod.getDeclaringClass()
0796: .getName());
0797: boolean isStatic = Modifier
0798: .isStatic(jmethod.getModifiers());
0799:
0800: int currentLocalIndex = 0;
0801:
0802: // Initialize the 'this' variable
0803: {
0804: if (!isStatic) {
0805: String name;
0806:
0807: if (!Util.v().useFaithfulNaming || la == null)
0808: name = "l0";
0809: else {
0810: name = la.getLocalVariableName(constant_pool,
0811: currentLocalIndex);
0812: if (!Util.v().isValidJimpleName(name))
0813: name = "l0";
0814: }
0815:
0816: Local local = Jimple.v().newLocal(name,
0817: UnknownType.v());
0818:
0819: listBody.getLocals().add(local);
0820:
0821: currentLocalIndex++;
0822:
0823: units.add(Jimple.v().newIdentityStmt(
0824: local,
0825: Jimple.v().newThisRef(
0826: jmethod.getDeclaringClass()
0827: .getType())));
0828: }
0829: }
0830:
0831: // Initialize parameters
0832: {
0833: Iterator typeIt = parameterTypes.iterator();
0834: int argCount = 0;
0835:
0836: while (typeIt.hasNext()) {
0837: String name;
0838: Type type = (Type) typeIt.next();
0839:
0840: if (!Util.v().useFaithfulNaming || la == null)
0841: name = "l" + currentLocalIndex;
0842: else {
0843: name = la.getLocalVariableName(constant_pool,
0844: currentLocalIndex);
0845: if (!Util.v().isValidJimpleName(name))
0846: name = "l" + currentLocalIndex;
0847: }
0848:
0849: Local local = Jimple.v().newLocal(name,
0850: UnknownType.v());
0851: initialLocals.add(local);
0852: listBody.getLocals().add(local);
0853:
0854: units
0855: .add(Jimple.v().newIdentityStmt(
0856: local,
0857: Jimple.v().newParameterRef(type,
0858: argCount)));
0859:
0860: if (type.equals(DoubleType.v())
0861: || type.equals(LongType.v())) {
0862: currentLocalIndex += 2;
0863: } else {
0864: currentLocalIndex += 1;
0865: }
0866:
0867: argCount++;
0868: }
0869: }
0870:
0871: Util.v().resetEasyNames();
0872: }
0873:
0874: jimplify(constant_pool, this _class);
0875:
0876: return true;
0877: }
0878:
0879: private void buildInsnCFGfromBBCFG() {
0880: BasicBlock block = cfg;
0881:
0882: while (block != null) {
0883: Instruction insn = block.head;
0884: while (insn != block.tail) {
0885: Instruction[] succs = new Instruction[1];
0886: succs[0] = insn.next;
0887: insn.succs = succs;
0888: insn = insn.next;
0889: }
0890:
0891: {
0892: // The successors are the ones from the basic block.
0893: Vector<BasicBlock> bsucc = block.succ;
0894: int size = bsucc.size();
0895: Instruction[] succs = new Instruction[size];
0896:
0897: for (int i = 0; i < size; i++)
0898: succs[i] = bsucc.elementAt(i).head;
0899: insn.succs = succs;
0900: }
0901:
0902: block = block.next;
0903: }
0904: }
0905:
0906: /** Main.v() entry point for converting list of Instructions to Jimple statements;
0907: * performs flow analysis, constructs Jimple statements, and fixes jumps.
0908: * @param constant_pool constant pool of ClassFile.
0909: * @param this_class constant pool index of the CONSTANT_Class_info object for
0910: * this' class.
0911: * @param clearStacks if <i>true</i> semantic stacks will be deleted after
0912: * the process is complete.
0913: * @return <i>true</i> if all ok, <i>false</i> if there was an error.
0914: * @see CFG#jimplify(cp_info[], int)
0915: * @see Stmt
0916: */
0917: void jimplify(cp_info constant_pool[], int this _class) {
0918: Code_attribute codeAttribute = method.locate_code_attribute();
0919: Set<Instruction> handlerInstructions = new ArraySet();
0920:
0921: Map<Instruction, SootClass> handlerInstructionToException = new HashMap<Instruction, SootClass>();
0922: Map<Instruction, TypeStack> instructionToTypeStack;
0923: Map<Instruction, TypeStack> instructionToPostTypeStack;
0924:
0925: {
0926: // build graph in
0927: buildInsnCFGfromBBCFG();
0928:
0929: // Put in successors due to exception handlers
0930: {
0931: for (int i = 0; i < codeAttribute.exception_table_length; i++) {
0932: Instruction startIns = codeAttribute.exception_table[i].start_inst;
0933: Instruction endIns = codeAttribute.exception_table[i].end_inst;
0934: Instruction handlerIns = codeAttribute.exception_table[i].handler_inst;
0935:
0936: handlerInstructions.add(handlerIns);
0937:
0938: // Determine exception to catch
0939: {
0940: int catchType = codeAttribute.exception_table[i].catch_type;
0941:
0942: SootClass exception;
0943:
0944: if (catchType != 0) {
0945: CONSTANT_Class_info classinfo = (CONSTANT_Class_info) constant_pool[catchType];
0946:
0947: String name = ((CONSTANT_Utf8_info) (constant_pool[classinfo.name_index]))
0948: .convert();
0949: name = name.replace('/', '.');
0950:
0951: exception = cm.getSootClass(name);
0952: } else
0953: exception = cm
0954: .getSootClass("java.lang.Throwable");
0955:
0956: handlerInstructionToException.put(handlerIns,
0957: exception);
0958: }
0959:
0960: if (startIns == endIns)
0961: throw new RuntimeException(
0962: "Empty catch range for exception handler");
0963:
0964: Instruction ins = startIns;
0965:
0966: for (;;) {
0967: Instruction[] succs = ins.succs;
0968: Instruction[] newsuccs = new Instruction[succs.length + 1];
0969:
0970: System.arraycopy(succs, 0, newsuccs, 0,
0971: succs.length);
0972:
0973: newsuccs[succs.length] = handlerIns;
0974: ins.succs = newsuccs;
0975:
0976: ins = ins.next;
0977: if (ins == endIns || ins == null)
0978: break;
0979: }
0980: }
0981: }
0982: }
0983:
0984: Set<Instruction> reachableInstructions = new HashSet<Instruction>();
0985:
0986: // Mark all the reachable instructions
0987: {
0988: LinkedList<Instruction> instructionsToVisit = new LinkedList<Instruction>();
0989:
0990: reachableInstructions.add(firstInstruction);
0991: instructionsToVisit.addLast(firstInstruction);
0992:
0993: while (!instructionsToVisit.isEmpty()) {
0994: Instruction ins = instructionsToVisit.removeFirst();
0995:
0996: Instruction[] succs = ins.succs;
0997:
0998: for (Instruction succ : succs) {
0999: if (!reachableInstructions.contains(succ)) {
1000: reachableInstructions.add(succ);
1001: instructionsToVisit.addLast(succ);
1002: }
1003: }
1004: }
1005: }
1006:
1007: /*
1008: // Check to see if any instruction is unmarked.
1009: {
1010: BasicBlock b = cfg;
1011:
1012: while(b != null)
1013: {
1014: Instruction ins = b.head;
1015:
1016: while(ins != null)
1017: {
1018: if(!reachableInstructions.contains(ins))
1019: throw new RuntimeException("Method to jimplify contains unreachable code! (not handled for now)");
1020:
1021: ins = ins.next;
1022: }
1023:
1024: b = b.next;
1025: }
1026: }
1027: */
1028:
1029: // Perform the flow analysis, and build up instructionToTypeStack and instructionToLocalArray
1030: {
1031: instructionToTypeStack = new HashMap<Instruction, TypeStack>();
1032: instructionToPostTypeStack = new HashMap<Instruction, TypeStack>();
1033:
1034: Set<Instruction> visitedInstructions = new HashSet<Instruction>();
1035: List<Instruction> changedInstructions = new ArrayList<Instruction>();
1036:
1037: TypeStack initialTypeStack;
1038:
1039: // Build up initial type stack and initial local array (for the first instruction)
1040: {
1041: initialTypeStack = TypeStack.v();
1042: // the empty stack with nothing on it.
1043: }
1044:
1045: // Get the loop cranked up.
1046: {
1047: instructionToTypeStack.put(firstInstruction,
1048: initialTypeStack);
1049:
1050: visitedInstructions.add(firstInstruction);
1051: changedInstructions.add(firstInstruction);
1052: }
1053:
1054: {
1055: while (!changedInstructions.isEmpty()) {
1056: Instruction ins = changedInstructions.get(0);
1057:
1058: changedInstructions.remove(0);
1059:
1060: OutFlow ret = processFlow(ins,
1061: instructionToTypeStack.get(ins),
1062: constant_pool);
1063:
1064: instructionToPostTypeStack.put(ins, ret.typeStack);
1065:
1066: Instruction[] successors = ins.succs;
1067:
1068: for (Instruction s : successors) {
1069: if (!visitedInstructions.contains(s)) {
1070: // Special case for the first time visiting.
1071:
1072: if (handlerInstructions.contains(s)) {
1073: TypeStack exceptionTypeStack = (TypeStack
1074: .v())
1075: .push(RefType
1076: .v(handlerInstructionToException
1077: .get(s)
1078: .getName()));
1079:
1080: instructionToTypeStack.put(s,
1081: exceptionTypeStack);
1082: } else {
1083: instructionToTypeStack.put(s,
1084: ret.typeStack);
1085: }
1086:
1087: visitedInstructions.add(s);
1088: changedInstructions.add(s);
1089:
1090: // G.v().out.println("adding successor: " + s);
1091: } else {
1092: // G.v().out.println("considering successor: " + s);
1093:
1094: TypeStack newTypeStack, oldTypeStack = instructionToTypeStack
1095: .get(s);
1096:
1097: if (handlerInstructions.contains(s)) {
1098: // The type stack for an instruction handler should always be that of
1099: // single object on the stack.
1100:
1101: TypeStack exceptionTypeStack = (TypeStack
1102: .v())
1103: .push(RefType
1104: .v(handlerInstructionToException
1105: .get(s)
1106: .getName()));
1107:
1108: newTypeStack = exceptionTypeStack;
1109: } else {
1110: try {
1111: newTypeStack = ret.typeStack
1112: .merge(oldTypeStack);
1113: } catch (RuntimeException re) {
1114: G.v().out.println("Considering "
1115: + s);
1116: throw re;
1117: }
1118: }
1119: if (!newTypeStack.equals(oldTypeStack)) {
1120: changedInstructions.add(s);
1121: // G.v().out.println("requires a revisit: " + s);
1122: }
1123:
1124: instructionToTypeStack.put(s, newTypeStack);
1125: }
1126: }
1127: }
1128: }
1129: }
1130:
1131: // Print out instructions + their localArray + typeStack
1132: {
1133: Instruction ins = firstInstruction;
1134:
1135: // G.v().out.println();
1136:
1137: while (ins != null) {
1138: TypeStack typeStack = instructionToTypeStack.get(ins);
1139: // TypeArray typeArray = (TypeArray) instructionToLocalArray.get(ins);
1140: /*
1141: G.v().out.println("[TypeArray]");
1142: typeArray.print(G.v().out);
1143: G.v().out.println();
1144:
1145: G.v().out.println("[TypeStack]");
1146: typeStack.print(G.v().out);
1147: G.v().out.println();
1148:
1149: G.v().out.println(ins.toString());
1150: */
1151:
1152: ins = ins.next;
1153: /*
1154:
1155: G.v().out.println();
1156: G.v().out.println();
1157: */
1158:
1159: }
1160: }
1161:
1162: // G.v().out.println("Producing Jimple code...");
1163:
1164: // Jimplify each statement
1165: {
1166: BasicBlock b = cfg;
1167:
1168: while (b != null) {
1169: Instruction ins = b.head;
1170: b.statements = new ArrayList<Stmt>();
1171:
1172: List<Stmt> blockStatements = b.statements;
1173:
1174: for (;;) {
1175: List<Stmt> statementsForIns = new ArrayList<Stmt>();
1176:
1177: if (reachableInstructions.contains(ins))
1178: generateJimple(ins, instructionToTypeStack
1179: .get(ins), instructionToPostTypeStack
1180: .get(ins), constant_pool,
1181: statementsForIns, b);
1182: else
1183: statementsForIns.add(Jimple.v().newNopStmt());
1184:
1185: if (!statementsForIns.isEmpty()) {
1186: for (int i = 0; i < statementsForIns.size(); i++) {
1187: units.add(statementsForIns.get(i));
1188: blockStatements
1189: .add(statementsForIns.get(i));
1190: }
1191:
1192: instructionToFirstStmt.put(ins,
1193: statementsForIns.get(0));
1194: instructionToLastStmt.put(ins, statementsForIns
1195: .get(statementsForIns.size() - 1));
1196: }
1197:
1198: if (ins == b.tail)
1199: break;
1200:
1201: ins = ins.next;
1202: }
1203:
1204: b = b.next;
1205: }
1206: }
1207:
1208: jimpleTargetFixup(); // fix up jump targets
1209:
1210: /*
1211: // Print out basic blocks
1212: {
1213: BasicBlock b = cfg;
1214:
1215: G.v().out.println("Basic blocks for: " + jmethod.getName());
1216:
1217: while(b != null)
1218: {
1219: Instruction ins = b.head;
1220:
1221: G.v().out.println();
1222:
1223: while(ins != null)
1224: {
1225: G.v().out.println(ins.toString());
1226: ins = ins.next;
1227: }
1228:
1229: b = b.next;
1230: }
1231: }
1232: */
1233:
1234: // Insert beginCatch/endCatch statements for exception handling
1235: {
1236: Map<Stmt, Stmt> targetToHandler = new HashMap<Stmt, Stmt>();
1237:
1238: for (int i = 0; i < codeAttribute.exception_table_length; i++) {
1239: Instruction startIns = codeAttribute.exception_table[i].start_inst;
1240: Instruction endIns = codeAttribute.exception_table[i].end_inst;
1241: Instruction targetIns = codeAttribute.exception_table[i].handler_inst;
1242:
1243: if (!instructionToFirstStmt.containsKey(startIns)
1244: || (endIns != null && (!instructionToLastStmt
1245: .containsKey(endIns)))) {
1246: throw new RuntimeException(
1247: "Exception range does not coincide with jimple instructions");
1248: }
1249:
1250: if (!instructionToFirstStmt.containsKey(targetIns)) {
1251: throw new RuntimeException(
1252: "Exception handler does not coincide with jimple instruction");
1253: }
1254:
1255: SootClass exception;
1256:
1257: // Determine exception to catch
1258: {
1259: int catchType = codeAttribute.exception_table[i].catch_type;
1260: if (catchType != 0) {
1261: CONSTANT_Class_info classinfo = (CONSTANT_Class_info) constant_pool[catchType];
1262:
1263: String name = ((CONSTANT_Utf8_info) (constant_pool[classinfo.name_index]))
1264: .convert();
1265: name = name.replace('/', '.');
1266: exception = cm.getSootClass(name);
1267: } else
1268: exception = cm
1269: .getSootClass("java.lang.Throwable");
1270: }
1271:
1272: Stmt newTarget;
1273:
1274: // Insert assignment of exception
1275: {
1276: Stmt firstTargetStmt = instructionToFirstStmt
1277: .get(targetIns);
1278:
1279: if (targetToHandler.containsKey(firstTargetStmt))
1280: newTarget = targetToHandler
1281: .get(firstTargetStmt);
1282: else {
1283: Local local = Util.v()
1284: .getLocalCreatingIfNecessary(listBody,
1285: "$stack0", UnknownType.v());
1286:
1287: newTarget = Jimple.v().newIdentityStmt(local,
1288: Jimple.v().newCaughtExceptionRef());
1289:
1290: // changed to account for catch blocks which are also part of normal control flow
1291: //units.insertBefore(newTarget, firstTargetStmt);
1292: ((PatchingChain) units).insertBeforeNoRedirect(
1293: newTarget, firstTargetStmt);
1294:
1295: targetToHandler.put(firstTargetStmt, newTarget);
1296: if (units.getFirst() != newTarget) {
1297: Unit prev = (Unit) units
1298: .getPredOf(newTarget);
1299: if (prev != null && prev.fallsThrough())
1300: units.insertAfter(Jimple.v()
1301: .newGotoStmt(firstTargetStmt),
1302: prev);
1303: }
1304: }
1305: }
1306:
1307: // Insert trap
1308: {
1309: Stmt firstStmt = instructionToFirstStmt
1310: .get(startIns);
1311: Stmt afterEndStmt;
1312: if (endIns == null) {
1313: // A kludge which isn't really correct, but
1314: // gets us closer to correctness (until we
1315: // clean up the rest of Soot to properly
1316: // represent Traps which extend to the end
1317: // of a method): if the protected code extends
1318: // to the end of the method, use the last Stmt
1319: // as the endUnit of the Trap, even though
1320: // that will leave the last unit outside
1321: // the protected area.
1322: afterEndStmt = (Stmt) units.getLast();
1323: } else {
1324: afterEndStmt = instructionToLastStmt
1325: .get(endIns);
1326: IdentityStmt catchStart = (IdentityStmt) targetToHandler
1327: .get(afterEndStmt);
1328: // (Cast to IdentityStmt as an assertion check.)
1329: if (catchStart != null) {
1330: // The protected region extends to the beginning of an
1331: // exception handler, so we need to reset afterEndStmt
1332: // to the identity statement which we have inserted
1333: // before the old afterEndStmt.
1334: if (catchStart != units
1335: .getPredOf(afterEndStmt)) {
1336: throw new IllegalStateException(
1337: "Assertion failure: catchStart != pred of afterEndStmt");
1338: }
1339: afterEndStmt = catchStart;
1340: }
1341: }
1342:
1343: Trap trap = Jimple.v().newTrap(exception,
1344: firstStmt, afterEndStmt, newTarget);
1345: listBody.getTraps().add(trap);
1346: }
1347: }
1348: }
1349:
1350: /* convert line number table to tags attached to statements */
1351: if (Options.v().keep_line_number()) {
1352: HashMap<Stmt, Tag> stmtstags = new HashMap<Stmt, Tag>();
1353: LinkedList<Stmt> startstmts = new LinkedList<Stmt>();
1354:
1355: attribute_info[] attrs = codeAttribute.attributes;
1356: for (attribute_info element : attrs) {
1357: if (element instanceof LineNumberTable_attribute) {
1358: LineNumberTable_attribute lntattr = (LineNumberTable_attribute) element;
1359: for (line_number_table_entry element0 : lntattr.line_number_table) {
1360: Stmt start_stmt = instructionToFirstStmt
1361: .get(element0.start_inst);
1362:
1363: if (start_stmt != null) {
1364: LineNumberTag lntag = new LineNumberTag(
1365: element0.line_number);
1366: stmtstags.put(start_stmt, lntag);
1367: startstmts.add(start_stmt);
1368: }
1369: }
1370: }
1371: }
1372:
1373: /* if the predecessor of a statement is a caughtexcetionref,
1374: * give it the tag of its successor */
1375: for (Iterator<Stmt> stmtIt = new ArrayList<Stmt>(stmtstags
1376: .keySet()).iterator(); stmtIt.hasNext();) {
1377: final Stmt stmt = stmtIt.next();
1378: Stmt pred = stmt;
1379: Tag tag = stmtstags.get(stmt);
1380: while (true) {
1381: pred = (Stmt) units.getPredOf(pred);
1382: if (pred == null)
1383: break;
1384: if (!(pred instanceof IdentityStmt))
1385: break;
1386: stmtstags.put(pred, tag);
1387: pred.addTag(tag);
1388: }
1389: }
1390:
1391: /* attach line number tag to each statement. */
1392: for (int i = 0; i < startstmts.size(); i++) {
1393: Stmt stmt = startstmts.get(i);
1394: Tag tag = stmtstags.get(stmt);
1395:
1396: stmt.addTag(tag);
1397:
1398: stmt = (Stmt) units.getSuccOf(stmt);
1399: while (stmt != null && !stmtstags.containsKey(stmt)) {
1400: stmt.addTag(tag);
1401: stmt = (Stmt) units.getSuccOf(stmt);
1402: }
1403: }
1404: }
1405: }
1406:
1407: private Type byteCodeTypeOf(Type type) {
1408: if (type.equals(ShortType.v()) || type.equals(CharType.v())
1409: || type.equals(ByteType.v())
1410: || type.equals(BooleanType.v())) {
1411: return IntType.v();
1412: } else
1413: return type;
1414: }
1415:
1416: OutFlow processFlow(Instruction ins, TypeStack typeStack,
1417: cp_info[] constant_pool) {
1418: int x;
1419: x = ((ins.code)) & 0xff;
1420:
1421: switch (x) {
1422: case ByteCode.BIPUSH:
1423: typeStack = typeStack.push(IntType.v());
1424: break;
1425:
1426: case ByteCode.SIPUSH:
1427: typeStack = typeStack.push(IntType.v());
1428: break;
1429:
1430: case ByteCode.LDC1:
1431: return processCPEntry(constant_pool,
1432: ((Instruction_Ldc1) ins).arg_b, typeStack, jmethod);
1433:
1434: case ByteCode.LDC2:
1435: case ByteCode.LDC2W:
1436: return processCPEntry(constant_pool,
1437: ((Instruction_intindex) ins).arg_i, typeStack,
1438: jmethod);
1439:
1440: case ByteCode.ACONST_NULL:
1441: typeStack = typeStack.push(RefType.v("java.lang.Object"));
1442: break;
1443:
1444: case ByteCode.ICONST_M1:
1445: case ByteCode.ICONST_0:
1446: case ByteCode.ICONST_1:
1447: case ByteCode.ICONST_2:
1448: case ByteCode.ICONST_3:
1449: case ByteCode.ICONST_4:
1450: case ByteCode.ICONST_5:
1451: typeStack = typeStack.push(IntType.v());
1452: break;
1453: case ByteCode.LCONST_0:
1454: case ByteCode.LCONST_1:
1455: typeStack = typeStack.push(LongType.v());
1456: typeStack = typeStack.push(Long2ndHalfType.v());
1457: break;
1458: case ByteCode.FCONST_0:
1459: case ByteCode.FCONST_1:
1460: case ByteCode.FCONST_2:
1461: typeStack = typeStack.push(FloatType.v());
1462: break;
1463: case ByteCode.DCONST_0:
1464: case ByteCode.DCONST_1:
1465: typeStack = typeStack.push(DoubleType.v());
1466: typeStack = typeStack.push(Double2ndHalfType.v());
1467: break;
1468: case ByteCode.ILOAD:
1469: typeStack = typeStack.push(IntType.v());
1470: break;
1471:
1472: case ByteCode.FLOAD:
1473: typeStack = typeStack.push(FloatType.v());
1474: break;
1475:
1476: case ByteCode.ALOAD:
1477: typeStack = typeStack.push(RefType.v("java.lang.Object"));
1478: // this is highly imprecise
1479: break;
1480:
1481: case ByteCode.DLOAD:
1482: typeStack = typeStack.push(DoubleType.v());
1483: typeStack = typeStack.push(Double2ndHalfType.v());
1484: break;
1485:
1486: case ByteCode.LLOAD:
1487: typeStack = typeStack.push(LongType.v());
1488: typeStack = typeStack.push(Long2ndHalfType.v());
1489: break;
1490:
1491: case ByteCode.ILOAD_0:
1492: case ByteCode.ILOAD_1:
1493: case ByteCode.ILOAD_2:
1494: case ByteCode.ILOAD_3:
1495: typeStack = typeStack.push(IntType.v());
1496: break;
1497:
1498: case ByteCode.FLOAD_0:
1499: case ByteCode.FLOAD_1:
1500: case ByteCode.FLOAD_2:
1501: case ByteCode.FLOAD_3:
1502: typeStack = typeStack.push(FloatType.v());
1503: break;
1504:
1505: case ByteCode.ALOAD_0:
1506: case ByteCode.ALOAD_1:
1507: case ByteCode.ALOAD_2:
1508: case ByteCode.ALOAD_3:
1509: typeStack = typeStack.push(RefType.v("java.lang.Object"));
1510: // this is highly imprecise
1511: break;
1512:
1513: case ByteCode.LLOAD_0:
1514: case ByteCode.LLOAD_1:
1515: case ByteCode.LLOAD_2:
1516: case ByteCode.LLOAD_3:
1517: typeStack = typeStack.push(LongType.v());
1518: typeStack = typeStack.push(Long2ndHalfType.v());
1519: break;
1520:
1521: case ByteCode.DLOAD_0:
1522: case ByteCode.DLOAD_1:
1523: case ByteCode.DLOAD_2:
1524: case ByteCode.DLOAD_3:
1525: typeStack = typeStack.push(DoubleType.v());
1526: typeStack = typeStack.push(Double2ndHalfType.v());
1527: break;
1528:
1529: case ByteCode.ISTORE:
1530: typeStack = popSafe(typeStack, IntType.v());
1531: break;
1532:
1533: case ByteCode.FSTORE:
1534: typeStack = popSafe(typeStack, FloatType.v());
1535: break;
1536:
1537: case ByteCode.ASTORE:
1538: typeStack = typeStack.pop();
1539: break;
1540:
1541: case ByteCode.LSTORE:
1542: typeStack = popSafe(typeStack, Long2ndHalfType.v());
1543: typeStack = popSafe(typeStack, LongType.v());
1544: break;
1545:
1546: case ByteCode.DSTORE:
1547: typeStack = popSafe(typeStack, Double2ndHalfType.v());
1548: typeStack = popSafe(typeStack, DoubleType.v());
1549: break;
1550:
1551: case ByteCode.ISTORE_0:
1552: case ByteCode.ISTORE_1:
1553: case ByteCode.ISTORE_2:
1554: case ByteCode.ISTORE_3:
1555: typeStack = popSafe(typeStack, IntType.v());
1556: break;
1557:
1558: case ByteCode.FSTORE_0:
1559: case ByteCode.FSTORE_1:
1560: case ByteCode.FSTORE_2:
1561: case ByteCode.FSTORE_3:
1562: typeStack = popSafe(typeStack, FloatType.v());
1563: break;
1564:
1565: case ByteCode.ASTORE_0:
1566: case ByteCode.ASTORE_1:
1567: case ByteCode.ASTORE_2:
1568: case ByteCode.ASTORE_3:
1569: if (!(typeStack.top() instanceof StmtAddressType)
1570: && !(typeStack.top() instanceof RefType)
1571: && !(typeStack.top() instanceof ArrayType)) {
1572: throw new RuntimeException(
1573: "Astore failed, invalid stack type: "
1574: + typeStack.top());
1575: }
1576:
1577: typeStack = typeStack.pop();
1578: break;
1579:
1580: case ByteCode.LSTORE_0:
1581: case ByteCode.LSTORE_1:
1582: case ByteCode.LSTORE_2:
1583: case ByteCode.LSTORE_3:
1584: typeStack = popSafe(typeStack, Long2ndHalfType.v());
1585: typeStack = popSafe(typeStack, LongType.v());
1586: break;
1587:
1588: case ByteCode.DSTORE_0:
1589: case ByteCode.DSTORE_1:
1590: case ByteCode.DSTORE_2:
1591: case ByteCode.DSTORE_3:
1592: typeStack = popSafe(typeStack, Double2ndHalfType.v());
1593: typeStack = popSafe(typeStack, DoubleType.v());
1594: break;
1595:
1596: case ByteCode.IINC:
1597: break;
1598:
1599: case ByteCode.WIDE:
1600: throw new RuntimeException(
1601: "Wide instruction should not be encountered");
1602: // break;
1603:
1604: case ByteCode.NEWARRAY: {
1605: typeStack = popSafe(typeStack, IntType.v());
1606: Type baseType = jimpleTypeOfAtype(((Instruction_Newarray) ins).atype);
1607:
1608: typeStack = typeStack.push(ArrayType.v(baseType, 1));
1609: break;
1610: }
1611:
1612: case ByteCode.ANEWARRAY: {
1613: CONSTANT_Class_info c = (CONSTANT_Class_info) constant_pool[((Instruction_Anewarray) ins).arg_i];
1614:
1615: String name = ((CONSTANT_Utf8_info) (constant_pool[c.name_index]))
1616: .convert();
1617: name = name.replace('/', '.');
1618:
1619: Type baseType;
1620:
1621: if (name.startsWith("[")) {
1622: String baseName = getClassName(constant_pool,
1623: ((Instruction_Anewarray) ins).arg_i);
1624: baseType = Util.v().jimpleTypeOfFieldDescriptor(
1625: baseName);
1626: } else {
1627: baseType = RefType.v(name);
1628: }
1629:
1630: typeStack = popSafe(typeStack, IntType.v());
1631: typeStack = typeStack.push(baseType.makeArrayType());
1632: break;
1633: }
1634:
1635: case ByteCode.MULTIANEWARRAY: {
1636: int bdims = (((Instruction_Multianewarray) ins).dims);
1637:
1638: CONSTANT_Class_info c = (CONSTANT_Class_info) constant_pool[((Instruction_Multianewarray) ins).arg_i];
1639:
1640: String arrayDescriptor = ((CONSTANT_Utf8_info) (constant_pool[c.name_index]))
1641: .convert();
1642:
1643: ArrayType arrayType = (ArrayType) Util.v()
1644: .jimpleTypeOfFieldDescriptor(arrayDescriptor);
1645:
1646: for (int j = 0; j < bdims; j++)
1647: typeStack = popSafe(typeStack, IntType.v());
1648:
1649: typeStack = typeStack.push(arrayType);
1650: break;
1651: }
1652:
1653: case ByteCode.ARRAYLENGTH:
1654: typeStack = popSafeRefType(typeStack);
1655: typeStack = typeStack.push(IntType.v());
1656: break;
1657:
1658: case ByteCode.IALOAD:
1659: case ByteCode.BALOAD:
1660: case ByteCode.CALOAD:
1661: case ByteCode.SALOAD:
1662: typeStack = popSafe(typeStack, IntType.v());
1663: typeStack = popSafeRefType(typeStack);
1664: typeStack = typeStack.push(IntType.v());
1665: break;
1666: case ByteCode.FALOAD:
1667: typeStack = popSafe(typeStack, FloatType.v());
1668: typeStack = popSafeRefType(typeStack);
1669: typeStack = typeStack.push(FloatType.v());
1670: break;
1671:
1672: case ByteCode.AALOAD: {
1673:
1674: typeStack = popSafe(typeStack, IntType.v());
1675:
1676: if (typeStack.top() instanceof ArrayType) {
1677: ArrayType arrayType = (ArrayType) typeStack.top();
1678: typeStack = popSafeRefType(typeStack);
1679:
1680: if (arrayType.numDimensions == 1)
1681: typeStack = typeStack.push(arrayType.baseType);
1682: else
1683: typeStack = typeStack.push(ArrayType.v(
1684: arrayType.baseType,
1685: arrayType.numDimensions - 1));
1686: } else {
1687: // it's a null object
1688:
1689: typeStack = popSafeRefType(typeStack);
1690:
1691: typeStack = typeStack.push(RefType
1692: .v("java.lang.Object"));
1693: }
1694:
1695: break;
1696: }
1697: case ByteCode.LALOAD:
1698: typeStack = popSafe(typeStack, IntType.v());
1699: typeStack = popSafeRefType(typeStack);
1700: typeStack = typeStack.push(LongType.v());
1701: typeStack = typeStack.push(Long2ndHalfType.v());
1702: break;
1703:
1704: case ByteCode.DALOAD:
1705: typeStack = popSafe(typeStack, IntType.v());
1706: typeStack = popSafeRefType(typeStack);
1707: typeStack = typeStack.push(DoubleType.v());
1708: typeStack = typeStack.push(Double2ndHalfType.v());
1709: break;
1710:
1711: case ByteCode.IASTORE:
1712: case ByteCode.BASTORE:
1713: case ByteCode.CASTORE:
1714: case ByteCode.SASTORE:
1715: typeStack = popSafe(typeStack, IntType.v());
1716: typeStack = popSafe(typeStack, IntType.v());
1717: typeStack = popSafeRefType(typeStack);
1718: break;
1719:
1720: case ByteCode.AASTORE:
1721: typeStack = popSafeRefType(typeStack);
1722: typeStack = popSafe(typeStack, IntType.v());
1723: typeStack = popSafeRefType(typeStack);
1724: break;
1725:
1726: case ByteCode.FASTORE:
1727: typeStack = popSafe(typeStack, FloatType.v());
1728: typeStack = popSafe(typeStack, IntType.v());
1729: typeStack = popSafeRefType(typeStack);
1730: break;
1731:
1732: case ByteCode.LASTORE:
1733: typeStack = popSafe(typeStack, Long2ndHalfType.v());
1734: typeStack = popSafe(typeStack, LongType.v());
1735: typeStack = popSafe(typeStack, IntType.v());
1736: typeStack = popSafeRefType(typeStack);
1737: break;
1738:
1739: case ByteCode.DASTORE:
1740: typeStack = popSafe(typeStack, Double2ndHalfType.v());
1741: typeStack = popSafe(typeStack, DoubleType.v());
1742: typeStack = popSafe(typeStack, IntType.v());
1743: typeStack = popSafeRefType(typeStack);
1744: break;
1745:
1746: case ByteCode.NOP:
1747: break;
1748:
1749: case ByteCode.POP:
1750: typeStack = typeStack.pop();
1751: break;
1752:
1753: case ByteCode.POP2:
1754: typeStack = typeStack.pop();
1755: typeStack = typeStack.pop();
1756: break;
1757:
1758: case ByteCode.DUP:
1759: typeStack = typeStack.push(typeStack.top());
1760: break;
1761:
1762: case ByteCode.DUP2: {
1763: Type topType = typeStack.get(typeStack.topIndex()), secondType = typeStack
1764: .get(typeStack.topIndex() - 1);
1765: typeStack = (typeStack.push(secondType)).push(topType);
1766: break;
1767: }
1768:
1769: case ByteCode.DUP_X1: {
1770: Type topType = typeStack.get(typeStack.topIndex()), secondType = typeStack
1771: .get(typeStack.topIndex() - 1);
1772:
1773: typeStack = typeStack.pop().pop();
1774:
1775: typeStack = typeStack.push(topType).push(secondType).push(
1776: topType);
1777: break;
1778: }
1779:
1780: case ByteCode.DUP_X2: {
1781: Type topType = typeStack.get(typeStack.topIndex()), secondType = typeStack
1782: .get(typeStack.topIndex() - 1), thirdType = typeStack
1783: .get(typeStack.topIndex() - 2);
1784:
1785: typeStack = typeStack.pop().pop().pop();
1786:
1787: typeStack = typeStack.push(topType).push(thirdType).push(
1788: secondType).push(topType);
1789: break;
1790: }
1791:
1792: case ByteCode.DUP2_X1: {
1793: Type topType = typeStack.get(typeStack.topIndex()), secondType = typeStack
1794: .get(typeStack.topIndex() - 1), thirdType = typeStack
1795: .get(typeStack.topIndex() - 2);
1796:
1797: typeStack = typeStack.pop().pop().pop();
1798:
1799: typeStack = typeStack.push(secondType).push(topType).push(
1800: thirdType).push(secondType).push(topType);
1801: break;
1802: }
1803:
1804: case ByteCode.DUP2_X2: {
1805: Type topType = typeStack.get(typeStack.topIndex()), secondType = typeStack
1806: .get(typeStack.topIndex() - 1), thirdType = typeStack
1807: .get(typeStack.topIndex() - 2), fourthType = typeStack
1808: .get(typeStack.topIndex() - 3);
1809:
1810: typeStack = typeStack.pop().pop().pop().pop();
1811:
1812: typeStack = typeStack.push(secondType).push(topType).push(
1813: fourthType).push(thirdType).push(secondType).push(
1814: topType);
1815: break;
1816: }
1817:
1818: case ByteCode.SWAP: {
1819: Type topType = typeStack.top();
1820:
1821: typeStack = typeStack.pop();
1822:
1823: Type secondType = typeStack.top();
1824:
1825: typeStack = typeStack.pop();
1826:
1827: typeStack = typeStack.push(topType);
1828: typeStack = typeStack.push(secondType);
1829: break;
1830: }
1831:
1832: case ByteCode.IADD:
1833: case ByteCode.ISUB:
1834: case ByteCode.IMUL:
1835: case ByteCode.IDIV:
1836: case ByteCode.IREM:
1837: case ByteCode.ISHL:
1838: case ByteCode.ISHR:
1839: case ByteCode.IUSHR:
1840: case ByteCode.IAND:
1841: case ByteCode.IOR:
1842: case ByteCode.IXOR:
1843: typeStack = popSafe(typeStack, IntType.v());
1844: typeStack = popSafe(typeStack, IntType.v());
1845: typeStack = typeStack.push(IntType.v());
1846: break;
1847:
1848: case ByteCode.LUSHR:
1849: case ByteCode.LSHR:
1850: case ByteCode.LSHL:
1851: typeStack = popSafe(typeStack, IntType.v());
1852: typeStack = popSafe(typeStack, Long2ndHalfType.v());
1853: typeStack = popSafe(typeStack, LongType.v());
1854: typeStack = typeStack.push(LongType.v());
1855: typeStack = typeStack.push(Long2ndHalfType.v());
1856: break;
1857:
1858: case ByteCode.LREM:
1859: case ByteCode.LDIV:
1860: case ByteCode.LMUL:
1861: case ByteCode.LSUB:
1862: case ByteCode.LADD:
1863: case ByteCode.LAND:
1864: case ByteCode.LOR:
1865: case ByteCode.LXOR:
1866: typeStack = popSafe(typeStack, Long2ndHalfType.v());
1867: typeStack = popSafe(typeStack, LongType.v());
1868: typeStack = popSafe(typeStack, Long2ndHalfType.v());
1869: typeStack = popSafe(typeStack, LongType.v());
1870: typeStack = typeStack.push(LongType.v());
1871: typeStack = typeStack.push(Long2ndHalfType.v());
1872: break;
1873:
1874: case ByteCode.FREM:
1875: case ByteCode.FDIV:
1876: case ByteCode.FMUL:
1877: case ByteCode.FSUB:
1878: case ByteCode.FADD:
1879: typeStack = popSafe(typeStack, FloatType.v());
1880: typeStack = popSafe(typeStack, FloatType.v());
1881: typeStack = typeStack.push(FloatType.v());
1882: break;
1883:
1884: case ByteCode.DREM:
1885: case ByteCode.DDIV:
1886: case ByteCode.DMUL:
1887: case ByteCode.DSUB:
1888: case ByteCode.DADD:
1889: typeStack = popSafe(typeStack, Double2ndHalfType.v());
1890: typeStack = popSafe(typeStack, DoubleType.v());
1891: typeStack = popSafe(typeStack, Double2ndHalfType.v());
1892: typeStack = popSafe(typeStack, DoubleType.v());
1893: typeStack = typeStack.push(DoubleType.v());
1894: typeStack = typeStack.push(Double2ndHalfType.v());
1895: break;
1896:
1897: case ByteCode.INEG:
1898: case ByteCode.LNEG:
1899: case ByteCode.FNEG:
1900: case ByteCode.DNEG:
1901: // Doesn't check to see if the required types are on the stack, but it should
1902: // if it wanted to be safe.
1903: break;
1904:
1905: case ByteCode.I2L:
1906: typeStack = popSafe(typeStack, IntType.v());
1907: typeStack = typeStack.push(LongType.v());
1908: typeStack = typeStack.push(Long2ndHalfType.v());
1909: break;
1910:
1911: case ByteCode.I2F:
1912: typeStack = popSafe(typeStack, IntType.v());
1913: typeStack = typeStack.push(FloatType.v());
1914: break;
1915:
1916: case ByteCode.I2D:
1917: typeStack = popSafe(typeStack, IntType.v());
1918: typeStack = typeStack.push(DoubleType.v());
1919: typeStack = typeStack.push(Double2ndHalfType.v());
1920: break;
1921:
1922: case ByteCode.L2I:
1923: typeStack = popSafe(typeStack, Long2ndHalfType.v());
1924: typeStack = popSafe(typeStack, LongType.v());
1925: typeStack = typeStack.push(IntType.v());
1926: break;
1927:
1928: case ByteCode.L2F:
1929: typeStack = popSafe(typeStack, Long2ndHalfType.v());
1930: typeStack = popSafe(typeStack, LongType.v());
1931: typeStack = typeStack.push(FloatType.v());
1932: break;
1933:
1934: case ByteCode.L2D:
1935: typeStack = popSafe(typeStack, Long2ndHalfType.v());
1936: typeStack = popSafe(typeStack, LongType.v());
1937: typeStack = typeStack.push(DoubleType.v());
1938: typeStack = typeStack.push(Double2ndHalfType.v());
1939: break;
1940:
1941: case ByteCode.F2I:
1942: typeStack = popSafe(typeStack, FloatType.v());
1943: typeStack = typeStack.push(IntType.v());
1944: break;
1945:
1946: case ByteCode.F2L:
1947: typeStack = popSafe(typeStack, FloatType.v());
1948: typeStack = typeStack.push(LongType.v());
1949: typeStack = typeStack.push(Long2ndHalfType.v());
1950: break;
1951:
1952: case ByteCode.F2D:
1953: typeStack = popSafe(typeStack, FloatType.v());
1954: typeStack = typeStack.push(DoubleType.v());
1955: typeStack = typeStack.push(Double2ndHalfType.v());
1956: break;
1957:
1958: case ByteCode.D2I:
1959: typeStack = popSafe(typeStack, Double2ndHalfType.v());
1960: typeStack = popSafe(typeStack, DoubleType.v());
1961: typeStack = typeStack.push(IntType.v());
1962: break;
1963:
1964: case ByteCode.D2L:
1965: typeStack = popSafe(typeStack, Double2ndHalfType.v());
1966: typeStack = popSafe(typeStack, DoubleType.v());
1967: typeStack = typeStack.push(LongType.v());
1968: typeStack = typeStack.push(Long2ndHalfType.v());
1969: break;
1970:
1971: case ByteCode.D2F:
1972: typeStack = popSafe(typeStack, Double2ndHalfType.v());
1973: typeStack = popSafe(typeStack, DoubleType.v());
1974: typeStack = typeStack.push(FloatType.v());
1975: break;
1976:
1977: case ByteCode.INT2BYTE:
1978: break;
1979: case ByteCode.INT2CHAR:
1980: break;
1981: case ByteCode.INT2SHORT:
1982: break;
1983:
1984: case ByteCode.IFEQ:
1985: case ByteCode.IFGT:
1986: case ByteCode.IFLT:
1987: case ByteCode.IFLE:
1988: case ByteCode.IFNE:
1989: case ByteCode.IFGE:
1990: typeStack = popSafe(typeStack, IntType.v());
1991: break;
1992:
1993: case ByteCode.IFNULL:
1994: case ByteCode.IFNONNULL:
1995: typeStack = popSafeRefType(typeStack);
1996: break;
1997:
1998: case ByteCode.IF_ICMPEQ:
1999: case ByteCode.IF_ICMPLT:
2000: case ByteCode.IF_ICMPLE:
2001: case ByteCode.IF_ICMPNE:
2002: case ByteCode.IF_ICMPGT:
2003: case ByteCode.IF_ICMPGE:
2004: typeStack = popSafe(typeStack, IntType.v());
2005: typeStack = popSafe(typeStack, IntType.v());
2006: break;
2007:
2008: case ByteCode.LCMP:
2009: typeStack = popSafe(typeStack, Long2ndHalfType.v());
2010: typeStack = popSafe(typeStack, LongType.v());
2011: typeStack = popSafe(typeStack, Long2ndHalfType.v());
2012: typeStack = popSafe(typeStack, LongType.v());
2013: typeStack = typeStack.push(IntType.v());
2014: break;
2015:
2016: case ByteCode.FCMPL:
2017: case ByteCode.FCMPG:
2018: typeStack = popSafe(typeStack, FloatType.v());
2019: typeStack = popSafe(typeStack, FloatType.v());
2020: typeStack = typeStack.push(IntType.v());
2021: break;
2022:
2023: case ByteCode.DCMPL:
2024: case ByteCode.DCMPG:
2025: typeStack = popSafe(typeStack, Double2ndHalfType.v());
2026: typeStack = popSafe(typeStack, DoubleType.v());
2027: typeStack = popSafe(typeStack, Double2ndHalfType.v());
2028: typeStack = popSafe(typeStack, DoubleType.v());
2029: typeStack = typeStack.push(IntType.v());
2030: break;
2031:
2032: case ByteCode.IF_ACMPEQ:
2033: case ByteCode.IF_ACMPNE:
2034: typeStack = popSafeRefType(typeStack);
2035: typeStack = popSafeRefType(typeStack);
2036: break;
2037:
2038: case ByteCode.GOTO:
2039: case ByteCode.GOTO_W:
2040: break;
2041:
2042: case ByteCode.JSR:
2043: case ByteCode.JSR_W:
2044: typeStack = typeStack.push(StmtAddressType.v());
2045: break;
2046:
2047: case ByteCode.RET:
2048: break;
2049:
2050: case ByteCode.RET_W:
2051: break;
2052:
2053: case ByteCode.RETURN:
2054: break;
2055:
2056: case ByteCode.IRETURN:
2057: typeStack = popSafe(typeStack, IntType.v());
2058: break;
2059:
2060: case ByteCode.FRETURN:
2061: typeStack = popSafe(typeStack, FloatType.v());
2062: break;
2063:
2064: case ByteCode.ARETURN:
2065: typeStack = popSafeRefType(typeStack);
2066: break;
2067:
2068: case ByteCode.DRETURN:
2069: typeStack = popSafe(typeStack, Double2ndHalfType.v());
2070: typeStack = popSafe(typeStack, DoubleType.v());
2071: break;
2072:
2073: case ByteCode.LRETURN:
2074: typeStack = popSafe(typeStack, Long2ndHalfType.v());
2075: typeStack = popSafe(typeStack, LongType.v());
2076: break;
2077:
2078: case ByteCode.BREAKPOINT:
2079: break;
2080:
2081: case ByteCode.TABLESWITCH:
2082: typeStack = popSafe(typeStack, IntType.v());
2083: break;
2084:
2085: case ByteCode.LOOKUPSWITCH:
2086: typeStack = popSafe(typeStack, IntType.v());
2087: break;
2088:
2089: case ByteCode.PUTFIELD: {
2090: Type type = byteCodeTypeOf(jimpleTypeOfFieldInFieldRef(cm,
2091: constant_pool, ((Instruction_Putfield) ins).arg_i));
2092:
2093: if (type.equals(DoubleType.v())) {
2094: typeStack = popSafe(typeStack, Double2ndHalfType.v());
2095: typeStack = popSafe(typeStack, DoubleType.v());
2096: } else if (type.equals(LongType.v())) {
2097: typeStack = popSafe(typeStack, Long2ndHalfType.v());
2098: typeStack = popSafe(typeStack, LongType.v());
2099: } else if (type instanceof RefType)
2100: typeStack = popSafeRefType(typeStack);
2101: else
2102: typeStack = popSafe(typeStack, type);
2103:
2104: typeStack = popSafeRefType(typeStack);
2105: break;
2106: }
2107:
2108: case ByteCode.GETFIELD: {
2109: Type type = byteCodeTypeOf(jimpleTypeOfFieldInFieldRef(cm,
2110: constant_pool, ((Instruction_Getfield) ins).arg_i));
2111:
2112: typeStack = popSafeRefType(typeStack);
2113:
2114: if (type.equals(DoubleType.v())) {
2115: typeStack = typeStack.push(DoubleType.v());
2116: typeStack = typeStack.push(Double2ndHalfType.v());
2117: } else if (type.equals(LongType.v())) {
2118: typeStack = typeStack.push(LongType.v());
2119: typeStack = typeStack.push(Long2ndHalfType.v());
2120: } else
2121: typeStack = typeStack.push(type);
2122: break;
2123: }
2124:
2125: case ByteCode.PUTSTATIC: {
2126: Type type = byteCodeTypeOf(jimpleTypeOfFieldInFieldRef(cm,
2127: constant_pool, ((Instruction_Putstatic) ins).arg_i));
2128:
2129: if (type.equals(DoubleType.v())) {
2130: typeStack = popSafe(typeStack, Double2ndHalfType.v());
2131: typeStack = popSafe(typeStack, DoubleType.v());
2132: } else if (type.equals(LongType.v())) {
2133: typeStack = popSafe(typeStack, Long2ndHalfType.v());
2134: typeStack = popSafe(typeStack, LongType.v());
2135: } else if (type instanceof RefType)
2136: typeStack = popSafeRefType(typeStack);
2137: else
2138: typeStack = popSafe(typeStack, type);
2139:
2140: break;
2141: }
2142:
2143: case ByteCode.GETSTATIC: {
2144: Type type = byteCodeTypeOf(jimpleTypeOfFieldInFieldRef(cm,
2145: constant_pool, ((Instruction_Getstatic) ins).arg_i));
2146:
2147: if (type.equals(DoubleType.v())) {
2148: typeStack = typeStack.push(DoubleType.v());
2149: typeStack = typeStack.push(Double2ndHalfType.v());
2150: } else if (type.equals(LongType.v())) {
2151: typeStack = typeStack.push(LongType.v());
2152: typeStack = typeStack.push(Long2ndHalfType.v());
2153: } else
2154: typeStack = typeStack.push(type);
2155: break;
2156: }
2157:
2158: case ByteCode.INVOKEVIRTUAL: {
2159: Instruction_Invokevirtual iv = (Instruction_Invokevirtual) ins;
2160: int args = cp_info.countParams(constant_pool, iv.arg_i);
2161: Type returnType = byteCodeTypeOf(jimpleReturnTypeOfMethodRef(
2162: cm, constant_pool, iv.arg_i));
2163:
2164: // pop off parameters.
2165: for (int j = args - 1; j >= 0; j--) {
2166: if (typeStack.top().equals(Long2ndHalfType.v())) {
2167: typeStack = popSafe(typeStack, Long2ndHalfType.v());
2168: typeStack = popSafe(typeStack, LongType.v());
2169:
2170: } else if (typeStack.top()
2171: .equals(Double2ndHalfType.v())) {
2172: typeStack = popSafe(typeStack, Double2ndHalfType
2173: .v());
2174: typeStack = popSafe(typeStack, DoubleType.v());
2175: } else
2176: typeStack = popSafe(typeStack, typeStack.top());
2177: }
2178:
2179: typeStack = popSafeRefType(typeStack);
2180:
2181: if (!returnType.equals(VoidType.v()))
2182: typeStack = smartPush(typeStack, returnType);
2183: break;
2184: }
2185:
2186: case ByteCode.INVOKENONVIRTUAL: {
2187: Instruction_Invokenonvirtual iv = (Instruction_Invokenonvirtual) ins;
2188: int args = cp_info.countParams(constant_pool, iv.arg_i);
2189: Type returnType = byteCodeTypeOf(jimpleReturnTypeOfMethodRef(
2190: cm, constant_pool, iv.arg_i));
2191:
2192: // pop off parameters.
2193: for (int j = args - 1; j >= 0; j--) {
2194: if (typeStack.top().equals(Long2ndHalfType.v())) {
2195: typeStack = popSafe(typeStack, Long2ndHalfType.v());
2196: typeStack = popSafe(typeStack, LongType.v());
2197:
2198: } else if (typeStack.top()
2199: .equals(Double2ndHalfType.v())) {
2200: typeStack = popSafe(typeStack, Double2ndHalfType
2201: .v());
2202: typeStack = popSafe(typeStack, DoubleType.v());
2203: } else
2204: typeStack = popSafe(typeStack, typeStack.top());
2205: }
2206:
2207: typeStack = popSafeRefType(typeStack);
2208:
2209: if (!returnType.equals(VoidType.v()))
2210: typeStack = smartPush(typeStack, returnType);
2211: break;
2212: }
2213:
2214: case ByteCode.INVOKESTATIC: {
2215: Instruction_Invokestatic iv = (Instruction_Invokestatic) ins;
2216: int args = cp_info.countParams(constant_pool, iv.arg_i);
2217: Type returnType = byteCodeTypeOf(jimpleReturnTypeOfMethodRef(
2218: cm, constant_pool, iv.arg_i));
2219:
2220: // pop off parameters.
2221: for (int j = args - 1; j >= 0; j--) {
2222: if (typeStack.top().equals(Long2ndHalfType.v())) {
2223: typeStack = popSafe(typeStack, Long2ndHalfType.v());
2224: typeStack = popSafe(typeStack, LongType.v());
2225:
2226: } else if (typeStack.top()
2227: .equals(Double2ndHalfType.v())) {
2228: typeStack = popSafe(typeStack, Double2ndHalfType
2229: .v());
2230: typeStack = popSafe(typeStack, DoubleType.v());
2231: } else
2232: typeStack = popSafe(typeStack, typeStack.top());
2233: }
2234:
2235: if (!returnType.equals(VoidType.v()))
2236: typeStack = smartPush(typeStack, returnType);
2237: break;
2238: }
2239:
2240: case ByteCode.INVOKEINTERFACE: {
2241: Instruction_Invokeinterface iv = (Instruction_Invokeinterface) ins;
2242: int args = cp_info.countParams(constant_pool, iv.arg_i);
2243: Type returnType = byteCodeTypeOf(jimpleReturnTypeOfInterfaceMethodRef(
2244: cm, constant_pool, iv.arg_i));
2245:
2246: // pop off parameters.
2247: for (int j = args - 1; j >= 0; j--) {
2248: if (typeStack.top().equals(Long2ndHalfType.v())) {
2249: typeStack = popSafe(typeStack, Long2ndHalfType.v());
2250: typeStack = popSafe(typeStack, LongType.v());
2251:
2252: } else if (typeStack.top()
2253: .equals(Double2ndHalfType.v())) {
2254: typeStack = popSafe(typeStack, Double2ndHalfType
2255: .v());
2256: typeStack = popSafe(typeStack, DoubleType.v());
2257: } else
2258: typeStack = popSafe(typeStack, typeStack.top());
2259: }
2260:
2261: typeStack = popSafeRefType(typeStack);
2262:
2263: if (!returnType.equals(VoidType.v()))
2264: typeStack = smartPush(typeStack, returnType);
2265: break;
2266: }
2267:
2268: case ByteCode.ATHROW:
2269: // technically athrow leaves the stack in an undefined
2270: // state. In fact, the top value is the one we actually
2271: // throw, but it should stay on the stack since the exception
2272: // handler expects to start that way, at least in the real JVM.
2273: break;
2274:
2275: case ByteCode.NEW: {
2276: Type type = RefType.v(getClassName(constant_pool,
2277: ((Instruction_New) ins).arg_i));
2278:
2279: typeStack = typeStack.push(type);
2280: break;
2281: }
2282:
2283: case ByteCode.CHECKCAST: {
2284: String className = getClassName(constant_pool,
2285: ((Instruction_Checkcast) ins).arg_i);
2286:
2287: Type castType;
2288:
2289: if (className.startsWith("["))
2290: castType = Util.v().jimpleTypeOfFieldDescriptor(
2291: getClassName(constant_pool,
2292: ((Instruction_Checkcast) ins).arg_i));
2293: else
2294: castType = RefType.v(className);
2295:
2296: typeStack = popSafeRefType(typeStack);
2297: typeStack = typeStack.push(castType);
2298: break;
2299: }
2300:
2301: case ByteCode.INSTANCEOF: {
2302: typeStack = popSafeRefType(typeStack);
2303: typeStack = typeStack.push(IntType.v());
2304: break;
2305: }
2306:
2307: case ByteCode.MONITORENTER:
2308: typeStack = popSafeRefType(typeStack);
2309: break;
2310: case ByteCode.MONITOREXIT:
2311: typeStack = popSafeRefType(typeStack);
2312: break;
2313:
2314: default:
2315: throw new RuntimeException(
2316: "processFlow failed: Unknown bytecode instruction: "
2317: + x);
2318: }
2319:
2320: return new OutFlow(typeStack);
2321: }
2322:
2323: private Type jimpleTypeOfFieldInFieldRef(Scene cm,
2324: cp_info[] constant_pool, int index) {
2325: CONSTANT_Fieldref_info fr = (CONSTANT_Fieldref_info) (constant_pool[index]);
2326:
2327: CONSTANT_NameAndType_info nat = (CONSTANT_NameAndType_info) (constant_pool[fr.name_and_type_index]);
2328:
2329: String fieldDescriptor = ((CONSTANT_Utf8_info) (constant_pool[nat.descriptor_index]))
2330: .convert();
2331:
2332: return Util.v().jimpleTypeOfFieldDescriptor(fieldDescriptor);
2333: }
2334:
2335: private Type jimpleReturnTypeOfMethodRef(Scene cm,
2336: cp_info[] constant_pool, int index) {
2337: CONSTANT_Methodref_info mr = (CONSTANT_Methodref_info) (constant_pool[index]);
2338:
2339: CONSTANT_NameAndType_info nat = (CONSTANT_NameAndType_info) (constant_pool[mr.name_and_type_index]);
2340:
2341: String methodDescriptor = ((CONSTANT_Utf8_info) (constant_pool[nat.descriptor_index]))
2342: .convert();
2343:
2344: return Util.v().jimpleReturnTypeOfMethodDescriptor(
2345: methodDescriptor);
2346: }
2347:
2348: private Type jimpleReturnTypeOfInterfaceMethodRef(Scene cm,
2349: cp_info[] constant_pool, int index) {
2350: CONSTANT_InterfaceMethodref_info mr = (CONSTANT_InterfaceMethodref_info) (constant_pool[index]);
2351:
2352: CONSTANT_NameAndType_info nat = (CONSTANT_NameAndType_info) (constant_pool[mr.name_and_type_index]);
2353:
2354: String methodDescriptor = ((CONSTANT_Utf8_info) (constant_pool[nat.descriptor_index]))
2355: .convert();
2356:
2357: return Util.v().jimpleReturnTypeOfMethodDescriptor(
2358: methodDescriptor);
2359: }
2360:
2361: private OutFlow processCPEntry(cp_info constant_pool[], int i,
2362: TypeStack typeStack, SootMethod jmethod) {
2363: cp_info c = constant_pool[i];
2364:
2365: if (c instanceof CONSTANT_Integer_info)
2366: typeStack = typeStack.push(IntType.v());
2367: else if (c instanceof CONSTANT_Float_info)
2368: typeStack = typeStack.push(FloatType.v());
2369: else if (c instanceof CONSTANT_Long_info) {
2370: typeStack = typeStack.push(LongType.v());
2371: typeStack = typeStack.push(Long2ndHalfType.v());
2372: } else if (c instanceof CONSTANT_Double_info) {
2373: typeStack = typeStack.push(DoubleType.v());
2374: typeStack = typeStack.push(Double2ndHalfType.v());
2375: } else if (c instanceof CONSTANT_String_info)
2376: typeStack = typeStack.push(RefType.v("java.lang.String"));
2377: else if (c instanceof CONSTANT_Utf8_info)
2378: typeStack = typeStack.push(RefType.v("java.lang.String"));
2379: else if (c instanceof CONSTANT_Class_info) {
2380: CONSTANT_Class_info info = (CONSTANT_Class_info) c;
2381: String name = ((CONSTANT_Utf8_info) (constant_pool[info.name_index]))
2382: .convert();
2383: name = name.replace('/', '.');
2384: if (name.charAt(0) == '[') {
2385: int dim = 0;
2386: while (name.charAt(dim) == '[') {
2387: dim++;
2388: }
2389: // array type
2390: Type baseType = null;
2391: char typeIndicator = name.charAt(dim);
2392: switch (typeIndicator) {
2393: case 'I':
2394: baseType = IntType.v();
2395: break;
2396: case 'C':
2397: baseType = CharType.v();
2398: break;
2399: case 'F':
2400: baseType = FloatType.v();
2401: break;
2402: case 'D':
2403: baseType = DoubleType.v();
2404: break;
2405: case 'B':
2406: baseType = ByteType.v();
2407: break;
2408: case 'S':
2409: baseType = ShortType.v();
2410: break;
2411: case 'Z':
2412: baseType = BooleanType.v();
2413: break;
2414: case 'J':
2415: baseType = LongType.v();
2416: break;
2417: case 'L':
2418: baseType = RefType.v(name.substring(dim + 1, name
2419: .length() - 1));
2420: break;
2421: default:
2422: throw new RuntimeException(
2423: "Unknown Array Base Type in Class Constant");
2424: }
2425: typeStack = typeStack.push(ArrayType.v(baseType, dim));
2426: } else {
2427: typeStack = typeStack.push(RefType.v(name));
2428: }
2429: } else
2430: throw new RuntimeException(
2431: "Attempting to push a non-constant cp entry"
2432: + c.getClass());
2433:
2434: return new OutFlow(typeStack);
2435: }
2436:
2437: TypeStack smartPush(TypeStack typeStack, Type type) {
2438: if (type.equals(LongType.v())) {
2439: typeStack = typeStack.push(LongType.v());
2440: typeStack = typeStack.push(Long2ndHalfType.v());
2441: } else if (type.equals(DoubleType.v())) {
2442: typeStack = typeStack.push(DoubleType.v());
2443: typeStack = typeStack.push(Double2ndHalfType.v());
2444: } else
2445: typeStack = typeStack.push(type);
2446:
2447: return typeStack;
2448: }
2449:
2450: TypeStack popSafeRefType(TypeStack typeStack) {
2451: /*
2452: if(!(typeStack.top() instanceof RefType) &&
2453: !(typeStack.top() instanceof ArrayType))
2454: {
2455: throw new RuntimeException("popSafe failed; top: " + typeStack.top() +
2456: " required: RefType");
2457: }
2458: */
2459:
2460: return typeStack.pop();
2461: }
2462:
2463: TypeStack popSafeArrayType(TypeStack typeStack) {
2464: /*
2465: if(!(typeStack.top() instanceof ArrayType) &&
2466: !(RefType.v("null").equals(typeStack.top())))
2467: {
2468: throw new RuntimeException("popSafe failed; top: " + typeStack.top() +
2469: " required: ArrayType");
2470: }
2471: */
2472:
2473: return typeStack.pop();
2474: }
2475:
2476: TypeStack popSafe(TypeStack typeStack, Type requiredType) {
2477: /*
2478: if(!typeStack.top().equals(requiredType))
2479: throw new RuntimeException("popSafe failed; top: " + typeStack.top() +
2480: " required: " + requiredType);
2481: */
2482:
2483: return typeStack.pop();
2484: }
2485:
2486: void confirmType(Type actualType, Type requiredType) {
2487: /*
2488: if(!actualType.equals(requiredType))
2489: throw new RuntimeException("confirmType failed; actualType: " + actualType +
2490: " required: " + requiredType);*/
2491: }
2492:
2493: String getClassName(cp_info[] constant_pool, int index) {
2494: CONSTANT_Class_info c = (CONSTANT_Class_info) constant_pool[index];
2495:
2496: String name = ((CONSTANT_Utf8_info) (constant_pool[c.name_index]))
2497: .convert();
2498:
2499: return name.replace('/', '.');
2500: }
2501:
2502: void confirmRefType(Type actualType) {
2503: /*
2504: if(!(actualType instanceof RefType) &&
2505: !(actualType instanceof ArrayType))
2506: throw new RuntimeException("confirmRefType failed; actualType: " + actualType);*/
2507: }
2508:
2509: /** Runs through the given bbq contents performing the target fix-up pass;
2510: * Requires all reachable blocks to have their done flags set to true, and
2511: * this resets them all back to false;
2512: * @param bbq queue of BasicBlocks to process.
2513: * @see jimpleTargetFixup
2514: */
2515: private void processTargetFixup(BBQ bbq) {
2516: BasicBlock b, p;
2517: Stmt s;
2518: while (!bbq.isEmpty()) {
2519: try {
2520: b = bbq.pull();
2521: } catch (NoSuchElementException e) {
2522: break;
2523: }
2524:
2525: s = b.getTailJStmt();
2526:
2527: if (s instanceof GotoStmt) {
2528: if (b.succ.size() == 1) {
2529: // Regular goto
2530:
2531: ((GotoStmt) s).setTarget(b.succ.firstElement()
2532: .getHeadJStmt());
2533: } else {
2534: // Goto derived from a jsr bytecode
2535: /*
2536: if((BasicBlock)(b.succ.firstElement())==b.next)
2537: ((GotoStmt)s).setTarget(((BasicBlock) b.succ.elementAt(1)).getHeadJStmt());
2538: else
2539: ((GotoStmt)s).setTarget(((BasicBlock) b.succ.firstElement()).getHeadJStmt());
2540: */
2541: G.v().out.println("Error :");
2542: for (int i = 0; i < b.statements.size(); i++)
2543: G.v().out.println(b.statements.get(i));
2544:
2545: throw new RuntimeException(b + " has "
2546: + b.succ.size() + " successors.");
2547: }
2548: } else if (s instanceof IfStmt) {
2549: if (b.succ.size() != 2)
2550: G.v().out
2551: .println("How can an if not have 2 successors?");
2552:
2553: if ((b.succ.firstElement()) == b.next) {
2554: ((IfStmt) s).setTarget(b.succ.elementAt(1)
2555: .getHeadJStmt());
2556: } else {
2557: ((IfStmt) s).setTarget(b.succ.firstElement()
2558: .getHeadJStmt());
2559: }
2560:
2561: } else if (s instanceof TableSwitchStmt) {
2562: int count = 0;
2563: TableSwitchStmt sts = (TableSwitchStmt) s;
2564: // Successors of the basic block ending with a switch statement
2565: // are listed in the successor vector in order, with the
2566: // default as the very first (0-th entry)
2567:
2568: for (BasicBlock basicBlock : b.succ) {
2569: p = (basicBlock);
2570: if (count == 0) {
2571: sts.setDefaultTarget(p.getHeadJStmt());
2572: } else {
2573: sts.setTarget(count - 1, p.getHeadJStmt());
2574: }
2575: count++;
2576: }
2577: } else if (s instanceof LookupSwitchStmt) {
2578: int count = 0;
2579: LookupSwitchStmt sls = (LookupSwitchStmt) s;
2580: // Successors of the basic block ending with a switch statement
2581: // are listed in the successor vector in order, with the
2582: // default as the very first (0-th entry)
2583:
2584: for (BasicBlock basicBlock : b.succ) {
2585: p = (basicBlock);
2586: if (count == 0) {
2587: sls.setDefaultTarget(p.getHeadJStmt());
2588: } else {
2589: sls.setTarget(count - 1, p.getHeadJStmt());
2590: }
2591: count++;
2592: }
2593: }
2594:
2595: b.done = false;
2596: for (BasicBlock basicBlock : b.succ) {
2597: p = (basicBlock);
2598: if (p.done)
2599: bbq.push(p);
2600: }
2601: }
2602: }
2603:
2604: /** After the initial jimple construction, a second pass is made to fix up
2605: * missing Stmt targets for <tt>goto</tt>s, <tt>if</tt>'s etc.
2606: * @param c code attribute of this method.
2607: * @see CFG#jimplify
2608: */
2609: void jimpleTargetFixup() {
2610: BasicBlock b;
2611: BBQ bbq = new BBQ();
2612:
2613: Code_attribute c = method.locate_code_attribute();
2614: if (c == null)
2615: return;
2616:
2617: // Reset all the dones to true
2618: {
2619: BasicBlock bb = cfg;
2620:
2621: while (bb != null) {
2622: bb.done = true;
2623: bb = bb.next;
2624: }
2625: }
2626:
2627: // first process the main code
2628: bbq.push(cfg);
2629: processTargetFixup(bbq);
2630:
2631: // then the exceptions
2632: if (bbq.isEmpty()) {
2633: int i;
2634: for (i = 0; i < c.exception_table_length; i++) {
2635: b = c.exception_table[i].b;
2636: // if block hasn't yet been processed...
2637: if (b != null && b.done) {
2638: bbq.push(b);
2639: processTargetFixup(bbq);
2640: if (!bbq.isEmpty()) {
2641: G.v().out
2642: .println("Error 2nd processing exception block.");
2643: break;
2644: }
2645: }
2646: }
2647: }
2648: }
2649:
2650: private void generateJimpleForCPEntry(cp_info constant_pool[],
2651: int i, TypeStack typeStack, TypeStack postTypeStack,
2652: SootMethod jmethod, List<Stmt> statements) {
2653: Stmt stmt;
2654: Value rvalue;
2655:
2656: cp_info c = constant_pool[i];
2657:
2658: if (c instanceof CONSTANT_Integer_info) {
2659: CONSTANT_Integer_info ci = (CONSTANT_Integer_info) c;
2660:
2661: rvalue = IntConstant.v((int) ci.bytes);
2662: stmt = Jimple.v().newAssignStmt(
2663: Util.v().getLocalForStackOp(listBody,
2664: postTypeStack, postTypeStack.topIndex()),
2665: rvalue);
2666: } else if (c instanceof CONSTANT_Float_info) {
2667: CONSTANT_Float_info cf = (CONSTANT_Float_info) c;
2668:
2669: rvalue = FloatConstant.v(cf.convert());
2670: stmt = Jimple.v().newAssignStmt(
2671: Util.v().getLocalForStackOp(listBody,
2672: postTypeStack, postTypeStack.topIndex()),
2673: rvalue);
2674: } else if (c instanceof CONSTANT_Long_info) {
2675: CONSTANT_Long_info cl = (CONSTANT_Long_info) c;
2676:
2677: rvalue = LongConstant.v(cl.convert());
2678: stmt = Jimple.v().newAssignStmt(
2679: Util.v().getLocalForStackOp(listBody,
2680: postTypeStack, postTypeStack.topIndex()),
2681: rvalue);
2682: } else if (c instanceof CONSTANT_Double_info) {
2683: CONSTANT_Double_info cd = (CONSTANT_Double_info) c;
2684:
2685: rvalue = DoubleConstant.v(cd.convert());
2686:
2687: stmt = Jimple.v().newAssignStmt(
2688: Util.v().getLocalForStackOp(listBody,
2689: postTypeStack, postTypeStack.topIndex()),
2690: rvalue);
2691: } else if (c instanceof CONSTANT_String_info) {
2692: CONSTANT_String_info cs = (CONSTANT_String_info) c;
2693:
2694: String constant = cs.toString(constant_pool);
2695:
2696: if (constant.startsWith("\"") && constant.endsWith("\""))
2697: constant = constant.substring(1, constant.length() - 1);
2698:
2699: rvalue = StringConstant.v(constant);
2700: stmt = Jimple.v().newAssignStmt(
2701: Util.v().getLocalForStackOp(listBody,
2702: postTypeStack, postTypeStack.topIndex()),
2703: rvalue);
2704: } else if (c instanceof CONSTANT_Utf8_info) {
2705: CONSTANT_Utf8_info cu = (CONSTANT_Utf8_info) c;
2706:
2707: String constant = cu.convert();
2708:
2709: if (constant.startsWith("\"") && constant.endsWith("\""))
2710: constant = constant.substring(1, constant.length() - 1);
2711:
2712: rvalue = StringConstant.v(constant);
2713: stmt = Jimple.v().newAssignStmt(
2714: Util.v().getLocalForStackOp(listBody,
2715: postTypeStack, postTypeStack.topIndex()),
2716: rvalue);
2717: } else if (c instanceof CONSTANT_Class_info) {
2718:
2719: String className = ((CONSTANT_Utf8_info) (constant_pool[((CONSTANT_Class_info) c).name_index]))
2720: .convert();
2721:
2722: rvalue = ClassConstant.v(className);
2723: stmt = Jimple.v().newAssignStmt(
2724: Util.v().getLocalForStackOp(listBody,
2725: postTypeStack, postTypeStack.topIndex()),
2726: rvalue);
2727: } else {
2728: throw new RuntimeException(
2729: "Attempting to push a non-constant cp entry" + c);
2730: }
2731:
2732: statements.add(stmt);
2733: }
2734:
2735: void generateJimple(Instruction ins, TypeStack typeStack,
2736: TypeStack postTypeStack, cp_info constant_pool[],
2737: List<Stmt> statements, BasicBlock basicBlock) {
2738: Value[] params;
2739: Local l1 = null, l2 = null, l3 = null, l4 = null;
2740:
2741: Expr rhs = null;
2742: ConditionExpr co = null;
2743:
2744: ArrayRef a = null;
2745: int args;
2746: Value rvalue;
2747:
2748: // int localIndex;
2749:
2750: Stmt stmt = null;
2751:
2752: int x = ((ins.code)) & 0xff;
2753:
2754: Util.v().activeOriginalIndex = ins.originalIndex;
2755: Util.v().isLocalStore = false;
2756: Util.v().isWideLocalStore = false;
2757:
2758: switch (x) {
2759: case ByteCode.BIPUSH:
2760: rvalue = IntConstant.v(((Instruction_Bipush) ins).arg_b);
2761: stmt = Jimple.v().newAssignStmt(
2762: Util.v().getLocalForStackOp(listBody,
2763: postTypeStack, postTypeStack.topIndex()),
2764: rvalue);
2765: break;
2766:
2767: case ByteCode.SIPUSH:
2768: rvalue = IntConstant.v(((Instruction_Sipush) ins).arg_i);
2769: stmt = Jimple.v().newAssignStmt(
2770: Util.v().getLocalForStackOp(listBody,
2771: postTypeStack, postTypeStack.topIndex()),
2772: rvalue);
2773: break;
2774:
2775: case ByteCode.LDC1:
2776: generateJimpleForCPEntry(constant_pool,
2777: ((Instruction_Ldc1) ins).arg_b, typeStack,
2778: postTypeStack, jmethod, statements);
2779: break;
2780:
2781: case ByteCode.LDC2:
2782: case ByteCode.LDC2W:
2783: generateJimpleForCPEntry(constant_pool,
2784: ((Instruction_intindex) ins).arg_i, typeStack,
2785: postTypeStack, jmethod, statements);
2786: break;
2787:
2788: case ByteCode.ACONST_NULL:
2789: rvalue = NullConstant.v();
2790: stmt = Jimple.v().newAssignStmt(
2791: Util.v().getLocalForStackOp(listBody,
2792: postTypeStack, postTypeStack.topIndex()),
2793: rvalue);
2794: break;
2795:
2796: case ByteCode.ICONST_M1:
2797: case ByteCode.ICONST_0:
2798: case ByteCode.ICONST_1:
2799: case ByteCode.ICONST_2:
2800: case ByteCode.ICONST_3:
2801: case ByteCode.ICONST_4:
2802: case ByteCode.ICONST_5:
2803: rvalue = IntConstant.v(x - ByteCode.ICONST_0);
2804: stmt = Jimple.v().newAssignStmt(
2805: Util.v().getLocalForStackOp(listBody,
2806: postTypeStack, postTypeStack.topIndex()),
2807: rvalue);
2808: break;
2809:
2810: case ByteCode.LCONST_0:
2811: case ByteCode.LCONST_1:
2812: rvalue = LongConstant.v(x - ByteCode.LCONST_0);
2813: stmt = Jimple.v().newAssignStmt(
2814: Util.v().getLocalForStackOp(listBody,
2815: postTypeStack, postTypeStack.topIndex()),
2816: rvalue);
2817: break;
2818:
2819: case ByteCode.FCONST_0:
2820: case ByteCode.FCONST_1:
2821: case ByteCode.FCONST_2:
2822: rvalue = FloatConstant.v((x - ByteCode.FCONST_0));
2823: stmt = Jimple.v().newAssignStmt(
2824: Util.v().getLocalForStackOp(listBody,
2825: postTypeStack, postTypeStack.topIndex()),
2826: rvalue);
2827: break;
2828:
2829: case ByteCode.DCONST_0:
2830: case ByteCode.DCONST_1:
2831: rvalue = DoubleConstant.v((x - ByteCode.DCONST_0));
2832: stmt = Jimple.v().newAssignStmt(
2833: Util.v().getLocalForStackOp(listBody,
2834: postTypeStack, postTypeStack.topIndex()),
2835: rvalue);
2836: break;
2837:
2838: case ByteCode.ILOAD: {
2839: Local local = Util.v().getLocalForIndex(listBody,
2840: ((Instruction_bytevar) ins).arg_b);
2841:
2842: stmt = Jimple.v().newAssignStmt(
2843: Util.v().getLocalForStackOp(listBody,
2844: postTypeStack, postTypeStack.topIndex()),
2845: local);
2846: break;
2847: }
2848:
2849: case ByteCode.FLOAD: {
2850: Local local = Util.v().getLocalForIndex(listBody,
2851: ((Instruction_bytevar) ins).arg_b);
2852:
2853: stmt = Jimple.v().newAssignStmt(
2854: Util.v().getLocalForStackOp(listBody,
2855: postTypeStack, postTypeStack.topIndex()),
2856: local);
2857: break;
2858: }
2859:
2860: case ByteCode.ALOAD: {
2861: Local local = Util.v().getLocalForIndex(listBody,
2862: ((Instruction_bytevar) ins).arg_b);
2863:
2864: stmt = Jimple.v().newAssignStmt(
2865: Util.v().getLocalForStackOp(listBody,
2866: postTypeStack, postTypeStack.topIndex()),
2867: local);
2868: break;
2869: }
2870:
2871: case ByteCode.DLOAD: {
2872: Local local = Util.v().getLocalForIndex(listBody,
2873: ((Instruction_bytevar) ins).arg_b);
2874:
2875: stmt = Jimple.v().newAssignStmt(
2876: Util.v().getLocalForStackOp(listBody,
2877: postTypeStack, postTypeStack.topIndex()),
2878: local);
2879: break;
2880: }
2881:
2882: case ByteCode.LLOAD: {
2883: Local local = Util.v().getLocalForIndex(listBody,
2884: ((Instruction_bytevar) ins).arg_b);
2885:
2886: stmt = Jimple.v().newAssignStmt(
2887: Util.v().getLocalForStackOp(listBody,
2888: postTypeStack, postTypeStack.topIndex()),
2889: local);
2890: break;
2891: }
2892:
2893: case ByteCode.ILOAD_0:
2894: case ByteCode.ILOAD_1:
2895: case ByteCode.ILOAD_2:
2896: case ByteCode.ILOAD_3: {
2897: Local local = Util.v().getLocalForIndex(listBody,
2898: (x - ByteCode.ILOAD_0));
2899:
2900: stmt = Jimple.v().newAssignStmt(
2901: Util.v().getLocalForStackOp(listBody,
2902: postTypeStack, postTypeStack.topIndex()),
2903: local);
2904: break;
2905: }
2906:
2907: case ByteCode.FLOAD_0:
2908: case ByteCode.FLOAD_1:
2909: case ByteCode.FLOAD_2:
2910: case ByteCode.FLOAD_3: {
2911: Local local = Util.v().getLocalForIndex(listBody,
2912: (x - ByteCode.FLOAD_0));
2913:
2914: stmt = Jimple.v().newAssignStmt(
2915: Util.v().getLocalForStackOp(listBody,
2916: postTypeStack, postTypeStack.topIndex()),
2917: local);
2918: break;
2919: }
2920:
2921: case ByteCode.ALOAD_0:
2922: case ByteCode.ALOAD_1:
2923: case ByteCode.ALOAD_2:
2924: case ByteCode.ALOAD_3: {
2925: Local local = Util.v().getLocalForIndex(listBody,
2926: (x - ByteCode.ALOAD_0));
2927:
2928: stmt = Jimple.v().newAssignStmt(
2929: Util.v().getLocalForStackOp(listBody,
2930: postTypeStack, postTypeStack.topIndex()),
2931: local);
2932: break;
2933: }
2934:
2935: case ByteCode.LLOAD_0:
2936: case ByteCode.LLOAD_1:
2937: case ByteCode.LLOAD_2:
2938: case ByteCode.LLOAD_3: {
2939: Local local = Util.v().getLocalForIndex(listBody,
2940: (x - ByteCode.LLOAD_0));
2941:
2942: stmt = Jimple.v().newAssignStmt(
2943: Util.v().getLocalForStackOp(listBody,
2944: postTypeStack, postTypeStack.topIndex()),
2945: local);
2946: break;
2947: }
2948:
2949: case ByteCode.DLOAD_0:
2950: case ByteCode.DLOAD_1:
2951: case ByteCode.DLOAD_2:
2952: case ByteCode.DLOAD_3: {
2953: Local local = Util.v().getLocalForIndex(listBody,
2954: (x - ByteCode.DLOAD_0));
2955:
2956: stmt = Jimple.v().newAssignStmt(
2957: Util.v().getLocalForStackOp(listBody,
2958: postTypeStack, postTypeStack.topIndex()),
2959: local);
2960: break;
2961: }
2962:
2963: case ByteCode.ISTORE: {
2964: Util.v().isLocalStore = true;
2965: Util.v().isWideLocalStore = true;
2966:
2967: Local local = Util.v().getLocalForIndex(listBody,
2968: ((Instruction_bytevar) ins).arg_b);
2969:
2970: stmt = Jimple.v().newAssignStmt(
2971: local,
2972: Util.v().getLocalForStackOp(listBody, typeStack,
2973: typeStack.topIndex()));
2974: break;
2975: }
2976:
2977: case ByteCode.FSTORE: {
2978: Util.v().isLocalStore = true;
2979: Util.v().isWideLocalStore = true;
2980:
2981: Local local = Util.v().getLocalForIndex(listBody,
2982: ((Instruction_bytevar) ins).arg_b);
2983:
2984: stmt = Jimple.v().newAssignStmt(
2985: local,
2986: Util.v().getLocalForStackOp(listBody, typeStack,
2987: typeStack.topIndex()));
2988: break;
2989: }
2990:
2991: case ByteCode.ASTORE: {
2992: Util.v().isLocalStore = true;
2993: Util.v().isWideLocalStore = true;
2994:
2995: Local local = Util.v().getLocalForIndex(listBody,
2996: ((Instruction_bytevar) ins).arg_b);
2997:
2998: stmt = Jimple.v().newAssignStmt(
2999: local,
3000: Util.v().getLocalForStackOp(listBody, typeStack,
3001: typeStack.topIndex()));
3002: break;
3003: }
3004:
3005: case ByteCode.LSTORE: {
3006: Util.v().isLocalStore = true;
3007: Util.v().isWideLocalStore = true;
3008:
3009: Local local = Util.v().getLocalForIndex(listBody,
3010: ((Instruction_bytevar) ins).arg_b);
3011:
3012: stmt = Jimple.v().newAssignStmt(
3013: local,
3014: Util.v().getLocalForStackOp(listBody, typeStack,
3015: typeStack.topIndex()));
3016: break;
3017: }
3018:
3019: case ByteCode.DSTORE: {
3020: Util.v().isLocalStore = true;
3021: Util.v().isWideLocalStore = true;
3022:
3023: Local local = Util.v().getLocalForIndex(listBody,
3024: ((Instruction_bytevar) ins).arg_b);
3025:
3026: stmt = Jimple.v().newAssignStmt(
3027: local,
3028: Util.v().getLocalForStackOp(listBody, typeStack,
3029: typeStack.topIndex()));
3030: break;
3031: }
3032:
3033: case ByteCode.ISTORE_0:
3034: case ByteCode.ISTORE_1:
3035: case ByteCode.ISTORE_2:
3036: case ByteCode.ISTORE_3: {
3037: Util.v().isLocalStore = true;
3038: Local local = Util.v().getLocalForIndex(listBody,
3039: (x - ByteCode.ISTORE_0));
3040:
3041: stmt = Jimple.v().newAssignStmt(
3042: local,
3043: Util.v().getLocalForStackOp(listBody, typeStack,
3044: typeStack.topIndex()));
3045: break;
3046: }
3047:
3048: case ByteCode.FSTORE_0:
3049: case ByteCode.FSTORE_1:
3050: case ByteCode.FSTORE_2:
3051: case ByteCode.FSTORE_3: {
3052: Util.v().isLocalStore = true;
3053: Local local = Util.v().getLocalForIndex(listBody,
3054: (x - ByteCode.FSTORE_0));
3055:
3056: stmt = Jimple.v().newAssignStmt(
3057: local,
3058: Util.v().getLocalForStackOp(listBody, typeStack,
3059: typeStack.topIndex()));
3060: break;
3061: }
3062:
3063: case ByteCode.ASTORE_0:
3064: case ByteCode.ASTORE_1:
3065: case ByteCode.ASTORE_2:
3066: case ByteCode.ASTORE_3: {
3067: Util.v().isLocalStore = true;
3068: Local local = Util.v().getLocalForIndex(listBody,
3069: (x - ByteCode.ASTORE_0));
3070:
3071: stmt = Jimple.v().newAssignStmt(
3072: local,
3073: Util.v().getLocalForStackOp(listBody, typeStack,
3074: typeStack.topIndex()));
3075: break;
3076: }
3077:
3078: case ByteCode.LSTORE_0:
3079: case ByteCode.LSTORE_1:
3080: case ByteCode.LSTORE_2:
3081: case ByteCode.LSTORE_3: {
3082: Util.v().isLocalStore = true;
3083: Local local = Util.v().getLocalForIndex(listBody,
3084: (x - ByteCode.LSTORE_0));
3085:
3086: stmt = Jimple.v().newAssignStmt(
3087: local,
3088: Util.v().getLocalForStackOp(listBody, typeStack,
3089: typeStack.topIndex()));
3090: break;
3091: }
3092:
3093: case ByteCode.DSTORE_0:
3094: case ByteCode.DSTORE_1:
3095: case ByteCode.DSTORE_2:
3096: case ByteCode.DSTORE_3: {
3097: Util.v().isLocalStore = true;
3098: Local local = Util.v().getLocalForIndex(listBody,
3099: (x - ByteCode.DSTORE_0));
3100:
3101: stmt = Jimple.v().newAssignStmt(
3102: local,
3103: Util.v().getLocalForStackOp(listBody, typeStack,
3104: typeStack.topIndex()));
3105: break;
3106: }
3107:
3108: case ByteCode.IINC: {
3109: Local local = Util.v().getLocalForIndex(listBody,
3110: ((Instruction_Iinc) ins).arg_b);
3111:
3112: int amt = (((Instruction_Iinc) ins).arg_c);
3113: rhs = Jimple.v().newAddExpr(local, IntConstant.v(amt));
3114: stmt = Jimple.v().newAssignStmt(local, rhs);
3115: break;
3116: }
3117:
3118: case ByteCode.WIDE:
3119: throw new RuntimeException(
3120: "WIDE instruction should not be encountered anymore");
3121: // break;
3122:
3123: case ByteCode.NEWARRAY: {
3124: Type baseType = jimpleTypeOfAtype(((Instruction_Newarray) ins).atype);
3125:
3126: rhs = Jimple.v().newNewArrayExpr(
3127: baseType,
3128: Util.v().getLocalForStackOp(listBody, typeStack,
3129: typeStack.topIndex()));
3130:
3131: stmt = Jimple.v().newAssignStmt(
3132: Util.v().getLocalForStackOp(listBody,
3133: postTypeStack, postTypeStack.topIndex()),
3134: rhs);
3135:
3136: break;
3137: }
3138:
3139: case ByteCode.ANEWARRAY: {
3140: String baseName = getClassName(constant_pool,
3141: ((Instruction_Anewarray) ins).arg_i);
3142:
3143: Type baseType;
3144:
3145: if (baseName.startsWith("["))
3146: baseType = Util.v().jimpleTypeOfFieldDescriptor(
3147: getClassName(constant_pool,
3148: ((Instruction_Anewarray) ins).arg_i));
3149: else
3150: baseType = RefType.v(baseName);
3151:
3152: rhs = Jimple.v().newNewArrayExpr(
3153: baseType,
3154: Util.v().getLocalForStackOp(listBody, typeStack,
3155: typeStack.topIndex()));
3156:
3157: stmt = Jimple.v().newAssignStmt(
3158: Util.v().getLocalForStackOp(listBody,
3159: postTypeStack, postTypeStack.topIndex()),
3160: rhs);
3161: break;
3162: }
3163:
3164: case ByteCode.MULTIANEWARRAY: {
3165: int bdims = (((Instruction_Multianewarray) ins).dims);
3166: List dims = new ArrayList();
3167:
3168: for (int j = 0; j < bdims; j++)
3169: dims.add(Util.v()
3170: .getLocalForStackOp(listBody, typeStack,
3171: typeStack.topIndex() - bdims + j + 1));
3172:
3173: String mstype = constant_pool[((Instruction_Multianewarray) ins).arg_i]
3174: .toString(constant_pool);
3175:
3176: ArrayType jimpleType = (ArrayType) Util.v()
3177: .jimpleTypeOfFieldDescriptor(mstype);
3178:
3179: rhs = Jimple.v().newNewMultiArrayExpr(jimpleType, dims);
3180:
3181: stmt = Jimple.v().newAssignStmt(
3182: Util.v().getLocalForStackOp(listBody,
3183: postTypeStack, postTypeStack.topIndex()),
3184: rhs);
3185: break;
3186: }
3187:
3188: case ByteCode.ARRAYLENGTH:
3189: rhs = Jimple.v().newLengthExpr(
3190: Util.v().getLocalForStackOp(listBody, typeStack,
3191: typeStack.topIndex()));
3192:
3193: stmt = Jimple.v().newAssignStmt(
3194: Util.v().getLocalForStackOp(listBody,
3195: postTypeStack, postTypeStack.topIndex()),
3196: rhs);
3197: break;
3198:
3199: case ByteCode.IALOAD:
3200: case ByteCode.BALOAD:
3201: case ByteCode.CALOAD:
3202: case ByteCode.SALOAD:
3203: case ByteCode.FALOAD:
3204: case ByteCode.LALOAD:
3205: case ByteCode.DALOAD:
3206: case ByteCode.AALOAD:
3207: a = Jimple.v().newArrayRef(
3208: Util.v().getLocalForStackOp(listBody, typeStack,
3209: typeStack.topIndex() - 1),
3210: Util.v().getLocalForStackOp(listBody, typeStack,
3211: typeStack.topIndex()));
3212:
3213: stmt = Jimple.v()
3214: .newAssignStmt(
3215: Util.v().getLocalForStackOp(listBody,
3216: postTypeStack,
3217: postTypeStack.topIndex()), a);
3218:
3219: break;
3220:
3221: case ByteCode.IASTORE:
3222: case ByteCode.FASTORE:
3223: case ByteCode.AASTORE:
3224: case ByteCode.BASTORE:
3225: case ByteCode.CASTORE:
3226: case ByteCode.SASTORE:
3227: a = Jimple.v().newArrayRef(
3228: Util.v().getLocalForStackOp(listBody, typeStack,
3229: typeStack.topIndex() - 2),
3230: Util.v().getLocalForStackOp(listBody, typeStack,
3231: typeStack.topIndex() - 1));
3232:
3233: stmt = Jimple.v().newAssignStmt(
3234: a,
3235: Util.v().getLocalForStackOp(listBody, typeStack,
3236: typeStack.topIndex()));
3237: break;
3238:
3239: case ByteCode.LASTORE:
3240: case ByteCode.DASTORE:
3241: a = Jimple.v().newArrayRef(
3242: Util.v().getLocalForStackOp(listBody, typeStack,
3243: typeStack.topIndex() - 3),
3244: Util.v().getLocalForStackOp(listBody, typeStack,
3245: typeStack.topIndex() - 2));
3246:
3247: stmt = Jimple.v().newAssignStmt(
3248: a,
3249: Util.v().getLocalForStackOp(listBody, typeStack,
3250: typeStack.topIndex()));
3251: break;
3252:
3253: case ByteCode.NOP:
3254: stmt = Jimple.v().newNopStmt();
3255: break;
3256:
3257: case ByteCode.POP:
3258: case ByteCode.POP2:
3259: stmt = Jimple.v().newNopStmt();
3260: break;
3261:
3262: case ByteCode.DUP:
3263: stmt = Jimple.v().newAssignStmt(
3264: Util.v().getLocalForStackOp(listBody,
3265: postTypeStack, postTypeStack.topIndex()),
3266: Util.v().getLocalForStackOp(listBody, typeStack,
3267: typeStack.topIndex()));
3268: break;
3269:
3270: case ByteCode.DUP2:
3271: if (typeSize(typeStack.top()) == 2) {
3272: stmt = Jimple.v().newAssignStmt(
3273: Util.v().getLocalForStackOp(listBody,
3274: postTypeStack,
3275: postTypeStack.topIndex() - 1),
3276: Util.v().getLocalForStackOp(listBody,
3277: typeStack, typeStack.topIndex() - 1));
3278: } else {
3279: stmt = Jimple.v().newAssignStmt(
3280: Util.v().getLocalForStackOp(listBody,
3281: postTypeStack,
3282: postTypeStack.topIndex() - 1),
3283: Util.v().getLocalForStackOp(listBody,
3284: typeStack, typeStack.topIndex() - 1));
3285:
3286: statements.add(stmt);
3287:
3288: stmt = Jimple.v().newAssignStmt(
3289: Util.v()
3290: .getLocalForStackOp(listBody,
3291: postTypeStack,
3292: postTypeStack.topIndex()),
3293: Util.v().getLocalForStackOp(listBody,
3294: typeStack, typeStack.topIndex()));
3295:
3296: statements.add(stmt);
3297:
3298: stmt = null;
3299: }
3300: break;
3301:
3302: case ByteCode.DUP_X1:
3303: l1 = Util.v().getLocalForStackOp(listBody, typeStack,
3304: typeStack.topIndex());
3305: l2 = Util.v().getLocalForStackOp(listBody, typeStack,
3306: typeStack.topIndex() - 1);
3307:
3308: stmt = Jimple.v().newAssignStmt(
3309: Util.v().getLocalForStackOp(listBody,
3310: postTypeStack, postTypeStack.topIndex()),
3311: l1);
3312:
3313: statements.add(stmt);
3314:
3315: stmt = Jimple.v().newAssignStmt(
3316: Util.v()
3317: .getLocalForStackOp(listBody,
3318: postTypeStack,
3319: postTypeStack.topIndex() - 1), l2);
3320:
3321: statements.add(stmt);
3322:
3323: stmt = Jimple.v().newAssignStmt(
3324: Util.v()
3325: .getLocalForStackOp(listBody,
3326: postTypeStack,
3327: postTypeStack.topIndex() - 2),
3328: Util.v().getLocalForStackOp(listBody,
3329: postTypeStack, postTypeStack.topIndex()));
3330:
3331: statements.add(stmt);
3332:
3333: stmt = null;
3334: break;
3335:
3336: case ByteCode.DUP_X2:
3337: if (typeSize(typeStack.get(typeStack.topIndex() - 2)) == 2) {
3338: l3 = Util.v().getLocalForStackOp(listBody, typeStack,
3339: typeStack.topIndex() - 2);
3340: l1 = Util.v().getLocalForStackOp(listBody, typeStack,
3341: typeStack.topIndex());
3342:
3343: stmt = Jimple.v().newAssignStmt(
3344: Util.v().getLocalForStackOp(listBody,
3345: postTypeStack,
3346: postTypeStack.topIndex() - 2), l3);
3347:
3348: statements.add(stmt);
3349:
3350: stmt = Jimple.v().newAssignStmt(
3351: Util.v().getLocalForStackOp(listBody,
3352: postTypeStack,
3353: postTypeStack.topIndex() - 3), l1);
3354:
3355: statements.add(stmt);
3356:
3357: stmt = Jimple.v().newAssignStmt(
3358: Util.v()
3359: .getLocalForStackOp(listBody,
3360: postTypeStack,
3361: postTypeStack.topIndex()), l1);
3362:
3363: statements.add(stmt);
3364:
3365: stmt = null;
3366: } else {
3367: l3 = Util.v().getLocalForStackOp(listBody, typeStack,
3368: typeStack.topIndex() - 2);
3369: l2 = Util.v().getLocalForStackOp(listBody, typeStack,
3370: typeStack.topIndex() - 1);
3371: l1 = Util.v().getLocalForStackOp(listBody, typeStack,
3372: typeStack.topIndex());
3373:
3374: stmt = Jimple.v().newAssignStmt(
3375: Util.v()
3376: .getLocalForStackOp(listBody,
3377: postTypeStack,
3378: postTypeStack.topIndex()), l1);
3379:
3380: statements.add(stmt);
3381:
3382: stmt = Jimple.v().newAssignStmt(
3383: Util.v().getLocalForStackOp(listBody,
3384: postTypeStack,
3385: postTypeStack.topIndex() - 1), l2);
3386:
3387: statements.add(stmt);
3388:
3389: stmt = Jimple.v().newAssignStmt(
3390: Util.v().getLocalForStackOp(listBody,
3391: postTypeStack,
3392: postTypeStack.topIndex() - 2), l3);
3393:
3394: statements.add(stmt);
3395:
3396: stmt = Jimple.v().newAssignStmt(
3397: Util.v().getLocalForStackOp(listBody,
3398: postTypeStack,
3399: postTypeStack.topIndex() - 3),
3400: Util.v()
3401: .getLocalForStackOp(listBody,
3402: postTypeStack,
3403: postTypeStack.topIndex()));
3404:
3405: statements.add(stmt);
3406:
3407: stmt = null;
3408: }
3409: break;
3410:
3411: case ByteCode.DUP2_X1:
3412: if (typeSize(typeStack.get(typeStack.topIndex() - 1)) == 2) {
3413: l2 = Util.v().getLocalForStackOp(listBody, typeStack,
3414: typeStack.topIndex() - 1);
3415: l3 = Util.v().getLocalForStackOp(listBody, typeStack,
3416: typeStack.topIndex() - 2);
3417:
3418: stmt = Jimple.v().newAssignStmt(
3419: Util.v().getLocalForStackOp(listBody,
3420: postTypeStack,
3421: postTypeStack.topIndex() - 1), l2);
3422:
3423: statements.add(stmt);
3424:
3425: stmt = Jimple.v().newAssignStmt(
3426: Util.v().getLocalForStackOp(listBody,
3427: postTypeStack,
3428: postTypeStack.topIndex() - 2), l3);
3429:
3430: statements.add(stmt);
3431:
3432: stmt = Jimple.v().newAssignStmt(
3433: Util.v().getLocalForStackOp(listBody,
3434: postTypeStack,
3435: postTypeStack.topIndex() - 4),
3436: Util.v().getLocalForStackOp(listBody,
3437: postTypeStack,
3438: postTypeStack.topIndex() - 1));
3439:
3440: statements.add(stmt);
3441:
3442: stmt = null;
3443: } else {
3444: l3 = Util.v().getLocalForStackOp(listBody, typeStack,
3445: typeStack.topIndex() - 2);
3446: l2 = Util.v().getLocalForStackOp(listBody, typeStack,
3447: typeStack.topIndex() - 1);
3448: l1 = Util.v().getLocalForStackOp(listBody, typeStack,
3449: typeStack.topIndex());
3450:
3451: stmt = Jimple.v().newAssignStmt(
3452: Util.v()
3453: .getLocalForStackOp(listBody,
3454: postTypeStack,
3455: postTypeStack.topIndex()), l1);
3456:
3457: statements.add(stmt);
3458:
3459: stmt = Jimple.v().newAssignStmt(
3460: Util.v().getLocalForStackOp(listBody,
3461: postTypeStack,
3462: postTypeStack.topIndex() - 1), l2);
3463:
3464: statements.add(stmt);
3465:
3466: stmt = Jimple.v().newAssignStmt(
3467: Util.v().getLocalForStackOp(listBody,
3468: postTypeStack,
3469: postTypeStack.topIndex() - 2), l3);
3470:
3471: statements.add(stmt);
3472:
3473: stmt = Jimple.v().newAssignStmt(
3474: Util.v().getLocalForStackOp(listBody,
3475: postTypeStack,
3476: postTypeStack.topIndex() - 3),
3477: Util.v()
3478: .getLocalForStackOp(listBody,
3479: postTypeStack,
3480: postTypeStack.topIndex()));
3481:
3482: statements.add(stmt);
3483:
3484: stmt = Jimple.v().newAssignStmt(
3485: Util.v().getLocalForStackOp(listBody,
3486: postTypeStack,
3487: postTypeStack.topIndex() - 4),
3488: Util.v().getLocalForStackOp(listBody,
3489: postTypeStack,
3490: postTypeStack.topIndex() - 1));
3491:
3492: statements.add(stmt);
3493:
3494: stmt = null;
3495: }
3496: break;
3497:
3498: case ByteCode.DUP2_X2:
3499: if (typeSize(typeStack.get(typeStack.topIndex() - 1)) == 2) {
3500: l2 = Util.v().getLocalForStackOp(listBody, typeStack,
3501: typeStack.topIndex() - 1);
3502:
3503: stmt = Jimple.v().newAssignStmt(
3504: Util.v().getLocalForStackOp(listBody,
3505: postTypeStack,
3506: postTypeStack.topIndex() - 1), l2);
3507:
3508: statements.add(stmt);
3509: } else {
3510: l1 = Util.v().getLocalForStackOp(listBody, typeStack,
3511: typeStack.topIndex());
3512: l2 = Util.v().getLocalForStackOp(listBody, typeStack,
3513: typeStack.topIndex() - 1);
3514:
3515: stmt = Jimple.v().newAssignStmt(
3516: Util.v().getLocalForStackOp(listBody,
3517: postTypeStack,
3518: postTypeStack.topIndex() - 1), l2);
3519:
3520: statements.add(stmt);
3521:
3522: stmt = Jimple.v().newAssignStmt(
3523: Util.v()
3524: .getLocalForStackOp(listBody,
3525: postTypeStack,
3526: postTypeStack.topIndex()), l1);
3527:
3528: statements.add(stmt);
3529:
3530: }
3531:
3532: if (typeSize(typeStack.get(typeStack.topIndex() - 3)) == 2) {
3533: l4 = Util.v().getLocalForStackOp(listBody, typeStack,
3534: typeStack.topIndex() - 3);
3535:
3536: stmt = Jimple.v().newAssignStmt(
3537: Util.v().getLocalForStackOp(listBody,
3538: postTypeStack,
3539: postTypeStack.topIndex() - 3), l4);
3540:
3541: statements.add(stmt);
3542: } else {
3543: l4 = Util.v().getLocalForStackOp(listBody, typeStack,
3544: typeStack.topIndex() - 3);
3545: l3 = Util.v().getLocalForStackOp(listBody, typeStack,
3546: typeStack.topIndex() - 2);
3547:
3548: stmt = Jimple.v().newAssignStmt(
3549: Util.v().getLocalForStackOp(listBody,
3550: postTypeStack,
3551: postTypeStack.topIndex() - 3), l4);
3552:
3553: statements.add(stmt);
3554:
3555: stmt = Jimple.v().newAssignStmt(
3556: Util.v().getLocalForStackOp(listBody,
3557: postTypeStack,
3558: postTypeStack.topIndex() - 2), l3);
3559:
3560: statements.add(stmt);
3561:
3562: }
3563:
3564: if (typeSize(typeStack.get(typeStack.topIndex() - 1)) == 2) {
3565: stmt = Jimple.v().newAssignStmt(
3566: Util.v().getLocalForStackOp(listBody,
3567: postTypeStack,
3568: postTypeStack.topIndex() - 5),
3569: Util.v().getLocalForStackOp(listBody,
3570: postTypeStack,
3571: postTypeStack.topIndex() - 1));
3572:
3573: statements.add(stmt);
3574: } else {
3575: stmt = Jimple.v().newAssignStmt(
3576: Util.v().getLocalForStackOp(listBody,
3577: postTypeStack,
3578: postTypeStack.topIndex() - 5),
3579: Util.v().getLocalForStackOp(listBody,
3580: postTypeStack,
3581: postTypeStack.topIndex() - 1));
3582:
3583: statements.add(stmt);
3584:
3585: stmt = Jimple.v().newAssignStmt(
3586: Util.v().getLocalForStackOp(listBody,
3587: postTypeStack,
3588: postTypeStack.topIndex() - 4),
3589: Util.v()
3590: .getLocalForStackOp(listBody,
3591: postTypeStack,
3592: postTypeStack.topIndex()));
3593:
3594: statements.add(stmt);
3595: }
3596: stmt = null;
3597: break;
3598:
3599: case ByteCode.SWAP: {
3600: Local first;
3601:
3602: typeStack = typeStack.push(typeStack.top());
3603: first = Util.v().getLocalForStackOp(listBody, typeStack,
3604: typeStack.topIndex());
3605: typeStack = typeStack.pop();
3606: // generation of a free temporary
3607:
3608: Local second = Util.v().getLocalForStackOp(listBody,
3609: postTypeStack, postTypeStack.topIndex());
3610:
3611: Local third = Util.v().getLocalForStackOp(listBody,
3612: postTypeStack, postTypeStack.topIndex() - 1);
3613:
3614: stmt = Jimple.v().newAssignStmt(first, second);
3615: statements.add(stmt);
3616:
3617: stmt = Jimple.v().newAssignStmt(second, third);
3618: statements.add(stmt);
3619:
3620: stmt = Jimple.v().newAssignStmt(third, first);
3621: statements.add(stmt);
3622:
3623: stmt = null;
3624: break;
3625: }
3626:
3627: case ByteCode.FADD:
3628: case ByteCode.IADD:
3629: rhs = Jimple.v().newAddExpr(
3630: Util.v().getLocalForStackOp(listBody, typeStack,
3631: typeStack.topIndex() - 1),
3632: Util.v().getLocalForStackOp(listBody, typeStack,
3633: typeStack.topIndex()));
3634:
3635: stmt = Jimple.v().newAssignStmt(
3636: Util.v().getLocalForStackOp(listBody,
3637: postTypeStack, postTypeStack.topIndex()),
3638: rhs);
3639: break;
3640:
3641: case ByteCode.DADD:
3642: case ByteCode.LADD:
3643: rhs = Jimple.v().newAddExpr(
3644: Util.v().getLocalForStackOp(listBody, typeStack,
3645: typeStack.topIndex() - 3),
3646: Util.v().getLocalForStackOp(listBody, typeStack,
3647: typeStack.topIndex() - 1));
3648:
3649: stmt = Jimple.v().newAssignStmt(
3650: Util.v().getLocalForStackOp(listBody,
3651: postTypeStack, postTypeStack.topIndex()),
3652: rhs);
3653: break;
3654:
3655: case ByteCode.FSUB:
3656: case ByteCode.ISUB:
3657: rhs = Jimple.v().newSubExpr(
3658: Util.v().getLocalForStackOp(listBody, typeStack,
3659: typeStack.topIndex() - 1),
3660: Util.v().getLocalForStackOp(listBody, typeStack,
3661: typeStack.topIndex()));
3662:
3663: stmt = Jimple.v().newAssignStmt(
3664: Util.v().getLocalForStackOp(listBody,
3665: postTypeStack, postTypeStack.topIndex()),
3666: rhs);
3667: break;
3668:
3669: case ByteCode.DSUB:
3670: case ByteCode.LSUB:
3671: rhs = Jimple.v().newSubExpr(
3672: Util.v().getLocalForStackOp(listBody, typeStack,
3673: typeStack.topIndex() - 3),
3674: Util.v().getLocalForStackOp(listBody, typeStack,
3675: typeStack.topIndex() - 1));
3676:
3677: stmt = Jimple.v().newAssignStmt(
3678: Util.v().getLocalForStackOp(listBody,
3679: postTypeStack, postTypeStack.topIndex()),
3680: rhs);
3681: break;
3682:
3683: case ByteCode.FMUL:
3684: case ByteCode.IMUL:
3685: rhs = Jimple.v().newMulExpr(
3686: Util.v().getLocalForStackOp(listBody, typeStack,
3687: typeStack.topIndex() - 1),
3688: Util.v().getLocalForStackOp(listBody, typeStack,
3689: typeStack.topIndex()));
3690:
3691: stmt = Jimple.v().newAssignStmt(
3692: Util.v().getLocalForStackOp(listBody,
3693: postTypeStack, postTypeStack.topIndex()),
3694: rhs);
3695: break;
3696:
3697: case ByteCode.DMUL:
3698: case ByteCode.LMUL:
3699: rhs = Jimple.v().newMulExpr(
3700: Util.v().getLocalForStackOp(listBody, typeStack,
3701: typeStack.topIndex() - 3),
3702: Util.v().getLocalForStackOp(listBody, typeStack,
3703: typeStack.topIndex() - 1));
3704:
3705: stmt = Jimple.v().newAssignStmt(
3706: Util.v().getLocalForStackOp(listBody,
3707: postTypeStack, postTypeStack.topIndex()),
3708: rhs);
3709: break;
3710:
3711: case ByteCode.FDIV:
3712: case ByteCode.IDIV:
3713: rhs = Jimple.v().newDivExpr(
3714: Util.v().getLocalForStackOp(listBody, typeStack,
3715: typeStack.topIndex() - 1),
3716: Util.v().getLocalForStackOp(listBody, typeStack,
3717: typeStack.topIndex()));
3718:
3719: stmt = Jimple.v().newAssignStmt(
3720: Util.v().getLocalForStackOp(listBody,
3721: postTypeStack, postTypeStack.topIndex()),
3722: rhs);
3723: break;
3724:
3725: case ByteCode.DDIV:
3726: case ByteCode.LDIV:
3727: rhs = Jimple.v().newDivExpr(
3728: Util.v().getLocalForStackOp(listBody, typeStack,
3729: typeStack.topIndex() - 3),
3730: Util.v().getLocalForStackOp(listBody, typeStack,
3731: typeStack.topIndex() - 1));
3732:
3733: stmt = Jimple.v().newAssignStmt(
3734: Util.v().getLocalForStackOp(listBody,
3735: postTypeStack, postTypeStack.topIndex()),
3736: rhs);
3737: break;
3738:
3739: case ByteCode.FREM:
3740: case ByteCode.IREM:
3741: rhs = Jimple.v().newRemExpr(
3742: Util.v().getLocalForStackOp(listBody, typeStack,
3743: typeStack.topIndex() - 1),
3744: Util.v().getLocalForStackOp(listBody, typeStack,
3745: typeStack.topIndex()));
3746:
3747: stmt = Jimple.v().newAssignStmt(
3748: Util.v().getLocalForStackOp(listBody,
3749: postTypeStack, postTypeStack.topIndex()),
3750: rhs);
3751: break;
3752:
3753: case ByteCode.DREM:
3754: case ByteCode.LREM:
3755: rhs = Jimple.v().newRemExpr(
3756: Util.v().getLocalForStackOp(listBody, typeStack,
3757: typeStack.topIndex() - 3),
3758: Util.v().getLocalForStackOp(listBody, typeStack,
3759: typeStack.topIndex() - 1));
3760:
3761: stmt = Jimple.v().newAssignStmt(
3762: Util.v().getLocalForStackOp(listBody,
3763: postTypeStack, postTypeStack.topIndex()),
3764: rhs);
3765: break;
3766:
3767: case ByteCode.INEG:
3768: case ByteCode.LNEG:
3769: case ByteCode.FNEG:
3770: case ByteCode.DNEG:
3771: rhs = Jimple.v().newNegExpr(
3772: Util.v().getLocalForStackOp(listBody, typeStack,
3773: typeStack.topIndex()));
3774: stmt = Jimple.v().newAssignStmt(
3775: Util.v().getLocalForStackOp(listBody,
3776: postTypeStack, postTypeStack.topIndex()),
3777: rhs);
3778: break;
3779:
3780: case ByteCode.ISHL:
3781: rhs = Jimple.v().newShlExpr(
3782: Util.v().getLocalForStackOp(listBody, typeStack,
3783: typeStack.topIndex() - 1),
3784: Util.v().getLocalForStackOp(listBody, typeStack,
3785: typeStack.topIndex()));
3786:
3787: stmt = Jimple.v().newAssignStmt(
3788: Util.v().getLocalForStackOp(listBody,
3789: postTypeStack, postTypeStack.topIndex()),
3790: rhs);
3791: break;
3792:
3793: case ByteCode.ISHR:
3794: rhs = Jimple.v().newShrExpr(
3795: Util.v().getLocalForStackOp(listBody, typeStack,
3796: typeStack.topIndex() - 1),
3797: Util.v().getLocalForStackOp(listBody, typeStack,
3798: typeStack.topIndex()));
3799:
3800: stmt = Jimple.v().newAssignStmt(
3801: Util.v().getLocalForStackOp(listBody,
3802: postTypeStack, postTypeStack.topIndex()),
3803: rhs);
3804: break;
3805:
3806: case ByteCode.IUSHR:
3807: rhs = Jimple.v().newUshrExpr(
3808: Util.v().getLocalForStackOp(listBody, typeStack,
3809: typeStack.topIndex() - 1),
3810: Util.v().getLocalForStackOp(listBody, typeStack,
3811: typeStack.topIndex()));
3812:
3813: stmt = Jimple.v().newAssignStmt(
3814: Util.v().getLocalForStackOp(listBody,
3815: postTypeStack, postTypeStack.topIndex()),
3816: rhs);
3817: break;
3818:
3819: case ByteCode.LSHL:
3820: rhs = Jimple.v().newShlExpr(
3821: Util.v().getLocalForStackOp(listBody, typeStack,
3822: typeStack.topIndex() - 2),
3823: Util.v().getLocalForStackOp(listBody, typeStack,
3824: typeStack.topIndex()));
3825:
3826: stmt = Jimple.v().newAssignStmt(
3827: Util.v().getLocalForStackOp(listBody,
3828: postTypeStack, postTypeStack.topIndex()),
3829: rhs);
3830: break;
3831:
3832: case ByteCode.LSHR:
3833: rhs = Jimple.v().newShrExpr(
3834: Util.v().getLocalForStackOp(listBody, typeStack,
3835: typeStack.topIndex() - 2),
3836: Util.v().getLocalForStackOp(listBody, typeStack,
3837: typeStack.topIndex()));
3838:
3839: stmt = Jimple.v().newAssignStmt(
3840: Util.v().getLocalForStackOp(listBody,
3841: postTypeStack, postTypeStack.topIndex()),
3842: rhs);
3843: break;
3844:
3845: case ByteCode.LUSHR:
3846: rhs = Jimple.v().newUshrExpr(
3847: Util.v().getLocalForStackOp(listBody, typeStack,
3848: typeStack.topIndex() - 2),
3849: Util.v().getLocalForStackOp(listBody, typeStack,
3850: typeStack.topIndex()));
3851:
3852: stmt = Jimple.v().newAssignStmt(
3853: Util.v().getLocalForStackOp(listBody,
3854: postTypeStack, postTypeStack.topIndex()),
3855: rhs);
3856: break;
3857:
3858: case ByteCode.IAND:
3859: rhs = Jimple.v().newAndExpr(
3860: Util.v().getLocalForStackOp(listBody, typeStack,
3861: typeStack.topIndex() - 1),
3862: Util.v().getLocalForStackOp(listBody, typeStack,
3863: typeStack.topIndex()));
3864:
3865: stmt = Jimple.v().newAssignStmt(
3866: Util.v().getLocalForStackOp(listBody,
3867: postTypeStack, postTypeStack.topIndex()),
3868: rhs);
3869: break;
3870:
3871: case ByteCode.LAND:
3872: rhs = Jimple.v().newAndExpr(
3873: Util.v().getLocalForStackOp(listBody, typeStack,
3874: typeStack.topIndex() - 3),
3875: Util.v().getLocalForStackOp(listBody, typeStack,
3876: typeStack.topIndex() - 1));
3877:
3878: stmt = Jimple.v().newAssignStmt(
3879: Util.v().getLocalForStackOp(listBody,
3880: postTypeStack, postTypeStack.topIndex()),
3881: rhs);
3882: break;
3883:
3884: case ByteCode.IOR:
3885: rhs = Jimple.v().newOrExpr(
3886: Util.v().getLocalForStackOp(listBody, typeStack,
3887: typeStack.topIndex() - 1),
3888: Util.v().getLocalForStackOp(listBody, typeStack,
3889: typeStack.topIndex()));
3890:
3891: stmt = Jimple.v().newAssignStmt(
3892: Util.v().getLocalForStackOp(listBody,
3893: postTypeStack, postTypeStack.topIndex()),
3894: rhs);
3895: break;
3896:
3897: case ByteCode.LOR:
3898: rhs = Jimple.v().newOrExpr(
3899: Util.v().getLocalForStackOp(listBody, typeStack,
3900: typeStack.topIndex() - 3),
3901: Util.v().getLocalForStackOp(listBody, typeStack,
3902: typeStack.topIndex() - 1));
3903:
3904: stmt = Jimple.v().newAssignStmt(
3905: Util.v().getLocalForStackOp(listBody,
3906: postTypeStack, postTypeStack.topIndex()),
3907: rhs);
3908: break;
3909:
3910: case ByteCode.IXOR:
3911: rhs = Jimple.v().newXorExpr(
3912: Util.v().getLocalForStackOp(listBody, typeStack,
3913: typeStack.topIndex() - 1),
3914: Util.v().getLocalForStackOp(listBody, typeStack,
3915: typeStack.topIndex()));
3916:
3917: stmt = Jimple.v().newAssignStmt(
3918: Util.v().getLocalForStackOp(listBody,
3919: postTypeStack, postTypeStack.topIndex()),
3920: rhs);
3921: break;
3922:
3923: case ByteCode.LXOR:
3924: rhs = Jimple.v().newXorExpr(
3925: Util.v().getLocalForStackOp(listBody, typeStack,
3926: typeStack.topIndex() - 3),
3927: Util.v().getLocalForStackOp(listBody, typeStack,
3928: typeStack.topIndex() - 1));
3929:
3930: stmt = Jimple.v().newAssignStmt(
3931: Util.v().getLocalForStackOp(listBody,
3932: postTypeStack, postTypeStack.topIndex()),
3933: rhs);
3934: break;
3935:
3936: case ByteCode.D2L:
3937: case ByteCode.F2L:
3938: case ByteCode.I2L:
3939: rhs = Jimple.v().newCastExpr(
3940: Util.v().getLocalForStackOp(listBody, typeStack,
3941: typeStack.topIndex()), LongType.v());
3942:
3943: stmt = Jimple.v().newAssignStmt(
3944: Util.v().getLocalForStackOp(listBody,
3945: postTypeStack, postTypeStack.topIndex()),
3946: rhs);
3947: break;
3948:
3949: case ByteCode.D2F:
3950: case ByteCode.L2F:
3951: case ByteCode.I2F:
3952: rhs = Jimple.v().newCastExpr(
3953: Util.v().getLocalForStackOp(listBody, typeStack,
3954: typeStack.topIndex()), FloatType.v());
3955:
3956: stmt = Jimple.v().newAssignStmt(
3957: Util.v().getLocalForStackOp(listBody,
3958: postTypeStack, postTypeStack.topIndex()),
3959: rhs);
3960: break;
3961:
3962: case ByteCode.I2D:
3963: case ByteCode.L2D:
3964: case ByteCode.F2D:
3965: rhs = Jimple.v().newCastExpr(
3966: Util.v().getLocalForStackOp(listBody, typeStack,
3967: typeStack.topIndex()), DoubleType.v());
3968:
3969: stmt = Jimple.v().newAssignStmt(
3970: Util.v().getLocalForStackOp(listBody,
3971: postTypeStack, postTypeStack.topIndex()),
3972: rhs);
3973: break;
3974:
3975: case ByteCode.L2I:
3976: case ByteCode.F2I:
3977: case ByteCode.D2I:
3978: rhs = Jimple.v().newCastExpr(
3979: Util.v().getLocalForStackOp(listBody, typeStack,
3980: typeStack.topIndex()), IntType.v());
3981:
3982: stmt = Jimple.v().newAssignStmt(
3983: Util.v().getLocalForStackOp(listBody,
3984: postTypeStack, postTypeStack.topIndex()),
3985: rhs);
3986: break;
3987:
3988: case ByteCode.INT2BYTE:
3989: rhs = Jimple.v().newCastExpr(
3990: Util.v().getLocalForStackOp(listBody, typeStack,
3991: typeStack.topIndex()), ByteType.v());
3992:
3993: stmt = Jimple.v().newAssignStmt(
3994: Util.v().getLocalForStackOp(listBody,
3995: postTypeStack, postTypeStack.topIndex()),
3996: rhs);
3997: break;
3998:
3999: case ByteCode.INT2CHAR:
4000: rhs = Jimple.v().newCastExpr(
4001: Util.v().getLocalForStackOp(listBody, typeStack,
4002: typeStack.topIndex()), CharType.v());
4003:
4004: stmt = Jimple.v().newAssignStmt(
4005: Util.v().getLocalForStackOp(listBody,
4006: postTypeStack, postTypeStack.topIndex()),
4007: rhs);
4008: break;
4009:
4010: case ByteCode.INT2SHORT:
4011: rhs = Jimple.v().newCastExpr(
4012: Util.v().getLocalForStackOp(listBody, typeStack,
4013: typeStack.topIndex()), ShortType.v());
4014:
4015: stmt = Jimple.v().newAssignStmt(
4016: Util.v().getLocalForStackOp(listBody,
4017: postTypeStack, postTypeStack.topIndex()),
4018: rhs);
4019: break;
4020:
4021: case ByteCode.IFEQ:
4022: co = Jimple.v().newEqExpr(
4023: Util.v().getLocalForStackOp(listBody, typeStack,
4024: typeStack.topIndex()), IntConstant.v(0));
4025:
4026: stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4027: break;
4028:
4029: case ByteCode.IFNULL:
4030: co = Jimple.v().newEqExpr(
4031: Util.v().getLocalForStackOp(listBody, typeStack,
4032: typeStack.topIndex()), NullConstant.v());
4033:
4034: stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4035: break;
4036:
4037: case ByteCode.IFLT:
4038: co = Jimple.v().newLtExpr(
4039: Util.v().getLocalForStackOp(listBody, typeStack,
4040: typeStack.topIndex()), IntConstant.v(0));
4041:
4042: stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4043: break;
4044:
4045: case ByteCode.IFLE:
4046: co = Jimple.v().newLeExpr(
4047: Util.v().getLocalForStackOp(listBody, typeStack,
4048: typeStack.topIndex()), IntConstant.v(0));
4049:
4050: stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4051: break;
4052:
4053: case ByteCode.IFNE:
4054: co = Jimple.v().newNeExpr(
4055: Util.v().getLocalForStackOp(listBody, typeStack,
4056: typeStack.topIndex()), IntConstant.v(0));
4057:
4058: stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4059: break;
4060:
4061: case ByteCode.IFNONNULL:
4062: co = Jimple.v().newNeExpr(
4063: Util.v().getLocalForStackOp(listBody, typeStack,
4064: typeStack.topIndex()), NullConstant.v());
4065:
4066: stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4067: break;
4068:
4069: case ByteCode.IFGT:
4070: co = Jimple.v().newGtExpr(
4071: Util.v().getLocalForStackOp(listBody, typeStack,
4072: typeStack.topIndex()), IntConstant.v(0));
4073:
4074: stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4075: break;
4076:
4077: case ByteCode.IFGE:
4078: co = Jimple.v().newGeExpr(
4079: Util.v().getLocalForStackOp(listBody, typeStack,
4080: typeStack.topIndex()), IntConstant.v(0));
4081:
4082: stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4083: break;
4084:
4085: case ByteCode.IF_ICMPEQ:
4086: co = Jimple.v().newEqExpr(
4087: Util.v().getLocalForStackOp(listBody, typeStack,
4088: typeStack.topIndex() - 1),
4089: Util.v().getLocalForStackOp(listBody, typeStack,
4090: typeStack.topIndex()));
4091:
4092: stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4093: break;
4094:
4095: case ByteCode.IF_ICMPLT:
4096: co = Jimple.v().newLtExpr(
4097: Util.v().getLocalForStackOp(listBody, typeStack,
4098: typeStack.topIndex() - 1),
4099: Util.v().getLocalForStackOp(listBody, typeStack,
4100: typeStack.topIndex()));
4101:
4102: stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4103: break;
4104:
4105: case ByteCode.IF_ICMPLE:
4106: co = Jimple.v().newLeExpr(
4107: Util.v().getLocalForStackOp(listBody, typeStack,
4108: typeStack.topIndex() - 1),
4109: Util.v().getLocalForStackOp(listBody, typeStack,
4110: typeStack.topIndex()));
4111:
4112: stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4113: break;
4114:
4115: case ByteCode.IF_ICMPNE:
4116: co = Jimple.v().newNeExpr(
4117: Util.v().getLocalForStackOp(listBody, typeStack,
4118: typeStack.topIndex() - 1),
4119: Util.v().getLocalForStackOp(listBody, typeStack,
4120: typeStack.topIndex()));
4121:
4122: stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4123: break;
4124:
4125: case ByteCode.IF_ICMPGT:
4126: co = Jimple.v().newGtExpr(
4127: Util.v().getLocalForStackOp(listBody, typeStack,
4128: typeStack.topIndex() - 1),
4129: Util.v().getLocalForStackOp(listBody, typeStack,
4130: typeStack.topIndex()));
4131:
4132: stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4133: break;
4134:
4135: case ByteCode.IF_ICMPGE:
4136: co = Jimple.v().newGeExpr(
4137: Util.v().getLocalForStackOp(listBody, typeStack,
4138: typeStack.topIndex() - 1),
4139: Util.v().getLocalForStackOp(listBody, typeStack,
4140: typeStack.topIndex()));
4141:
4142: stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4143: break;
4144:
4145: case ByteCode.LCMP:
4146: rhs = Jimple.v().newCmpExpr(
4147: Util.v().getLocalForStackOp(listBody, typeStack,
4148: typeStack.topIndex() - 3),
4149: Util.v().getLocalForStackOp(listBody, typeStack,
4150: typeStack.topIndex() - 1));
4151:
4152: stmt = Jimple.v().newAssignStmt(
4153: Util.v().getLocalForStackOp(listBody,
4154: postTypeStack, postTypeStack.topIndex()),
4155: rhs);
4156: break;
4157:
4158: case ByteCode.FCMPL:
4159: rhs = Jimple.v().newCmplExpr(
4160: Util.v().getLocalForStackOp(listBody, typeStack,
4161: typeStack.topIndex() - 1),
4162: Util.v().getLocalForStackOp(listBody, typeStack,
4163: typeStack.topIndex()));
4164:
4165: stmt = Jimple.v().newAssignStmt(
4166: Util.v().getLocalForStackOp(listBody,
4167: postTypeStack, postTypeStack.topIndex()),
4168: rhs);
4169: break;
4170:
4171: case ByteCode.FCMPG:
4172: rhs = Jimple.v().newCmpgExpr(
4173: Util.v().getLocalForStackOp(listBody, typeStack,
4174: typeStack.topIndex() - 1),
4175: Util.v().getLocalForStackOp(listBody, typeStack,
4176: typeStack.topIndex()));
4177:
4178: stmt = Jimple.v().newAssignStmt(
4179: Util.v().getLocalForStackOp(listBody,
4180: postTypeStack, postTypeStack.topIndex()),
4181: rhs);
4182: break;
4183:
4184: case ByteCode.DCMPL:
4185: rhs = Jimple.v().newCmplExpr(
4186: Util.v().getLocalForStackOp(listBody, typeStack,
4187: typeStack.topIndex() - 3),
4188: Util.v().getLocalForStackOp(listBody, typeStack,
4189: typeStack.topIndex() - 1));
4190:
4191: stmt = Jimple.v().newAssignStmt(
4192: Util.v().getLocalForStackOp(listBody,
4193: postTypeStack, postTypeStack.topIndex()),
4194: rhs);
4195: break;
4196:
4197: case ByteCode.DCMPG:
4198: rhs = Jimple.v().newCmpgExpr(
4199: Util.v().getLocalForStackOp(listBody, typeStack,
4200: typeStack.topIndex() - 3),
4201: Util.v().getLocalForStackOp(listBody, typeStack,
4202: typeStack.topIndex() - 1));
4203:
4204: stmt = Jimple.v().newAssignStmt(
4205: Util.v().getLocalForStackOp(listBody,
4206: postTypeStack, postTypeStack.topIndex()),
4207: rhs);
4208: break;
4209:
4210: case ByteCode.IF_ACMPEQ:
4211: co = Jimple.v().newEqExpr(
4212: Util.v().getLocalForStackOp(listBody, typeStack,
4213: typeStack.topIndex() - 1),
4214: Util.v().getLocalForStackOp(listBody, typeStack,
4215: typeStack.topIndex()));
4216:
4217: stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4218: break;
4219:
4220: case ByteCode.IF_ACMPNE:
4221: co = Jimple.v().newNeExpr(
4222: Util.v().getLocalForStackOp(listBody, typeStack,
4223: typeStack.topIndex() - 1),
4224: Util.v().getLocalForStackOp(listBody, typeStack,
4225: typeStack.topIndex()));
4226:
4227: stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4228: break;
4229:
4230: case ByteCode.GOTO:
4231: stmt = Jimple.v().newGotoStmt(new FutureStmt());
4232: break;
4233:
4234: case ByteCode.GOTO_W:
4235: stmt = Jimple.v().newGotoStmt(new FutureStmt());
4236: break;
4237: /*
4238: case ByteCode.JSR:
4239: case ByteCode.JSR_W:
4240: {
4241: stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
4242: postTypeStack.topIndex()), Jimple.v().newNextNextStmtRef());
4243:
4244: statements.add(stmt);
4245:
4246: stmt = Jimple.v().newGotoStmt(new FutureStmt());
4247: statements.add(stmt);
4248:
4249: stmt = null;
4250: break;
4251: }
4252: */
4253:
4254: case ByteCode.RET: {
4255: Local local = Util.v().getLocalForIndex(listBody,
4256: ((Instruction_Ret) ins).arg_b);
4257:
4258: stmt = Jimple.v().newRetStmt(local);
4259: break;
4260: }
4261:
4262: case ByteCode.RET_W: {
4263: Local local = Util.v().getLocalForIndex(listBody,
4264: ((Instruction_Ret_w) ins).arg_i);
4265:
4266: stmt = Jimple.v().newRetStmt(local);
4267: break;
4268: }
4269:
4270: case ByteCode.RETURN:
4271: stmt = Jimple.v().newReturnVoidStmt();
4272: break;
4273:
4274: case ByteCode.LRETURN:
4275: case ByteCode.DRETURN:
4276: case ByteCode.IRETURN:
4277: case ByteCode.FRETURN:
4278: case ByteCode.ARETURN:
4279: stmt = Jimple.v().newReturnStmt(
4280: Util.v().getLocalForStackOp(listBody, typeStack,
4281: typeStack.topIndex()));
4282: break;
4283:
4284: case ByteCode.BREAKPOINT:
4285: stmt = Jimple.v().newBreakpointStmt();
4286: break;
4287:
4288: case ByteCode.TABLESWITCH: {
4289: int lowIndex = ((Instruction_Tableswitch) ins).low, highIndex = ((Instruction_Tableswitch) ins).high;
4290:
4291: stmt = Jimple.v().newTableSwitchStmt(
4292: Util.v().getLocalForStackOp(listBody, typeStack,
4293: typeStack.topIndex()),
4294: lowIndex,
4295: highIndex,
4296: Arrays.asList(new FutureStmt[highIndex - lowIndex
4297: + 1]), new FutureStmt());
4298: break;
4299: }
4300:
4301: case ByteCode.LOOKUPSWITCH: {
4302: List matches = new ArrayList();
4303: int npairs = ((Instruction_Lookupswitch) ins).npairs;
4304:
4305: for (int j = 0; j < npairs; j++)
4306: matches
4307: .add(IntConstant
4308: .v(((Instruction_Lookupswitch) ins).match_offsets[j * 2]));
4309:
4310: stmt = Jimple.v().newLookupSwitchStmt(
4311: Util.v().getLocalForStackOp(listBody, typeStack,
4312: typeStack.topIndex()), matches,
4313: Arrays.asList(new FutureStmt[npairs]),
4314: new FutureStmt());
4315: break;
4316: }
4317:
4318: case ByteCode.PUTFIELD: {
4319: CONSTANT_Fieldref_info fieldInfo = (CONSTANT_Fieldref_info) constant_pool[((Instruction_Putfield) ins).arg_i];
4320:
4321: CONSTANT_Class_info c = (CONSTANT_Class_info) constant_pool[fieldInfo.class_index];
4322:
4323: String className = ((CONSTANT_Utf8_info) (constant_pool[c.name_index]))
4324: .convert();
4325: className = className.replace('/', '.');
4326:
4327: CONSTANT_NameAndType_info i = (CONSTANT_NameAndType_info) constant_pool[fieldInfo.name_and_type_index];
4328:
4329: String fieldName = ((CONSTANT_Utf8_info) (constant_pool[i.name_index]))
4330: .convert();
4331: String fieldDescriptor = ((CONSTANT_Utf8_info) (constant_pool[i.descriptor_index]))
4332: .convert();
4333:
4334: Type fieldType = Util.v().jimpleTypeOfFieldDescriptor(
4335: fieldDescriptor);
4336:
4337: SootClass bclass = cm.getSootClass(className);
4338:
4339: SootFieldRef fieldRef = Scene.v().makeFieldRef(bclass,
4340: fieldName, fieldType, false);
4341:
4342: InstanceFieldRef fr = Jimple.v().newInstanceFieldRef(
4343: Util.v().getLocalForStackOp(
4344: listBody,
4345: typeStack,
4346: typeStack.topIndex()
4347: - typeSize(typeStack.top())),
4348: fieldRef);
4349:
4350: rvalue = Util.v().getLocalForStackOp(listBody, typeStack,
4351: typeStack.topIndex());
4352: stmt = Jimple.v().newAssignStmt(fr, rvalue);
4353: break;
4354: }
4355:
4356: case ByteCode.GETFIELD: {
4357: InstanceFieldRef fr = null;
4358:
4359: CONSTANT_Fieldref_info fieldInfo = (CONSTANT_Fieldref_info) constant_pool[((Instruction_Getfield) ins).arg_i];
4360:
4361: CONSTANT_Class_info c = (CONSTANT_Class_info) constant_pool[fieldInfo.class_index];
4362:
4363: String className = ((CONSTANT_Utf8_info) (constant_pool[c.name_index]))
4364: .convert();
4365: className = className.replace('/', '.');
4366:
4367: CONSTANT_NameAndType_info i = (CONSTANT_NameAndType_info) constant_pool[fieldInfo.name_and_type_index];
4368:
4369: String fieldName = ((CONSTANT_Utf8_info) (constant_pool[i.name_index]))
4370: .convert();
4371: String fieldDescriptor = ((CONSTANT_Utf8_info) (constant_pool[i.descriptor_index]))
4372: .convert();
4373:
4374: if (className.charAt(0) == '[')
4375: className = "java.lang.Object";
4376:
4377: SootClass bclass = cm.getSootClass(className);
4378:
4379: Type fieldType = Util.v().jimpleTypeOfFieldDescriptor(
4380: fieldDescriptor);
4381: SootFieldRef fieldRef = Scene.v().makeFieldRef(bclass,
4382: fieldName, fieldType, false);
4383:
4384: fr = Jimple.v().newInstanceFieldRef(
4385: Util.v().getLocalForStackOp(listBody, typeStack,
4386: typeStack.topIndex()), fieldRef);
4387:
4388: stmt = Jimple.v().newAssignStmt(
4389: Util.v().getLocalForStackOp(listBody,
4390: postTypeStack, postTypeStack.topIndex()),
4391: fr);
4392: break;
4393: }
4394:
4395: case ByteCode.PUTSTATIC: {
4396: StaticFieldRef fr = null;
4397:
4398: CONSTANT_Fieldref_info fieldInfo = (CONSTANT_Fieldref_info) constant_pool[((Instruction_Putstatic) ins).arg_i];
4399:
4400: CONSTANT_Class_info c = (CONSTANT_Class_info) constant_pool[fieldInfo.class_index];
4401:
4402: String className = ((CONSTANT_Utf8_info) (constant_pool[c.name_index]))
4403: .convert();
4404: className = className.replace('/', '.');
4405:
4406: CONSTANT_NameAndType_info i = (CONSTANT_NameAndType_info) constant_pool[fieldInfo.name_and_type_index];
4407:
4408: String fieldName = ((CONSTANT_Utf8_info) (constant_pool[i.name_index]))
4409: .convert();
4410: String fieldDescriptor = ((CONSTANT_Utf8_info) (constant_pool[i.descriptor_index]))
4411: .convert();
4412:
4413: Type fieldType = Util.v().jimpleTypeOfFieldDescriptor(
4414: fieldDescriptor);
4415:
4416: SootClass bclass = cm.getSootClass(className);
4417: SootFieldRef fieldRef = Scene.v().makeFieldRef(bclass,
4418: fieldName, fieldType, true);
4419:
4420: fr = Jimple.v().newStaticFieldRef(fieldRef);
4421:
4422: stmt = Jimple.v().newAssignStmt(
4423: fr,
4424: Util.v().getLocalForStackOp(listBody, typeStack,
4425: typeStack.topIndex()));
4426: break;
4427: }
4428:
4429: case ByteCode.GETSTATIC: {
4430: StaticFieldRef fr = null;
4431:
4432: CONSTANT_Fieldref_info fieldInfo = (CONSTANT_Fieldref_info) constant_pool[((Instruction_Getstatic) ins).arg_i];
4433:
4434: CONSTANT_Class_info c = (CONSTANT_Class_info) constant_pool[fieldInfo.class_index];
4435:
4436: String className = ((CONSTANT_Utf8_info) (constant_pool[c.name_index]))
4437: .convert();
4438: className = className.replace('/', '.');
4439:
4440: CONSTANT_NameAndType_info i = (CONSTANT_NameAndType_info) constant_pool[fieldInfo.name_and_type_index];
4441:
4442: String fieldName = ((CONSTANT_Utf8_info) (constant_pool[i.name_index]))
4443: .convert();
4444: String fieldDescriptor = ((CONSTANT_Utf8_info) (constant_pool[i.descriptor_index]))
4445: .convert();
4446:
4447: Type fieldType = Util.v().jimpleTypeOfFieldDescriptor(
4448: fieldDescriptor);
4449:
4450: SootClass bclass = cm.getSootClass(className);
4451: SootFieldRef fieldRef = Scene.v().makeFieldRef(bclass,
4452: fieldName, fieldType, true);
4453:
4454: fr = Jimple.v().newStaticFieldRef(fieldRef);
4455:
4456: stmt = Jimple.v().newAssignStmt(
4457: Util.v().getLocalForStackOp(listBody,
4458: postTypeStack, postTypeStack.topIndex()),
4459: fr);
4460: break;
4461: }
4462:
4463: case ByteCode.INVOKEVIRTUAL: {
4464: Instruction_Invokevirtual iv = (Instruction_Invokevirtual) ins;
4465: args = cp_info.countParams(constant_pool, iv.arg_i);
4466:
4467: SootMethodRef methodRef = null;
4468:
4469: CONSTANT_Methodref_info methodInfo = (CONSTANT_Methodref_info) constant_pool[iv.arg_i];
4470:
4471: CONSTANT_Class_info c = (CONSTANT_Class_info) constant_pool[methodInfo.class_index];
4472:
4473: String className = ((CONSTANT_Utf8_info) (constant_pool[c.name_index]))
4474: .convert();
4475: className = className.replace('/', '.');
4476:
4477: CONSTANT_NameAndType_info i = (CONSTANT_NameAndType_info) constant_pool[methodInfo.name_and_type_index];
4478:
4479: String methodName = ((CONSTANT_Utf8_info) (constant_pool[i.name_index]))
4480: .convert();
4481: String methodDescriptor = ((CONSTANT_Utf8_info) (constant_pool[i.descriptor_index]))
4482: .convert();
4483:
4484: if (className.charAt(0) == '[')
4485: className = "java.lang.Object";
4486:
4487: SootClass bclass = cm.getSootClass(className);
4488:
4489: List parameterTypes;
4490: Type returnType;
4491:
4492: // Generate parameters & returnType & parameterTypes
4493: {
4494: Type[] types = Util.v()
4495: .jimpleTypesOfFieldOrMethodDescriptor(
4496: methodDescriptor);
4497:
4498: parameterTypes = new ArrayList();
4499:
4500: for (int k = 0; k < types.length - 1; k++) {
4501: parameterTypes.add(types[k]);
4502: }
4503:
4504: returnType = types[types.length - 1];
4505: }
4506:
4507: methodRef = Scene.v().makeMethodRef(bclass, methodName,
4508: parameterTypes, returnType, false);
4509:
4510: // build array of parameters
4511: params = new Value[args];
4512: for (int j = args - 1; j >= 0; j--) {
4513: params[j] = Util.v().getLocalForStackOp(listBody,
4514: typeStack, typeStack.topIndex());
4515:
4516: if (typeSize(typeStack.top()) == 2) {
4517: typeStack = typeStack.pop();
4518: typeStack = typeStack.pop();
4519: } else
4520: typeStack = typeStack.pop();
4521: }
4522:
4523: rvalue = Jimple.v().newVirtualInvokeExpr(
4524: Util.v().getLocalForStackOp(listBody, typeStack,
4525: typeStack.topIndex()), methodRef,
4526: Arrays.asList(params));
4527:
4528: if (!returnType.equals(VoidType.v())) {
4529: stmt = Jimple.v().newAssignStmt(
4530: Util.v()
4531: .getLocalForStackOp(listBody,
4532: postTypeStack,
4533: postTypeStack.topIndex()),
4534: rvalue);
4535: } else
4536: stmt = Jimple.v().newInvokeStmt(rvalue);
4537: break;
4538: }
4539:
4540: case ByteCode.INVOKENONVIRTUAL: {
4541: Instruction_Invokenonvirtual iv = (Instruction_Invokenonvirtual) ins;
4542: args = cp_info.countParams(constant_pool, iv.arg_i);
4543:
4544: SootMethodRef methodRef = null;
4545:
4546: CONSTANT_Methodref_info methodInfo = (CONSTANT_Methodref_info) constant_pool[iv.arg_i];
4547:
4548: CONSTANT_Class_info c = (CONSTANT_Class_info) constant_pool[methodInfo.class_index];
4549:
4550: String className = ((CONSTANT_Utf8_info) (constant_pool[c.name_index]))
4551: .convert();
4552: className = className.replace('/', '.');
4553:
4554: CONSTANT_NameAndType_info i = (CONSTANT_NameAndType_info) constant_pool[methodInfo.name_and_type_index];
4555:
4556: String methodName = ((CONSTANT_Utf8_info) (constant_pool[i.name_index]))
4557: .convert();
4558: String methodDescriptor = ((CONSTANT_Utf8_info) (constant_pool[i.descriptor_index]))
4559: .convert();
4560:
4561: SootClass bclass = cm.getSootClass(className);
4562:
4563: List parameterTypes;
4564: Type returnType;
4565:
4566: // Generate parameters & returnType & parameterTypes
4567: {
4568: Type[] types = Util.v()
4569: .jimpleTypesOfFieldOrMethodDescriptor(
4570: methodDescriptor);
4571:
4572: parameterTypes = new ArrayList();
4573:
4574: for (int k = 0; k < types.length - 1; k++) {
4575: parameterTypes.add(types[k]);
4576: }
4577:
4578: returnType = types[types.length - 1];
4579: }
4580:
4581: methodRef = Scene.v().makeMethodRef(bclass, methodName,
4582: parameterTypes, returnType, false);
4583:
4584: // build array of parameters
4585: params = new Value[args];
4586: for (int j = args - 1; j >= 0; j--) {
4587: params[j] = Util.v().getLocalForStackOp(listBody,
4588: typeStack, typeStack.topIndex());
4589:
4590: if (typeSize(typeStack.top()) == 2) {
4591: typeStack = typeStack.pop();
4592: typeStack = typeStack.pop();
4593: } else
4594: typeStack = typeStack.pop();
4595: }
4596:
4597: rvalue = Jimple.v().newSpecialInvokeExpr(
4598: Util.v().getLocalForStackOp(listBody, typeStack,
4599: typeStack.topIndex()), methodRef,
4600: Arrays.asList(params));
4601:
4602: if (!returnType.equals(VoidType.v())) {
4603: stmt = Jimple.v().newAssignStmt(
4604: Util.v()
4605: .getLocalForStackOp(listBody,
4606: postTypeStack,
4607: postTypeStack.topIndex()),
4608: rvalue);
4609: } else
4610: stmt = Jimple.v().newInvokeStmt(rvalue);
4611: break;
4612: }
4613:
4614: case ByteCode.INVOKESTATIC: {
4615: Instruction_Invokestatic is = (Instruction_Invokestatic) ins;
4616: args = cp_info.countParams(constant_pool, is.arg_i);
4617:
4618: SootMethodRef methodRef = null;
4619:
4620: CONSTANT_Methodref_info methodInfo = (CONSTANT_Methodref_info) constant_pool[is.arg_i];
4621:
4622: CONSTANT_Class_info c = (CONSTANT_Class_info) constant_pool[methodInfo.class_index];
4623:
4624: String className = ((CONSTANT_Utf8_info) (constant_pool[c.name_index]))
4625: .convert();
4626: className = className.replace('/', '.');
4627:
4628: CONSTANT_NameAndType_info i = (CONSTANT_NameAndType_info) constant_pool[methodInfo.name_and_type_index];
4629:
4630: String methodName = ((CONSTANT_Utf8_info) (constant_pool[i.name_index]))
4631: .convert();
4632: String methodDescriptor = ((CONSTANT_Utf8_info) (constant_pool[i.descriptor_index]))
4633: .convert();
4634:
4635: if (className.charAt(0) == '[')
4636: className = "java.lang.Object";
4637:
4638: SootClass bclass = cm.getSootClass(className);
4639:
4640: List parameterTypes;
4641: Type returnType;
4642:
4643: // Generate parameters & returnType & parameterTypes
4644: {
4645: Type[] types = Util.v()
4646: .jimpleTypesOfFieldOrMethodDescriptor(
4647: methodDescriptor);
4648:
4649: parameterTypes = new ArrayList();
4650:
4651: for (int k = 0; k < types.length - 1; k++) {
4652: parameterTypes.add(types[k]);
4653: }
4654:
4655: returnType = types[types.length - 1];
4656: }
4657:
4658: methodRef = Scene.v().makeMethodRef(bclass, methodName,
4659: parameterTypes, returnType, true);
4660:
4661: // build Vector of parameters
4662: params = new Value[args];
4663: for (int j = args - 1; j >= 0; j--) {
4664: /* G.v().out.println("BeforeTypeStack");
4665: typeStack.print(G.v().out);
4666:
4667: G.v().out.println("AfterTypeStack");
4668: postTypeStack.print(G.v().out);
4669: */
4670:
4671: params[j] = Util.v().getLocalForStackOp(listBody,
4672: typeStack, typeStack.topIndex());
4673:
4674: if (typeSize(typeStack.top()) == 2) {
4675: typeStack = typeStack.pop();
4676: typeStack = typeStack.pop();
4677: } else
4678: typeStack = typeStack.pop();
4679: }
4680:
4681: rvalue = Jimple.v().newStaticInvokeExpr(methodRef,
4682: Arrays.asList(params));
4683:
4684: if (!returnType.equals(VoidType.v())) {
4685: stmt = Jimple.v().newAssignStmt(
4686: Util.v()
4687: .getLocalForStackOp(listBody,
4688: postTypeStack,
4689: postTypeStack.topIndex()),
4690: rvalue);
4691: } else
4692: stmt = Jimple.v().newInvokeStmt(rvalue);
4693:
4694: break;
4695: }
4696:
4697: case ByteCode.INVOKEINTERFACE: {
4698: Instruction_Invokeinterface ii = (Instruction_Invokeinterface) ins;
4699: args = cp_info.countParams(constant_pool, ii.arg_i);
4700:
4701: SootMethodRef methodRef = null;
4702:
4703: CONSTANT_InterfaceMethodref_info methodInfo = (CONSTANT_InterfaceMethodref_info) constant_pool[ii.arg_i];
4704:
4705: CONSTANT_Class_info c = (CONSTANT_Class_info) constant_pool[methodInfo.class_index];
4706:
4707: String className = ((CONSTANT_Utf8_info) (constant_pool[c.name_index]))
4708: .convert();
4709: className = className.replace('/', '.');
4710:
4711: CONSTANT_NameAndType_info i = (CONSTANT_NameAndType_info) constant_pool[methodInfo.name_and_type_index];
4712:
4713: String methodName = ((CONSTANT_Utf8_info) (constant_pool[i.name_index]))
4714: .convert();
4715: String methodDescriptor = ((CONSTANT_Utf8_info) (constant_pool[i.descriptor_index]))
4716: .convert();
4717:
4718: if (className.charAt(0) == '[')
4719: className = "java.lang.Object";
4720:
4721: SootClass bclass = cm.getSootClass(className);
4722:
4723: List parameterTypes;
4724: Type returnType;
4725:
4726: // Generate parameters & returnType & parameterTypes
4727: {
4728: Type[] types = Util.v()
4729: .jimpleTypesOfFieldOrMethodDescriptor(
4730: methodDescriptor);
4731:
4732: parameterTypes = new ArrayList();
4733:
4734: for (int k = 0; k < types.length - 1; k++) {
4735: parameterTypes.add(types[k]);
4736: }
4737:
4738: returnType = types[types.length - 1];
4739: }
4740:
4741: methodRef = Scene.v().makeMethodRef(bclass, methodName,
4742: parameterTypes, returnType, false);
4743:
4744: // build Vector of parameters
4745: params = new Value[args];
4746: for (int j = args - 1; j >= 0; j--) {
4747: params[j] = Util.v().getLocalForStackOp(listBody,
4748: typeStack, typeStack.topIndex());
4749:
4750: if (typeSize(typeStack.top()) == 2) {
4751: typeStack = typeStack.pop();
4752: typeStack = typeStack.pop();
4753: } else
4754: typeStack = typeStack.pop();
4755: }
4756:
4757: rvalue = Jimple.v().newInterfaceInvokeExpr(
4758: Util.v().getLocalForStackOp(listBody, typeStack,
4759: typeStack.topIndex()), methodRef,
4760: Arrays.asList(params));
4761:
4762: if (!returnType.equals(VoidType.v())) {
4763: stmt = Jimple.v().newAssignStmt(
4764: Util.v()
4765: .getLocalForStackOp(listBody,
4766: postTypeStack,
4767: postTypeStack.topIndex()),
4768: rvalue);
4769: } else
4770: stmt = Jimple.v().newInvokeStmt(rvalue);
4771: break;
4772: }
4773:
4774: case ByteCode.ATHROW:
4775: stmt = Jimple.v().newThrowStmt(
4776: Util.v().getLocalForStackOp(listBody, typeStack,
4777: typeStack.topIndex()));
4778: break;
4779:
4780: case ByteCode.NEW: {
4781: SootClass bclass = cm.getSootClass(getClassName(
4782: constant_pool, ((Instruction_New) ins).arg_i));
4783:
4784: stmt = Jimple.v().newAssignStmt(
4785: Util.v().getLocalForStackOp(listBody,
4786: postTypeStack, postTypeStack.topIndex()),
4787: Jimple.v().newNewExpr(RefType.v(bclass.getName())));
4788: break;
4789: }
4790:
4791: case ByteCode.CHECKCAST: {
4792: String className = getClassName(constant_pool,
4793: ((Instruction_Checkcast) ins).arg_i);
4794:
4795: Type castType;
4796:
4797: if (className.startsWith("["))
4798: castType = Util.v().jimpleTypeOfFieldDescriptor(
4799: getClassName(constant_pool,
4800: ((Instruction_Checkcast) ins).arg_i));
4801: else
4802: castType = RefType.v(className);
4803:
4804: rhs = Jimple.v().newCastExpr(
4805: Util.v().getLocalForStackOp(listBody, typeStack,
4806: typeStack.topIndex()), castType);
4807:
4808: stmt = Jimple.v().newAssignStmt(
4809: Util.v().getLocalForStackOp(listBody,
4810: postTypeStack, postTypeStack.topIndex()),
4811: rhs);
4812: break;
4813: }
4814:
4815: case ByteCode.INSTANCEOF: {
4816: Type checkType;
4817:
4818: String className = getClassName(constant_pool,
4819: ((Instruction_Instanceof) ins).arg_i);
4820:
4821: if (className.startsWith("["))
4822: checkType = Util.v().jimpleTypeOfFieldDescriptor(
4823: getClassName(constant_pool,
4824: ((Instruction_Instanceof) ins).arg_i));
4825: else
4826: checkType = RefType.v(className);
4827:
4828: rhs = Jimple.v().newInstanceOfExpr(
4829: Util.v().getLocalForStackOp(listBody, typeStack,
4830: typeStack.topIndex()), checkType);
4831:
4832: stmt = Jimple.v().newAssignStmt(
4833: Util.v().getLocalForStackOp(listBody,
4834: postTypeStack, postTypeStack.topIndex()),
4835: rhs);
4836: break;
4837: }
4838:
4839: case ByteCode.MONITORENTER:
4840: stmt = Jimple.v().newEnterMonitorStmt(
4841: Util.v().getLocalForStackOp(listBody, typeStack,
4842: typeStack.topIndex()));
4843: break;
4844: case ByteCode.MONITOREXIT:
4845: stmt = Jimple.v().newExitMonitorStmt(
4846: Util.v().getLocalForStackOp(listBody, typeStack,
4847: typeStack.topIndex()));
4848: break;
4849:
4850: default:
4851: throw new RuntimeException(
4852: "Unrecognized bytecode instruction: " + x);
4853: }
4854:
4855: if (stmt != null) {
4856: if (Options.v().keep_offset()) {
4857: stmt.addTag(new BytecodeOffsetTag(ins.label));
4858: }
4859: statements.add(stmt);
4860: }
4861: }
4862:
4863: Type jimpleTypeOfAtype(int atype) {
4864: switch (atype) {
4865: case 4:
4866: return BooleanType.v();
4867:
4868: case 5:
4869: return CharType.v();
4870:
4871: case 6:
4872: return FloatType.v();
4873:
4874: case 7:
4875: return DoubleType.v();
4876:
4877: case 8:
4878: return ByteType.v();
4879:
4880: case 9:
4881: return ShortType.v();
4882:
4883: case 10:
4884: return IntType.v();
4885:
4886: case 11:
4887: return LongType.v();
4888:
4889: default:
4890: throw new RuntimeException(
4891: "Undefined 'atype' in NEWARRAY byte instruction");
4892: }
4893: }
4894:
4895: int typeSize(Type type) {
4896: if (type.equals(LongType.v()) || type.equals(DoubleType.v())
4897: || type.equals(Long2ndHalfType.v())
4898: || type.equals(Double2ndHalfType.v())) {
4899: return 2;
4900: } else
4901: return 1;
4902: }
4903: }
4904:
4905: class OutFlow {
4906: TypeStack typeStack;
4907:
4908: OutFlow(TypeStack typeStack) {
4909: this.typeStack = typeStack;
4910: }
4911: }
|