KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > soot > coffi > CFG


1 /* Soot - a J*va Optimization Framework
2  * Copyright (C) 1997 Clark Verbrugge
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */

19
20 /*
21  * Modified by the Sable Research Group and others 1997-1999.
22  * See the 'credits' file distributed with Soot for the complete list of
23  * contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot)
24  */

25
26
27
28
29
30
31
32 package soot.coffi;
33 import soot.options.*;
34
35 import java.lang.*;
36 import java.util.*;
37
38 import soot.*;
39 import soot.jimple.*;
40 import soot.baf.*;
41 import soot.util.*;
42 import soot.tagkit.*;
43
44 /** A Control Flow Graph.
45  * @author Clark Verbrugge
46  */

47 public class CFG {
48
49     /** Method for which this is a control flow graph.
50      * @see method_info
51      */

52     private method_info method;
53     /** Ordered list of BasicBlocks comprising the code of this CFG.
54      */

55     BasicBlock cfg;
56
57     Chain units;
58     JimpleBody listBody;
59
60     Map instructionToFirstStmt;
61     Map instructionToLastStmt;
62     SootMethod jmethod;
63     Scene cm;
64
65     Instruction firstInstruction;
66     Instruction lastInstruction;
67
68     private short wide; // convert indices when parsing jimple
69

70     private Instruction sentinel;
71     private Hashtable h2bb, t2bb;
72     private int bbcount; // statistics, number of BBs processed
73

74     /** Constructs a new control flow graph for the given method.
75      * @param m the method in question.
76      * @see method_info
77      */

78     public CFG(method_info m)
79     {
80     this.method = m;
81
82     this.sentinel = new Instruction_Nop();
83     this.sentinel.next = m.instructions;
84     m.instructions.prev = this.sentinel;
85
86     // printInstructions();
87
// printExceptionTable();
88

89     eliminateJsrRets();
90
91     // printInstructions();
92
// printExceptionTable();
93

94     buildBBCFG();
95
96     // printBBs();
97
// printBBCFGSucc();
98

99     cfg.beginCode = true;
100
101     m.cfg = this;
102
103     if(cfg != null)
104         firstInstruction = cfg.head;
105     else
106         firstInstruction = null;
107
108     /*
109     if (m.code_attr != null)
110     {
111         for (int i=0; i<m.code_attr.attributes.length; i++)
112         {
113         if (m.code_attr.attributes[i]
114             instanceof LineNumberTable_attribute)
115         {
116             G.v().out.print(m.code_attr.attributes[i]);
117         }
118         }
119     }
120     */

121     }
122
123     private void printBBCFGSucc()
124     {
125     BasicBlock b = this.cfg;
126     while ( b!= null )
127     {
128         G.v().out.print(b.id +" -> ");
129         for (int i=0; i<b.succ.size(); i++)
130         {
131         BasicBlock bs = (BasicBlock)b.succ.elementAt(i);
132         G.v().out.print(bs.id+" ");
133         }
134         G.v().out.println();
135         b = b.next;
136     }
137     }
138
139     private void printBBCFGPred()
140     {
141     BasicBlock b = this.cfg;
142     while ( b!= null )
143     {
144         G.v().out.print(b.id +" <- ");
145         for (int i=0; i<b.pred.size(); i++)
146         {
147         BasicBlock bs = (BasicBlock)b.pred.elementAt(i);
148         G.v().out.print(bs.id+" ");
149         }
150         G.v().out.println();
151         b = b.next;
152     }
153     }
154
155     private void printOneBasicBlock(BasicBlock b)
156     {
157     G.v().out.println("Block "+b.id);
158     
159     Instruction insn = b.head;
160     G.v().out.println(insn);
161     while (insn != b.tail && insn != null)
162     {
163         insn = insn.next;
164         G.v().out.println(insn);
165     }
166
167     G.v().out.println();
168     }
169
170     private void printBBHeadTail(BasicBlock fb)
171     {
172     BasicBlock b = fb;
173     while (b != null)
174     {
175         G.v().out.println(b.head);
176         G.v().out.println(b.tail+"\n");
177         b = b.next;
178     }
179     }
180
181     private void printBBs()
182     {
183     BasicBlock bb = this.cfg;
184     while (bb != null)
185     {
186         printOneBasicBlock(bb);
187         bb = bb.next;
188     }
189     }
190
191     private void printInstructions()
192     {
193     Instruction insn = method.instructions;
194     while (insn != null)
195     {
196         G.v().out.println(insn);
197         insn = insn.next;
198     }
199     }
200
201     private void printExceptionTable()
202     {
203     Code_attribute ca = this.method.locate_code_attribute();
204     
205     G.v().out.println("\nException table :");
206     G.v().out.println("start\tend\thandler");
207     for (int i=0; i<ca.exception_table.length; i++)
208     {
209         exception_table_entry ete = ca.exception_table[i];
210         G.v().out.println((ete.start_inst == null ? "null" :
211                    Integer.toString(ete.start_inst.label)) + " \t " +
212                   (ete.end_inst == null ? "null" :
213                    Integer.toString(ete.end_inst.label)) + " \t " +
214                   ete.handler_inst.label);
215     }
216     }
217     // Constructs the actual control flow graph. Assumes the hash table
218
// currently associates leaders with BasicBlocks, this function
219
// builds the next[] and prev[] pointer arrays.
220
private void buildBBCFG()
221     {
222     Object JavaDoc branches[], nextinsn;
223     Code_attribute ca = method.locate_code_attribute();
224
225     {
226         h2bb = new Hashtable(100,25);
227         t2bb = new Hashtable(100,25);
228
229         Instruction insn = this.sentinel.next;
230         BasicBlock blast = null;
231         if (insn != null)
232         {
233         Instruction tail = buildBasicBlock(insn);
234         cfg = new BasicBlock(insn, tail);
235         h2bb.put(insn, cfg);
236         t2bb.put(tail, cfg);
237         insn = tail.next;
238         blast = cfg;
239         }
240
241         while (insn != null)
242         {
243         Instruction tail = buildBasicBlock(insn);
244         BasicBlock block = new BasicBlock(insn, tail);
245         blast.next = block;
246         blast = block;
247         h2bb.put(insn, block);
248         t2bb.put(tail, block);
249         insn = tail.next;
250         }
251     }
252
253     BasicBlock block = cfg;
254
255     while (block != null)
256     {
257         Instruction insn = block.tail;
258
259         if (insn.branches)
260         {
261         if (insn instanceof Instruction_Athrow)
262         {
263             // see how many targets it can reach. Note that this is a
264
// subset of the exception_table.
265
HashSet ethandlers = new HashSet();
266
267             // not quite a subset---could also be that control
268
// exits this method, so start icount at 1
269
for (int i=0; i<ca.exception_table_length; i++)
270             {
271             exception_table_entry etentry =
272                 ca.exception_table[i];
273
274             if (insn.label >= etentry.start_inst.label
275                 && (etentry.end_inst==null
276                 || insn.label < etentry.end_inst.label))
277             {
278                 ethandlers.add(etentry.handler_inst);
279             }
280             }
281
282             branches = ethandlers.toArray();
283         }
284         else
285         {
286             branches = insn.branchpoints(insn.next);
287         }
288
289         if (branches != null)
290         {
291             block.succ.ensureCapacity(block.succ.size()+branches.length);
292
293             for (int i=0; i<branches.length; i++)
294             {
295             if ( branches[i]!=null ) {
296                 BasicBlock bb = (BasicBlock)h2bb.get(branches[i]);
297                  
298                 if (bb == null)
299                 {
300                 G.v().out.println("Warning: "
301                            +"target of a branch is null");
302                 G.v().out.println ( insn );
303                 }
304                 else
305                 {
306                 block.succ.addElement(bb);
307                 bb.pred.addElement(block);
308                 }
309             }
310             }
311         }
312         }
313         else
314         if (block.next!=null)
315         { // BB ended not with a branch, so just go to next
316
block.succ.addElement(block.next);
317         block.next.pred.addElement(block);
318         }
319         block = block.next;
320     }
321
322     // One final step, run through exception handlers and mark which
323
// basic blocks begin their code
324
for (int i=0; i<ca.exception_table_length; i++)
325     {
326         BasicBlock bb = (BasicBlock)h2bb.get(
327                      ca.exception_table[i].handler_inst);
328         if ( bb == null )
329         {
330         G.v().out.println("Warning: No basic block found for" +
331                    " start of exception handler code.");
332         }
333         else
334         {
335         bb.beginException = true;
336         ca.exception_table[i].b = bb;
337         }
338     }
339     }
340
341     /* given the list of instructions head, this pulls off the front
342      * basic block, terminates it with a null, and returns the next
343      * instruction after.
344      */

345     private static Instruction buildBasicBlock(Instruction head)
346     {
347     Instruction insn, next;
348     insn = head;
349     next = insn.next;
350
351     if (next == null)
352         return insn;
353
354     do
355     {
356         if (insn.branches || next.labelled)
357         break;
358         else
359         {
360         insn = next;
361         next = insn.next;
362         }
363     } while (next != null);
364
365     return insn;
366     }
367
368     /* get a set of reachable instructions from an astore to matching ret.
369      * it does not consider the exception handler as reachable now.
370      */

371     private Set getReachableInsns(Instruction from, Instruction to)
372     {
373     Code_attribute codeAttribute = method.locate_code_attribute();
374
375     /* find all reachable blocks. */
376     Set reachableinsns = new HashSet();
377     LinkedList tovisit = new LinkedList();
378
379     reachableinsns.add(from);
380     tovisit.add(from);
381     
382     while (!tovisit.isEmpty())
383     {
384         Instruction insn = (Instruction)tovisit.removeFirst();
385
386         if (insn == to)
387         continue;
388
389         Instruction[] bps = null;
390         if (insn.branches)
391         {
392         bps = insn.branchpoints(insn.next);
393         }
394         else
395         {
396         bps = new Instruction[1];
397         bps[0] = insn.next;
398         }
399
400         if (bps != null)
401         {
402         for (int i=0; i<bps.length; i++)
403         {
404             Instruction bp = bps[i];
405
406             if (bp != null
407             && !reachableinsns.contains(bp))
408             {
409             reachableinsns.add(bp);
410             tovisit.add(bp);
411             }
412         }
413         }
414     }
415
416     return reachableinsns;
417     }
418
419     /* We only handle simple cases. */
420     Map jsr2astore = new HashMap();
421     Map astore2ret = new HashMap();
422     
423     LinkedList jsrorder = new LinkedList();
424
425     /* Eliminate subroutines ( JSR/RET instructions ) by inlining the
426        routine bodies. */

427     private boolean eliminateJsrRets()
428     {
429     Instruction insn = this.sentinel;
430
431     // find the last instruction, for copying blocks.
432
while (insn.next != null) {
433         insn = insn.next;
434     }
435     this.lastInstruction = insn;
436
437     HashMap todoBlocks = new HashMap();
438     todoBlocks.put(this.sentinel.next, this.lastInstruction);
439     LinkedList todoList = new LinkedList();
440     todoList.add(this.sentinel.next);
441
442     while (!todoList.isEmpty()) {
443         Instruction firstInsn = (Instruction)todoList.removeFirst();
444         Instruction lastInsn = (Instruction)todoBlocks.get(firstInsn);
445
446         jsrorder.clear();
447         jsr2astore.clear();
448         astore2ret.clear();
449
450         if (findOutmostJsrs(firstInsn, lastInsn)) {
451         HashMap newblocks = inliningJsrTargets();
452         todoBlocks.putAll(newblocks);
453         todoList.addAll(newblocks.keySet());
454         }
455     }
456
457     /* patch exception table and others.*/
458     {
459         method.instructions = this.sentinel.next;
460
461         adjustExceptionTable();
462             adjustLineNumberTable();
463         adjustBranchTargets();
464     }
465
466     // we should prune the code and exception table here.
467
// remove any exception handler whose region is in a jsr/ret block.
468
// pruneExceptionTable();
469

470     return true;
471     }
472
473     // find outmost jsr/ret pairs in a code area, all information is
474
// saved in jsr2astore, and astore2ret
475
// start : start instruction, inclusively.
476
// end : the last instruction, inclusively.
477
// return the last instruction encounted ( before end )
478
// the caller cleans jsr2astore, astore2ret
479
private boolean findOutmostJsrs(Instruction start, Instruction end) {
480     // use to put innerJsrs.
481
HashSet innerJsrs = new HashSet();
482     boolean unusual = false;
483
484     Instruction insn = start;
485     do {
486         if (insn instanceof Instruction_Jsr
487         || insn instanceof Instruction_Jsr_w)
488         {
489         if (innerJsrs.contains(insn)) {
490             // skip it
491
insn = insn.next;
492             continue;
493         }
494
495         Instruction astore = ((Instruction_branch)insn).target;
496         if (! (astore instanceof Interface_Astore))
497         {
498             unusual = true;
499             break;
500         }
501         
502         Instruction ret = findMatchingRet(astore, insn, innerJsrs);
503
504         /*
505         if (ret == null)
506         {
507             unusual = true;
508             break;
509         }
510         */

511
512         jsrorder.addLast(insn);
513         jsr2astore.put(insn, astore);
514         astore2ret.put(astore, ret);
515         }
516  
517         insn = insn.next;
518        
519     } while (insn != end.next);
520
521     if (unusual)
522     {
523         G.v().out.println("Sorry, I cannot handle this method.");
524         return false;
525     }
526     
527     return true;
528     }
529
530     private Instruction findMatchingRet(Instruction astore,
531                     Instruction jsr,
532                     HashSet innerJsrs)
533     {
534     int astorenum = ((Interface_Astore)astore).getLocalNumber();
535     
536     Instruction insn = astore.next;
537     while (insn != null)
538     {
539         if (insn instanceof Instruction_Ret
540         || insn instanceof Instruction_Ret_w)
541         {
542         int retnum = ((Interface_OneIntArg)insn).getIntArg();
543         if (astorenum == retnum)
544             return insn;
545         }
546         else
547         /* adjust the jsr inlining order. */
548         if (insn instanceof Instruction_Jsr
549         || insn instanceof Instruction_Jsr_w)
550         {
551         innerJsrs.add(insn);
552         }
553
554         insn = insn.next;
555     }
556
557     return null;
558     }
559
560     // make copies of jsr/ret blocks
561
// return new blocks
562
private HashMap inliningJsrTargets()
563     {
564     /*
565     for (int i=0, n=jsrorder.size(); i<n; i++) {
566         Instruction jsr = (Instruction)jsrorder.get(i);
567         Instruction astore = (Instruction)jsr2astore.get(jsr);
568         Instruction ret = (Instruction)astore2ret.get(astore);
569         G.v().out.println("jsr"+jsr.label+"\t"
570                    +"as"+astore.label+"\t"
571                    +"ret"+ret.label);
572     }
573     */

574     HashMap newblocks = new HashMap();
575
576     while (!jsrorder.isEmpty())
577     {
578         Instruction jsr = (Instruction)jsrorder.removeFirst();
579         Instruction astore = (Instruction)jsr2astore.get(jsr);
580
581         Instruction ret = (Instruction)astore2ret.get(astore);
582
583         // make a copy of the code, append to the last instruction.
584
Instruction newhead = makeCopyOf(astore, ret, jsr.next);
585
586         // jsr is replaced by goto newhead
587
// astore has been removed
588
// ret is replaced by goto jsr.next
589
Instruction_Goto togo = new Instruction_Goto();
590         togo.target = newhead;
591         newhead.labelled = true;
592         togo.label = jsr.label;
593         togo.labelled = jsr.labelled;
594         togo.prev = jsr.prev;
595         togo.next = jsr.next;
596         togo.prev.next = togo;
597         togo.next.prev = togo;
598
599         replacedInsns.put(jsr, togo);
600
601         // just quick hack
602
if (ret != null) {
603         newblocks.put(newhead, this.lastInstruction);
604         }
605     }
606
607     return newblocks;
608     }
609
610     /* make a copy of code between from and to exclusively,
611      * fixup targets of branch instructions in the code.
612      */

613     private Instruction makeCopyOf(Instruction astore,
614                    Instruction ret,
615                    Instruction target)
616     {
617     // do a quick hacker for ret == null
618
if (ret == null) {
619         return astore.next;
620     }
621
622     Instruction last = this.lastInstruction;
623     Instruction headbefore = last;
624
625     int curlabel = this.lastInstruction.label;
626
627     // mapping from original instructions to new instructions.
628
HashMap insnmap = new HashMap();
629     Instruction insn = astore.next;
630     
631     while (insn != ret && insn != null)
632     {
633         try {
634         Instruction newone = (Instruction)insn.clone();
635
636         newone.label = ++curlabel;
637         newone.prev = last;
638         last.next = newone;
639         last = newone;
640
641         insnmap.put(insn, newone);
642         } catch (CloneNotSupportedException JavaDoc e)
643         {
644         G.v().out.println("Error !");
645         }
646         insn = insn.next;
647     }
648
649     // replace ret by a goto
650
Instruction_Goto togo = new Instruction_Goto();
651     togo.target = target;
652     target.labelled = true;
653     togo.label = ++curlabel;
654     last.next = togo;
655     togo.prev = last;
656     last = togo;
657
658     this.lastInstruction = last;
659
660     // The ret instruction is removed,
661
insnmap.put(astore, headbefore.next);
662     insnmap.put(ret, togo);
663
664     // fixup targets in new instruction (only in the scope of
665
// new instructions).
666
// do not forget set target labelled as TRUE
667
insn = headbefore.next;
668     while (insn != last)
669     {
670         if (insn instanceof Instruction_branch)
671         {
672         Instruction oldtgt = ((Instruction_branch)insn).target;
673         Instruction newtgt = (Instruction)insnmap.get(oldtgt);
674         if (newtgt != null)
675         {
676             ((Instruction_branch)insn).target = newtgt;
677             newtgt.labelled = true;
678         }
679         }
680         else
681         if (insn instanceof Instruction_Lookupswitch)
682         {
683         Instruction_Lookupswitch switchinsn =
684             (Instruction_Lookupswitch)insn;
685         
686         Instruction newdefault = (Instruction)insnmap.get(switchinsn.default_inst);
687         if (newdefault != null)
688         {
689             switchinsn.default_inst = newdefault;
690             newdefault.labelled = true;
691         }
692
693         for (int i=0; i<switchinsn.match_insts.length; i++)
694         {
695             Instruction newtgt = (Instruction)insnmap.get(switchinsn.match_insts[i]);
696             if (newtgt != null)
697             {
698             switchinsn.match_insts[i] = newtgt;
699             newtgt.labelled = true;
700             }
701         }
702         }
703         else
704         if (insn instanceof Instruction_Tableswitch)
705         {
706         Instruction_Tableswitch switchinsn =
707             (Instruction_Tableswitch)insn;
708         
709         Instruction newdefault = (Instruction)insnmap.get(switchinsn.default_inst);
710         if (newdefault != null)
711         {
712             switchinsn.default_inst = newdefault;
713             newdefault.labelled = true;
714         }
715
716         for (int i=0; i<switchinsn.jump_insts.length; i++)
717         {
718             Instruction newtgt = (Instruction)insnmap.get(switchinsn.jump_insts[i]);
719             if (newtgt != null)
720             {
721             switchinsn.jump_insts[i] = newtgt;
722             newtgt.labelled = true;
723             }
724         }
725         }
726
727         insn = insn.next;
728     }
729     
730     // do we need to copy a new exception table entry?
731
// new exception table has new exception range,
732
// and the new exception handler.
733
{
734         Code_attribute ca = method.locate_code_attribute();
735
736         LinkedList newentries = new LinkedList();
737
738         int orig_start_of_subr = astore.next.originalIndex; // inclusive
739
int orig_end_of_subr = ret.originalIndex; // again, inclusive
740

741         for (int i=0; i<ca.exception_table_length; i++)
742         {
743         exception_table_entry etentry =
744             ca.exception_table[i];
745
746         int orig_start_of_trap = etentry.start_pc; // inclusive
747
int orig_end_of_trap = etentry.end_pc; // exclusive
748
if ( orig_start_of_trap < orig_end_of_subr &&
749              orig_end_of_trap > orig_start_of_subr) {
750             // At least a portion of the cloned subroutine is trapped.
751
exception_table_entry newone =
752             new exception_table_entry();
753             if (orig_start_of_trap <= orig_start_of_subr) {
754             newone.start_inst = headbefore.next;
755             } else {
756             newone.start_inst = (Instruction)insnmap.get(etentry.start_inst);
757             }
758             if (orig_end_of_trap > orig_end_of_subr) {
759             newone.end_inst = null; // Representing the insn after
760
// the last instruction in the
761
// subr; we need to fix it if
762
// we inline another subr.
763
} else {
764             newone.end_inst = (Instruction)insnmap.get(etentry.end_inst);
765             }
766
767             newone.handler_inst = (Instruction)insnmap.get(etentry.handler_inst);
768             if (newone.handler_inst == null)
769             newone.handler_inst = etentry.handler_inst;
770
771             // We can leave newone.start_pc == 0 and newone.end_pc == 0.
772
// since that cannot overlap the range of any other
773
// subroutines that get inlined later.
774

775             newentries.add(newone);
776         }
777         // Finally, fix up the old entry if its protected area
778
// ran to the end of the method we have just lengthened:
779
// patch its end marker to be the first
780
// instruction in the subroutine we've just inlined.
781
if (etentry.end_inst == null) {
782             etentry.end_inst = headbefore.next;
783         }
784         }
785
786         if (newentries.size() > 0)
787         {
788         ca.exception_table_length += newentries.size();
789         exception_table_entry[] newtable = new exception_table_entry[ca.exception_table_length];
790         System.arraycopy(ca.exception_table, 0, newtable, 0, ca.exception_table.length);
791         for (int i=0, j=ca.exception_table.length; i<newentries.size(); i++, j++)
792         {
793             newtable[j] = (exception_table_entry)newentries.get(i);
794         }
795         
796         ca.exception_table = newtable;
797         }
798     }
799     
800     return headbefore.next;
801     }
802
803     private void pruneExceptionTable() {
804     HashSet invalidInsns = new HashSet();
805     Instruction insn = this.sentinel.next;
806         do {
807         if (insn instanceof Instruction_Jsr
808         || insn instanceof Instruction_Jsr_w) {
809         Instruction astore = ((Instruction_branch)insn).target;
810         int astorenum = ((Interface_Astore)astore).getLocalNumber();
811         Instruction ret = astore.next;
812         do {
813             invalidInsns.add(ret);
814             if (ret instanceof Instruction_Ret
815             || ret instanceof Instruction_Ret_w) {
816             int retnum = ((Interface_OneIntArg)ret).getIntArg();
817             if (astorenum == retnum) {
818                 insn = ret;
819                 break;
820             }
821             }
822             ret = ret.next;
823         } while (true);
824         }
825         insn = insn.next;
826     } while (insn != null);
827
828     Iterator it = invalidInsns.iterator();
829     while (it.hasNext()) {
830         G.v().out.println(it.next());
831     }
832
833     // pruning exception table
834
LinkedList validEntries = new LinkedList();
835
836     Code_attribute codeAttribute = method.locate_code_attribute();
837     for(int i = 0; i < codeAttribute.exception_table_length; i++)
838     {
839         exception_table_entry entry = codeAttribute.exception_table[i];
840
841         if (!invalidInsns.contains(entry.start_inst)) {
842         validEntries.add(entry);
843         }
844     }
845
846     if (validEntries.size() != codeAttribute.exception_table_length) {
847         exception_table_entry newtable[] =
848         new exception_table_entry[validEntries.size()];
849         for (int i=0; i<newtable.length; i++) {
850         newtable[i] =
851             (exception_table_entry)validEntries.get(i);
852         }
853         codeAttribute.exception_table = newtable;
854         codeAttribute.exception_table_length = newtable.length;
855     }
856     }
857
858     /* if a jsr/astore/ret is replaced by some other instruction, it will be put on this table. */
859     private Hashtable replacedInsns = new Hashtable();
860     private void dumpReplacedInsns()
861     {
862     G.v().out.println("replaced table:");
863     Set keys = replacedInsns.keySet();
864     Iterator keyIt = keys.iterator();
865     while (keyIt.hasNext())
866     {
867         Object JavaDoc key = keyIt.next();
868         Object JavaDoc value = replacedInsns.get(key);
869         G.v().out.println(key + " ==> "+ value);
870     }
871     }
872
873     /* do not forget set the target labelled as TRUE.*/
874     private void adjustBranchTargets()
875     {
876     Instruction insn = this.sentinel.next;
877     while (insn != null)
878     {
879         if (insn instanceof Instruction_branch)
880         {
881         Instruction_branch binsn = (Instruction_branch)insn;
882         Instruction newtgt = (Instruction)replacedInsns.get(binsn.target);
883         if (newtgt != null)
884         {
885             binsn.target = newtgt;
886             newtgt.labelled = true;
887         }
888         }
889         else
890         if (insn instanceof Instruction_Lookupswitch)
891         {
892         Instruction_Lookupswitch switchinsn =
893             (Instruction_Lookupswitch)insn;
894         
895         Instruction newdefault =
896             (Instruction)replacedInsns.get(switchinsn.default_inst);
897         if (newdefault != null)
898         {
899             switchinsn.default_inst = newdefault;
900             newdefault.labelled = true;
901         }
902         
903         for (int i=0; i<switchinsn.npairs; i++)
904         {
905             Instruction newtgt =
906             (Instruction)replacedInsns.get(switchinsn.match_insts[i]);
907             if (newtgt != null)
908             {
909             switchinsn.match_insts[i] = newtgt;
910             newtgt.labelled = true;
911             }
912         }
913         }
914         else
915         if (insn instanceof Instruction_Tableswitch)
916         {
917         Instruction_Tableswitch switchinsn =
918             (Instruction_Tableswitch)insn;
919         
920         Instruction newdefault = (Instruction)replacedInsns.get(switchinsn.default_inst);
921         if (newdefault != null)
922         {
923             switchinsn.default_inst = newdefault;
924             newdefault.labelled = true;
925         }
926
927         for (int i=0; i<=switchinsn.high-switchinsn.low; i++)
928         {
929             Instruction newtgt =
930             (Instruction)replacedInsns.get(switchinsn.jump_insts[i]);
931             if (newtgt != null)
932             {
933             switchinsn.jump_insts[i] = newtgt;
934             newtgt.labelled = true;
935             }
936         }
937         }
938         
939         insn = insn.next;
940     }
941     }
942
943
944     private void adjustExceptionTable()
945     {
946     Code_attribute codeAttribute = method.locate_code_attribute();
947
948     for(int i = 0; i < codeAttribute.exception_table_length; i++)
949     {
950         exception_table_entry entry = codeAttribute.exception_table[i];
951
952         Instruction oldinsn = entry.start_inst;
953         Instruction newinsn = (Instruction)replacedInsns.get(oldinsn);
954         if (newinsn != null)
955         entry.start_inst = newinsn;
956
957         oldinsn = entry.end_inst;
958         if (entry.end_inst != null)
959         {
960         newinsn = (Instruction)replacedInsns.get(oldinsn);
961         if (newinsn != null)
962             entry.end_inst = newinsn;
963         }
964
965         oldinsn = entry.handler_inst;
966         newinsn = (Instruction)replacedInsns.get(oldinsn);
967         if (newinsn != null)
968         entry.handler_inst = newinsn;
969     }
970     }
971
972     private void adjustLineNumberTable()
973     {
974     if (!Options.v().keep_line_number())
975         return;
976     if (method.code_attr == null)
977         return;
978
979     attribute_info[] attributes = method.code_attr.attributes;
980
981     for (int i=0; i<attributes.length; i++)
982     {
983         if (attributes[i] instanceof LineNumberTable_attribute)
984         {
985         LineNumberTable_attribute lntattr =
986             (LineNumberTable_attribute)attributes[i];
987         for (int j=0; j<lntattr.line_number_table.length; j++)
988         {
989             Instruction oldinst =
990             lntattr.line_number_table[j].start_inst;
991             Instruction newinst =
992             (Instruction)replacedInsns.get(oldinst);
993             if (newinst != null)
994             lntattr.line_number_table[j].start_inst = newinst;
995         }
996         }
997     }
998     }
999     
1000   /** Reconstructs the instruction stream by appending the Instruction
1001    * lists associated with each basic block.
1002    * <p>
1003    * Note that this joins up the basic block Instruction lists, and so
1004    * they will no longer end with <i>null</i> after this.
1005    * @return the head of the list of instructions.
1006    */

1007    public Instruction reconstructInstructions()
1008    {
1009    if (cfg != null)
1010        return cfg.head;
1011    else
1012        return null;
1013    }
1014
1015   /** Main.v() entry point for converting list of Instructions to Jimple statements;
1016    * performs flow analysis, constructs Jimple statements, and fixes jumps.
1017    * @param constant_pool constant pool of ClassFile.
1018    * @param this_class constant pool index of the CONSTANT_Class_info object for
1019    * this' class.
1020    * @return <i>true</i> if all ok, <i>false</i> if there was an error.
1021    * @see Stmt
1022    */

1023    public boolean jimplify(cp_info constant_pool[],int this_class, JimpleBody listBody)
1024   {
1025        Util.v().setClassNameToAbbreviation(new HashMap());
1026
1027        Chain units = listBody.getUnits();
1028
1029        this.listBody = listBody;
1030        this.units = units;
1031        instructionToFirstStmt = new HashMap();
1032        instructionToLastStmt = new HashMap();
1033
1034        jmethod = listBody.getMethod();
1035        cm = Scene.v();
1036        
1037        //TypeArray.setClassManager(cm);
1038
//TypeStack.setClassManager(cm);
1039

1040        Set initialLocals = new ArraySet();
1041
1042        List parameterTypes = jmethod.getParameterTypes();
1043
1044        // Initialize nameToLocal which is an index*Type->Local map, which is used
1045
// to determine local in bytecode references.
1046
{
1047            Code_attribute ca = method.locate_code_attribute();
1048            LocalVariableTable_attribute la = ca.findLocalVariableTable();
1049            LocalVariableTypeTable_attribute lt = ca.findLocalVariableTypeTable();
1050
1051            Util.v().activeVariableTable = la;
1052            Util.v().activeVariableTypeTable = lt;
1053            
1054            Util.v().activeConstantPool = constant_pool;
1055            
1056            Type thisType = RefType.v(jmethod.getDeclaringClass().getName());
1057            boolean isStatic = Modifier.isStatic(jmethod.getModifiers());
1058
1059            int currentLocalIndex = 0;
1060
1061            // Initialize the 'this' variable
1062
{
1063                if(!isStatic)
1064                {
1065                    String JavaDoc name;
1066                    
1067                    if(!Util.v().useFaithfulNaming || la == null)
1068                        name = "l0";
1069                    else
1070            {
1071                        name = la.getLocalVariableName(constant_pool, currentLocalIndex);
1072            if (!Util.v().isValidJimpleName(name))
1073                name = "l0";
1074            }
1075                        
1076                    Local local = Jimple.v().newLocal(name, UnknownType.v());
1077
1078                    listBody.getLocals().add(local);
1079
1080                    currentLocalIndex++;
1081
1082                    units.add(Jimple.v().newIdentityStmt(local, Jimple.v().newThisRef(jmethod.getDeclaringClass().getType())));
1083                }
1084            }
1085
1086            // Initialize parameters
1087
{
1088                Iterator typeIt = parameterTypes.iterator();
1089                int argCount = 0;
1090
1091                while(typeIt.hasNext())
1092                {
1093                    String JavaDoc name;
1094                    Type type = (Type) typeIt.next();
1095
1096                    if(!Util.v().useFaithfulNaming || la == null)
1097                        name = "l" + currentLocalIndex;
1098                    else
1099            {
1100                        name = la.getLocalVariableName(constant_pool, currentLocalIndex);
1101            if (!Util.v().isValidJimpleName(name))
1102                name = "l" + currentLocalIndex;
1103            }
1104
1105                    Local local = Jimple.v().newLocal(name, UnknownType.v());
1106                    initialLocals.add(local);
1107                    listBody.getLocals().add(local);
1108
1109                    units.add(Jimple.v().newIdentityStmt(local, Jimple.v().newParameterRef(type, argCount)));
1110
1111                    if(type.equals(DoubleType.v()) ||
1112                        type.equals(LongType.v()))
1113                    {
1114                        currentLocalIndex += 2;
1115                    }
1116                    else {
1117                        currentLocalIndex += 1;
1118                    }
1119
1120                    argCount++;
1121                }
1122            }
1123
1124            Util.v().resetEasyNames();
1125        }
1126
1127        jimplify(constant_pool,this_class);
1128
1129        return true;
1130   }
1131
1132    private void buildInsnCFGfromBBCFG()
1133    {
1134    BasicBlock block = cfg;
1135
1136    while(block != null)
1137    {
1138        Instruction insn = block.head;
1139        while (insn != block.tail)
1140        {
1141        Instruction[] succs = new Instruction[1];
1142        succs[0] = insn.next;
1143        insn.succs = succs;
1144        insn = insn.next;
1145        }
1146 
1147        {
1148        // The successors are the ones from the basic block.
1149
Vector bsucc = block.succ;
1150        int size = bsucc.size();
1151        Instruction[] succs = new Instruction[size];
1152
1153        for(int i = 0; i<size; i++)
1154            succs[i] = ((BasicBlock)bsucc.elementAt(i)).head;
1155        insn.succs = succs;
1156        }
1157
1158        block = block.next;
1159    }
1160    }
1161
1162    private void printInsnCFG()
1163    {
1164    Instruction insn = cfg.head;
1165    while (insn != null)
1166    {
1167        G.v().out.println(insn + " --> " + makeString(insn.succs));
1168        insn = insn.next;
1169    }
1170    }
1171
1172    private String JavaDoc makeString(Object JavaDoc[] objs)
1173    {
1174    String JavaDoc buf = "";
1175    for (int i=0; i<objs.length; i++)
1176        buf += " , "+objs[i];
1177
1178    return buf;
1179    }
1180
1181    /** Main.v() entry point for converting list of Instructions to Jimple statements;
1182     * performs flow analysis, constructs Jimple statements, and fixes jumps.
1183     * @param constant_pool constant pool of ClassFile.
1184     * @param this_class constant pool index of the CONSTANT_Class_info object for
1185     * this' class.
1186     * @param clearStacks if <i>true</i> semantic stacks will be deleted after
1187     * the process is complete.
1188     * @return <i>true</i> if all ok, <i>false</i> if there was an error.
1189     * @see CFG#jimplify(cp_info[], int)
1190     * @see Stmt
1191     */

1192    void jimplify(cp_info constant_pool[],int this_class)
1193    {
1194        Code_attribute codeAttribute = method.locate_code_attribute();
1195        Set handlerInstructions = new ArraySet();
1196
1197        Map handlerInstructionToException = new HashMap();
1198        Map instructionToTypeStack;
1199        Map instructionToPostTypeStack;
1200
1201        {
1202            // build graph in
1203
buildInsnCFGfromBBCFG();
1204
1205        // Put in successors due to exception handlers
1206
{
1207                for(int i = 0; i < codeAttribute.exception_table_length; i++)
1208                {
1209                    Instruction startIns = codeAttribute.exception_table[i].start_inst;
1210                    Instruction endIns = codeAttribute.exception_table[i].end_inst;
1211                    Instruction handlerIns = codeAttribute.exception_table[i].handler_inst;
1212
1213                    handlerInstructions.add(handlerIns);
1214
1215                    // Determine exception to catch
1216
{
1217                        int catchType = codeAttribute.exception_table[i].catch_type;
1218
1219                        SootClass exception;
1220
1221                        if(catchType != 0)
1222                        {
1223                            CONSTANT_Class_info classinfo = (CONSTANT_Class_info)
1224                                constant_pool[catchType];
1225
1226                            String JavaDoc name = ((CONSTANT_Utf8_info) (constant_pool[classinfo.name_index])).
1227                                convert();
1228                            name = name.replace('/', '.');
1229
1230                            exception = cm.getSootClass(name);
1231                        }
1232                        else
1233                            exception = cm.getSootClass("java.lang.Throwable");
1234
1235                        handlerInstructionToException.put(handlerIns, exception);
1236                    }
1237
1238
1239                    if(startIns == endIns)
1240                        throw new RuntimeException JavaDoc("Empty catch range for exception handler");
1241
1242                    Instruction ins = startIns;
1243
1244                    for(;;)
1245                    {
1246                        Instruction[] succs = ins.succs;
1247            Instruction[] newsuccs = new Instruction[succs.length+1];
1248
1249            System.arraycopy(succs, 0, newsuccs, 0, succs.length);
1250
1251            newsuccs[succs.length] = handlerIns;
1252                ins.succs = newsuccs;
1253
1254                        ins = ins.next;
1255                        if (ins == endIns || ins == null)
1256                            break;
1257            }
1258                }
1259            }
1260        }
1261
1262        Set reachableInstructions = new HashSet();
1263        
1264        // Mark all the reachable instructions
1265
{
1266            LinkedList instructionsToVisit = new LinkedList();
1267            
1268            reachableInstructions.add(firstInstruction);
1269            instructionsToVisit.addLast(firstInstruction);
1270            
1271            while( !instructionsToVisit.isEmpty())
1272            {
1273                Instruction ins = (Instruction) instructionsToVisit.removeFirst();
1274
1275        Instruction[] succs = ins.succs;
1276           
1277        for (int i=0; i<succs.length; i++)
1278        {
1279            Instruction succ = succs[i];
1280                    
1281            if(!reachableInstructions.contains(succ))
1282            {
1283            reachableInstructions.add(succ);
1284            instructionsToVisit.addLast(succ);
1285            }
1286                }
1287            }
1288        }
1289            
1290        /*
1291        // Check to see if any instruction is unmarked.
1292        {
1293            BasicBlock b = cfg;
1294
1295             while(b != null)
1296            {
1297                Instruction ins = b.head;
1298
1299                 while(ins != null)
1300                {
1301                    if(!reachableInstructions.contains(ins))
1302                        throw new RuntimeException("Method to jimplify contains unreachable code! (not handled for now)");
1303
1304                     ins = ins.next;
1305                }
1306
1307                 b = b.next;
1308            }
1309        }
1310        */

1311        
1312        // Perform the flow analysis, and build up instructionToTypeStack and instructionToLocalArray
1313
{
1314            instructionToTypeStack = new HashMap();
1315            instructionToPostTypeStack = new HashMap();
1316
1317            Set visitedInstructions = new HashSet();
1318            List changedInstructions = new ArrayList();
1319
1320            TypeStack initialTypeStack;
1321
1322            // Build up initial type stack and initial local array (for the first instruction)
1323
{
1324                initialTypeStack = TypeStack.v();
1325                    // the empty stack with nothing on it.
1326
}
1327
1328            // Get the loop cranked up.
1329
{
1330                instructionToTypeStack.put(firstInstruction, initialTypeStack);
1331
1332                visitedInstructions.add(firstInstruction);
1333                changedInstructions.add(firstInstruction);
1334            }
1335
1336            {
1337                while(!changedInstructions.isEmpty())
1338                {
1339                    Instruction ins = (Instruction) changedInstructions.get(0);
1340
1341                    changedInstructions.remove(0);
1342
1343                    OutFlow ret = processFlow(ins, (TypeStack) instructionToTypeStack.get(ins),
1344                        constant_pool);
1345
1346                    instructionToPostTypeStack.put(ins, ret.typeStack);
1347
1348                    Instruction[] successors = ins.succs;
1349
1350                    for(int i = 0; i < successors.length; i++)
1351                    {
1352                        Instruction s = successors[i];
1353
1354                        if(!visitedInstructions.contains(s))
1355                        {
1356                            // Special case for the first time visiting.
1357

1358                            if(handlerInstructions.contains(s))
1359                            {
1360                                TypeStack exceptionTypeStack = (TypeStack.v()).push(RefType.v(
1361                                    ((SootClass) handlerInstructionToException.get(s)).getName()));
1362
1363                                instructionToTypeStack.put(s, exceptionTypeStack);
1364                            }
1365                            else {
1366                                instructionToTypeStack.put(s, ret.typeStack);
1367                            }
1368
1369                            visitedInstructions.add(s);
1370                            changedInstructions.add(s);
1371
1372                            // G.v().out.println("adding successor: " + s);
1373
}
1374                        else {
1375                            // G.v().out.println("considering successor: " + s);
1376

1377                            TypeStack newTypeStack,
1378                                oldTypeStack = (TypeStack) instructionToTypeStack.get(s);
1379
1380                            if(handlerInstructions.contains(s))
1381                            {
1382                                // The type stack for an instruction handler should always be that of
1383
// single object on the stack.
1384

1385                                TypeStack exceptionTypeStack = (TypeStack.v()).push(RefType.v(
1386                                    ((SootClass) handlerInstructionToException.get(s)).getName()));
1387
1388                                newTypeStack = exceptionTypeStack;
1389                            }
1390                            else
1391                            {
1392                                try {
1393                                    newTypeStack = ret.typeStack.merge(oldTypeStack);
1394                                } catch (RuntimeException JavaDoc re)
1395                                {
1396                                    G.v().out.println("Considering "+s);
1397                                    throw re;
1398                                }
1399                            }
1400                            if(!newTypeStack.equals(oldTypeStack))
1401                            {
1402                                changedInstructions.add(s);
1403                                // G.v().out.println("requires a revisit: " + s);
1404
}
1405
1406                            instructionToTypeStack.put(s, newTypeStack);
1407                        }
1408                    }
1409                }
1410            }
1411        }
1412
1413        // Print out instructions + their localArray + typeStack
1414
{
1415            Instruction ins = firstInstruction;
1416
1417     // G.v().out.println();
1418

1419            while(ins != null)
1420            {
1421                TypeStack typeStack = (TypeStack) instructionToTypeStack.get(ins);
1422                // TypeArray typeArray = (TypeArray) instructionToLocalArray.get(ins);
1423
/*
1424                G.v().out.println("[TypeArray]");
1425                typeArray.print(G.v().out);
1426                G.v().out.println();
1427
1428                G.v().out.println("[TypeStack]");
1429                typeStack.print(G.v().out);
1430                G.v().out.println();
1431
1432                G.v().out.println(ins.toString());
1433*/

1434
1435                ins = ins.next;
1436/*
1437
1438                G.v().out.println();
1439                G.v().out.println();
1440*/

1441
1442            }
1443        }
1444
1445
1446        // G.v().out.println("Producing Jimple code...");
1447

1448        // Jimplify each statement
1449
{
1450            BasicBlock b = cfg;
1451
1452            while(b != null)
1453            {
1454                Instruction ins = b.head;
1455                b.statements = new ArrayList();
1456
1457                List blockStatements = b.statements;
1458
1459        for (;;)
1460        {
1461                    List statementsForIns = new ArrayList();
1462
1463                    if(reachableInstructions.contains(ins))
1464                        generateJimple(ins, (TypeStack) instructionToTypeStack.get(ins),
1465                            (TypeStack) instructionToPostTypeStack.get(ins), constant_pool,
1466                            statementsForIns, b);
1467                    else
1468                        statementsForIns.add(Jimple.v().newNopStmt());
1469
1470                    if(!statementsForIns.isEmpty())
1471                    {
1472                        for(int i = 0; i < statementsForIns.size(); i++)
1473                        {
1474                            units.add(statementsForIns.get(i));
1475                            blockStatements.add(statementsForIns.get(i));
1476                        }
1477
1478                        instructionToFirstStmt.put(ins, statementsForIns.get(0));
1479                        instructionToLastStmt.put(ins, statementsForIns.get(statementsForIns.size() - 1));
1480                    }
1481
1482            if (ins == b.tail)
1483            break;
1484
1485                    ins = ins.next;
1486                }
1487
1488                b = b.next;
1489            }
1490        }
1491
1492        jimpleTargetFixup(); // fix up jump targets
1493

1494        /*
1495        // Print out basic blocks
1496        {
1497            BasicBlock b = cfg;
1498
1499            G.v().out.println("Basic blocks for: " + jmethod.getName());
1500
1501            while(b != null)
1502            {
1503                Instruction ins = b.head;
1504
1505                G.v().out.println();
1506
1507                while(ins != null)
1508                {
1509                    G.v().out.println(ins.toString());
1510                    ins = ins.next;
1511                }
1512
1513                b = b.next;
1514            }
1515        }
1516        */

1517
1518        // Insert beginCatch/endCatch statements for exception handling
1519
{
1520            Map targetToHandler = new HashMap();
1521            
1522        for(int i = 0; i < codeAttribute.exception_table_length; i++)
1523        {
1524        Instruction startIns =
1525            codeAttribute.exception_table[i].start_inst;
1526        Instruction endIns =
1527            codeAttribute.exception_table[i].end_inst;
1528        Instruction targetIns =
1529            codeAttribute.exception_table[i].handler_inst;
1530
1531        if(!instructionToFirstStmt.containsKey(startIns) ||
1532           (endIns != null && (!instructionToLastStmt.containsKey(endIns))))
1533                {
1534            throw new RuntimeException JavaDoc("Exception range does not coincide with jimple instructions");
1535        }
1536
1537        if(!instructionToFirstStmt.containsKey(targetIns))
1538                {
1539            throw new RuntimeException JavaDoc
1540            ("Exception handler does not coincide with jimple instruction");
1541        }
1542
1543        SootClass exception;
1544
1545        // Determine exception to catch
1546
{
1547            int catchType =
1548            codeAttribute.exception_table[i].catch_type;
1549            if(catchType != 0)
1550                    {
1551            CONSTANT_Class_info classinfo = (CONSTANT_Class_info)
1552                constant_pool[catchType];
1553
1554            String JavaDoc name = ((CONSTANT_Utf8_info)
1555                       (constant_pool[classinfo.name_index])).convert();
1556            name = name.replace('/', '.');
1557            exception = cm.getSootClass(name);
1558            }
1559            else
1560            exception = cm.getSootClass("java.lang.Throwable");
1561        }
1562
1563        Stmt newTarget;
1564
1565        // Insert assignment of exception
1566
{
1567            Stmt firstTargetStmt =
1568            (Stmt) instructionToFirstStmt.get(targetIns);
1569                        
1570            if(targetToHandler.containsKey(firstTargetStmt))
1571            newTarget =
1572                (Stmt) targetToHandler.get(firstTargetStmt);
1573            else
1574                    {
1575            Local local =
1576                Util.v().getLocalCreatingIfNecessary(listBody, "$stack0",UnknownType.v());
1577            
1578            newTarget = Jimple.v().newIdentityStmt(local, Jimple.v().newCaughtExceptionRef());
1579            
1580            units.insertBefore(newTarget, firstTargetStmt);
1581            targetToHandler.put(firstTargetStmt, newTarget);
1582            }
1583        }
1584
1585        // Insert trap
1586
{
1587            Stmt firstStmt = (Stmt)instructionToFirstStmt.get(startIns);
1588            Stmt afterEndStmt;
1589            if (endIns == null) {
1590            // A kludge which isn't really correct, but
1591
// gets us closer to correctness (until we
1592
// clean up the rest of Soot to properly
1593
// represent Traps which extend to the end
1594
// of a method): if the protected code extends
1595
// to the end of the method, use the last Stmt
1596
// as the endUnit of the Trap, even though
1597
// that will leave the last unit outside
1598
// the protected area.
1599
afterEndStmt = (Stmt) units.getLast();
1600            } else {
1601            afterEndStmt = (Stmt) instructionToLastStmt.get(endIns);
1602            IdentityStmt catchStart =
1603                (IdentityStmt) targetToHandler.get(afterEndStmt);
1604                                // (Cast to IdentityStmt as an assertion check.)
1605
if (catchStart != null) {
1606                // The protected region extends to the beginning of an
1607
// exception handler, so we need to reset afterEndStmt
1608
// to the identity statement which we have inserted
1609
// before the old afterEndStmt.
1610
if (catchStart != units.getPredOf(afterEndStmt)) {
1611                throw new IllegalStateException JavaDoc("Assertion failure: catchStart != pred of afterEndStmt");
1612                }
1613                afterEndStmt = catchStart;
1614            }
1615            }
1616
1617            Trap trap = Jimple.v().newTrap(exception,
1618                           firstStmt,
1619                           afterEndStmt,
1620                           newTarget);
1621            listBody.getTraps().add(trap);
1622        }
1623        }
1624        }
1625
1626    /* convert line number table to tags attached to statements */
1627    if (Options.v().keep_line_number())
1628    {
1629        HashMap stmtstags = new HashMap();
1630        LinkedList startstmts = new LinkedList();
1631
1632        attribute_info[] attrs = codeAttribute.attributes;
1633        for (int i=0; i<attrs.length; i++)
1634        {
1635        if (attrs[i] instanceof LineNumberTable_attribute)
1636        {
1637            LineNumberTable_attribute lntattr =
1638            (LineNumberTable_attribute)attrs[i];
1639            for (int j=0; j<lntattr.line_number_table.length; j++)
1640            {
1641            Stmt start_stmt = (Stmt)instructionToFirstStmt.get(
1642                 lntattr.line_number_table[j].start_inst);
1643
1644            if (start_stmt != null)
1645            {
1646                LineNumberTag lntag= new LineNumberTag(
1647                    lntattr.line_number_table[j].line_number);
1648                stmtstags.put(start_stmt, lntag);
1649                startstmts.add(start_stmt);
1650            }
1651            }
1652        }
1653        }
1654
1655        /* if the predecessor of a statement is a caughtexcetionref,
1656             * give it the tag of its successor */

1657            for( Iterator stmtIt = new ArrayList(stmtstags.keySet()).iterator(); stmtIt.hasNext(); ) {
1658                final Stmt stmt = (Stmt) stmtIt.next();
1659                Stmt pred = stmt;
1660                Tag tag = (Tag) stmtstags.get(stmt);
1661                while(true) {
1662                    pred = (Stmt)units.getPredOf(pred);
1663                    if( pred == null ) break;
1664                    if(!(pred instanceof IdentityStmt)) break;
1665                    stmtstags.put(pred, tag);
1666                    pred.addTag(tag);
1667                }
1668            }
1669
1670        /* attach line number tag to each statement. */
1671        for (int i=0; i<startstmts.size(); i++)
1672        {
1673        Stmt stmt = (Stmt)startstmts.get(i);
1674        Tag tag = (Tag)stmtstags.get(stmt);
1675        
1676        stmt.addTag(tag);
1677        
1678        stmt = (Stmt)units.getSuccOf(stmt);
1679        while (stmt != null
1680               && !stmtstags.containsKey(stmt))
1681        {
1682            stmt.addTag(tag);
1683            stmt = (Stmt)units.getSuccOf(stmt);
1684        }
1685        }
1686    }
1687    }
1688
1689    private Type byteCodeTypeOf(Type type)
1690    {
1691        if(type.equals(ShortType.v()) ||
1692            type.equals(CharType.v()) ||
1693            type.equals(ByteType.v()) ||
1694            type.equals(BooleanType.v()))
1695        {
1696            return IntType.v();
1697        }
1698        else
1699            return type;
1700    }
1701
1702     OutFlow processFlow(Instruction ins, TypeStack typeStack,
1703        cp_info[] constant_pool)
1704    {
1705        int x;
1706        x = ((int)(ins.code))&0xff;
1707
1708        switch(x)
1709        {
1710         case ByteCode.BIPUSH:
1711            typeStack = typeStack.push(IntType.v());
1712            break;
1713
1714         case ByteCode.SIPUSH:
1715            typeStack = typeStack.push(IntType.v());
1716            break;
1717
1718         case ByteCode.LDC1:
1719            return processCPEntry(constant_pool,
1720                ((Instruction_Ldc1)ins).arg_b, typeStack, jmethod);
1721
1722         case ByteCode.LDC2:
1723         case ByteCode.LDC2W:
1724            return processCPEntry(constant_pool,
1725                ((Instruction_intindex)ins).arg_i, typeStack, jmethod);
1726
1727         case ByteCode.ACONST_NULL:
1728            typeStack = typeStack.push(RefType.v("java.lang.Object"));
1729            break;
1730
1731         case ByteCode.ICONST_M1:
1732         case ByteCode.ICONST_0:
1733         case ByteCode.ICONST_1:
1734         case ByteCode.ICONST_2:
1735         case ByteCode.ICONST_3:
1736         case ByteCode.ICONST_4:
1737         case ByteCode.ICONST_5:
1738            typeStack = typeStack.push(IntType.v());
1739            break;
1740         case ByteCode.LCONST_0:
1741         case ByteCode.LCONST_1:
1742            typeStack = typeStack.push(LongType.v());
1743            typeStack = typeStack.push(Long2ndHalfType.v());
1744            break;
1745         case ByteCode.FCONST_0:
1746         case ByteCode.FCONST_1:
1747         case ByteCode.FCONST_2:
1748            typeStack = typeStack.push(FloatType.v());
1749            break;
1750         case ByteCode.DCONST_0:
1751         case ByteCode.DCONST_1:
1752            typeStack = typeStack.push(DoubleType.v());
1753            typeStack = typeStack.push(Double2ndHalfType.v());
1754            break;
1755         case ByteCode.ILOAD:
1756            typeStack = typeStack.push(IntType.v());
1757            break;
1758
1759         case ByteCode.FLOAD:
1760            typeStack = typeStack.push(FloatType.v());
1761            break;
1762
1763         case ByteCode.ALOAD:
1764            typeStack = typeStack.push(RefType.v("java.lang.Object"));
1765                // this is highly imprecise
1766
break;
1767
1768         case ByteCode.DLOAD:
1769            typeStack = typeStack.push(DoubleType.v());
1770            typeStack = typeStack.push(Double2ndHalfType.v());
1771            break;
1772
1773         case ByteCode.LLOAD:
1774            typeStack = typeStack.push(LongType.v());
1775            typeStack = typeStack.push(Long2ndHalfType.v());
1776            break;
1777
1778         case ByteCode.ILOAD_0:
1779         case ByteCode.ILOAD_1:
1780         case ByteCode.ILOAD_2:
1781         case ByteCode.ILOAD_3:
1782            typeStack = typeStack.push(IntType.v());
1783            break;
1784
1785         case ByteCode.FLOAD_0:
1786         case ByteCode.FLOAD_1:
1787         case ByteCode.FLOAD_2:
1788         case ByteCode.FLOAD_3:
1789            typeStack = typeStack.push(FloatType.v());
1790            break;
1791
1792         case ByteCode.ALOAD_0:
1793         case ByteCode.ALOAD_1:
1794         case ByteCode.ALOAD_2:
1795         case ByteCode.ALOAD_3:
1796            typeStack = typeStack.push(RefType.v("java.lang.Object"));
1797                // this is highly imprecise
1798
break;
1799
1800         case ByteCode.LLOAD_0:
1801         case ByteCode.LLOAD_1:
1802         case ByteCode.LLOAD_2:
1803         case ByteCode.LLOAD_3:
1804            typeStack = typeStack.push(LongType.v());
1805            typeStack = typeStack.push(Long2ndHalfType.v());
1806            break;
1807
1808         case ByteCode.DLOAD_0:
1809         case ByteCode.DLOAD_1:
1810         case ByteCode.DLOAD_2:
1811         case ByteCode.DLOAD_3:
1812            typeStack = typeStack.push(DoubleType.v());
1813            typeStack = typeStack.push(Double2ndHalfType.v());
1814            break;
1815
1816         case ByteCode.ISTORE:
1817            typeStack = popSafe(typeStack, IntType.v());
1818            break;
1819
1820         case ByteCode.FSTORE:
1821            typeStack = popSafe(typeStack, FloatType.v());
1822            break;
1823
1824         case ByteCode.ASTORE:
1825            typeStack = typeStack.pop();
1826            break;
1827
1828         case ByteCode.LSTORE:
1829            typeStack = popSafe(typeStack, Long2ndHalfType.v());
1830            typeStack = popSafe(typeStack, LongType.v());
1831            break;
1832
1833         case ByteCode.DSTORE:
1834            typeStack = popSafe(typeStack, Double2ndHalfType.v());
1835            typeStack = popSafe(typeStack, DoubleType.v());
1836            break;
1837
1838         case ByteCode.ISTORE_0:
1839         case ByteCode.ISTORE_1:
1840         case ByteCode.ISTORE_2:
1841         case ByteCode.ISTORE_3:
1842            typeStack = popSafe(typeStack, IntType.v());
1843            break;
1844
1845         case ByteCode.FSTORE_0:
1846         case ByteCode.FSTORE_1:
1847         case ByteCode.FSTORE_2:
1848         case ByteCode.FSTORE_3:
1849            typeStack = popSafe(typeStack, FloatType.v());
1850            break;
1851
1852         case ByteCode.ASTORE_0:
1853         case ByteCode.ASTORE_1:
1854         case ByteCode.ASTORE_2:
1855         case ByteCode.ASTORE_3:
1856            if(!(typeStack.top() instanceof StmtAddressType) &&
1857                !(typeStack.top() instanceof RefType) &&
1858                !(typeStack.top() instanceof ArrayType))
1859            {
1860                throw new RuntimeException JavaDoc("Astore failed, invalid stack type: " + typeStack.top());
1861            }
1862
1863            typeStack = typeStack.pop();
1864            break;
1865
1866         case ByteCode.LSTORE_0:
1867         case ByteCode.LSTORE_1:
1868         case ByteCode.LSTORE_2:
1869         case ByteCode.LSTORE_3:
1870            typeStack = popSafe(typeStack, Long2ndHalfType.v());
1871            typeStack = popSafe(typeStack, LongType.v());
1872            break;
1873
1874         case ByteCode.DSTORE_0:
1875         case ByteCode.DSTORE_1:
1876         case ByteCode.DSTORE_2:
1877         case ByteCode.DSTORE_3:
1878            typeStack = popSafe(typeStack, Double2ndHalfType.v());
1879            typeStack = popSafe(typeStack, DoubleType.v());
1880            break;
1881
1882         case ByteCode.IINC:
1883            break;
1884
1885         case ByteCode.WIDE:
1886            throw new RuntimeException JavaDoc("Wide instruction should not be encountered");
1887            // break;
1888

1889         case ByteCode.NEWARRAY:
1890         {
1891            typeStack = popSafe(typeStack, IntType.v());
1892            Type baseType = (Type) jimpleTypeOfAtype(((Instruction_Newarray)ins).atype);
1893
1894            typeStack = typeStack.push(ArrayType.v(baseType, 1));
1895            break;
1896         }
1897
1898        case ByteCode.ANEWARRAY:
1899        {
1900            CONSTANT_Class_info c = (CONSTANT_Class_info) constant_pool[
1901                ((Instruction_Anewarray)ins).arg_i];
1902
1903            String JavaDoc name = ((CONSTANT_Utf8_info) (constant_pool[c.name_index])).convert();
1904            name = name.replace('/', '.');
1905
1906            Type baseType;
1907
1908            if(name.startsWith("[")) {
1909                String JavaDoc baseName = getClassName(constant_pool, ((Instruction_Anewarray)ins).arg_i);
1910                baseType = Util.v().jimpleTypeOfFieldDescriptor(baseName);
1911            } else {
1912                baseType = RefType.v(name);
1913            }
1914
1915            typeStack = popSafe(typeStack, IntType.v());
1916            typeStack = typeStack.push(baseType.makeArrayType());
1917            break;
1918        }
1919
1920        case ByteCode.MULTIANEWARRAY:
1921        {
1922            int bdims = (int)(((Instruction_Multianewarray)ins).dims);
1923
1924
1925            CONSTANT_Class_info c = (CONSTANT_Class_info) constant_pool[
1926               ((Instruction_Multianewarray)ins).arg_i];
1927
1928            String JavaDoc arrayDescriptor = ((CONSTANT_Utf8_info) (constant_pool[c.name_index])).convert();
1929
1930            ArrayType arrayType = (ArrayType)
1931                Util.v().jimpleTypeOfFieldDescriptor(arrayDescriptor);
1932
1933            for (int j=0;j<bdims;j++)
1934                typeStack = popSafe(typeStack, IntType.v());
1935
1936            typeStack = typeStack.push(arrayType);
1937            break;
1938        }
1939
1940         case ByteCode.ARRAYLENGTH:
1941            typeStack = popSafeRefType(typeStack);
1942            typeStack = typeStack.push(IntType.v());
1943            break;
1944
1945         case ByteCode.IALOAD:
1946         case ByteCode.BALOAD:
1947         case ByteCode.CALOAD:
1948         case ByteCode.SALOAD:
1949            typeStack = popSafe(typeStack, IntType.v());
1950            typeStack = popSafeRefType(typeStack);
1951            typeStack = typeStack.push(IntType.v());
1952            break;
1953         case ByteCode.FALOAD:
1954            typeStack = popSafe(typeStack, FloatType.v());
1955            typeStack = popSafeRefType(typeStack);
1956            typeStack = typeStack.push(FloatType.v());
1957            break;
1958
1959         case ByteCode.AALOAD:
1960         {
1961
1962            typeStack = popSafe(typeStack, IntType.v());
1963
1964            if(typeStack.top() instanceof ArrayType)
1965            {
1966                ArrayType arrayType = (ArrayType) typeStack.top();
1967                typeStack = popSafeRefType(typeStack);
1968
1969                if(arrayType.numDimensions == 1)
1970                    typeStack = typeStack.push(arrayType.baseType);
1971                else
1972                    typeStack = typeStack.push(ArrayType.v(arrayType.baseType, arrayType.numDimensions - 1));
1973            }
1974            else {
1975                // it's a null object
1976

1977                typeStack = popSafeRefType(typeStack);
1978
1979                typeStack = typeStack.push(RefType.v("java.lang.Object"));
1980            }
1981
1982            break;
1983         }
1984         case ByteCode.LALOAD:
1985            typeStack = popSafe(typeStack, IntType.v());
1986            typeStack = popSafeRefType(typeStack);
1987            typeStack = typeStack.push(LongType.v());
1988            typeStack = typeStack.push(Long2ndHalfType.v());
1989            break;
1990
1991         case ByteCode.DALOAD:
1992            typeStack = popSafe(typeStack, IntType.v());
1993            typeStack = popSafeRefType(typeStack);
1994            typeStack = typeStack.push(DoubleType.v());
1995            typeStack = typeStack.push(Double2ndHalfType.v());
1996            break;
1997
1998         case ByteCode.IASTORE:
1999         case ByteCode.BASTORE:
2000         case ByteCode.CASTORE:
2001         case ByteCode.SASTORE:
2002            typeStack = popSafe(typeStack, IntType.v());
2003            typeStack = popSafe(typeStack, IntType.v());
2004            typeStack = popSafeRefType(typeStack);
2005            break;
2006
2007         case ByteCode.AASTORE:
2008            typeStack = popSafeRefType(typeStack);
2009            typeStack = popSafe(typeStack, IntType.v());
2010            typeStack = popSafeRefType(typeStack);
2011            break;
2012
2013         case ByteCode.FASTORE:
2014            typeStack = popSafe(typeStack, FloatType.v());
2015            typeStack = popSafe(typeStack, IntType.v());
2016            typeStack = popSafeRefType(typeStack);
2017            break;
2018
2019         case ByteCode.LASTORE:
2020            typeStack = popSafe(typeStack, Long2ndHalfType.v());
2021            typeStack = popSafe(typeStack, LongType.v());
2022            typeStack = popSafe(typeStack, IntType.v());
2023            typeStack = popSafeRefType(typeStack);
2024            break;
2025
2026         case ByteCode.DASTORE:
2027            typeStack = popSafe(typeStack, Double2ndHalfType.v());
2028            typeStack = popSafe(typeStack, DoubleType.v());
2029            typeStack = popSafe(typeStack, IntType.v());
2030            typeStack = popSafeRefType(typeStack);
2031            break;
2032
2033         case ByteCode.NOP:
2034            break;
2035
2036         case ByteCode.POP:
2037            typeStack = typeStack.pop();
2038            break;
2039
2040         case ByteCode.POP2:
2041            typeStack = typeStack.pop();
2042            typeStack = typeStack.pop();
2043            break;
2044
2045         case ByteCode.DUP:
2046            typeStack = typeStack.push(typeStack.top());
2047            break;
2048
2049         case ByteCode.DUP2:
2050         {
2051            Type topType = typeStack.get(typeStack.topIndex()),
2052                              secondType = typeStack.get(typeStack.topIndex()-1);
2053            typeStack = (typeStack.push(secondType)).push(topType);
2054            break;
2055         }
2056
2057         case ByteCode.DUP_X1:
2058         {
2059            Type topType = typeStack.get(typeStack.topIndex()),
2060                              secondType = typeStack.get(typeStack.topIndex()-1);
2061
2062            typeStack = typeStack.pop().pop();
2063
2064            typeStack = typeStack.push(topType).push(secondType).push(topType);
2065            break;
2066         }
2067
2068         case ByteCode.DUP_X2:
2069         {
2070            Type topType = typeStack.get(typeStack.topIndex()),
2071                              secondType = typeStack.get(typeStack.topIndex()-1),
2072                              thirdType = typeStack.get(typeStack.topIndex()-2);
2073
2074            typeStack = typeStack.pop().pop().pop();
2075
2076            typeStack = typeStack.push(topType).push(thirdType).push(secondType).push(topType);
2077            break;
2078         }
2079
2080         case ByteCode.DUP2_X1:
2081         {
2082            Type topType = typeStack.get(typeStack.topIndex()),
2083                              secondType = typeStack.get(typeStack.topIndex()-1),
2084                              thirdType = typeStack.get(typeStack.topIndex()-2);
2085
2086            typeStack = typeStack.pop().pop().pop();
2087
2088            typeStack = typeStack.push(secondType).push(topType).
2089                push(thirdType).push(secondType).push(topType);
2090            break;
2091         }
2092
2093         case ByteCode.DUP2_X2:
2094         {
2095            Type topType = typeStack.get(typeStack.topIndex()),
2096                              secondType = typeStack.get(typeStack.topIndex()-1),
2097                              thirdType = typeStack.get(typeStack.topIndex()-2),
2098                              fourthType = typeStack.get(typeStack.topIndex()-3);
2099
2100            typeStack = typeStack.pop().pop().pop().pop();
2101
2102            typeStack = typeStack.push(secondType).push(topType).
2103                push(fourthType).push(thirdType).push(secondType).push(topType);
2104            break;
2105         }
2106
2107         case ByteCode.SWAP:
2108         {
2109            Type topType = typeStack.top();
2110
2111            typeStack = typeStack.pop();
2112
2113            Type secondType = typeStack.top();
2114
2115            typeStack = typeStack.pop();
2116
2117            typeStack = typeStack.push(topType);
2118            typeStack = typeStack.push(secondType);
2119            break;
2120         }
2121
2122
2123         case ByteCode.IADD:
2124         case ByteCode.ISUB:
2125         case ByteCode.IMUL:
2126         case ByteCode.IDIV:
2127         case ByteCode.IREM:
2128         case ByteCode.ISHL:
2129         case ByteCode.ISHR:
2130         case ByteCode.IUSHR:
2131         case ByteCode.IAND:
2132         case ByteCode.IOR:
2133         case ByteCode.IXOR:
2134            typeStack = popSafe(typeStack, IntType.v());
2135            typeStack = popSafe(typeStack, IntType.v());
2136            typeStack = typeStack.push(IntType.v());
2137            break;
2138
2139         case ByteCode.LUSHR:
2140         case ByteCode.LSHR:
2141         case ByteCode.LSHL:
2142            typeStack = popSafe(typeStack, IntType.v());
2143            typeStack = popSafe(typeStack, Long2ndHalfType.v());
2144            typeStack = popSafe(typeStack, LongType.v());
2145            typeStack = typeStack.push(LongType.v());
2146            typeStack = typeStack.push(Long2ndHalfType.v());
2147            break;
2148
2149         case ByteCode.LREM:
2150         case ByteCode.LDIV:
2151         case ByteCode.LMUL:
2152         case ByteCode.LSUB:
2153         case ByteCode.LADD:
2154         case ByteCode.LAND:
2155         case ByteCode.LOR:
2156         case ByteCode.LXOR:
2157            typeStack = popSafe(typeStack, Long2ndHalfType.v());
2158            typeStack = popSafe(typeStack, LongType.v());
2159            typeStack = popSafe(typeStack, Long2ndHalfType.v());
2160            typeStack = popSafe(typeStack, LongType.v());
2161            typeStack = typeStack.push(LongType.v());
2162            typeStack = typeStack.push(Long2ndHalfType.v());
2163            break;
2164
2165         case ByteCode.FREM:
2166         case ByteCode.FDIV:
2167         case ByteCode.FMUL:
2168         case ByteCode.FSUB:
2169         case ByteCode.FADD:
2170            typeStack = popSafe(typeStack, FloatType.v());
2171            typeStack = popSafe(typeStack, FloatType.v());
2172            typeStack = typeStack.push(FloatType.v());
2173            break;
2174
2175         case ByteCode.DREM:
2176         case ByteCode.DDIV:
2177         case ByteCode.DMUL:
2178         case ByteCode.DSUB:
2179         case ByteCode.DADD:
2180            typeStack = popSafe(typeStack, Double2ndHalfType.v());
2181            typeStack = popSafe(typeStack, DoubleType.v());
2182            typeStack = popSafe(typeStack, Double2ndHalfType.v());
2183            typeStack = popSafe(typeStack, DoubleType.v());
2184            typeStack = typeStack.push(DoubleType.v());
2185            typeStack = typeStack.push(Double2ndHalfType.v());
2186            break;
2187
2188         case ByteCode.INEG:
2189         case ByteCode.LNEG:
2190         case ByteCode.FNEG:
2191         case ByteCode.DNEG:
2192            // Doesn't check to see if the required types are on the stack, but it should
2193
// if it wanted to be safe.
2194
break;
2195
2196         case ByteCode.I2L:
2197            typeStack = popSafe(typeStack, IntType.v());
2198            typeStack = typeStack.push(LongType.v());
2199            typeStack = typeStack.push(Long2ndHalfType.v());
2200            break;
2201
2202         case ByteCode.I2F:
2203            typeStack = popSafe(typeStack, IntType.v());
2204            typeStack = typeStack.push(FloatType.v());
2205            break;
2206
2207         case ByteCode.I2D:
2208            typeStack = popSafe(typeStack, IntType.v());
2209            typeStack = typeStack.push(DoubleType.v());
2210            typeStack = typeStack.push(Double2ndHalfType.v());
2211            break;
2212
2213         case ByteCode.L2I:
2214            typeStack = popSafe(typeStack, Long2ndHalfType.v());
2215            typeStack = popSafe(typeStack, LongType.v());
2216            typeStack = typeStack.push(IntType.v());
2217            break;
2218
2219         case ByteCode.L2F:
2220            typeStack = popSafe(typeStack, Long2ndHalfType.v());
2221            typeStack = popSafe(typeStack, LongType.v());
2222            typeStack = typeStack.push(FloatType.v());
2223            break;
2224
2225         case ByteCode.L2D:
2226            typeStack = popSafe(typeStack, Long2ndHalfType.v());
2227            typeStack = popSafe(typeStack, LongType.v());
2228            typeStack = typeStack.push(DoubleType.v());
2229            typeStack = typeStack.push(Double2ndHalfType.v());
2230            break;
2231
2232         case ByteCode.F2I:
2233            typeStack = popSafe(typeStack, FloatType.v());
2234            typeStack = typeStack.push(IntType.v());
2235            break;
2236
2237         case ByteCode.F2L:
2238            typeStack = popSafe(typeStack, FloatType.v());
2239            typeStack = typeStack.push(LongType.v());
2240            typeStack = typeStack.push(Long2ndHalfType.v());
2241            break;
2242
2243         case ByteCode.F2D:
2244            typeStack = popSafe(typeStack, FloatType.v());
2245            typeStack = typeStack.push(DoubleType.v());
2246            typeStack = typeStack.push(Double2ndHalfType.v());
2247            break;
2248
2249         case ByteCode.D2I:
2250            typeStack = popSafe(typeStack, Double2ndHalfType.v());
2251            typeStack = popSafe(typeStack, DoubleType.v());
2252            typeStack = typeStack.push(IntType.v());
2253            break;
2254
2255         case ByteCode.D2L:
2256            typeStack = popSafe(typeStack, Double2ndHalfType.v());
2257            typeStack = popSafe(typeStack, DoubleType.v());
2258            typeStack = typeStack.push(LongType.v());
2259            typeStack = typeStack.push(Long2ndHalfType.v());
2260            break;
2261
2262         case ByteCode.D2F:
2263            typeStack = popSafe(typeStack, Double2ndHalfType.v());
2264            typeStack = popSafe(typeStack, DoubleType.v());
2265            typeStack = typeStack.push(FloatType.v());
2266            break;
2267
2268         case ByteCode.INT2BYTE:
2269            break;
2270         case ByteCode.INT2CHAR:
2271            break;
2272         case ByteCode.INT2SHORT:
2273            break;
2274
2275         case ByteCode.IFEQ:
2276         case ByteCode.IFGT:
2277         case ByteCode.IFLT:
2278         case ByteCode.IFLE:
2279         case ByteCode.IFNE:
2280         case ByteCode.IFGE:
2281            typeStack = popSafe(typeStack, IntType.v());
2282            break;
2283
2284         case ByteCode.IFNULL:
2285         case ByteCode.IFNONNULL:
2286            typeStack = popSafeRefType(typeStack);
2287            break;
2288
2289         case ByteCode.IF_ICMPEQ:
2290         case ByteCode.IF_ICMPLT:
2291         case ByteCode.IF_ICMPLE:
2292         case ByteCode.IF_ICMPNE:
2293         case ByteCode.IF_ICMPGT:
2294         case ByteCode.IF_ICMPGE:
2295            typeStack = popSafe(typeStack, IntType.v());
2296            typeStack = popSafe(typeStack, IntType.v());
2297            break;
2298
2299         case ByteCode.LCMP:
2300            typeStack = popSafe(typeStack, Long2ndHalfType.v());
2301            typeStack = popSafe(typeStack, LongType.v());
2302            typeStack = popSafe(typeStack, Long2ndHalfType.v());
2303            typeStack = popSafe(typeStack, LongType.v());
2304            typeStack = typeStack.push(IntType.v());
2305            break;
2306
2307         case ByteCode.FCMPL:
2308         case ByteCode.FCMPG:
2309            typeStack = popSafe(typeStack, FloatType.v());
2310            typeStack = popSafe(typeStack, FloatType.v());
2311            typeStack = typeStack.push(IntType.v());
2312            break;
2313
2314         case ByteCode.DCMPL:
2315         case ByteCode.DCMPG:
2316            typeStack = popSafe(typeStack, Double2ndHalfType.v());
2317            typeStack = popSafe(typeStack, DoubleType.v());
2318            typeStack = popSafe(typeStack, Double2ndHalfType.v());
2319            typeStack = popSafe(typeStack, DoubleType.v());
2320            typeStack = typeStack.push(IntType.v());
2321            break;
2322
2323         case ByteCode.IF_ACMPEQ:
2324         case ByteCode.IF_ACMPNE:
2325            typeStack = popSafeRefType(typeStack);
2326            typeStack = popSafeRefType(typeStack);
2327            break;
2328
2329         case ByteCode.GOTO:
2330         case ByteCode.GOTO_W:
2331            break;
2332
2333         case ByteCode.JSR:
2334         case ByteCode.JSR_W:
2335            typeStack = typeStack.push(StmtAddressType.v());
2336            break;
2337
2338         case ByteCode.RET:
2339            break;
2340
2341         case ByteCode.RET_W:
2342            break;
2343
2344         case ByteCode.RETURN:
2345            break;
2346
2347         case ByteCode.IRETURN:
2348            typeStack = popSafe(typeStack, IntType.v());
2349            break;
2350
2351         case ByteCode.FRETURN:
2352            typeStack = popSafe(typeStack, FloatType.v());
2353            break;
2354
2355         case ByteCode.ARETURN:
2356             typeStack = popSafeRefType(typeStack);
2357            break;
2358
2359         case ByteCode.DRETURN:
2360            typeStack = popSafe(typeStack, Double2ndHalfType.v());
2361            typeStack = popSafe(typeStack, DoubleType.v());
2362            break;
2363
2364         case ByteCode.LRETURN:
2365            typeStack = popSafe(typeStack, Long2ndHalfType.v());
2366            typeStack = popSafe(typeStack, LongType.v());
2367            break;
2368
2369         case ByteCode.BREAKPOINT:
2370            break;
2371
2372         case ByteCode.TABLESWITCH:
2373            typeStack = popSafe(typeStack, IntType.v());
2374            break;
2375
2376         case ByteCode.LOOKUPSWITCH:
2377            typeStack = popSafe(typeStack, IntType.v());
2378            break;
2379
2380         case ByteCode.PUTFIELD:
2381         {
2382            Type type = byteCodeTypeOf(jimpleTypeOfFieldInFieldRef(cm, constant_pool,
2383                ((Instruction_Putfield)ins).arg_i));
2384
2385            if(type.equals(DoubleType.v()))
2386            {
2387                typeStack = popSafe(typeStack, Double2ndHalfType.v());
2388                typeStack = popSafe(typeStack, DoubleType.v());
2389            }
2390            else if(type.equals(LongType.v()))
2391            {
2392                typeStack = popSafe(typeStack, Long2ndHalfType.v());
2393                typeStack = popSafe(typeStack, LongType.v());
2394            }
2395            else if(type instanceof RefType)
2396                typeStack = popSafeRefType(typeStack);
2397            else
2398                typeStack = popSafe(typeStack, type);
2399
2400            typeStack = popSafeRefType(typeStack);
2401            break;
2402         }
2403
2404         case ByteCode.GETFIELD:
2405         {
2406            Type type = byteCodeTypeOf(jimpleTypeOfFieldInFieldRef(cm, constant_pool,
2407                ((Instruction_Getfield)ins).arg_i));
2408
2409            typeStack = popSafeRefType(typeStack);
2410
2411            if (type.equals(DoubleType.v()))
2412            {
2413                typeStack = typeStack.push(DoubleType.v());
2414                typeStack = typeStack.push(Double2ndHalfType.v());
2415            }
2416            else if(type.equals(LongType.v()))
2417            {
2418                typeStack = typeStack.push(LongType.v());
2419                typeStack = typeStack.push(Long2ndHalfType.v());
2420            }
2421            else
2422                typeStack = typeStack.push(type);
2423            break;
2424         }
2425
2426         case ByteCode.PUTSTATIC:
2427         {
2428            Type type = byteCodeTypeOf(jimpleTypeOfFieldInFieldRef(cm, constant_pool,
2429                ((Instruction_Putstatic)ins).arg_i));
2430
2431            if(type.equals(DoubleType.v()))
2432            {
2433                typeStack = popSafe(typeStack, Double2ndHalfType.v());
2434                typeStack = popSafe(typeStack, DoubleType.v());
2435            }
2436            else if(type.equals(LongType.v()))
2437            {
2438                typeStack = popSafe(typeStack, Long2ndHalfType.v());
2439                typeStack = popSafe(typeStack, LongType.v());
2440            }
2441            else if(type instanceof RefType)
2442                typeStack = popSafeRefType(typeStack);
2443            else
2444                typeStack = popSafe(typeStack, type);
2445
2446            break;
2447         }
2448
2449         case ByteCode.GETSTATIC:
2450         {
2451            Type type = byteCodeTypeOf(jimpleTypeOfFieldInFieldRef(cm, constant_pool,
2452                ((Instruction_Getstatic)ins).arg_i));
2453
2454            if (type.equals(DoubleType.v()))
2455            {
2456                typeStack = typeStack.push(DoubleType.v());
2457                typeStack = typeStack.push(Double2ndHalfType.v());
2458            }
2459            else if(type.equals(LongType.v()))
2460            {
2461                typeStack = typeStack.push(LongType.v());
2462                typeStack = typeStack.push(Long2ndHalfType.v());
2463            }
2464            else
2465                typeStack = typeStack.push(type);
2466            break;
2467         }
2468
2469         case ByteCode.INVOKEVIRTUAL:
2470         {
2471            Instruction_Invokevirtual iv = (Instruction_Invokevirtual)ins;
2472            int args = cp_info.countParams(constant_pool,iv.arg_i);
2473            Type returnType = byteCodeTypeOf(jimpleReturnTypeOfMethodRef(cm,
2474                constant_pool, iv.arg_i));
2475
2476            // pop off parameters.
2477
for (int j=args-1;j>=0;j--)
2478                {
2479                    if(typeStack.top().equals(Long2ndHalfType.v()))
2480                    {
2481                        typeStack = popSafe(typeStack, Long2ndHalfType.v());
2482                        typeStack = popSafe(typeStack, LongType.v());
2483
2484                    }
2485                    else if(typeStack.top().equals(Double2ndHalfType.v()))
2486                    {
2487                        typeStack = popSafe(typeStack, Double2ndHalfType.v());
2488                        typeStack = popSafe(typeStack, DoubleType.v());
2489                    }
2490                    else
2491                        typeStack = popSafe(typeStack, typeStack.top());
2492                }
2493
2494            typeStack = popSafeRefType(typeStack);
2495
2496            if(!returnType.equals(VoidType.v()))
2497                typeStack = smartPush(typeStack, returnType);
2498            break;
2499        }
2500
2501        case ByteCode.INVOKENONVIRTUAL:
2502        {
2503            Instruction_Invokenonvirtual iv = (Instruction_Invokenonvirtual)ins;
2504            int args = cp_info.countParams(constant_pool,iv.arg_i);
2505            Type returnType = byteCodeTypeOf(jimpleReturnTypeOfMethodRef(cm,
2506                constant_pool, iv.arg_i));
2507
2508            // pop off parameters.
2509
for (int j=args-1;j>=0;j--)
2510                {
2511                    if(typeStack.top().equals(Long2ndHalfType.v()))
2512                    {
2513                        typeStack = popSafe(typeStack, Long2ndHalfType.v());
2514                        typeStack = popSafe(typeStack, LongType.v());
2515
2516                    }
2517                    else if(typeStack.top().equals(Double2ndHalfType.v()))
2518                    {
2519                        typeStack = popSafe(typeStack, Double2ndHalfType.v());
2520                        typeStack = popSafe(typeStack, DoubleType.v());
2521                    }
2522                    else
2523                        typeStack = popSafe(typeStack, typeStack.top());
2524                }
2525
2526            typeStack = popSafeRefType(typeStack);
2527
2528            if(!returnType.equals(VoidType.v()))
2529                typeStack = smartPush(typeStack, returnType);
2530            break;
2531        }
2532
2533         case ByteCode.INVOKESTATIC:
2534         {
2535            Instruction_Invokestatic iv = (Instruction_Invokestatic)ins;
2536            int args = cp_info.countParams(constant_pool,iv.arg_i);
2537            Type returnType = byteCodeTypeOf(jimpleReturnTypeOfMethodRef(cm,
2538                constant_pool, iv.arg_i));
2539
2540            // pop off parameters.
2541
for (int j=args-1;j>=0;j--)
2542                {
2543                    if(typeStack.top().equals(Long2ndHalfType.v()))
2544                    {
2545                        typeStack = popSafe(typeStack, Long2ndHalfType.v());
2546                        typeStack = popSafe(typeStack, LongType.v());
2547
2548                    }
2549                    else if(typeStack.top().equals(Double2ndHalfType.v()))
2550                    {
2551                        typeStack = popSafe(typeStack, Double2ndHalfType.v());
2552                        typeStack = popSafe(typeStack, DoubleType.v());
2553                    }
2554                    else
2555                        typeStack = popSafe(typeStack, typeStack.top());
2556                }
2557
2558            if(!returnType.equals(VoidType.v()))
2559                typeStack = smartPush(typeStack, returnType);
2560            break;
2561         }
2562
2563         case ByteCode.INVOKEINTERFACE:
2564         {
2565            Instruction_Invokeinterface iv = (Instruction_Invokeinterface) ins;
2566            int args = cp_info.countParams(constant_pool,iv.arg_i);
2567            Type returnType = byteCodeTypeOf(jimpleReturnTypeOfInterfaceMethodRef(cm,
2568                constant_pool, iv.arg_i));
2569
2570            // pop off parameters.
2571
for (int j=args-1;j>=0;j--)
2572                {
2573                    if(typeStack.top().equals(Long2ndHalfType.v()))
2574                    {
2575                        typeStack = popSafe(typeStack, Long2ndHalfType.v());
2576                        typeStack = popSafe(typeStack, LongType.v());
2577
2578                    }
2579                    else if(typeStack.top().equals(Double2ndHalfType.v()))
2580                    {
2581                        typeStack = popSafe(typeStack, Double2ndHalfType.v());
2582                        typeStack = popSafe(typeStack, DoubleType.v());
2583                    }
2584                    else
2585                        typeStack = popSafe(typeStack, typeStack.top());
2586                }
2587
2588            typeStack = popSafeRefType(typeStack);
2589
2590            if(!returnType.equals(VoidType.v()))
2591                typeStack = smartPush(typeStack, returnType);
2592            break;
2593         }
2594
2595         case ByteCode.ATHROW:
2596            // technically athrow leaves the stack in an undefined
2597
// state. In fact, the top value is the one we actually
2598
// throw, but it should stay on the stack since the exception
2599
// handler expects to start that way, at least in the real JVM.
2600
break;
2601
2602         case ByteCode.NEW:
2603         {
2604            Type type = RefType.v(getClassName(constant_pool, ((Instruction_New)ins).arg_i));
2605
2606            typeStack = typeStack.push(type);
2607            break;
2608         }
2609
2610         case ByteCode.CHECKCAST:
2611         {
2612            String JavaDoc className = getClassName(constant_pool, ((Instruction_Checkcast)ins).arg_i);
2613
2614            Type castType;
2615
2616            if(className.startsWith("["))
2617                castType = Util.v().jimpleTypeOfFieldDescriptor(getClassName(constant_pool,
2618                ((Instruction_Checkcast)ins).arg_i));
2619            else
2620                castType = RefType.v(className);
2621
2622            typeStack = popSafeRefType(typeStack);
2623            typeStack = typeStack.push(castType);
2624            break;
2625         }
2626
2627         case ByteCode.INSTANCEOF:
2628         {
2629            typeStack = popSafeRefType(typeStack);
2630            typeStack = typeStack.push(IntType.v());
2631            break;
2632         }
2633
2634         case ByteCode.MONITORENTER:
2635            typeStack = popSafeRefType(typeStack);
2636            break;
2637         case ByteCode.MONITOREXIT:
2638            typeStack = popSafeRefType(typeStack);
2639            break;
2640
2641         default:
2642            throw new RuntimeException JavaDoc("processFlow failed: Unknown bytecode instruction: " + x);
2643         }
2644
2645         return new OutFlow(typeStack);
2646    }
2647
2648    private Type jimpleTypeOfFieldInFieldRef(Scene cm,
2649        cp_info[] constant_pool, int index)
2650    {
2651        CONSTANT_Fieldref_info fr = (CONSTANT_Fieldref_info)
2652                (constant_pool[index]);
2653
2654        CONSTANT_NameAndType_info nat = (CONSTANT_NameAndType_info)
2655            (constant_pool[fr.name_and_type_index]);
2656
2657        String JavaDoc fieldDescriptor = ((CONSTANT_Utf8_info)
2658        (constant_pool[nat.descriptor_index])).convert();
2659
2660        return Util.v().jimpleTypeOfFieldDescriptor(fieldDescriptor);
2661    }
2662
2663    private Type jimpleReturnTypeOfMethodRef(Scene cm,
2664        cp_info[] constant_pool, int index)
2665    {
2666        CONSTANT_Methodref_info mr = (CONSTANT_Methodref_info)
2667                (constant_pool[index]);
2668
2669        CONSTANT_NameAndType_info nat = (CONSTANT_NameAndType_info)
2670            (constant_pool[mr.name_and_type_index]);
2671
2672        String JavaDoc methodDescriptor = ((CONSTANT_Utf8_info)
2673            (constant_pool[nat.descriptor_index])).convert();
2674
2675        return Util.v().jimpleReturnTypeOfMethodDescriptor(methodDescriptor);
2676    }
2677
2678    private Type jimpleReturnTypeOfInterfaceMethodRef(Scene cm,
2679        cp_info[] constant_pool, int index)
2680    {
2681        CONSTANT_InterfaceMethodref_info mr = (CONSTANT_InterfaceMethodref_info)
2682                (constant_pool[index]);
2683
2684        CONSTANT_NameAndType_info nat = (CONSTANT_NameAndType_info)
2685            (constant_pool[mr.name_and_type_index]);
2686
2687        String JavaDoc methodDescriptor = ((CONSTANT_Utf8_info)
2688            (constant_pool[nat.descriptor_index])).convert();
2689
2690        return Util.v().jimpleReturnTypeOfMethodDescriptor(methodDescriptor);
2691    }
2692
2693    private OutFlow processCPEntry(cp_info constant_pool[],int i,
2694                            TypeStack typeStack,
2695                            SootMethod jmethod)
2696    {
2697        cp_info c = constant_pool[i];
2698
2699        if (c instanceof CONSTANT_Integer_info)
2700            typeStack = typeStack.push(IntType.v());
2701        else if (c instanceof CONSTANT_Float_info)
2702            typeStack = typeStack.push(FloatType.v());
2703        else if (c instanceof CONSTANT_Long_info)
2704        {
2705            typeStack = typeStack.push(LongType.v());
2706            typeStack = typeStack.push(Long2ndHalfType.v());
2707        }
2708        else if (c instanceof CONSTANT_Double_info)
2709        {
2710            typeStack = typeStack.push(DoubleType.v());
2711            typeStack = typeStack.push(Double2ndHalfType.v());
2712        }
2713        else if (c instanceof CONSTANT_String_info)
2714            typeStack = typeStack.push(RefType.v("java.lang.String"));
2715        else if (c instanceof CONSTANT_Utf8_info)
2716            typeStack = typeStack.push(RefType.v("java.lang.String"));
2717        else if (c instanceof CONSTANT_Class_info){
2718            CONSTANT_Class_info info = (CONSTANT_Class_info)c;
2719            String JavaDoc name = ((CONSTANT_Utf8_info) (constant_pool[info.name_index])).convert();
2720            if (name.charAt(0) == '['){
2721                int dim = 0;
2722                while (name.charAt(dim) == '['){
2723                    dim++;
2724                }
2725                // array type
2726
Type baseType = null;
2727                char typeIndicator = name.charAt(dim);
2728                switch (typeIndicator){
2729                    case 'I': baseType = IntType.v(); break;
2730                    case 'C': baseType = CharType.v(); break;
2731                    case 'F': baseType = FloatType.v(); break;
2732                    case 'D': baseType = DoubleType.v(); break;
2733                    case 'B': baseType = ByteType.v(); break;
2734                    case 'S': baseType = ShortType.v(); break;
2735                    case 'Z': baseType = BooleanType.v(); break;
2736                    case 'J': baseType = LongType.v(); break;
2737                    case 'L': baseType = RefType.v(name.substring(dim+1)); break; default : throw new RuntimeException JavaDoc("Unknown Array Base Type in Class Constant");
2738                }
2739                typeStack = typeStack.push(ArrayType.v(baseType, dim));
2740            }
2741            else {
2742                typeStack = typeStack.push(RefType.v(name));
2743            }
2744        }
2745        else
2746            throw new RuntimeException JavaDoc("Attempting to push a non-constant cp entry"+c.getClass());
2747
2748        return new OutFlow(typeStack);
2749    }
2750
2751   TypeStack smartPush(TypeStack typeStack, Type type)
2752   {
2753        if(type.equals(LongType.v()))
2754        {
2755            typeStack = typeStack.push(LongType.v());
2756            typeStack = typeStack.push(Long2ndHalfType.v());
2757        }
2758        else if(type.equals(DoubleType.v()))
2759        {
2760            typeStack = typeStack.push(DoubleType.v());
2761            typeStack = typeStack.push(Double2ndHalfType.v());
2762        }
2763        else
2764            typeStack = typeStack.push(type);
2765
2766        return typeStack;
2767   }
2768
2769   TypeStack popSafeRefType(TypeStack typeStack)
2770   {
2771        /*
2772        if(!(typeStack.top() instanceof RefType) &&
2773            !(typeStack.top() instanceof ArrayType))
2774        {
2775            throw new RuntimeException("popSafe failed; top: " + typeStack.top() +
2776                    " required: RefType");
2777        }
2778        */

2779
2780        return typeStack.pop();
2781   }
2782
2783   TypeStack popSafeArrayType(TypeStack typeStack)
2784   {
2785    /*
2786        if(!(typeStack.top() instanceof ArrayType) &&
2787            !(RefType.v("null").equals(typeStack.top())))
2788        {
2789            throw new RuntimeException("popSafe failed; top: " + typeStack.top() +
2790                    " required: ArrayType");
2791        }
2792      */

2793
2794        return typeStack.pop();
2795   }
2796
2797   TypeStack popSafe(TypeStack typeStack, Type requiredType)
2798   {
2799    /*
2800        if(!typeStack.top().equals(requiredType))
2801            throw new RuntimeException("popSafe failed; top: " + typeStack.top() +
2802            " required: " + requiredType);
2803      */

2804
2805        return typeStack.pop();
2806   }
2807
2808   void confirmType(Type actualType, Type requiredType)
2809   {
2810    /*
2811        if(!actualType.equals(requiredType))
2812            throw new RuntimeException("confirmType failed; actualType: " + actualType +
2813                " required: " + requiredType);*/

2814   }
2815
2816   String JavaDoc getClassName(cp_info[] constant_pool, int index)
2817   {
2818        CONSTANT_Class_info c = (CONSTANT_Class_info) constant_pool[index];
2819
2820        String JavaDoc name = ((CONSTANT_Utf8_info) (constant_pool[c.name_index])).convert();
2821
2822        return name.replace('/', '.');
2823   }
2824
2825   void confirmRefType(Type actualType)
2826   {
2827    /*
2828        if(!(actualType instanceof RefType) &&
2829            !(actualType instanceof ArrayType))
2830            throw new RuntimeException("confirmRefType failed; actualType: " + actualType);*/

2831   }
2832
2833    /** Runs through the given bbq contents performing the target fix-up pass;
2834     * Requires all reachable blocks to have their done flags set to true, and
2835     * this resets them all back to false;
2836     * @param bbq queue of BasicBlocks to process.
2837     * @see jimpleTargetFixup
2838     */

2839    private void processTargetFixup(BBQ bbq)
2840    {
2841    BasicBlock b,p;
2842    Stmt s;
2843    while (!bbq.isEmpty()) {
2844        try {
2845        b = bbq.pull();
2846        } catch(NoSuchElementException e)
2847        { break; }
2848
2849        s = b.getTailJStmt();
2850
2851            if (s instanceof GotoStmt)
2852        {
2853        if (b.succ.size() == 1)
2854        {
2855                   // Regular goto
2856

2857                    ((GotoStmt)s).setTarget(((BasicBlock) b.succ.firstElement()).getHeadJStmt());
2858                }
2859                else
2860                {
2861                    // Goto derived from a jsr bytecode
2862
/*
2863                    if((BasicBlock)(b.succ.firstElement())==b.next)
2864                        ((GotoStmt)s).setTarget(((BasicBlock) b.succ.elementAt(1)).getHeadJStmt());
2865                    else
2866                        ((GotoStmt)s).setTarget(((BasicBlock) b.succ.firstElement()).getHeadJStmt());
2867            */

2868            G.v().out.println("Error :");
2869            for (int i=0; i<b.statements.size(); i++)
2870            G.v().out.println(b.statements.get(i));
2871            
2872            throw new RuntimeException JavaDoc(b +" has "+b.succ.size()+" successors.");
2873                }
2874            }
2875            else if (s instanceof IfStmt)
2876            {
2877               if (b.succ.size()!=2)
2878                  G.v().out.println("How can an if not have 2 successors?");
2879
2880               if((BasicBlock)(b.succ.firstElement())==b.next)
2881               {
2882                  ((IfStmt)s).setTarget(((BasicBlock) b.succ.elementAt(1)).getHeadJStmt());
2883               }
2884               else
2885               {
2886                  ((IfStmt)s).setTarget(((BasicBlock) b.succ.firstElement()).getHeadJStmt());
2887               }
2888
2889            }
2890            else if (s instanceof TableSwitchStmt)
2891            {
2892               int count=0;
2893               TableSwitchStmt sts = (TableSwitchStmt)s;
2894               // Successors of the basic block ending with a switch statement
2895
// are listed in the successor vector in order, with the
2896
// default as the very first (0-th entry)
2897

2898               for (Enumeration e = b.succ.elements();e.hasMoreElements();) {
2899                  p = (BasicBlock)(e.nextElement());
2900                  if (count==0) {
2901                     sts.setDefaultTarget(p.getHeadJStmt());
2902                  } else {
2903                     sts.setTarget(count-1, p.getHeadJStmt());
2904                  }
2905                  count++;
2906               }
2907            } else if (s instanceof LookupSwitchStmt)
2908            {
2909               int count=0;
2910               LookupSwitchStmt sls = (LookupSwitchStmt)s;
2911               // Successors of the basic block ending with a switch statement
2912
// are listed in the successor vector in order, with the
2913
// default as the very first (0-th entry)
2914

2915               for (Enumeration e = b.succ.elements();e.hasMoreElements();) {
2916                  p = (BasicBlock)(e.nextElement());
2917                  if (count==0) {
2918                     sls.setDefaultTarget(p.getHeadJStmt());
2919                  } else {
2920                     sls.setTarget(count-1, p.getHeadJStmt());
2921                  }
2922                  count++;
2923               }
2924            }
2925
2926         b.done = false;
2927         for (Enumeration e = b.succ.elements();e.hasMoreElements();) {
2928            p = (BasicBlock)(e.nextElement());
2929            if (p.done) bbq.push(p);
2930         }
2931      }
2932   }
2933
2934    /** After the initial jimple construction, a second pass is made to fix up
2935     * missing Stmt targets for <tt>goto</tt>s, <tt>if</tt>'s etc.
2936     * @param c code attribute of this method.
2937     * @see CFG#jimplify
2938    */

2939    void jimpleTargetFixup()
2940    {
2941    BasicBlock b;
2942    BBQ bbq = new BBQ();
2943
2944    Code_attribute c = method.locate_code_attribute();
2945    if (c==null)
2946        return;
2947
2948    // Reset all the dones to true
2949
{
2950            BasicBlock bb = cfg;
2951
2952        while(bb != null)
2953        {
2954        bb.done = true;
2955        bb = bb.next;
2956        }
2957    }
2958
2959
2960    // first process the main code
2961
bbq.push(cfg);
2962    processTargetFixup(bbq);
2963
2964    // then the exceptions
2965
if (bbq.isEmpty())
2966    {
2967        int i;
2968        for (i=0;i<c.exception_table_length;i++)
2969        {
2970        b = c.exception_table[i].b;
2971        // if block hasn't yet been processed...
2972
if (b!=null && b.done)
2973        {
2974            bbq.push(b);
2975            processTargetFixup(bbq);
2976            if (!bbq.isEmpty()) {
2977            G.v().out.println("Error 2nd processing exception block.");
2978            break;
2979            }
2980        }
2981        }
2982    }
2983    }
2984
2985   private void generateJimpleForCPEntry(cp_info constant_pool[], int i,
2986                            TypeStack typeStack, TypeStack postTypeStack,
2987                            SootMethod jmethod, List statements)
2988   {
2989      Expr e;
2990      Stmt stmt;
2991      Value rvalue;
2992
2993      cp_info c = constant_pool[i];
2994
2995      if (c instanceof CONSTANT_Integer_info)
2996      {
2997         CONSTANT_Integer_info ci = (CONSTANT_Integer_info)c;
2998
2999         rvalue = IntConstant.v((int) ci.bytes);
3000         stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3001            postTypeStack.topIndex()), rvalue);
3002      }
3003      else if (c instanceof CONSTANT_Float_info)
3004      {
3005         CONSTANT_Float_info cf = (CONSTANT_Float_info)c;
3006
3007         rvalue = FloatConstant.v(cf.convert());
3008         stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3009            postTypeStack.topIndex()), rvalue);
3010      }
3011      else if (c instanceof CONSTANT_Long_info)
3012      {
3013         CONSTANT_Long_info cl = (CONSTANT_Long_info)c;
3014
3015         rvalue = LongConstant.v(cl.convert());
3016         stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3017            postTypeStack.topIndex()), rvalue);
3018      }
3019      else if (c instanceof CONSTANT_Double_info)
3020      {
3021         CONSTANT_Double_info cd = (CONSTANT_Double_info)c;
3022
3023         rvalue = DoubleConstant.v(cd.convert());
3024
3025         stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3026            postTypeStack.topIndex()), rvalue);
3027      }
3028      else if (c instanceof CONSTANT_String_info)
3029      {
3030         CONSTANT_String_info cs = (CONSTANT_String_info)c;
3031
3032         String JavaDoc constant = cs.toString(constant_pool);
3033
3034         if(constant.startsWith("\"") && constant.endsWith("\""))
3035            constant = constant.substring(1, constant.length() - 1);
3036
3037         rvalue = StringConstant.v(constant);
3038         stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3039            postTypeStack.topIndex()), rvalue);
3040      }
3041      else if (c instanceof CONSTANT_Utf8_info)
3042      {
3043         CONSTANT_Utf8_info cu = (CONSTANT_Utf8_info)c;
3044
3045         String JavaDoc constant = cu.convert();
3046
3047         if(constant.startsWith("\"") && constant.endsWith("\""))
3048            constant = constant.substring(1, constant.length() - 1);
3049
3050         rvalue = StringConstant.v(constant);
3051         stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3052            postTypeStack.topIndex()), rvalue);
3053      }
3054      else if (c instanceof CONSTANT_Class_info){
3055
3056        String JavaDoc className = ((CONSTANT_Utf8_info) (constant_pool[((CONSTANT_Class_info)c).name_index])).convert();
3057
3058
3059        rvalue = ClassConstant.v(className);
3060        stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex()), rvalue);
3061      }
3062      else {
3063        throw new RuntimeException JavaDoc("Attempting to push a non-constant cp entry"+c);
3064      }
3065
3066      statements.add(stmt);
3067    }
3068
3069    void generateJimple(Instruction ins, TypeStack typeStack, TypeStack postTypeStack,
3070        cp_info constant_pool[],
3071        List statements, BasicBlock basicBlock)
3072   {
3073      Value[] params;
3074      Value v1=null,v2=null,v3=null,v4=null;
3075      Local l1 = null, l2 = null, l3 = null, l4 = null;
3076
3077      Expr e=null,rhs=null;
3078      BinopExpr b=null;
3079      ConditionExpr co = null;
3080
3081      ArrayRef a=null;
3082      int args;
3083      Value rvalue;
3084
3085      // int localIndex;
3086

3087      Stmt stmt = null;
3088
3089      int x = ((int)(ins.code))&0xff;
3090
3091      Util.v().activeOriginalIndex = ins.originalIndex;
3092      Util.v().isLocalStore = false;
3093      Util.v().isWideLocalStore = false;
3094      
3095      switch(x)
3096      {
3097         case ByteCode.BIPUSH:
3098            rvalue = IntConstant.v(((Instruction_Bipush)ins).arg_b);
3099            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3100                postTypeStack.topIndex()), rvalue);
3101            break;
3102
3103         case ByteCode.SIPUSH:
3104            rvalue = IntConstant.v(((Instruction_Sipush)ins).arg_i);
3105            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3106                postTypeStack.topIndex()), rvalue);
3107            break;
3108
3109         case ByteCode.LDC1:
3110            generateJimpleForCPEntry(constant_pool,((Instruction_Ldc1)ins).arg_b, typeStack, postTypeStack,
3111                jmethod, statements);
3112            break;
3113
3114         case ByteCode.LDC2:
3115         case ByteCode.LDC2W:
3116            generateJimpleForCPEntry(constant_pool, ((Instruction_intindex)ins).arg_i,
3117                typeStack, postTypeStack, jmethod, statements);
3118            break;
3119
3120         case ByteCode.ACONST_NULL:
3121            rvalue = NullConstant.v();
3122            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3123                postTypeStack.topIndex()), rvalue);
3124            break;
3125
3126         case ByteCode.ICONST_M1:
3127         case ByteCode.ICONST_0:
3128         case ByteCode.ICONST_1:
3129         case ByteCode.ICONST_2:
3130         case ByteCode.ICONST_3:
3131         case ByteCode.ICONST_4:
3132         case ByteCode.ICONST_5:
3133            rvalue = IntConstant.v(x-ByteCode.ICONST_0);
3134            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3135                postTypeStack.topIndex()), rvalue);
3136            break;
3137
3138         case ByteCode.LCONST_0:
3139         case ByteCode.LCONST_1:
3140            rvalue = LongConstant.v(x-ByteCode.LCONST_0);
3141            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3142                postTypeStack.topIndex()), rvalue);
3143            break;
3144
3145         case ByteCode.FCONST_0:
3146         case ByteCode.FCONST_1:
3147         case ByteCode.FCONST_2:
3148            rvalue = FloatConstant.v((float)(x - ByteCode.FCONST_0));
3149            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3150                postTypeStack.topIndex()), rvalue);
3151            break;
3152
3153         case ByteCode.DCONST_0:
3154         case ByteCode.DCONST_1:
3155            rvalue = DoubleConstant.v((double)(x-ByteCode.DCONST_0));
3156            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3157                postTypeStack.topIndex()), rvalue);
3158            break;
3159
3160         case ByteCode.ILOAD:
3161         {
3162            Local local = (Local)
3163                Util.v().getLocalForIndex(listBody, ((Instruction_bytevar) ins).arg_b);
3164
3165            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3166                postTypeStack.topIndex()), local);
3167            break;
3168         }
3169
3170         case ByteCode.FLOAD:
3171         {
3172            Local local = (Local)
3173                Util.v().getLocalForIndex(listBody, ((Instruction_bytevar)ins).arg_b);
3174
3175            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3176                postTypeStack.topIndex()), local);
3177            break;
3178         }
3179
3180         case ByteCode.ALOAD:
3181         {
3182            Local local =
3183                Util.v().getLocalForIndex(listBody, ((Instruction_bytevar)ins).arg_b);
3184
3185            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3186                postTypeStack.topIndex()), local);
3187            break;
3188         }
3189
3190         case ByteCode.DLOAD:
3191         {
3192            Local local =
3193                Util.v().getLocalForIndex(listBody, ((Instruction_bytevar)ins).arg_b);
3194
3195            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3196                postTypeStack.topIndex()), local);
3197            break;
3198         }
3199
3200         case ByteCode.LLOAD:
3201         {
3202            Local local =
3203                Util.v().getLocalForIndex(listBody, ((Instruction_bytevar)ins).arg_b);
3204
3205            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3206                postTypeStack.topIndex()), local);
3207            break;
3208         }
3209
3210         case ByteCode.ILOAD_0:
3211         case ByteCode.ILOAD_1:
3212         case ByteCode.ILOAD_2:
3213         case ByteCode.ILOAD_3:
3214         {
3215            Local local =
3216                Util.v().getLocalForIndex(listBody, (x - ByteCode.ILOAD_0));
3217
3218            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3219                postTypeStack.topIndex()), local);
3220            break;
3221         }
3222
3223         case ByteCode.FLOAD_0:
3224         case ByteCode.FLOAD_1:
3225         case ByteCode.FLOAD_2:
3226         case ByteCode.FLOAD_3:
3227         {
3228            Local local =
3229                Util.v().getLocalForIndex(listBody, (x - ByteCode.FLOAD_0));
3230
3231            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3232                postTypeStack.topIndex()), local);
3233            break;
3234         }
3235
3236         case ByteCode.ALOAD_0:
3237         case ByteCode.ALOAD_1:
3238         case ByteCode.ALOAD_2:
3239         case ByteCode.ALOAD_3:
3240         {
3241            Local local =
3242                Util.v().getLocalForIndex(listBody, (x - ByteCode.ALOAD_0));
3243
3244            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3245                postTypeStack.topIndex()), local);
3246            break;
3247         }
3248
3249         case ByteCode.LLOAD_0:
3250         case ByteCode.LLOAD_1:
3251         case ByteCode.LLOAD_2:
3252         case ByteCode.LLOAD_3:
3253         {
3254            Local local =
3255                Util.v().getLocalForIndex(listBody, (x - ByteCode.LLOAD_0));
3256
3257            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3258                postTypeStack.topIndex()), local);
3259            break;
3260         }
3261
3262         case ByteCode.DLOAD_0:
3263         case ByteCode.DLOAD_1:
3264         case ByteCode.DLOAD_2:
3265         case ByteCode.DLOAD_3:
3266         {
3267            Local local =
3268                Util.v().getLocalForIndex(listBody, (x - ByteCode.DLOAD_0));
3269
3270            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3271                postTypeStack.topIndex()), local);
3272            break;
3273         }
3274
3275         case ByteCode.ISTORE:
3276         {
3277            Util.v().isLocalStore = true;
3278            Util.v().isWideLocalStore = true;
3279            
3280            Local local =
3281                Util.v().getLocalForIndex(listBody,
3282                ((Instruction_bytevar)ins).arg_b);
3283
3284            stmt = Jimple.v().newAssignStmt(local, Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
3285            break;
3286         }
3287
3288         case ByteCode.FSTORE:
3289         {
3290            Util.v().isLocalStore = true;
3291            Util.v().isWideLocalStore = true;
3292            
3293            Local local =
3294                Util.v().getLocalForIndex(listBody,
3295                ((Instruction_bytevar)ins).arg_b);
3296
3297            stmt = Jimple.v().newAssignStmt(local, Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
3298            break;
3299         }
3300
3301         case ByteCode.ASTORE:
3302         {
3303            Util.v().isLocalStore = true;
3304            Util.v().isWideLocalStore = true;
3305            
3306            Local local =
3307                Util.v().getLocalForIndex(listBody,
3308                ((Instruction_bytevar)ins).arg_b);
3309
3310            stmt = Jimple.v().newAssignStmt(local, Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
3311            break;
3312         }
3313
3314         case ByteCode.LSTORE:
3315         {
3316            Util.v().isLocalStore = true;
3317            Util.v().isWideLocalStore = true;
3318            
3319            Local local =
3320                Util.v().getLocalForIndex(listBody,
3321                ((Instruction_bytevar)ins).arg_b);
3322
3323            stmt = Jimple.v().newAssignStmt(local, Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
3324            break;
3325         }
3326
3327         case ByteCode.DSTORE:
3328         {
3329            Util.v().isLocalStore = true;
3330            Util.v().isWideLocalStore = true;
3331            
3332            Local local =
3333                Util.v().getLocalForIndex(listBody,
3334                ((Instruction_bytevar)ins).arg_b);
3335
3336            stmt = Jimple.v().newAssignStmt(local, Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
3337            break;
3338         }
3339
3340         case ByteCode.ISTORE_0:
3341         case ByteCode.ISTORE_1:
3342         case ByteCode.ISTORE_2:
3343         case ByteCode.ISTORE_3:
3344         {
3345            Util.v().isLocalStore = true;
3346            Local local =
3347                Util.v().getLocalForIndex(listBody, (x - ByteCode.ISTORE_0));
3348
3349            stmt = Jimple.v().newAssignStmt(local, Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
3350            break;
3351         }
3352
3353         case ByteCode.FSTORE_0:
3354         case ByteCode.FSTORE_1:
3355         case ByteCode.FSTORE_2:
3356         case ByteCode.FSTORE_3:
3357         {
3358            Util.v().isLocalStore = true;
3359            Local local = (Local)
3360                Util.v().getLocalForIndex(listBody, (x - ByteCode.FSTORE_0));
3361
3362            stmt = Jimple.v().newAssignStmt(local, Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
3363            break;
3364         }
3365
3366         case ByteCode.ASTORE_0:
3367         case ByteCode.ASTORE_1:
3368         case ByteCode.ASTORE_2:
3369         case ByteCode.ASTORE_3:
3370         {
3371            Util.v().isLocalStore = true;
3372            Local local = Util.v().getLocalForIndex(listBody, (x - ByteCode.ASTORE_0));
3373
3374            stmt = Jimple.v().newAssignStmt(local, Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
3375            break;
3376         }
3377
3378         case ByteCode.LSTORE_0:
3379         case ByteCode.LSTORE_1:
3380         case ByteCode.LSTORE_2:
3381         case ByteCode.LSTORE_3:
3382         {
3383            Util.v().isLocalStore = true;
3384            Local local =
3385                Util.v().getLocalForIndex(listBody, (x - ByteCode.LSTORE_0));
3386
3387            stmt = Jimple.v().newAssignStmt(local, Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
3388            break;
3389         }
3390
3391         case ByteCode.DSTORE_0:
3392         case ByteCode.DSTORE_1:
3393         case ByteCode.DSTORE_2:
3394         case ByteCode.DSTORE_3:
3395         {
3396            Util.v().isLocalStore = true;
3397            Local local =
3398                Util.v().getLocalForIndex(listBody, (x - ByteCode.DSTORE_0));
3399
3400            stmt = Jimple.v().newAssignStmt(local, Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
3401            break;
3402         }
3403
3404         case ByteCode.IINC:
3405         {
3406            Local local =
3407                Util.v().getLocalForIndex(listBody,
3408                ((Instruction_Iinc)ins).arg_b);
3409
3410            int amt = (((Instruction_Iinc)ins).arg_c);
3411            rhs = Jimple.v().newAddExpr(local, IntConstant.v(amt));
3412            stmt = Jimple.v().newAssignStmt(local,rhs);
3413            break;
3414         }
3415
3416         case ByteCode.WIDE:
3417            throw new RuntimeException JavaDoc("WIDE instruction should not be encountered anymore");
3418            // break;
3419

3420         case ByteCode.NEWARRAY:
3421         {
3422            Type baseType = (Type) jimpleTypeOfAtype(((Instruction_Newarray)ins).atype);
3423
3424            rhs = Jimple.v().newNewArrayExpr(baseType,
3425                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
3426
3427            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody,
3428                postTypeStack, postTypeStack.topIndex()), rhs);
3429
3430            break;
3431         }
3432
3433         case ByteCode.ANEWARRAY:
3434         {
3435            String JavaDoc baseName = getClassName(constant_pool, ((Instruction_Anewarray)ins).arg_i);
3436
3437            Type baseType;
3438
3439            if(baseName.startsWith("["))
3440                baseType = Util.v().jimpleTypeOfFieldDescriptor(getClassName(constant_pool, ((Instruction_Anewarray)ins).arg_i));
3441            else
3442                baseType = RefType.v(baseName);
3443
3444            rhs = Jimple.v().newNewArrayExpr(baseType, Util.v().getLocalForStackOp(listBody,
3445                typeStack, typeStack.topIndex()));
3446
3447            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody,
3448                postTypeStack, postTypeStack.topIndex()),rhs);
3449            break;
3450         }
3451
3452         case ByteCode.MULTIANEWARRAY:
3453         {
3454               int bdims = (int)(((Instruction_Multianewarray)ins).dims);
3455               List dims = new ArrayList();
3456
3457               for (int j=0; j < bdims; j++)
3458                  dims.add(Util.v().getLocalForStackOp(listBody, typeStack,
3459                    typeStack.topIndex() - bdims + j + 1));
3460
3461               String JavaDoc mstype = constant_pool[((Instruction_Multianewarray)ins).arg_i].
3462                  toString(constant_pool);
3463
3464               ArrayType jimpleType = (ArrayType) Util.v().jimpleTypeOfFieldDescriptor(mstype);
3465
3466               rhs = Jimple.v().newNewMultiArrayExpr(jimpleType, dims);
3467
3468               stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3469                postTypeStack.topIndex()),rhs);
3470            break;
3471         }
3472
3473
3474         case ByteCode.ARRAYLENGTH:
3475            rhs = Jimple.v().newLengthExpr(
3476                    Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
3477
3478            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3479                postTypeStack.topIndex()),rhs);
3480            break;
3481
3482         case ByteCode.IALOAD:
3483         case ByteCode.BALOAD:
3484         case ByteCode.CALOAD:
3485         case ByteCode.SALOAD:
3486         case ByteCode.FALOAD:
3487         case ByteCode.LALOAD:
3488         case ByteCode.DALOAD:
3489         case ByteCode.AALOAD:
3490            a = Jimple.v().newArrayRef(Util.v().getLocalForStackOp(listBody, typeStack,
3491                typeStack.topIndex() - 1),
3492                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
3493
3494            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody,
3495                postTypeStack, postTypeStack.topIndex()), a);
3496
3497            break;
3498
3499         case ByteCode.IASTORE:
3500         case ByteCode.FASTORE:
3501         case ByteCode.AASTORE:
3502         case ByteCode.BASTORE:
3503         case ByteCode.CASTORE:
3504         case ByteCode.SASTORE:
3505            a = Jimple.v().newArrayRef(Util.v().getLocalForStackOp(listBody, typeStack,
3506                typeStack.topIndex() - 2), Util.v().getLocalForStackOp(listBody, typeStack,
3507                typeStack.topIndex() - 1));
3508
3509            stmt = Jimple.v().newAssignStmt(a, Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
3510            break;
3511
3512         case ByteCode.LASTORE:
3513         case ByteCode.DASTORE:
3514            a = Jimple.v().newArrayRef(Util.v().getLocalForStackOp(listBody, typeStack,
3515                typeStack.topIndex() - 3), Util.v().getLocalForStackOp(listBody, typeStack,
3516                typeStack.topIndex() - 2));
3517
3518            stmt = Jimple.v().newAssignStmt(a, Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
3519            break;
3520
3521
3522         case ByteCode.NOP:
3523            stmt = Jimple.v().newNopStmt();
3524            break;
3525
3526         case ByteCode.POP:
3527         case ByteCode.POP2:
3528            stmt = Jimple.v().newNopStmt();
3529            break;
3530
3531         case ByteCode.DUP:
3532            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3533                postTypeStack.topIndex()), Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
3534            break;
3535
3536         case ByteCode.DUP2:
3537            if(typeSize(typeStack.top()) == 2)
3538            {
3539                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3540                    postTypeStack.topIndex() - 1),
3541                    Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1));
3542            }
3543            else {
3544                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3545                    postTypeStack.topIndex() - 1),
3546                    Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1));
3547
3548                statements.add(stmt);
3549
3550                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3551                    postTypeStack.topIndex()), Util.v().getLocalForStackOp(listBody,
3552                    typeStack, typeStack.topIndex()));
3553
3554                statements.add(stmt);
3555
3556                stmt = null;
3557            }
3558            break;
3559
3560         case ByteCode.DUP_X1:
3561            l1 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex());
3562            l2 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()-1);
3563
3564            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3565                postTypeStack.topIndex()), l1);
3566
3567            statements.add(stmt);
3568
3569            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3570                postTypeStack.topIndex() - 1), l2);
3571
3572            statements.add(stmt);
3573
3574            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3575                postTypeStack.topIndex() - 2), Util.v().getLocalForStackOp(listBody,
3576                postTypeStack, postTypeStack.topIndex()));
3577
3578            statements.add(stmt);
3579
3580            stmt = null;
3581            break;
3582
3583         case ByteCode.DUP_X2:
3584            if(typeSize(typeStack.get(typeStack.topIndex() - 2)) == 2)
3585            {
3586                l3 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 2);
3587                l1 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex());
3588
3589                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3590                    postTypeStack.topIndex() - 2), l3);
3591
3592                statements.add(stmt);
3593
3594                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3595                    postTypeStack.topIndex() - 3), l1);
3596
3597                statements.add(stmt);
3598
3599                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3600                    postTypeStack.topIndex()), l1);
3601
3602                statements.add(stmt);
3603
3604                stmt = null;
3605            }
3606            else {
3607                l3 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 2);
3608                l2 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1);
3609                l1 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex());
3610
3611                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3612                    postTypeStack.topIndex()), l1);
3613
3614                statements.add(stmt);
3615
3616                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3617                    postTypeStack.topIndex() - 1), l2);
3618
3619                statements.add(stmt);
3620
3621                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3622                    postTypeStack.topIndex() - 2), l3);
3623
3624                statements.add(stmt);
3625
3626                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3627                    postTypeStack.topIndex() - 3), Util.v().getLocalForStackOp(
3628                    listBody, postTypeStack, postTypeStack.topIndex()));
3629
3630                statements.add(stmt);
3631
3632                stmt = null;
3633            }
3634            break;
3635            
3636        case ByteCode.DUP2_X1:
3637            if(typeSize(typeStack.get(typeStack.topIndex() - 1)) == 2)
3638            {
3639                l2 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1);
3640                l3 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 2);
3641
3642                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3643                    postTypeStack.topIndex() -1), l2);
3644
3645                statements.add(stmt);
3646
3647                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3648                    postTypeStack.topIndex() - 2), l3);
3649                
3650                statements.add(stmt);
3651
3652                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3653                    postTypeStack.topIndex() - 4),
3654                    Util.v().getLocalForStackOp(listBody, postTypeStack, postTypeStack.topIndex() - 1));
3655
3656                statements.add(stmt);
3657
3658                stmt = null;
3659            }
3660            else {
3661                l3 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 2);
3662                l2 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1);
3663                l1 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex());
3664
3665                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3666                    postTypeStack.topIndex()), l1);
3667
3668                statements.add(stmt);
3669
3670                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3671                    postTypeStack.topIndex() - 1), l2);
3672
3673                statements.add(stmt);
3674
3675                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3676                    postTypeStack.topIndex() - 2), l3);
3677
3678                statements.add(stmt);
3679
3680                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3681                    postTypeStack.topIndex() - 3), Util.v().getLocalForStackOp(
3682                    listBody, postTypeStack, postTypeStack.topIndex()));
3683
3684                statements.add(stmt);
3685
3686                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3687                    postTypeStack.topIndex() - 4), Util.v().getLocalForStackOp(
3688                    listBody, postTypeStack, postTypeStack.topIndex() - 1));
3689
3690                statements.add(stmt);
3691
3692                stmt = null;
3693            }
3694            break;
3695
3696         case ByteCode.DUP2_X2:
3697            if(typeSize(typeStack.get(typeStack.topIndex() - 1)) == 2)
3698            {
3699                l2 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1);
3700
3701                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3702                    postTypeStack.topIndex() - 1), l2);
3703
3704                statements.add(stmt);
3705            }
3706            else {
3707                l1 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex());
3708                l2 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 1);
3709
3710                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3711                    postTypeStack.topIndex() - 1), l2);
3712
3713                statements.add(stmt);
3714
3715                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3716                    postTypeStack.topIndex()), l1);
3717
3718                statements.add(stmt);
3719
3720            }
3721
3722            if(typeSize(typeStack.get(typeStack.topIndex() - 3)) == 2)
3723            {
3724                l4 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 3);
3725
3726                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3727                    postTypeStack.topIndex() - 3), l4);
3728
3729                statements.add(stmt);
3730            }
3731            else {
3732                l4 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 3);
3733                l3 = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex() - 2);
3734
3735                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3736                    postTypeStack.topIndex() - 3), l4);
3737
3738                statements.add(stmt);
3739
3740                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3741                    postTypeStack.topIndex() - 2), l3);
3742
3743                statements.add(stmt);
3744
3745            }
3746
3747            if(typeSize(typeStack.get(typeStack.topIndex() - 1)) == 2)
3748            {
3749                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3750                    postTypeStack.topIndex() - 5), Util.v().getLocalForStackOp(
3751                    listBody, postTypeStack, postTypeStack.topIndex() - 1));
3752
3753                statements.add(stmt);
3754            }
3755            else {
3756                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3757                    postTypeStack.topIndex() - 5), Util.v().getLocalForStackOp(
3758                    listBody, postTypeStack, postTypeStack.topIndex() - 1));
3759
3760                statements.add(stmt);
3761
3762                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3763                    postTypeStack.topIndex() - 4), Util.v().getLocalForStackOp(
3764                    listBody, postTypeStack, postTypeStack.topIndex()));
3765
3766                statements.add(stmt);
3767            }
3768               stmt = null;
3769            break;
3770
3771         case ByteCode.SWAP:
3772         {
3773            Local first;
3774
3775            typeStack = typeStack.push(typeStack.top());
3776            first = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex());
3777            typeStack = typeStack.pop();
3778                // generation of a free temporary
3779

3780            Local second = Util.v().getLocalForStackOp(listBody, postTypeStack,
3781                postTypeStack.topIndex());
3782
3783            Local third = Util.v().getLocalForStackOp(listBody, postTypeStack,
3784                postTypeStack.topIndex() - 1);
3785
3786            stmt = Jimple.v().newAssignStmt(first, second);
3787            statements.add(stmt);
3788
3789            stmt = Jimple.v().newAssignStmt(second, third);
3790            statements.add(stmt);
3791
3792            stmt = Jimple.v().newAssignStmt(third, first);
3793            statements.add(stmt);
3794
3795            stmt = null;
3796            break;
3797         }
3798
3799         case ByteCode.FADD:
3800         case ByteCode.IADD:
3801            rhs = Jimple.v().newAddExpr(Util.v().getLocalForStackOp(listBody, typeStack,
3802                typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack,
3803                typeStack.topIndex()));
3804
3805            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3806                postTypeStack.topIndex()), rhs);
3807            break;
3808
3809         case ByteCode.DADD:
3810         case ByteCode.LADD:
3811            rhs = Jimple.v().newAddExpr(Util.v().getLocalForStackOp(listBody, typeStack,
3812                typeStack.topIndex() - 3), Util.v().getLocalForStackOp(listBody, typeStack,
3813                typeStack.topIndex() - 1));
3814
3815            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3816                postTypeStack.topIndex()), rhs);
3817            break;
3818
3819         case ByteCode.FSUB:
3820         case ByteCode.ISUB:
3821            rhs = Jimple.v().newSubExpr(Util.v().getLocalForStackOp(listBody, typeStack,
3822                typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack,
3823                typeStack.topIndex()));
3824
3825            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3826                postTypeStack.topIndex()), rhs);
3827            break;
3828
3829         case ByteCode.DSUB:
3830         case ByteCode.LSUB:
3831            rhs = Jimple.v().newSubExpr(Util.v().getLocalForStackOp(listBody, typeStack,
3832                typeStack.topIndex() - 3), Util.v().getLocalForStackOp(listBody, typeStack,
3833                typeStack.topIndex() - 1));
3834
3835            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3836                postTypeStack.topIndex()), rhs);
3837            break;
3838
3839         case ByteCode.FMUL:
3840         case ByteCode.IMUL:
3841            rhs = Jimple.v().newMulExpr(Util.v().getLocalForStackOp(listBody, typeStack,
3842                typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack,
3843                typeStack.topIndex()));
3844
3845            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3846                postTypeStack.topIndex()), rhs);
3847            break;
3848
3849         case ByteCode.DMUL:
3850         case ByteCode.LMUL:
3851            rhs = Jimple.v().newMulExpr(Util.v().getLocalForStackOp(listBody, typeStack,
3852                typeStack.topIndex() - 3), Util.v().getLocalForStackOp(listBody, typeStack,
3853                typeStack.topIndex() - 1));
3854
3855            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3856                postTypeStack.topIndex()), rhs);
3857            break;
3858
3859         case ByteCode.FDIV:
3860         case ByteCode.IDIV:
3861            rhs = Jimple.v().newDivExpr(Util.v().getLocalForStackOp(listBody, typeStack,
3862                typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack,
3863                typeStack.topIndex()));
3864
3865            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3866                postTypeStack.topIndex()), rhs);
3867            break;
3868
3869         case ByteCode.DDIV:
3870         case ByteCode.LDIV:
3871            rhs = Jimple.v().newDivExpr(Util.v().getLocalForStackOp(listBody, typeStack,
3872                typeStack.topIndex() - 3), Util.v().getLocalForStackOp(listBody, typeStack,
3873                typeStack.topIndex() - 1));
3874
3875            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3876                postTypeStack.topIndex()), rhs);
3877            break;
3878
3879         case ByteCode.FREM:
3880         case ByteCode.IREM:
3881            rhs = Jimple.v().newRemExpr(Util.v().getLocalForStackOp(listBody, typeStack,
3882                typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack,
3883                typeStack.topIndex()));
3884
3885            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3886                postTypeStack.topIndex()), rhs);
3887            break;
3888
3889         case ByteCode.DREM:
3890         case ByteCode.LREM:
3891            rhs = Jimple.v().newRemExpr(Util.v().getLocalForStackOp(listBody, typeStack,
3892                typeStack.topIndex() - 3), Util.v().getLocalForStackOp(listBody, typeStack,
3893                typeStack.topIndex() - 1));
3894
3895            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3896                postTypeStack.topIndex()), rhs);
3897            break;
3898
3899         case ByteCode.INEG:
3900         case ByteCode.LNEG:
3901         case ByteCode.FNEG:
3902         case ByteCode.DNEG:
3903            rhs = Jimple.v().newNegExpr(Util.v().getLocalForStackOp(listBody, typeStack,
3904                typeStack.topIndex()));
3905            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3906                postTypeStack.topIndex()),rhs);
3907            break;
3908
3909         case ByteCode.ISHL:
3910            rhs = Jimple.v().newShlExpr(Util.v().getLocalForStackOp(listBody, typeStack,
3911                typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack,
3912                typeStack.topIndex()));
3913
3914            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3915                postTypeStack.topIndex()), rhs);
3916            break;
3917
3918         case ByteCode.ISHR:
3919            rhs = Jimple.v().newShrExpr(Util.v().getLocalForStackOp(listBody, typeStack,
3920                typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack,
3921                typeStack.topIndex()));
3922
3923            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3924                postTypeStack.topIndex()), rhs);
3925            break;
3926
3927         case ByteCode.IUSHR:
3928            rhs = Jimple.v().newUshrExpr(Util.v().getLocalForStackOp(listBody, typeStack,
3929                typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack,
3930                typeStack.topIndex()));
3931
3932            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3933                postTypeStack.topIndex()), rhs);
3934            break;
3935
3936         case ByteCode.LSHL:
3937            rhs = Jimple.v().newShlExpr(Util.v().getLocalForStackOp(listBody, typeStack,
3938                typeStack.topIndex() - 2), Util.v().getLocalForStackOp(listBody, typeStack,
3939                typeStack.topIndex()));
3940
3941            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3942                postTypeStack.topIndex()), rhs);
3943            break;
3944
3945         case ByteCode.LSHR:
3946            rhs = Jimple.v().newShrExpr(Util.v().getLocalForStackOp(listBody, typeStack,
3947                typeStack.topIndex() - 2), Util.v().getLocalForStackOp(listBody, typeStack,
3948                typeStack.topIndex()));
3949
3950            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3951                postTypeStack.topIndex()), rhs);
3952            break;
3953
3954         case ByteCode.LUSHR:
3955            rhs = Jimple.v().newUshrExpr(Util.v().getLocalForStackOp(listBody, typeStack,
3956                typeStack.topIndex() - 2), Util.v().getLocalForStackOp(listBody, typeStack,
3957                typeStack.topIndex()));
3958
3959            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3960                postTypeStack.topIndex()), rhs);
3961            break;
3962
3963         case ByteCode.IAND:
3964            rhs = Jimple.v().newAndExpr(Util.v().getLocalForStackOp(listBody, typeStack,
3965                typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack,
3966                typeStack.topIndex()));
3967
3968            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3969                postTypeStack.topIndex()), rhs);
3970            break;
3971
3972         case ByteCode.LAND:
3973            rhs = Jimple.v().newAndExpr(Util.v().getLocalForStackOp(listBody, typeStack,
3974                typeStack.topIndex() - 3), Util.v().getLocalForStackOp(listBody, typeStack,
3975                typeStack.topIndex() - 1));
3976
3977            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3978                postTypeStack.topIndex()), rhs);
3979            break;
3980
3981         case ByteCode.IOR:
3982            rhs = Jimple.v().newOrExpr(Util.v().getLocalForStackOp(listBody, typeStack,
3983                typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack,
3984                typeStack.topIndex()));
3985
3986            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3987                postTypeStack.topIndex()), rhs);
3988            break;
3989
3990         case ByteCode.LOR:
3991            rhs = Jimple.v().newOrExpr(Util.v().getLocalForStackOp(listBody, typeStack,
3992                typeStack.topIndex() - 3), Util.v().getLocalForStackOp(listBody, typeStack,
3993                typeStack.topIndex() - 1));
3994
3995            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
3996                postTypeStack.topIndex()), rhs);
3997            break;
3998
3999         case ByteCode.IXOR:
4000            rhs = Jimple.v().newXorExpr(Util.v().getLocalForStackOp(listBody, typeStack,
4001                typeStack.topIndex() - 1), Util.v().getLocalForStackOp(listBody, typeStack,
4002                typeStack.topIndex()));
4003
4004            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
4005                postTypeStack.topIndex()), rhs);
4006            break;
4007
4008         case ByteCode.LXOR:
4009            rhs = Jimple.v().newXorExpr(Util.v().getLocalForStackOp(listBody, typeStack,
4010                typeStack.topIndex() - 3), Util.v().getLocalForStackOp(listBody, typeStack,
4011                typeStack.topIndex() - 1));
4012
4013            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
4014                postTypeStack.topIndex()), rhs);
4015            break;
4016
4017         case ByteCode.D2L:
4018         case ByteCode.F2L:
4019         case ByteCode.I2L:
4020            rhs = Jimple.v().newCastExpr(Util.v().getLocalForStackOp(listBody, typeStack,
4021                typeStack.topIndex()), LongType.v());
4022
4023            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
4024                postTypeStack.topIndex()), rhs);
4025            break;
4026
4027         case ByteCode.D2F:
4028         case ByteCode.L2F:
4029         case ByteCode.I2F:
4030            rhs = Jimple.v().newCastExpr(Util.v().getLocalForStackOp(listBody, typeStack,
4031                typeStack.topIndex()), FloatType.v());
4032
4033            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
4034                postTypeStack.topIndex()), rhs);
4035            break;
4036
4037         case ByteCode.I2D:
4038         case ByteCode.L2D:
4039         case ByteCode.F2D:
4040            rhs = Jimple.v().newCastExpr(Util.v().getLocalForStackOp(listBody, typeStack,
4041                typeStack.topIndex()), DoubleType.v());
4042
4043            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
4044                postTypeStack.topIndex()), rhs);
4045            break;
4046
4047         case ByteCode.L2I:
4048         case ByteCode.F2I:
4049         case ByteCode.D2I:
4050            rhs = Jimple.v().newCastExpr(Util.v().getLocalForStackOp(listBody, typeStack,
4051                typeStack.topIndex()), IntType.v());
4052
4053            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
4054                postTypeStack.topIndex()), rhs);
4055            break;
4056
4057         case ByteCode.INT2BYTE:
4058            rhs = Jimple.v().newCastExpr(Util.v().getLocalForStackOp(listBody, typeStack,
4059                typeStack.topIndex()), ByteType.v());
4060
4061            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
4062                postTypeStack.topIndex()), rhs);
4063            break;
4064
4065         case ByteCode.INT2CHAR:
4066            rhs = Jimple.v().newCastExpr(Util.v().getLocalForStackOp(listBody, typeStack,
4067                typeStack.topIndex()), CharType.v());
4068
4069            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
4070                postTypeStack.topIndex()), rhs);
4071            break;
4072
4073         case ByteCode.INT2SHORT:
4074            rhs = Jimple.v().newCastExpr(Util.v().getLocalForStackOp(listBody, typeStack,
4075                typeStack.topIndex()), ShortType.v());
4076
4077            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
4078                postTypeStack.topIndex()), rhs);
4079            break;
4080
4081         case ByteCode.IFEQ:
4082            co = Jimple.v().newEqExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()),
4083                IntConstant.v(0));
4084
4085               stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4086            break;
4087
4088         case ByteCode.IFNULL:
4089            co = Jimple.v().newEqExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()),
4090                NullConstant.v());
4091
4092            stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4093            break;
4094
4095         case ByteCode.IFLT:
4096            co = Jimple.v().newLtExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()),
4097                IntConstant.v(0));
4098
4099               stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4100            break;
4101
4102         case ByteCode.IFLE:
4103            co = Jimple.v().newLeExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()),
4104                    IntConstant.v(0));
4105
4106            stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4107            break;
4108
4109         case ByteCode.IFNE:
4110            co = Jimple.v().newNeExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()),
4111                    IntConstant.v(0));
4112
4113            stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4114            break;
4115
4116         case ByteCode.IFNONNULL:
4117            co = Jimple.v().newNeExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()),
4118                NullConstant.v());
4119
4120                stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4121            break;
4122
4123         case ByteCode.IFGT:
4124            co = Jimple.v().newGtExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()),
4125                    IntConstant.v(0));
4126
4127            stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4128            break;
4129
4130         case ByteCode.IFGE:
4131            co = Jimple.v().newGeExpr(Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()),
4132                IntConstant.v(0));
4133
4134            stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4135            break;
4136
4137         case ByteCode.IF_ICMPEQ:
4138            co = Jimple.v().newEqExpr(
4139                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()-1),
4140                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
4141
4142            stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4143            break;
4144
4145         case ByteCode.IF_ICMPLT:
4146            co = Jimple.v().newLtExpr(
4147                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()-1),
4148                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
4149
4150            stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4151            break;
4152
4153         case ByteCode.IF_ICMPLE:
4154            co = Jimple.v().newLeExpr(
4155                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()-1),
4156                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
4157
4158            stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4159            break;
4160
4161         case ByteCode.IF_ICMPNE:
4162            co = Jimple.v().newNeExpr(
4163                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()-1),
4164                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
4165
4166            stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4167            break;
4168
4169         case ByteCode.IF_ICMPGT:
4170            co = Jimple.v().newGtExpr(
4171                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()-1),
4172                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
4173
4174            stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4175            break;
4176
4177         case ByteCode.IF_ICMPGE:
4178            co = Jimple.v().newGeExpr(
4179                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()-1),
4180                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
4181
4182            stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4183            break;
4184
4185         case ByteCode.LCMP:
4186            rhs = Jimple.v().newCmpExpr(
4187                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()-3),
4188                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()-1));
4189
4190            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
4191                postTypeStack.topIndex()), rhs);
4192            break;
4193
4194         case ByteCode.FCMPL:
4195            rhs = Jimple.v().newCmplExpr(
4196                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()-1),
4197                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
4198
4199            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody,
4200                postTypeStack, postTypeStack.topIndex()),rhs);
4201            break;
4202
4203         case ByteCode.FCMPG:
4204            rhs = Jimple.v().newCmpgExpr(
4205                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()-1),
4206                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
4207
4208            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody,
4209                postTypeStack, postTypeStack.topIndex()),rhs);
4210            break;
4211
4212         case ByteCode.DCMPL:
4213            rhs = Jimple.v().newCmplExpr(
4214                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()-3),
4215                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()-1));
4216
4217            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody,
4218                postTypeStack, postTypeStack.topIndex()),rhs);
4219            break;
4220
4221         case ByteCode.DCMPG:
4222            rhs = Jimple.v().newCmpgExpr(
4223                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()-3),
4224                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()-1));
4225
4226            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody,
4227                postTypeStack, postTypeStack.topIndex()),rhs);
4228            break;
4229
4230         case ByteCode.IF_ACMPEQ:
4231            co = Jimple.v().newEqExpr(
4232                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()-1),
4233                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
4234
4235            stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4236            break;
4237
4238         case ByteCode.IF_ACMPNE:
4239            co = Jimple.v().newNeExpr(
4240                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()-1),
4241                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()));
4242
4243            stmt = Jimple.v().newIfStmt(co, new FutureStmt());
4244            break;
4245
4246         case ByteCode.GOTO:
4247            stmt = Jimple.v().newGotoStmt(new FutureStmt());
4248             break;
4249
4250         case ByteCode.GOTO_W:
4251            stmt = Jimple.v().newGotoStmt(new FutureStmt());
4252            break;
4253/*
4254         case ByteCode.JSR:
4255         case ByteCode.JSR_W:
4256         {
4257             stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
4258                postTypeStack.topIndex()), Jimple.v().newNextNextStmtRef());
4259
4260             statements.add(stmt);
4261
4262             stmt = Jimple.v().newGotoStmt(new FutureStmt());
4263             statements.add(stmt);
4264
4265             stmt = null;
4266             break;
4267         }
4268*/

4269
4270         case ByteCode.RET:
4271         {
4272            Local local =
4273                Util.v().getLocalForIndex(listBody, ((Instruction_Ret)ins).arg_b);
4274
4275            stmt = Jimple.v().newRetStmt(local);
4276            break;
4277         }
4278
4279         case ByteCode.RET_W:
4280         {
4281            Local local =
4282                Util.v().getLocalForIndex(listBody, ((Instruction_Ret_w)ins).arg_i);
4283
4284
4285            stmt = Jimple.v().newRetStmt(local);
4286            break;
4287         }
4288
4289         case ByteCode.RETURN:
4290            stmt = Jimple.v().newReturnVoidStmt();
4291            break;
4292
4293         case ByteCode.LRETURN:
4294         case ByteCode.DRETURN:
4295         case ByteCode.IRETURN:
4296         case ByteCode.FRETURN:
4297         case ByteCode.ARETURN:
4298            stmt = Jimple.v().newReturnStmt(Util.v().getLocalForStackOp(listBody,
4299                typeStack, typeStack.topIndex()));
4300            break;
4301
4302         case ByteCode.BREAKPOINT:
4303            stmt = Jimple.v().newBreakpointStmt();
4304            break;
4305
4306         case ByteCode.TABLESWITCH:
4307         {
4308            int lowIndex = ((Instruction_Tableswitch)ins).low,
4309                highIndex = ((Instruction_Tableswitch)ins).high;
4310
4311            stmt = Jimple.v().newTableSwitchStmt(
4312                    Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()),
4313                    lowIndex,
4314                    highIndex,
4315                    Arrays.asList(new FutureStmt[highIndex - lowIndex + 1]),
4316                    new FutureStmt());
4317            break;
4318         }
4319
4320         case ByteCode.LOOKUPSWITCH:
4321         {
4322            List matches = new ArrayList();
4323            int npairs = ((Instruction_Lookupswitch)ins).npairs;
4324
4325            for (int j = 0; j < npairs; j++)
4326                matches.add(IntConstant.v( ((Instruction_Lookupswitch)ins).match_offsets[j*2]));
4327
4328            stmt = Jimple.v().newLookupSwitchStmt(
4329                Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex()),
4330                matches,
4331                Arrays.asList(new FutureStmt[npairs]),
4332                new FutureStmt());
4333            break;
4334         }
4335
4336         case ByteCode.PUTFIELD:
4337         {
4338            CONSTANT_Fieldref_info fieldInfo =
4339                   (CONSTANT_Fieldref_info) constant_pool[((Instruction_Putfield)ins).arg_i];
4340
4341            CONSTANT_Class_info c =
4342                (CONSTANT_Class_info) constant_pool[fieldInfo.class_index];
4343
4344            String JavaDoc className = ((CONSTANT_Utf8_info) (constant_pool[c.name_index])).convert();
4345            className = className.replace('/', '.');
4346
4347            CONSTANT_NameAndType_info i =
4348                (CONSTANT_NameAndType_info) constant_pool[fieldInfo.name_and_type_index];
4349
4350            String JavaDoc fieldName = ((CONSTANT_Utf8_info) (constant_pool[i.name_index])).convert();
4351            String JavaDoc fieldDescriptor = ((CONSTANT_Utf8_info) (constant_pool[i.descriptor_index])).
4352                    convert();
4353
4354            Type fieldType = Util.v().jimpleTypeOfFieldDescriptor(fieldDescriptor);
4355                
4356            SootClass bclass = cm.getSootClass(className);
4357
4358            SootFieldRef fieldRef = Scene.v().makeFieldRef(bclass, fieldName, fieldType, false);
4359
4360            InstanceFieldRef fr =
4361                Jimple.v().newInstanceFieldRef(Util.v().getLocalForStackOp(listBody,
4362                typeStack, typeStack.topIndex() - typeSize(typeStack.top())), fieldRef);
4363
4364            rvalue = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex());
4365            stmt = Jimple.v().newAssignStmt(fr,rvalue);
4366            break;
4367         }
4368
4369         case ByteCode.GETFIELD:
4370         {
4371            InstanceFieldRef fr = null;
4372
4373            CONSTANT_Fieldref_info fieldInfo =
4374                (CONSTANT_Fieldref_info) constant_pool[((Instruction_Getfield)ins).arg_i];
4375
4376            CONSTANT_Class_info c =
4377                (CONSTANT_Class_info) constant_pool[fieldInfo.class_index];
4378
4379            String JavaDoc className = ((CONSTANT_Utf8_info) (constant_pool[c.name_index])).convert();
4380            className = className.replace('/', '.');
4381
4382            CONSTANT_NameAndType_info i =
4383                (CONSTANT_NameAndType_info) constant_pool[fieldInfo.name_and_type_index];
4384
4385            String JavaDoc fieldName = ((CONSTANT_Utf8_info) (constant_pool[i.name_index])).convert();
4386            String JavaDoc fieldDescriptor = ((CONSTANT_Utf8_info) (constant_pool[i.descriptor_index])).
4387                convert();
4388
4389        if (className.charAt(0) == '[')
4390            className = "java.lang.Object";
4391
4392            SootClass bclass = cm.getSootClass(className);
4393
4394            
4395            Type fieldType = Util.v().jimpleTypeOfFieldDescriptor(fieldDescriptor);
4396            SootFieldRef fieldRef = Scene.v().makeFieldRef(bclass, fieldName, fieldType, false);
4397
4398            fr = Jimple.v().newInstanceFieldRef(Util.v().getLocalForStackOp(listBody, typeStack,
4399                typeStack.topIndex()), fieldRef);
4400
4401            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
4402                postTypeStack.topIndex()), fr);
4403            break;
4404         }
4405
4406
4407         case ByteCode.PUTSTATIC:
4408         {
4409            StaticFieldRef fr = null;
4410
4411            CONSTANT_Fieldref_info fieldInfo =
4412                (CONSTANT_Fieldref_info) constant_pool[((Instruction_Putstatic)ins).arg_i];
4413
4414            CONSTANT_Class_info c =
4415                (CONSTANT_Class_info) constant_pool[fieldInfo.class_index];
4416
4417             String JavaDoc className = ((CONSTANT_Utf8_info) (constant_pool[c.name_index])).convert();
4418            className = className.replace('/', '.');
4419
4420            CONSTANT_NameAndType_info i =
4421                (CONSTANT_NameAndType_info) constant_pool[fieldInfo.name_and_type_index];
4422
4423            String JavaDoc fieldName = ((CONSTANT_Utf8_info) (constant_pool[i.name_index])).convert();
4424            String JavaDoc fieldDescriptor = ((CONSTANT_Utf8_info) (constant_pool[i.descriptor_index])).
4425                convert();
4426
4427            Type fieldType = Util.v().jimpleTypeOfFieldDescriptor(fieldDescriptor);
4428            
4429            SootClass bclass = cm.getSootClass(className);
4430            SootFieldRef fieldRef = Scene.v().makeFieldRef(bclass, fieldName, fieldType, true);
4431
4432            fr = Jimple.v().newStaticFieldRef(fieldRef);
4433
4434            stmt = Jimple.v().newAssignStmt(fr, Util.v().getLocalForStackOp(listBody, typeStack,
4435                typeStack.topIndex()));
4436            break;
4437         }
4438
4439         case ByteCode.GETSTATIC:
4440         {
4441            StaticFieldRef fr = null;
4442
4443            CONSTANT_Fieldref_info fieldInfo =
4444                (CONSTANT_Fieldref_info) constant_pool[((Instruction_Getstatic)ins).arg_i];
4445
4446            CONSTANT_Class_info c =
4447                (CONSTANT_Class_info) constant_pool[fieldInfo.class_index];
4448
4449            String JavaDoc className = ((CONSTANT_Utf8_info) (constant_pool[c.name_index])).convert();
4450            className = className.replace('/', '.');
4451
4452            CONSTANT_NameAndType_info i =
4453                (CONSTANT_NameAndType_info) constant_pool[fieldInfo.name_and_type_index];
4454
4455            String JavaDoc fieldName = ((CONSTANT_Utf8_info) (constant_pool[i.name_index])).convert();
4456            String JavaDoc fieldDescriptor = ((CONSTANT_Utf8_info) (constant_pool[i.descriptor_index])).
4457                convert();
4458
4459            Type fieldType = Util.v().jimpleTypeOfFieldDescriptor(fieldDescriptor);
4460            
4461            SootClass bclass = cm.getSootClass(className);
4462            SootFieldRef fieldRef = Scene.v().makeFieldRef(bclass, fieldName, fieldType, true);
4463
4464            fr = Jimple.v().newStaticFieldRef(fieldRef);
4465
4466            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
4467                postTypeStack.topIndex()), fr);
4468            break;
4469         }
4470
4471
4472         case ByteCode.INVOKEVIRTUAL:
4473         {
4474            Instruction_Invokevirtual iv = (Instruction_Invokevirtual)ins;
4475            args = cp_info.countParams(constant_pool,iv.arg_i);
4476
4477            SootMethodRef methodRef = null;
4478
4479            CONSTANT_Methodref_info methodInfo =
4480                (CONSTANT_Methodref_info) constant_pool[iv.arg_i];
4481
4482            CONSTANT_Class_info c =
4483                (CONSTANT_Class_info) constant_pool[methodInfo.class_index];
4484
4485             String JavaDoc className = ((CONSTANT_Utf8_info) (constant_pool[c.name_index])).convert();
4486                className = className.replace('/', '.');
4487
4488            CONSTANT_NameAndType_info i =
4489                (CONSTANT_NameAndType_info) constant_pool[methodInfo.name_and_type_index];
4490
4491            String JavaDoc methodName = ((CONSTANT_Utf8_info) (constant_pool[i.name_index])).convert();
4492            String JavaDoc methodDescriptor = ((CONSTANT_Utf8_info) (constant_pool[i.descriptor_index])).
4493                convert();
4494
4495           if (className.charAt(0) == '[')
4496               className = "java.lang.Object";
4497
4498            SootClass bclass = cm.getSootClass(className);
4499
4500            Local[] parameters;
4501            List parameterTypes;
4502            Type returnType;
4503
4504            // Generate parameters & returnType & parameterTypes
4505
{
4506                Type[] types = Util.v().jimpleTypesOfFieldOrMethodDescriptor(methodDescriptor);
4507
4508                parameterTypes = new ArrayList();
4509
4510                for(int k = 0; k < types.length - 1; k++)
4511                {
4512                    parameterTypes.add(types[k]);
4513                }
4514
4515                returnType = types[types.length - 1];
4516            }
4517
4518            methodRef = Scene.v().makeMethodRef(bclass, methodName, parameterTypes, returnType, false);
4519
4520            // build array of parameters
4521
params = new Value[args];
4522                for (int j=args-1;j>=0;j--)
4523                {
4524                   params[j] = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex());
4525
4526                   if(typeSize(typeStack.top()) == 2)
4527                   {
4528                      typeStack = typeStack.pop();
4529                      typeStack = typeStack.pop();
4530                   }
4531                   else
4532                      typeStack = typeStack.pop();
4533                }
4534
4535            rvalue = Jimple.v().newVirtualInvokeExpr(Util.v().getLocalForStackOp(listBody, typeStack,
4536                typeStack.topIndex()), methodRef, Arrays.asList(params));
4537
4538            if(!returnType.equals(VoidType.v()))
4539            {
4540                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
4541                    postTypeStack.topIndex()),rvalue);
4542            }
4543            else
4544               stmt = Jimple.v().newInvokeStmt((InvokeExpr) rvalue);
4545            break;
4546        }
4547
4548        case ByteCode.INVOKENONVIRTUAL:
4549         {
4550            Instruction_Invokenonvirtual iv = (Instruction_Invokenonvirtual)ins;
4551            args = cp_info.countParams(constant_pool,iv.arg_i);
4552
4553            SootMethodRef methodRef = null;
4554
4555                CONSTANT_Methodref_info methodInfo =
4556                    (CONSTANT_Methodref_info) constant_pool[iv.arg_i];
4557
4558                CONSTANT_Class_info c =
4559                    (CONSTANT_Class_info) constant_pool[methodInfo.class_index];
4560
4561                String JavaDoc className = ((CONSTANT_Utf8_info) (constant_pool[c.name_index])).convert();
4562                className = className.replace('/', '.');
4563
4564                CONSTANT_NameAndType_info i =
4565                    (CONSTANT_NameAndType_info) constant_pool[methodInfo.name_and_type_index];
4566
4567                String JavaDoc methodName = ((CONSTANT_Utf8_info) (constant_pool[i.name_index])).convert();
4568                String JavaDoc methodDescriptor = ((CONSTANT_Utf8_info) (constant_pool[i.descriptor_index])).
4569                    convert();
4570
4571                SootClass bclass = cm.getSootClass(className);
4572
4573                Local[] parameters;
4574                List parameterTypes;
4575                Type returnType;
4576
4577                // Generate parameters & returnType & parameterTypes
4578
{
4579                    Type[] types = Util.v().jimpleTypesOfFieldOrMethodDescriptor(methodDescriptor);
4580
4581                    parameterTypes = new ArrayList();
4582
4583                    for(int k = 0; k < types.length - 1; k++)
4584                    {
4585                        parameterTypes.add(types[k]);
4586                    }
4587
4588                    returnType = types[types.length - 1];
4589                }
4590
4591                methodRef = Scene.v().makeMethodRef( bclass, methodName, parameterTypes, returnType, false);
4592
4593            // build array of parameters
4594
params = new Value[args];
4595                for (int j=args-1;j>=0;j--)
4596                {
4597                   params[j] = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex());
4598
4599                   if(typeSize(typeStack.top()) == 2)
4600                   {
4601                      typeStack = typeStack.pop();
4602                      typeStack = typeStack.pop();
4603                   }
4604                   else
4605                      typeStack = typeStack.pop();
4606                }
4607
4608            rvalue = Jimple.v().newSpecialInvokeExpr(Util.v().getLocalForStackOp(listBody, typeStack,
4609                typeStack.topIndex()), methodRef, Arrays.asList(params));
4610
4611            if(!returnType.equals(VoidType.v()))
4612            {
4613                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
4614                    postTypeStack.topIndex()), rvalue);
4615            }
4616            else
4617                stmt = Jimple.v().newInvokeStmt((InvokeExpr) rvalue);
4618            break;
4619        }
4620
4621         case ByteCode.INVOKESTATIC:
4622         {
4623            Instruction_Invokestatic is = (Instruction_Invokestatic)ins;
4624            args = cp_info.countParams(constant_pool,is.arg_i);
4625
4626            SootMethodRef methodRef = null;
4627
4628                CONSTANT_Methodref_info methodInfo =
4629                    (CONSTANT_Methodref_info) constant_pool[is.arg_i];
4630
4631                CONSTANT_Class_info c =
4632                    (CONSTANT_Class_info) constant_pool[methodInfo.class_index];
4633
4634                String JavaDoc className = ((CONSTANT_Utf8_info) (constant_pool[c.name_index])).convert();
4635                className = className.replace('/', '.');
4636
4637                CONSTANT_NameAndType_info i =
4638                    (CONSTANT_NameAndType_info) constant_pool[methodInfo.name_and_type_index];
4639
4640                String JavaDoc methodName = ((CONSTANT_Utf8_info) (constant_pool[i.name_index])).convert();
4641                String JavaDoc methodDescriptor = ((CONSTANT_Utf8_info) (constant_pool[i.descriptor_index])).
4642                    convert();
4643
4644        if (className.charAt(0) == '[')
4645            className = "java.lang.Object";
4646
4647                SootClass bclass = cm.getSootClass(className);
4648
4649                Local[] parameters;
4650                List parameterTypes;
4651                Type returnType;
4652
4653                // Generate parameters & returnType & parameterTypes
4654
{
4655                    Type[] types = Util.v().jimpleTypesOfFieldOrMethodDescriptor(methodDescriptor);
4656
4657                    parameterTypes = new ArrayList();
4658
4659                    for(int k = 0; k < types.length - 1; k++)
4660                    {
4661                        parameterTypes.add(types[k]);
4662                    }
4663
4664                    returnType = types[types.length - 1];
4665                }
4666
4667                methodRef = Scene.v().makeMethodRef(bclass, methodName, parameterTypes, returnType, true);
4668
4669            // build Vector of parameters
4670
params = new Value[args];
4671                for (int j=args-1;j>=0;j--)
4672                {
4673                    /* G.v().out.println("BeforeTypeStack");
4674                    typeStack.print(G.v().out);
4675
4676                    G.v().out.println("AfterTypeStack");
4677                    postTypeStack.print(G.v().out);
4678                    */

4679
4680                   params[j] = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex());
4681
4682                   if(typeSize(typeStack.top()) == 2)
4683                   {
4684                      typeStack = typeStack.pop();
4685                      typeStack = typeStack.pop();
4686                   }
4687                   else
4688                      typeStack = typeStack.pop();
4689                }
4690
4691            rvalue = Jimple.v().newStaticInvokeExpr(methodRef, Arrays.asList(params));
4692
4693            if(!returnType.equals(VoidType.v()))
4694            {
4695                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
4696                    postTypeStack.topIndex()),rvalue);
4697            }
4698            else
4699               stmt = Jimple.v().newInvokeStmt((InvokeExpr) rvalue);
4700
4701            break;
4702         }
4703
4704         case ByteCode.INVOKEINTERFACE:
4705         {
4706            Instruction_Invokeinterface ii = (Instruction_Invokeinterface)ins;
4707            args = cp_info.countParams(constant_pool,ii.arg_i);
4708
4709            SootMethodRef methodRef = null;
4710
4711                CONSTANT_InterfaceMethodref_info methodInfo =
4712                    (CONSTANT_InterfaceMethodref_info) constant_pool[ii.arg_i];
4713
4714                CONSTANT_Class_info c =
4715                    (CONSTANT_Class_info) constant_pool[methodInfo.class_index];
4716
4717                String JavaDoc className = ((CONSTANT_Utf8_info) (constant_pool[c.name_index])).convert();
4718                className = className.replace('/', '.');
4719
4720                CONSTANT_NameAndType_info i =
4721                    (CONSTANT_NameAndType_info) constant_pool[methodInfo.name_and_type_index];
4722
4723                String JavaDoc methodName = ((CONSTANT_Utf8_info) (constant_pool[i.name_index])).convert();
4724                String JavaDoc methodDescriptor = ((CONSTANT_Utf8_info) (constant_pool[i.descriptor_index])).
4725                    convert();
4726
4727               if (className.charAt(0) == '[')
4728                   className = "java.lang.Object";
4729
4730                SootClass bclass = cm.getSootClass(className);
4731
4732                Local[] parameters;
4733                List parameterTypes;
4734                Type returnType;
4735
4736                // Generate parameters & returnType & parameterTypes
4737
{
4738                    Type[] types = Util.v().jimpleTypesOfFieldOrMethodDescriptor(methodDescriptor);
4739
4740                    parameterTypes = new ArrayList();
4741
4742                    for(int k = 0; k < types.length - 1; k++)
4743                    {
4744                        parameterTypes.add(types[k]);
4745                    }
4746
4747                    returnType = types[types.length - 1];
4748                }
4749
4750                methodRef = Scene.v().makeMethodRef(bclass, methodName, parameterTypes, returnType, false);
4751
4752            // build Vector of parameters
4753
params = new Value[args];
4754                for (int j=args-1;j>=0;j--)
4755                {
4756                   params[j] = Util.v().getLocalForStackOp(listBody, typeStack, typeStack.topIndex());
4757
4758                   if(typeSize(typeStack.top()) == 2)
4759                   {
4760                      typeStack = typeStack.pop();
4761                      typeStack = typeStack.pop();
4762                   }
4763                   else
4764                      typeStack = typeStack.pop();
4765                }
4766
4767            rvalue = Jimple.v().newInterfaceInvokeExpr(Util.v().getLocalForStackOp(listBody, typeStack,
4768                typeStack.topIndex()), methodRef, Arrays.asList(params));
4769
4770            if(!returnType.equals(VoidType.v()))
4771            {
4772                stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
4773                    postTypeStack.topIndex()), rvalue);
4774            }
4775            else
4776               stmt = Jimple.v().newInvokeStmt((InvokeExpr) rvalue);
4777            break;
4778        }
4779
4780         case ByteCode.ATHROW:
4781            stmt = Jimple.v().newThrowStmt(Util.v().getLocalForStackOp(listBody, typeStack,
4782                typeStack.topIndex()));
4783            break;
4784
4785         case ByteCode.NEW:
4786         {
4787            SootClass bclass = cm.getSootClass(getClassName(constant_pool,
4788                ((Instruction_New)ins).arg_i));
4789
4790            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
4791                postTypeStack.topIndex()), Jimple.v().newNewExpr(RefType.v(bclass.getName())));
4792            break;
4793         }
4794
4795         case ByteCode.CHECKCAST:
4796         {
4797            String JavaDoc className = getClassName(constant_pool, ((Instruction_Checkcast)ins).arg_i);
4798
4799            Type castType;
4800
4801            if(className.startsWith("["))
4802                castType = Util.v().jimpleTypeOfFieldDescriptor(getClassName(constant_pool,
4803                    ((Instruction_Checkcast)ins).arg_i));
4804            else
4805                castType = RefType.v(className);
4806
4807            rhs = Jimple.v().newCastExpr(Util.v().getLocalForStackOp(listBody, typeStack,
4808                typeStack.topIndex()), castType);
4809
4810            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
4811                postTypeStack.topIndex()),rhs);
4812            break;
4813         }
4814
4815         case ByteCode.INSTANCEOF:
4816         {
4817            Type checkType;
4818
4819            String JavaDoc className = getClassName(constant_pool, ((Instruction_Instanceof)ins).arg_i);
4820
4821            if(className.startsWith("["))
4822                checkType = Util.v().jimpleTypeOfFieldDescriptor(getClassName(constant_pool,
4823                ((Instruction_Instanceof)ins).arg_i));
4824            else
4825                checkType = RefType.v(className);
4826
4827            rhs = Jimple.v().newInstanceOfExpr(Util.v().getLocalForStackOp(listBody, typeStack,
4828                typeStack.topIndex()), checkType);
4829
4830            stmt = Jimple.v().newAssignStmt(Util.v().getLocalForStackOp(listBody, postTypeStack,
4831                postTypeStack.topIndex()),rhs);
4832            break;
4833         }
4834
4835         case ByteCode.MONITORENTER:
4836            stmt = Jimple.v().newEnterMonitorStmt(Util.v().getLocalForStackOp(listBody, typeStack,
4837                typeStack.topIndex()));
4838            break;
4839         case ByteCode.MONITOREXIT:
4840            stmt = Jimple.v().newExitMonitorStmt(Util.v().getLocalForStackOp(listBody, typeStack,
4841                typeStack.topIndex()));
4842            break;
4843
4844         default:
4845            throw new RuntimeException JavaDoc("Unrecognized bytecode instruction: " + x);
4846        }
4847
4848      if(stmt != null) {
4849    if (Options.v().keep_offset()) {
4850      stmt.addTag(new BytecodeOffsetTag(ins.label));
4851    }
4852        statements.add(stmt);
4853      }
4854   }
4855
4856     Type jimpleTypeOfAtype(int atype)
4857    {
4858        switch(atype)
4859        {
4860            case 4:
4861                return BooleanType.v();
4862
4863            case 5:
4864                return CharType.v();
4865
4866            case 6:
4867                return FloatType.v();
4868
4869            case 7:
4870                return DoubleType.v();
4871
4872            case 8:
4873                return ByteType.v();
4874
4875            case 9:
4876                return ShortType.v();
4877
4878            case 10:
4879                return IntType.v();
4880
4881            case 11:
4882                return LongType.v();
4883
4884            default:
4885                throw new RuntimeException JavaDoc("Undefined 'atype' in NEWARRAY byte instruction");
4886        }
4887   }
4888
4889    int typeSize(Type type)
4890    {
4891        if (type.equals(LongType.v()) || type.equals(DoubleType.v()) ||
4892        type.equals(Long2ndHalfType.v()) || type.equals(Double2ndHalfType.v()))
4893    {
4894            return 2;
4895        }
4896        else
4897            return 1;
4898    }
4899}
4900
4901class OutFlow
4902{
4903    TypeStack typeStack;
4904
4905    OutFlow(TypeStack typeStack)
4906    {
4907        this.typeStack = typeStack;
4908    }
4909}
4910
Popular Tags