KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > soot > jimple > JasminClass


1 /* Soot - a J*va Optimization Framework
2  * Copyright (C) 1997-1999 Raja Vallee-Rai
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 package soot.jimple;
28 import soot.options.*;
29 import soot.*;
30 import soot.jimple.internal.*;
31 import soot.toolkits.graph.*;
32 import soot.toolkits.scalar.*;
33 import soot.util.*;
34 import java.util.*;
35 import java.io.*;
36 import soot.grimp.*;
37
38 /** Methods for producing Jasmin code from Jimple. */
39 public class JasminClass extends AbstractJasminClass
40 {
41     void emit(String JavaDoc s, int stackChange)
42     {
43         modifyStackHeight(stackChange);
44         okayEmit(s);
45     }
46     
47     void modifyStackHeight(int stackChange)
48     {
49         if(currentStackHeight > maxStackHeight)
50             maxStackHeight = currentStackHeight;
51
52         currentStackHeight += stackChange;
53         
54         if(currentStackHeight < 0)
55             throw new RuntimeException JavaDoc("Stack height is negative!");
56             
57         if(currentStackHeight > maxStackHeight)
58             maxStackHeight = currentStackHeight;
59     }
60     
61     public JasminClass(SootClass sootClass)
62     {
63         super(sootClass);
64     }
65
66     protected void assignColorsToLocals(Body body)
67     {
68         super.assignColorsToLocals(body);
69         
70         // Call the graph colorer.
71
FastColorer.assignColorsToLocals(body, localToGroup,
72                 localToColor, groupToColorCount);
73
74         if(Options.v().time())
75             Timers.v().packTimer.end();
76                     
77     }
78     
79     
80     protected void emitMethodBody(SootMethod method)//, Map options)
81
{
82         if(Options.v().time())
83             Timers.v().buildJasminTimer.end();
84                     
85      
86         Body activeBody = method.getActiveBody();
87         
88         if(!(activeBody instanceof StmtBody))
89             throw new RuntimeException JavaDoc("method: " + method.getName() + " has an invalid active body!");
90         
91         StmtBody body = (StmtBody) activeBody;
92         
93         body.validate();
94             
95         if(body == null)
96             
97         if(Options.v().time())
98             Timers.v().buildJasminTimer.start();
99         
100         Chain units = body.getUnits();
101
102         ExceptionalUnitGraph stmtGraph = null;
103         LocalDefs ld = null;
104         LocalUses lu = null;
105
106         
107         // let's create a u-d web for the ++ peephole optimization.
108

109         if(Options.v().verbose())
110             G.v().out.println("[" + body.getMethod().getName() +
111                 "] Performing peephole optimizations...");
112
113         //boolean disablePeephole = PhaseOptions.getBoolean(options, "no-peephole");
114
boolean disablePeephole = true;
115
116         if (!disablePeephole)
117         {
118             stmtGraph = new ExceptionalUnitGraph(body);
119             ld = new SmartLocalDefs(stmtGraph, new SimpleLiveLocals(stmtGraph));
120             lu = new SimpleLocalUses(stmtGraph, ld);
121         }
122
123         int stackLimitIndex = -1;
124         
125         subroutineToReturnAddressSlot = new HashMap(10, 0.7f);
126
127         // Determine the unitToLabel map
128
{
129             Iterator boxIt = body.getUnitBoxes(true).iterator();
130
131             unitToLabel = new HashMap(units.size() * 2 + 1, 0.7f);
132             labelCount = 0;
133
134             while(boxIt.hasNext())
135             {
136                 // Assign a label for each statement reference
137
{
138                     StmtBox box = (StmtBox) boxIt.next();
139
140                     if(!unitToLabel.containsKey(box.getUnit()))
141                         unitToLabel.put(box.getUnit(), "label" + labelCount++);
142                 }
143             }
144         }
145
146         // Emit the exceptions
147
{
148             Iterator trapIt = body.getTraps().iterator();
149
150             while(trapIt.hasNext())
151             {
152                 Trap trap = (Trap) trapIt.next();
153
154                 if(trap.getBeginUnit() != trap.getEndUnit())
155                     emit(".catch " + slashify(trap.getException().getName()) + " from " +
156                         unitToLabel.get(trap.getBeginUnit()) + " to " + unitToLabel.get(trap.getEndUnit()) +
157                         " using " + unitToLabel.get(trap.getHandlerUnit()));
158             }
159         }
160
161         // Determine where the locals go
162
{
163             int localCount = 0;
164             int[] paramSlots = new int[method.getParameterCount()];
165             int thisSlot = 0;
166             Set assignedLocals = new HashSet();
167             Map groupColorPairToSlot = new HashMap(body.getLocalCount() * 2 + 1, 0.7f);
168             
169             localToSlot = new HashMap(body.getLocalCount() * 2 + 1, 0.7f);
170
171             assignColorsToLocals(body);
172             
173             // Determine slots for 'this' and parameters
174
{
175                 List paramTypes = method.getParameterTypes();
176
177                 if(!method.isStatic())
178                 {
179                     thisSlot = 0;
180                     localCount++;
181                 }
182
183                 for(int i = 0; i < paramTypes.size(); i++)
184                 {
185                     paramSlots[i] = localCount;
186                     localCount += sizeOfType((Type) paramTypes.get(i));
187                 }
188             }
189
190             // Handle identity statements
191
{
192                 Iterator stmtIt = units.iterator();
193
194                 while(stmtIt.hasNext())
195                 {
196                     Stmt s = (Stmt) stmtIt.next();
197
198                     if(s instanceof IdentityStmt && ((IdentityStmt) s).getLeftOp() instanceof Local)
199                     {
200                         Local l = (Local) ((IdentityStmt) s).getLeftOp();
201                         IdentityRef identity = (IdentityRef) ((IdentityStmt) s).getRightOp();
202
203                         int slot = 0;
204                                                 
205                         if(identity instanceof ThisRef)
206                         {
207                             if(method.isStatic())
208                                 throw new RuntimeException JavaDoc("Attempting to use 'this' in static method");
209
210                             slot = thisSlot;
211                         }
212                         else if(identity instanceof ParameterRef)
213                             slot = paramSlots[((ParameterRef) identity).getIndex()];
214                         else {
215                             // Exception ref. Skip over this
216
continue;
217                         }
218                         
219                         // Make this (group, color) point to the given slot,
220
// so that all locals of the same color can be pointed here too
221
{
222                             
223                             GroupIntPair pair = new GroupIntPair(localToGroup.get(l),
224                                 ((Integer JavaDoc) localToColor.get(l)).intValue());
225                                 
226                             groupColorPairToSlot.put(pair, new Integer JavaDoc(slot));
227                         }
228                             
229                         localToSlot.put(l, new Integer JavaDoc(slot));
230                         assignedLocals.add(l);
231                         
232                     }
233                 }
234             }
235
236             // Assign the rest of the locals
237
{
238                 Iterator localIt = body.getLocals().iterator();
239
240                 while(localIt.hasNext())
241                 {
242                     Local local = (Local) localIt.next();
243
244                     if(!assignedLocals.contains(local))
245                     {
246                         GroupIntPair pair = new GroupIntPair(localToGroup.get(local),
247                                 ((Integer JavaDoc) localToColor.get(local)).intValue());
248                             
249                         int slot;
250
251                         if(groupColorPairToSlot.containsKey(pair))
252                         {
253                             // This local should share the same slot as the previous local with
254
// the same (group, color);
255

256                             slot = ((Integer JavaDoc) groupColorPairToSlot.get(pair)).intValue();
257                         }
258                         else {
259                             slot = localCount;
260                             localCount += sizeOfType(local.getType());
261                     
262                             groupColorPairToSlot.put(pair, new Integer JavaDoc(slot));
263                          }
264                             
265                         localToSlot.put(local, new Integer JavaDoc(slot));
266                         assignedLocals.add(local);
267                     }
268                 }
269
270                 if (!Modifier.isNative(method.getModifiers())
271                     && !Modifier.isAbstract(method.getModifiers()))
272                   {
273                     emit(" .limit stack ?");
274                     stackLimitIndex = code.size() - 1;
275                     
276                     emit(" .limit locals " + localCount);
277                   }
278             }
279         }
280
281         // Emit code in one pass
282
{
283             Iterator codeIt = units.iterator();
284
285             isEmittingMethodCode = true;
286             maxStackHeight = 0;
287             isNextGotoAJsr = false;
288
289             while(codeIt.hasNext())
290             {
291                 Stmt s = (Stmt) codeIt.next();
292
293                 if(unitToLabel.containsKey(s))
294                     emit(unitToLabel.get(s) + ":");
295
296                 if(subroutineToReturnAddressSlot.containsKey(s))
297                 {
298                     AssignStmt assignStmt = (AssignStmt) s;
299
300                     modifyStackHeight(1); // simulate the pushing of address onto the stack by the jsr
301

302                     int slot = ((Integer JavaDoc) localToSlot.get(assignStmt.getLeftOp())).intValue();
303                     
304                     if(slot >= 0 && slot <= 3)
305                         emit("astore_" + slot, -1);
306                     else
307                         emit("astore " + slot, -1);
308
309                     //emit("astore " + ( ( Integer ) subroutineToReturnAddressSlot.get( s ) ).intValue() );
310

311                 }
312
313                 // Test for postincrement operators ++ and --
314
// We can optimize them further.
315

316                 boolean contFlag = false;
317                 // this is a fake do, to give us break;
318
do
319                 {
320                     if (disablePeephole)
321                       break;
322
323                     if (!(s instanceof AssignStmt))
324                       break;
325
326                     AssignStmt stmt = (AssignStmt)s;
327
328                     // sanityCheck: see that we have another statement after s.
329
if (!codeIt.hasNext())
330                       break;
331
332                     Stmt ns = (Stmt)(stmtGraph.getSuccsOf(stmt).get(0));
333                     if (!(ns instanceof AssignStmt))
334                       break;
335                     AssignStmt nextStmt = (AssignStmt)ns;
336
337                     List l = stmtGraph.getSuccsOf(nextStmt);
338                     if (l.size() != 1)
339                       break;
340
341                     Stmt nextNextStmt = (Stmt)(l.get(0));
342
343                     Value lvalue = stmt.getLeftOp();
344                     final Value rvalue = stmt.getRightOp();
345
346                     if (!(lvalue instanceof Local))
347                       break;
348
349                     // we're looking for this pattern:
350
// a: <lvalue> = <rvalue>; <rvalue> = <rvalue> +/- 1; use(<lvalue>);
351
// b: <lvalue> = <rvalue>; <rvalue> = <lvalue> +/- 1; use(<lvalue>);
352
// case a is emitted when rvalue is a local;
353
// case b when rvalue is, eg. a field ref.
354

355                     // we use structural equality
356
// for rvalue & nextStmt.getLeftOp().
357

358                     if (!(lvalue instanceof Local)
359                         || !nextStmt.getLeftOp().equivTo(rvalue)
360                         || !(nextStmt.getRightOp() instanceof AddExpr))
361                       break;
362
363                     // make sure that nextNextStmt uses the local exactly once
364
{
365                         Iterator boxIt = nextNextStmt.getUseBoxes().iterator();
366                         
367                         boolean foundExactlyOnce = false;
368                         
369                         while(boxIt.hasNext())
370                         {
371                             ValueBox box = (ValueBox) boxIt.next();
372                             
373                             if(box.getValue() == lvalue)
374                             {
375                                 if(!foundExactlyOnce)
376                                     foundExactlyOnce = true;
377                                 else
378                                 {
379                                     foundExactlyOnce = false;
380                                     break;
381                                 }
382                             }
383                         }
384                         
385                         if(!foundExactlyOnce)
386                             break;
387                     }
388                     
389                     // Specifically exclude the case where rvalue is on the lhs
390
// of nextNextStmt (what a mess!)
391
// this takes care of the extremely pathological case where
392
// the thing being incremented is also on the lhs of nns (!)
393
{
394                         Iterator boxIt = nextNextStmt.getDefBoxes().iterator();
395                         
396                         boolean found = false;
397                         
398                         while(boxIt.hasNext())
399                         {
400                             ValueBox box = (ValueBox) boxIt.next();
401                             
402                             if(box.getValue().equivTo(rvalue))
403                             {
404                                 found = true;
405                             }
406                         }
407                         
408                         if(found)
409                             break;
410                     }
411
412                     AddExpr addexp = (AddExpr)nextStmt.getRightOp();
413                     if (!addexp.getOp1().equivTo(lvalue) && !addexp.getOp1().equivTo(rvalue))
414                       break;
415
416                     Value added /* tax? */ = addexp.getOp2();
417                         
418                     if (!(added instanceof IntConstant)
419                         || ((IntConstant)(added)).value != 1)
420                       break;
421
422                     /* check that we have two uses and that these */
423                     /* uses live precisely in nextStmt and nextNextStmt */
424                     /* LocalDefs tells us this: if there was no use, */
425                     /* there would be no corresponding def. */
426                     if (addexp.getOp1().equivTo(lvalue))
427                     {
428                         if (lu.getUsesOf(stmt).size() != 2 ||
429                             ld.getDefsOfAt((Local)lvalue, nextStmt).size() != 1 ||
430                             ld.getDefsOfAt((Local)lvalue, nextNextStmt).size() !=1)
431                             break;
432                         plusPlusState = 0;
433                     }
434                     else
435                     {
436                         if (lu.getUsesOf(stmt).size() != 1 ||
437                             ld.getDefsOfAt((Local)lvalue, nextNextStmt).size() !=1)
438                             break;
439                         plusPlusState = 10;
440                     }
441
442                     /* emit dup slot */
443
444 // G.v().out.println("found ++ instance:");
445
// G.v().out.println(s); G.v().out.println(nextStmt);
446
// G.v().out.println(nextNextStmt);
447

448                     /* this should be redundant, but we do it */
449                     /* just in case. */
450                     if (lvalue.getType() != IntType.v())
451                         break;
452
453                     /* our strategy is as follows: eat the */
454                     /* two incrementing statements, push the lvalue to */
455                     /* be incremented & its holding local on a */
456                     /* plusPlusStack and deal with it in */
457                     /* emitLocal. */
458                        
459                     currentStackHeight = 0;
460
461                     /* emit statements as before */
462                     plusPlusValue = rvalue;
463                     plusPlusHolder = (Local)lvalue;
464                     plusPlusIncrementer = nextStmt;
465
466                     /* emit new statement with quickness */
467                     emitStmt(nextNextStmt);
468
469                     /* hm. we didn't use local. emit incrementage */
470                     if (plusPlusHolder != null)
471                         { emitStmt(stmt); emitStmt(nextStmt); }
472
473                     if(currentStackHeight != 0)
474                         throw new RuntimeException JavaDoc("Stack has height " + currentStackHeight + " after execution of stmt: " + s);
475                     contFlag = true;
476                     codeIt.next(); codeIt.next();
477                   }
478                 while(false);
479                 if (contFlag)
480                     continue;
481
482                 // end of peephole opts.
483

484                 // emit this statement
485
{
486                     currentStackHeight = 0;
487                     emitStmt(s);
488                         
489                     if(currentStackHeight != 0)
490                         throw new RuntimeException JavaDoc("Stack has height " + currentStackHeight + " after execution of stmt: " + s);
491                 }
492             }
493
494             isEmittingMethodCode = false;
495             
496             if (!Modifier.isNative(method.getModifiers())
497                 && !Modifier.isAbstract(method.getModifiers()))
498               code.set(stackLimitIndex, " .limit stack " + maxStackHeight);
499         }
500     }
501
502
503     void emitAssignStmt(AssignStmt stmt)
504     {
505         final Value lvalue = stmt.getLeftOp();
506         final Value rvalue = stmt.getRightOp();
507
508         // Handle simple subcase where you can use the efficient iinc bytecode
509
if(lvalue instanceof Local && (rvalue instanceof AddExpr || rvalue instanceof SubExpr))
510             {
511                 Local l = (Local) lvalue;
512                 BinopExpr expr = (BinopExpr) rvalue;
513                 Value op1 = expr.getOp1();
514                 Value op2 = expr.getOp2();
515
516                 // more peephole stuff.
517
if (lvalue == plusPlusHolder)
518                 {
519                     emitValue(lvalue);
520                     plusPlusHolder = null;
521                     plusPlusState = 0;
522                 }
523                 // end of peephole
524

525                 if(l.getType().equals(IntType.v()))
526                 {
527                     boolean isValidCase = false;
528                     int x = 0;
529                     
530                     if(op1 == l && op2 instanceof IntConstant)
531                     {
532                         x = ((IntConstant) op2).value;
533                         isValidCase = true;
534                     }
535                     else if(expr instanceof AddExpr &&
536                         op2 == l && op1 instanceof IntConstant)
537                     {
538                         // Note expr can't be a SubExpr because that would be x = 3 - x
539

540                         x = ((IntConstant) op1).value;
541                         isValidCase = true;
542                     }
543                     
544                     if(isValidCase && x >= Short.MIN_VALUE && x <= Short.MAX_VALUE)
545                     {
546                         emit("iinc " + ((Integer JavaDoc) localToSlot.get(l)).intValue() + " " +
547                             ((expr instanceof AddExpr) ? x : -x), 0);
548                         return;
549                     }
550                 }
551             }
552
553             lvalue.apply(new AbstractJimpleValueSwitch()
554             {
555                 public void caseArrayRef(ArrayRef v)
556                 {
557                     emitValue(v.getBase());
558                     emitValue(v.getIndex());
559                     emitValue(rvalue);
560                     
561                     v.getType().apply(new TypeSwitch()
562                     {
563                         public void caseArrayType(ArrayType t)
564                         {
565                             emit("aastore", -3);
566                         }
567
568                         public void caseDoubleType(DoubleType t)
569                         {
570                             emit("dastore", -4);
571                         }
572
573                         public void caseFloatType(FloatType t)
574                         {
575                             emit("fastore", -3);
576                         }
577
578                         public void caseIntType(IntType t)
579                         {
580                             emit("iastore", -3);
581                         }
582
583                         public void caseLongType(LongType t)
584                         {
585                             emit("lastore", -4);
586                         }
587
588                         public void caseRefType(RefType t)
589                         {
590                             emit("aastore", -3);
591                         }
592
593                         public void caseByteType(ByteType t)
594                         {
595                             emit("bastore", -3);
596                         }
597
598                         public void caseBooleanType(BooleanType t)
599                         {
600                             emit("bastore", -3);
601                         }
602
603                         public void caseCharType(CharType t)
604                         {
605                             emit("castore", -3);
606                         }
607
608                         public void caseShortType(ShortType t)
609                         {
610                             emit("sastore", -3);
611                         }
612
613                         public void defaultCase(Type t)
614                         {
615                             throw new RuntimeException JavaDoc("Invalid type: " + t);
616                         }
617                     });
618                 }
619                 
620                 public void defaultCase(Value v)
621                     {
622                         throw new RuntimeException JavaDoc("Can't store in value " + v);
623                     }
624                 
625                 public void caseInstanceFieldRef(InstanceFieldRef v)
626                     {
627                         emitValue(v.getBase());
628                         emitValue(rvalue);
629                         
630                         emit("putfield " + slashify(v.getFieldRef().declaringClass().getName()) + "/" +
631                              v.getFieldRef().name() + " " + jasminDescriptorOf(v.getFieldRef().type()),
632                              -1 + -sizeOfType(v.getFieldRef().type()));
633                     }
634                 
635                 public void caseLocal(final Local v)
636                 {
637                     final int slot = ((Integer JavaDoc) localToSlot.get(v)).intValue();
638                         
639                     v.getType().apply(new TypeSwitch()
640                     {
641                 private void handleIntegerType(IntegerType t)
642             {
643                                 emitValue(rvalue);
644                                 
645                                 if(slot >= 0 && slot <= 3)
646                                     emit("istore_" + slot, -1);
647                                 else
648                                     emit("istore " + slot, -1);
649             }
650
651                 public void caseBooleanType(BooleanType t)
652             {
653                 handleIntegerType(t);
654             }
655
656             public void caseByteType(ByteType t)
657             {
658                 handleIntegerType(t);
659             }
660
661             public void caseShortType(ShortType t)
662             {
663                 handleIntegerType(t);
664             }
665
666             public void caseCharType(CharType t)
667             {
668                 handleIntegerType(t);
669             }
670             
671             public void caseIntType(IntType t)
672               {
673                 handleIntegerType(t);
674               }
675
676                         public void caseArrayType(ArrayType t)
677                         {
678                             emitValue(rvalue);
679
680                             if(slot >= 0 && slot <= 3)
681                                 emit("astore_" + slot, -1);
682                             else
683                                 emit("astore " + slot, -1);
684                         }
685
686                         public void caseDoubleType(DoubleType t)
687                         {
688                             emitValue(rvalue);
689
690                             if(slot >= 0 && slot <= 3)
691                                 emit("dstore_" + slot, -2);
692                             else
693                                 emit("dstore " + slot, -2);
694                         }
695                         
696                         public void caseFloatType(FloatType t)
697                         {
698                             emitValue(rvalue);
699                             
700                             if(slot >= 0 && slot <= 3)
701                                 emit("fstore_" + slot, -1);
702                             else
703                                 emit("fstore " + slot, -1);
704                         }
705
706                         public void caseLongType(LongType t)
707                             {
708                                 emitValue(rvalue);
709                                 
710                                 if(slot >= 0 && slot <= 3)
711                                     emit("lstore_" + slot, -2);
712                                 else
713                                     emit("lstore " + slot, -2);
714                             }
715                         
716                         public void caseRefType(RefType t)
717                             {
718                                 emitValue(rvalue);
719                                 
720                                 if(slot >= 0 && slot <= 3)
721                                     emit("astore_" + slot, -1);
722                                 else
723                                     emit("astore " + slot, -1);
724                             }
725
726                         public void caseStmtAddressType(StmtAddressType t)
727                             {
728                                 isNextGotoAJsr = true;
729                                 returnAddressSlot = slot;
730                                 
731                                 /*
732                                   if ( slot >= 0 && slot <= 3)
733                                   emit("astore_" + slot, );
734                                   else
735                                   emit("astore " + slot, );
736                                   
737                                 */

738                                 
739                             }
740                         
741                         public void caseNullType(NullType t)
742                             {
743                                 emitValue(rvalue);
744                                 
745                                 if(slot >= 0 && slot <= 3)
746                                     emit("astore_" + slot, -1);
747                                 else
748                                     emit("astore " + slot, -1);
749                             }
750                         
751                         public void defaultCase(Type t)
752                             {
753                                 throw new RuntimeException JavaDoc("Invalid local type: " + t);
754                             }
755                     });
756                 }
757                 
758                 public void caseStaticFieldRef(StaticFieldRef v)
759                     {
760                         SootFieldRef field = v.getFieldRef();
761                         
762                         emitValue(rvalue);
763                         emit("putstatic " + slashify(field.declaringClass().getName()) + "/" +
764                              field.name() + " " + jasminDescriptorOf(field.type()),
765                              -sizeOfType(v.getFieldRef().type()));
766                     }
767             });
768     }
769
770     void emitIfStmt(IfStmt stmt)
771     {
772         Value cond = stmt.getCondition();
773
774         final Value op1 = ((BinopExpr) cond).getOp1();
775         final Value op2 = ((BinopExpr) cond).getOp2();
776         final String JavaDoc label = (String JavaDoc) unitToLabel.get(stmt.getTarget());
777
778         // Handle simple subcase where op1 is null
779
if(op2 instanceof NullConstant || op1 instanceof NullConstant)
780             {
781                 if(op2 instanceof NullConstant)
782                     emitValue(op1);
783                 else
784                     emitValue(op2);
785                     
786                 if(cond instanceof EqExpr)
787                     emit("ifnull " + label, -1);
788                 else if(cond instanceof NeExpr)
789                     emit("ifnonnull "+ label, -1);
790                 else
791                     throw new RuntimeException JavaDoc("invalid condition");
792                     
793                 return;
794             }
795
796         // Handle simple subcase where op2 is 0
797
if(op2 instanceof IntConstant && ((IntConstant) op2).value == 0)
798             {
799                 emitValue(op1);
800                 
801                 cond.apply(new AbstractJimpleValueSwitch()
802                 {
803                     public void caseEqExpr(EqExpr expr)
804                     {
805                         emit("ifeq " + label, -1);
806                     }
807         
808                     public void caseNeExpr(NeExpr expr)
809                     {
810                         emit("ifne " + label, -1);
811                     }
812         
813                     public void caseLtExpr(LtExpr expr)
814                     {
815                         emit("iflt " + label, -1);
816                     }
817                     
818                     public void caseLeExpr(LeExpr expr)
819                     {
820                         emit("ifle " + label, -1);
821                     }
822         
823                     public void caseGtExpr(GtExpr expr)
824                     {
825                         emit("ifgt " + label, -1);
826                     }
827         
828                     public void caseGeExpr(GeExpr expr)
829                     {
830                         emit("ifge " + label, -1);
831                     }
832         
833                     public void defaultCase(Value v)
834                     {
835                         throw new RuntimeException JavaDoc("invalid condition " + v);
836                     }
837                 });
838                  
839                 return;
840             }
841         
842         // Handle simple subcase where op1 is 0 (flip directions)
843
if(op1 instanceof IntConstant && ((IntConstant) op1).value == 0)
844             {
845                 emitValue(op2);
846                 
847                 cond.apply(new AbstractJimpleValueSwitch()
848                 {
849                     public void caseEqExpr(EqExpr expr)
850                     {
851                         emit("ifeq " + label, -1);
852                     }
853         
854                     public void caseNeExpr(NeExpr expr)
855                     {
856                         emit("ifne " + label, -1);
857                     }
858         
859                     public void caseLtExpr(LtExpr expr)
860                     {
861                         emit("ifgt " + label, -1);
862                     }
863                     
864                     public void caseLeExpr(LeExpr expr)
865                     {
866                         emit("ifge " + label, -1);
867                     }
868         
869                     public void caseGtExpr(GtExpr expr)
870                     {
871                         emit("iflt " + label, -1);
872                     }
873         
874                     public void caseGeExpr(GeExpr expr)
875                     {
876                         emit("ifle " + label, -1);
877                     }
878         
879                     public void defaultCase(Value v)
880                     {
881                         throw new RuntimeException JavaDoc("invalid condition " + v);
882                     }
883                 });
884                  
885                 return;
886             }
887         
888         emitValue(op1);
889         emitValue(op2);
890
891         cond.apply(new AbstractJimpleValueSwitch()
892         {
893             public void caseEqExpr(EqExpr expr)
894             {
895                 op1.getType().apply(new TypeSwitch()
896                 {
897                     public void caseIntType(IntType t)
898                     {
899                         emit("if_icmpeq " + label, -2);
900                     }
901
902                     public void caseBooleanType(BooleanType t)
903                     {
904                         emit("if_icmpeq " + label, -2);
905                     }
906
907                     public void caseShortType(ShortType t)
908                     {
909                         emit("if_icmpeq " + label, -2);
910                     }
911
912                     public void caseCharType(CharType t)
913                     {
914                         emit("if_icmpeq " + label, -2);
915                     }
916
917                     public void caseByteType(ByteType t)
918                     {
919                         emit("if_icmpeq " + label, -2);
920                     }
921
922                     public void caseDoubleType(DoubleType t)
923                     {
924                         emit("dcmpg", -3);
925                         emit("ifeq " + label, -1);
926                     }
927
928                     public void caseLongType(LongType t)
929                     {
930                         emit("lcmp", -3);
931                         emit("ifeq " + label, -1);
932                     }
933
934                     public void caseFloatType(FloatType t)
935                     {
936                         emit("fcmpg", -1);
937                         emit("ifeq " + label, -1);
938                     }
939
940                     public void caseArrayType(ArrayType t)
941                     {
942                         emit("if_acmpeq " + label, -2);
943                     }
944
945                     public void caseRefType(RefType t)
946                     {
947                         emit("if_acmpeq " + label, -2);
948                     }
949
950                     public void caseNullType(NullType t)
951                     {
952                         emit("if_acmpeq " + label, -2);
953                     }
954
955                     public void defaultCase(Type t)
956                     {
957                         throw new RuntimeException JavaDoc("invalid type");
958                     }
959                 });
960             }
961
962             public void caseNeExpr(NeExpr expr)
963             {
964                 op1.getType().apply(new TypeSwitch()
965                 {
966                     public void caseIntType(IntType t)
967                     {
968                         emit("if_icmpne " + label, -2);
969                     }
970
971                     public void caseBooleanType(BooleanType t)
972                     {
973                         emit("if_icmpne " + label, -2);
974                     }
975
976                     public void caseShortType(ShortType t)
977                     {
978                         emit("if_icmpne " + label, -2);
979                     }
980
981                     public void caseCharType(CharType t)
982                     {
983                         emit("if_icmpne " + label, -2);
984                     }
985
986                     public void caseByteType(ByteType t)
987                     {
988                         emit("if_icmpne " + label, -2);
989                     }
990
991                     public void caseDoubleType(DoubleType t)
992                     {
993                         emit("dcmpg", -3);
994                         emit("ifne " + label, -1);
995                     }
996
997                     public void caseLongType(LongType t)
998                     {
999                         emit("lcmp", -3);
1000                        emit("ifne " + label, -1);
1001                    }
1002
1003                    public void caseFloatType(FloatType t)
1004                    {
1005                        emit("fcmpg", -1);
1006                        emit("ifne " + label, -1);
1007                    }
1008
1009                    public void caseArrayType(ArrayType t)
1010                    {
1011                        emit("if_acmpne " + label, -2);
1012                    }
1013
1014                    public void caseRefType(RefType t)
1015                    {
1016                        emit("if_acmpne " + label, -2);
1017                    }
1018
1019                    public void caseNullType(NullType t)
1020                    {
1021                        emit("if_acmpne " + label, -2);
1022                    }
1023
1024                    public void defaultCase(Type t)
1025                    {
1026                        throw new RuntimeException JavaDoc("invalid type for NeExpr: " + t);
1027                    }
1028                });
1029            }
1030
1031            public void caseLtExpr(LtExpr expr)
1032            {
1033                op1.getType().apply(new TypeSwitch()
1034                {
1035                    public void caseIntType(IntType t)
1036                    {
1037                        emit("if_icmplt " + label, -2);
1038                    }
1039
1040                    public void caseBooleanType(BooleanType t)
1041                    {
1042                        emit("if_icmplt " + label, -2);
1043                    }
1044
1045                    public void caseShortType(ShortType t)
1046                    {
1047                        emit("if_icmplt " + label, -2);
1048                    }
1049
1050                    public void caseCharType(CharType t)
1051                    {
1052                        emit("if_icmplt " + label, -2);
1053                    }
1054
1055                    public void caseByteType(ByteType t)
1056                    {
1057                        emit("if_icmplt " + label, -2);
1058                    }
1059
1060
1061                    public void caseDoubleType(DoubleType t)
1062                    {
1063                        emit("dcmpg", -3);
1064                        emit("iflt " + label, -1);
1065                    }
1066
1067                    public void caseLongType(LongType t)
1068                    {
1069                        emit("lcmp", -3);
1070                        emit("iflt " + label, -1);
1071                    }
1072
1073                    public void caseFloatType(FloatType t)
1074                    {
1075                        emit("fcmpg", -1);
1076                        emit("iflt " + label, -1);
1077                    }
1078
1079                    public void defaultCase(Type t)
1080                    {
1081                        throw new RuntimeException JavaDoc("invalid type");
1082                    }
1083                });
1084            }
1085
1086            public void caseLeExpr(LeExpr expr)
1087            {
1088                op1.getType().apply(new TypeSwitch()
1089                {
1090                    public void caseIntType(IntType t)
1091                    {
1092                        emit("if_icmple " + label, -2);
1093                    }
1094
1095                    public void caseBooleanType(BooleanType t)
1096                    {
1097                        emit("if_icmple " + label, -2);
1098                    }
1099
1100                    public void caseShortType(ShortType t)
1101                    {
1102                        emit("if_icmple " + label, -2);
1103                    }
1104
1105                    public void caseCharType(CharType t)
1106                    {
1107                        emit("if_icmple " + label, -2);
1108                    }
1109
1110                    public void caseByteType(ByteType t)
1111                    {
1112                        emit("if_icmple " + label, -2);
1113                    }
1114
1115                    public void caseDoubleType(DoubleType t)
1116                    {
1117                        emit("dcmpg", -3);
1118                        emit("ifle " + label, -1);
1119                    }
1120
1121                    public void caseLongType(LongType t)
1122                    {
1123                        emit("lcmp", -3);
1124                        emit("ifle " + label, -1);
1125                    }
1126
1127                    public void caseFloatType(FloatType t)
1128                    {
1129                        emit("fcmpg", -1);
1130                        emit("ifle " + label, -1);
1131                    }
1132
1133                    public void defaultCase(Type t)
1134                    {
1135                        throw new RuntimeException JavaDoc("invalid type");
1136                    }
1137                });
1138            }
1139
1140            public void caseGtExpr(GtExpr expr)
1141            {
1142                op1.getType().apply(new TypeSwitch()
1143                {
1144                    public void caseIntType(IntType t)
1145                    {
1146                        emit("if_icmpgt " + label, -2);
1147                    }
1148
1149                    public void caseBooleanType(BooleanType t)
1150                    {
1151                        emit("if_icmpgt " + label, -2);
1152                    }
1153
1154                    public void caseShortType(ShortType t)
1155                    {
1156                        emit("if_icmpgt " + label, -2);
1157                    }
1158
1159                    public void caseCharType(CharType t)
1160                    {
1161                        emit("if_icmpgt " + label, -2);
1162                    }
1163
1164                    public void caseByteType(ByteType t)
1165                    {
1166                        emit("if_icmpgt " + label, -2);
1167                    }
1168
1169                    public void caseDoubleType(DoubleType t)
1170                    {
1171                        emit("dcmpg", -3);
1172                        emit("ifgt " + label, -1);
1173                    }
1174
1175                    public void caseLongType(LongType t)
1176                    {
1177                        emit("lcmp", -3);
1178                        emit("ifgt " + label, -1);
1179                    }
1180
1181                    public void caseFloatType(FloatType t)
1182                    {
1183                        emit("fcmpg", -1);
1184                        emit("ifgt " + label, -1);
1185                    }
1186
1187                    public void defaultCase(Type t)
1188                    {
1189                        throw new RuntimeException JavaDoc("invalid type");
1190                    }
1191                });
1192            }
1193
1194            public void caseGeExpr(GeExpr expr)
1195            {
1196                op1.getType().apply(new TypeSwitch()
1197                {
1198                    public void caseIntType(IntType t)
1199                    {
1200                        emit("if_icmpge " + label, -2);
1201                    }
1202
1203                    public void caseBooleanType(BooleanType t)
1204                    {
1205                        emit("if_icmpge " + label, -2);
1206                    }
1207
1208                    public void caseShortType(ShortType t)
1209                    {
1210                        emit("if_icmpge " + label, -2);
1211                    }
1212
1213                    public void caseCharType(CharType t)
1214                    {
1215                        emit("if_icmpge " + label, -2);
1216                    }
1217
1218                    public void caseByteType(ByteType t)
1219                    {
1220                        emit("if_icmpge " + label, -2);
1221                    }
1222
1223                    public void caseDoubleType(DoubleType t)
1224                    {
1225                        emit("dcmpg", -3);
1226                        emit("ifge " + label, -1);
1227                    }
1228
1229                    public void caseLongType(LongType t)
1230                    {
1231                        emit("lcmp", -3);
1232                        emit("ifge " + label, -1);
1233                    }
1234
1235                    public void caseFloatType(FloatType t)
1236                    {
1237                        emit("fcmpg", -1);
1238                        emit("ifge " + label, -1);
1239                    }
1240
1241                    public void defaultCase(Type t)
1242                    {
1243                        throw new RuntimeException JavaDoc("invalid type");
1244                    }
1245                });
1246            }
1247
1248            public void defaultCase(Value v)
1249            {
1250                throw new RuntimeException JavaDoc("invalid condition " + v);
1251            }
1252        });
1253    }
1254
1255    void emitStmt(Stmt stmt)
1256    {
1257        stmt.apply(new AbstractStmtSwitch()
1258        {
1259            public void caseAssignStmt(AssignStmt s)
1260            {
1261                emitAssignStmt(s);
1262            }
1263
1264            public void caseIdentityStmt(IdentityStmt s)
1265            {
1266                if(s.getRightOp() instanceof CaughtExceptionRef &&
1267                    s.getLeftOp() instanceof Local)
1268                {
1269                    int slot = ((Integer JavaDoc) localToSlot.get(s.getLeftOp())).intValue();
1270
1271                    modifyStackHeight(1); // simulate the pushing of the exception onto the
1272
// stack by the jvm
1273

1274                    if(slot >= 0 && slot <= 3)
1275                        emit("astore_" + slot, -1);
1276                    else
1277                        emit("astore " + slot, -1);
1278                }
1279            }
1280
1281            public void caseBreakpointStmt(BreakpointStmt s)
1282            {
1283                emit("breakpoint", 0);
1284            }
1285
1286            public void caseInvokeStmt(InvokeStmt s)
1287            {
1288                emitValue(s.getInvokeExpr());
1289
1290                Type returnType = ((InvokeExpr) s.getInvokeExpr()).getMethodRef().returnType();
1291
1292                if(!returnType.equals(VoidType.v()))
1293                {
1294                    // Need to do some cleanup because this value is not used.
1295

1296                    if(sizeOfType(returnType) == 1)
1297                        emit("pop", -1);
1298                    else
1299                        emit("pop2", -2);
1300                }
1301            }
1302
1303            public void defaultCase(Stmt s)
1304            {
1305                throw new RuntimeException JavaDoc("invalid stmt: " + s);
1306            }
1307
1308            public void caseEnterMonitorStmt(EnterMonitorStmt s)
1309            {
1310                emitValue(s.getOp());
1311                emit("monitorenter", -1);
1312            }
1313
1314            public void caseExitMonitorStmt(ExitMonitorStmt s)
1315            {
1316                emitValue(s.getOp());
1317                emit("monitorexit", -1);
1318            }
1319
1320            public void caseGotoStmt(GotoStmt s)
1321            {
1322                if(isNextGotoAJsr)
1323                {
1324                    emit("jsr " + unitToLabel.get(s.getTarget()));
1325                    isNextGotoAJsr = false;
1326
1327                    subroutineToReturnAddressSlot.put(s.getTarget(), new Integer JavaDoc(returnAddressSlot));
1328                }
1329                else
1330                    emit("goto " + unitToLabel.get(s.getTarget()));
1331            }
1332
1333
1334            public void caseIfStmt(IfStmt s)
1335            {
1336                emitIfStmt(s);
1337            }
1338
1339            public void caseLookupSwitchStmt(LookupSwitchStmt s)
1340            {
1341                emitValue(s.getKey());
1342                emit("lookupswitch", -1);
1343
1344                List lookupValues = s.getLookupValues();
1345                List targets = s.getTargets();
1346
1347                for(int i = 0; i < lookupValues.size(); i++)
1348                    emit(" " + lookupValues.get(i) + " : " + unitToLabel.get(targets.get(i)));
1349
1350                emit(" default : " + unitToLabel.get(s.getDefaultTarget()));
1351            }
1352
1353            public void caseNopStmt(NopStmt s)
1354            {
1355                emit("nop", 0);
1356            }
1357
1358            public void caseRetStmt(RetStmt s)
1359            {
1360                emit("ret " + localToSlot.get(s.getStmtAddress()), 0);
1361            }
1362
1363            public void caseReturnStmt(ReturnStmt s)
1364            {
1365                emitValue(s.getOp());
1366
1367                Value returnValue = s.getOp();
1368
1369                returnValue.getType().apply(new TypeSwitch()
1370                {
1371                    public void defaultCase(Type t)
1372                    {
1373                        throw new RuntimeException JavaDoc("invalid return type " + t.toString());
1374                     }
1375
1376                     public void caseDoubleType(DoubleType t)
1377                     {
1378                        emit("dreturn", -2);
1379                     }
1380
1381                     public void caseFloatType(FloatType t)
1382                     {
1383                        emit("freturn", -1);
1384                     }
1385
1386                     public void caseIntType(IntType t)
1387                     {
1388                        emit("ireturn", -1);
1389                     }
1390
1391                     public void caseByteType(ByteType t)
1392                     {
1393                        emit("ireturn", -1);
1394                     }
1395
1396                     public void caseShortType(ShortType t)
1397                     {
1398                        emit("ireturn", -1);
1399                     }
1400
1401                     public void caseCharType(CharType t)
1402                     {
1403                        emit("ireturn", -1);
1404                     }
1405
1406                     public void caseBooleanType(BooleanType t)
1407                     {
1408                        emit("ireturn", -1);
1409                     }
1410
1411                     public void caseLongType(LongType t)
1412                     {
1413                        emit("lreturn", -2);
1414                     }
1415
1416                     public void caseArrayType(ArrayType t)
1417                     {
1418                        emit("areturn", -1);
1419                     }
1420
1421                     public void caseRefType(RefType t)
1422                     {
1423                        emit("areturn", -1);
1424                     }
1425
1426                     public void caseNullType(NullType t)
1427                     {
1428                        emit("areturn", -1);
1429                     }
1430
1431                });
1432            }
1433
1434            public void caseReturnVoidStmt(ReturnVoidStmt s)
1435            {
1436                emit("return", 0);
1437            }
1438
1439            public void caseTableSwitchStmt(TableSwitchStmt s)
1440            {
1441                emitValue(s.getKey());
1442                emit("tableswitch " + s.getLowIndex() + " ; high = " + s.getHighIndex(), -1);
1443
1444                List targets = s.getTargets();
1445
1446                for(int i = 0; i < targets.size(); i++)
1447                    emit(" " + unitToLabel.get(targets.get(i)));
1448
1449                emit("default : " + unitToLabel.get(s.getDefaultTarget()));
1450            }
1451
1452            public void caseThrowStmt(ThrowStmt s)
1453            {
1454                emitValue(s.getOp());
1455                emit("athrow", -1);
1456            }
1457        });
1458    }
1459
1460    /* try to pre-duplicate a local and fix-up its dup_xn parameter. */
1461    /* if we find that we're unable to proceed, we swap the dup_xn */
1462    /* for a store pl, load pl combination */
1463    Value plusPlusValue;
1464    Local plusPlusHolder;
1465    int plusPlusState;
1466    int plusPlusPlace;
1467    int plusPlusHeight;
1468    Stmt plusPlusIncrementer;
1469    /* end of plusplus stuff. */
1470
1471    void emitLocal(Local v)
1472    {
1473        final int slot = ((Integer JavaDoc) localToSlot.get(v)).intValue();
1474        final Local vAlias = v;
1475
1476        v.getType().apply(new TypeSwitch()
1477        {
1478            public void caseArrayType(ArrayType t)
1479            {
1480                if(slot >= 0 && slot <= 3)
1481                    emit("aload_" + slot, 1);
1482                else
1483                    emit("aload " + slot, 1);
1484            }
1485            
1486            public void defaultCase(Type t)
1487            {
1488                throw new RuntimeException JavaDoc("invalid local type to load" + t);
1489            }
1490
1491            public void caseDoubleType(DoubleType t)
1492            {
1493                if(slot >= 0 && slot <= 3)
1494                    emit("dload_" + slot, 2);
1495                else
1496                    emit("dload " + slot, 2);
1497            }
1498
1499            public void caseFloatType(FloatType t)
1500            {
1501                if(slot >= 0 && slot <= 3)
1502                    emit("fload_" + slot, 1);
1503                else
1504                    emit("fload " + slot, 1);
1505            }
1506          
1507        // add boolean, byte, short, and char type
1508
public void caseBooleanType(BooleanType t)
1509          {
1510        handleIntegerType(t);
1511          }
1512
1513        public void caseByteType(ByteType t)
1514          {
1515        handleIntegerType(t);
1516          }
1517
1518        public void caseShortType(ShortType t)
1519          {
1520        handleIntegerType(t);
1521          }
1522
1523        public void caseCharType(CharType t)
1524          {
1525        handleIntegerType(t);
1526          }
1527
1528            public void caseIntType(IntType t)
1529            {
1530                handleIntegerType(t);
1531        }
1532
1533            // peephole stuff appears here.
1534
public void handleIntegerType(IntegerType t)
1535        {
1536                if (vAlias.equals(plusPlusHolder))
1537                {
1538                    switch(plusPlusState)
1539                    {
1540                    case 0:
1541                    {
1542                        // ok, we're called upon to emit the
1543
// ++ target, whatever it was.
1544

1545                        // now we need to emit a statement incrementing
1546
// the correct value.
1547
// actually, just remember the local to be incremented.
1548

1549                        // here ppi is of the form ppv = pph + 1
1550

1551                        plusPlusState = 1;
1552                        
1553                        emitStmt(plusPlusIncrementer);
1554                        int diff = plusPlusHeight - currentStackHeight + 1;
1555                        if (diff > 0)
1556                          code.set(plusPlusPlace, " dup_x"+diff);
1557                        plusPlusHolder = null;
1558
1559                        // afterwards we have the value on the stack.
1560
return;
1561                    }
1562                    case 1:
1563                        plusPlusHeight = currentStackHeight;
1564                        plusPlusHolder = null;
1565
1566                        emitValue(plusPlusValue);
1567
1568                        plusPlusPlace = code.size();
1569                        emit("dup", 1);
1570
1571                        return;
1572                    case 10:
1573                    {
1574                        // this time we have ppi of the form ppv = ppv + 1
1575
plusPlusState = 11;
1576
1577// G.v().out.println("ppV "+plusPlusValue);
1578
// G.v().out.println("ppH "+plusPlusHolder);
1579
// G.v().out.println("ppI "+plusPlusIncrementer);
1580

1581                        plusPlusHolder = (Local)plusPlusValue;
1582                        emitStmt(plusPlusIncrementer);
1583                        int diff = plusPlusHeight - currentStackHeight + 1;
1584                        if (diff > 0 && plusPlusState == 11)
1585                          code.set(plusPlusPlace, " dup_x"+diff);
1586                        plusPlusHolder = null;
1587
1588                        // afterwards we have the value on the stack.
1589
return;
1590                    }
1591                    case 11:
1592                        plusPlusHeight = currentStackHeight;
1593                        plusPlusHolder = null;
1594
1595                        emitValue(plusPlusValue);
1596                        if (plusPlusState != 11)
1597                            emit("dup", 1);
1598
1599                        plusPlusPlace = code.size();
1600
1601                        return;
1602                    }
1603                }
1604                if(slot >= 0 && slot <= 3)
1605                    emit("iload_" + slot, 1);
1606                else
1607                    emit("iload " + slot, 1);
1608            }
1609            // end of peephole stuff.
1610

1611            public void caseLongType(LongType t)
1612            {
1613                if(slot >= 0 && slot <= 3)
1614                    emit("lload_" + slot, 2);
1615                else
1616                    emit("lload " + slot, 2);
1617            }
1618
1619            public void caseRefType(RefType t)
1620            {
1621                if(slot >= 0 && slot <= 3)
1622                    emit("aload_" + slot, 1);
1623                else
1624                    emit("aload " + slot, 1);
1625            }
1626
1627            public void caseNullType(NullType t)
1628            {
1629                if(slot >= 0 && slot <= 3)
1630                    emit("aload_" + slot, 1);
1631                else
1632                    emit("aload " + slot, 1);
1633            }
1634        });
1635    }
1636
1637    void emitValue(Value value)
1638    {
1639        value.apply(new AbstractGrimpValueSwitch()
1640        {
1641            public void caseAddExpr(AddExpr v)
1642            {
1643                emitValue(v.getOp1());
1644                emitValue(v.getOp2());
1645
1646                v.getType().apply(new TypeSwitch()
1647                {
1648                    private void handleIntCase()
1649                    {
1650                        emit("iadd", -1);
1651                    }
1652                    
1653                    public void caseIntType(IntType t) { handleIntCase(); }
1654                    public void caseBooleanType(BooleanType t) { handleIntCase(); }
1655                    public void caseShortType(ShortType t) { handleIntCase(); }
1656                    public void caseCharType(CharType t) { handleIntCase(); }
1657                    public void caseByteType(ByteType t) { handleIntCase(); }
1658
1659                    public void caseLongType(LongType t)
1660                    {
1661                        emit("ladd", -2);
1662                    }
1663
1664                    public void caseDoubleType(DoubleType t)
1665                    {
1666                        emit("dadd", -2);
1667                    }
1668
1669                    public void caseFloatType(FloatType t)
1670                    {
1671                        emit("fadd", -1);
1672                    }
1673
1674                    public void defaultCase(Type t)
1675                    {
1676                        throw new RuntimeException JavaDoc("Invalid argument type for add");
1677                    }
1678                });
1679
1680            }
1681
1682            public void caseAndExpr(AndExpr v)
1683            {
1684                emitValue(v.getOp1());
1685                emitValue(v.getOp2());
1686
1687                v.getType().apply(new TypeSwitch()
1688                {
1689                    private void handleIntCase()
1690                    {
1691                        emit("iand", -1);
1692                    }
1693
1694                    public void caseIntType(IntType t) { handleIntCase(); }
1695                    public void caseBooleanType(BooleanType t) { handleIntCase(); }
1696                    public void caseShortType(ShortType t) { handleIntCase(); }
1697                    public void caseCharType(CharType t) { handleIntCase(); }
1698                    public void caseByteType(ByteType t) { handleIntCase(); }
1699
1700                    public void caseLongType(LongType t)
1701                    {
1702                        emit("land", -2);
1703                    }
1704
1705                    public void defaultCase(Type t)
1706                    {
1707                        throw new RuntimeException JavaDoc("Invalid argument type for and");
1708                    }
1709                });
1710            }
1711
1712            public void caseArrayRef(ArrayRef v)
1713            {
1714                emitValue(v.getBase());
1715                emitValue(v.getIndex());
1716
1717                v.getType().apply(new TypeSwitch()
1718                {
1719                    public void caseArrayType(ArrayType ty)
1720                    {
1721                        emit("aaload", -1);
1722                    }
1723
1724                    public void caseBooleanType(BooleanType ty)
1725                    {
1726                        emit("baload", -1);
1727                    }
1728
1729                    public void caseByteType(ByteType ty)
1730                    {
1731                        emit("baload", -1);
1732                    }
1733
1734                    public void caseCharType(CharType ty)
1735                    {
1736                        emit("caload", -1);
1737                    }
1738
1739                    public void defaultCase(Type ty)
1740                    {
1741                        throw new RuntimeException JavaDoc("invalid base type");
1742                    }
1743
1744                    public void caseDoubleType(DoubleType ty)
1745                    {
1746                        emit("daload", 0);
1747                    }
1748
1749                    public void caseFloatType(FloatType ty)
1750                    {
1751                        emit("faload", -1);
1752                    }
1753
1754                    public void caseIntType(IntType ty)
1755                    {
1756                        emit("iaload", -1);
1757                    }
1758
1759                    public void caseLongType(LongType ty)
1760                    {
1761                        emit("laload", 0);
1762                    }
1763
1764                    public void caseNullType(NullType ty)
1765                    {
1766                        emit("aaload", -1);
1767                    }
1768                    public void caseRefType(RefType ty)
1769                    {
1770                        emit("aaload", -1);
1771                    }
1772
1773                    public void caseShortType(ShortType ty)
1774                    {
1775                        emit("saload", -1);
1776                    }
1777                });
1778            }
1779
1780            public void caseCastExpr(final CastExpr v)
1781            {
1782                final Type toType = v.getCastType();
1783                final Type fromType = v.getOp().getType();
1784
1785                emitValue(v.getOp());
1786
1787                if(toType instanceof RefType)
1788                    emit("checkcast " + slashify(toType.toString()), 0);
1789                else if(toType instanceof ArrayType)
1790                    emit("checkcast " + jasminDescriptorOf(toType), 0);
1791                else {
1792                    fromType.apply(new TypeSwitch()
1793                    {
1794                        public void defaultCase(Type ty)
1795                        {
1796                            throw new RuntimeException JavaDoc("invalid fromType " + fromType);
1797                        }
1798
1799                        public void caseDoubleType(DoubleType ty)
1800                        {
1801                            if(toType.equals(IntType.v()))
1802                                emit("d2i", -1);
1803                            else if(toType.equals(LongType.v()))
1804                                emit("d2l", 0);
1805                            else if(toType.equals(FloatType.v()))
1806                                emit("d2f", -1);
1807                            else
1808                                throw new RuntimeException JavaDoc("invalid toType from double: " + toType);
1809                        }
1810
1811                        public void caseFloatType(FloatType ty)
1812                        {
1813                            if(toType.equals(IntType.v()))
1814                                emit("f2i", 0);
1815                            else if(toType.equals(LongType.v()))
1816                                emit("f2l", 1);
1817                            else if(toType.equals(DoubleType.v()))
1818                                emit("f2d", 1);
1819                            else
1820                                throw new RuntimeException JavaDoc("invalid toType from float: " + toType);
1821                        }
1822
1823                        public void caseIntType(IntType ty)
1824                        {
1825                            emitIntToTypeCast();
1826                        }
1827
1828                        public void caseBooleanType(BooleanType ty)
1829                        {
1830                              emitIntToTypeCast();
1831                        }
1832
1833                        public void caseByteType(ByteType ty)
1834                        {
1835                            emitIntToTypeCast();
1836                        }
1837
1838                        public void caseCharType(CharType ty)
1839                        {
1840                            emitIntToTypeCast();
1841                        }
1842
1843                        public void caseShortType(ShortType ty)
1844                        {
1845                            emitIntToTypeCast();
1846                        }
1847
1848                        private void emitIntToTypeCast()
1849                        {
1850                            if(toType.equals(ByteType.v()))
1851                                emit("i2b", 0);
1852                            else if(toType.equals(CharType.v()))
1853                                emit("i2c", 0);
1854                            else if(toType.equals(ShortType.v()))
1855                                emit("i2s", 0);
1856                            else if(toType.equals(FloatType.v()))
1857                                emit("i2f", 0);
1858                            else if(toType.equals(LongType.v()))
1859                                emit("i2l", 1);
1860                            else if(toType.equals(DoubleType.v()))
1861                                emit("i2d", 1);
1862                            else if(toType.equals(IntType.v()))
1863                                ; // this shouldn't happen?
1864
else if(toType.equals(BooleanType.v()))
1865                ;
1866                            else
1867                                throw new RuntimeException JavaDoc("invalid toType from int: " + toType +
1868                                    " " + v.toString());
1869                        }
1870
1871                        public void caseLongType(LongType ty)
1872                        {
1873                            if(toType.equals(IntType.v()))
1874                                emit("l2i", -1);
1875                            else if(toType.equals(FloatType.v()))
1876                                emit("l2f", -1);
1877                            else if(toType.equals(DoubleType.v()))
1878                                emit("l2d", 0);
1879                            else if(toType.equals(ByteType.v()))
1880                              { emit("l2i", -1); emitIntToTypeCast(); }
1881                            else if(toType.equals(ShortType.v()))
1882                              { emit("l2i", -1); emitIntToTypeCast(); }
1883                            else if(toType.equals(CharType.v()))
1884                              { emit("l2i", -1); emitIntToTypeCast(); }
1885                            else if(toType.equals(BooleanType.v()))
1886                              { emit("l2i", -1); emitIntToTypeCast(); }
1887                            else
1888                                throw new RuntimeException JavaDoc("invalid toType from long: " + toType);
1889                        }
1890                    });
1891                }
1892            }
1893
1894            public void caseCmpExpr(CmpExpr v)
1895            {
1896                emitValue(v.getOp1());
1897                emitValue(v.getOp2());
1898                emit("lcmp", -3);
1899            }
1900
1901            public void caseCmpgExpr(CmpgExpr v)
1902            {
1903                emitValue(v.getOp1());
1904                emitValue(v.getOp2());
1905
1906                if(v.getOp1().getType().equals(FloatType.v()))
1907                    emit("fcmpg", -1);
1908                else
1909                    emit("dcmpg", -3);
1910            }
1911
1912            public void caseCmplExpr(CmplExpr v)
1913            {
1914                emitValue(v.getOp1());
1915                emitValue(v.getOp2());
1916
1917                if(v.getOp1().getType().equals(FloatType.v()))
1918                    emit("fcmpl", -1);
1919                else
1920                    emit("dcmpl", -3);
1921            }
1922
1923            public void defaultCase(Value v)
1924            {
1925                throw new RuntimeException JavaDoc("Can't load value: " + v);
1926            }
1927
1928            public void caseDivExpr(DivExpr v)
1929            {
1930                emitValue(v.getOp1());
1931                emitValue(v.getOp2());
1932
1933                v.getType().apply(new TypeSwitch()
1934                {
1935                    private void handleIntCase()
1936                    {
1937                        emit("idiv", -1);
1938                    }
1939
1940                    public void caseIntType(IntType t) { handleIntCase(); }
1941                    public void caseBooleanType(BooleanType t) { handleIntCase(); }
1942                    public void caseShortType(ShortType t) { handleIntCase(); }
1943                    public void caseCharType(CharType t) { handleIntCase(); }
1944                    public void caseByteType(ByteType t) { handleIntCase(); }
1945
1946                    public void caseLongType(LongType t)
1947                    {
1948                        emit("ldiv", -2);
1949                    }
1950
1951                    public void caseDoubleType(DoubleType t)
1952                    {
1953                        emit("ddiv", -2);
1954                    }
1955
1956                    public void caseFloatType(FloatType t)
1957                    {
1958                        emit("fdiv", -1);
1959                    }
1960
1961                    public void defaultCase(Type t)
1962                    {
1963                        throw new RuntimeException JavaDoc("Invalid argument type for div");
1964                    }
1965                });
1966
1967            }
1968
1969            public void caseDoubleConstant(DoubleConstant v)
1970            {
1971                if((v.value == 0) && ((1.0/v.value) > 0.0))
1972                    emit("dconst_0", 2);
1973                else if(v.value == 1)
1974                    emit("dconst_1", 2);
1975                else {
1976                    String JavaDoc s = v.toString();
1977                    
1978                    if(s.equals("#Infinity"))
1979                        s="+DoubleInfinity";
1980                    
1981                    if(s.equals("#-Infinity"))
1982                        s="-DoubleInfinity";
1983                    
1984                    if(s.equals("#NaN"))
1985                        s="+DoubleNaN";
1986                        
1987                    emit("ldc2_w " + s, 2);
1988                }
1989            }
1990
1991            public void caseFloatConstant(FloatConstant v)
1992            {
1993                if((v.value == 0) && ((1.0f/v.value) > 0.0f))
1994                    emit("fconst_0", 1);
1995                else if(v.value == 1)
1996                    emit("fconst_1", 1);
1997                else if(v.value == 2)
1998                    emit("fconst_2", 1);
1999                else {
2000                    String JavaDoc s = v.toString();
2001                    
2002                    if(s.equals("#InfinityF"))
2003                        s="+FloatInfinity";
2004                    if(s.equals("#-InfinityF"))
2005                        s="-FloatInfinity";
2006                        
2007                    if(s.equals("#NaNF"))
2008                        s="+FloatNaN";
2009                    
2010                    emit("ldc " + s, 1);
2011                }
2012            }
2013
2014
2015            public void caseInstanceFieldRef(InstanceFieldRef v)
2016            {
2017                emitValue(v.getBase());
2018
2019                emit("getfield " + slashify(v.getFieldRef().declaringClass().getName()) + "/" +
2020                    v.getFieldRef().name() + " " + jasminDescriptorOf(v.getFieldRef().type()),
2021                    -1 + sizeOfType(v.getFieldRef().type()));
2022            }
2023
2024            public void caseInstanceOfExpr(InstanceOfExpr v)
2025            {
2026                final Type checkType;
2027                
2028                emitValue(v.getOp());
2029
2030                checkType = v.getCheckType();
2031                
2032                if(checkType instanceof RefType)
2033                    emit("instanceof " + slashify(checkType.toString()), 0);
2034                else if(checkType instanceof ArrayType)
2035                    emit("instanceof " + jasminDescriptorOf(checkType), 0);
2036            }
2037
2038            public void caseIntConstant(IntConstant v)
2039            {
2040                if(v.value == -1)
2041                    emit("iconst_m1", 1);
2042                else if(v.value >= 0 && v.value <= 5)
2043                    emit("iconst_" + v.value, 1);
2044                else if(v.value >= Byte.MIN_VALUE && v.value <= Byte.MAX_VALUE)
2045                    emit("bipush " + v.value, 1);
2046                else if(v.value >= Short.MIN_VALUE && v.value <= Short.MAX_VALUE)
2047                    emit("sipush " + v.value, 1);
2048                else
2049                    emit("ldc " + v.toString(), 1);
2050            }
2051
2052            public void caseInterfaceInvokeExpr(InterfaceInvokeExpr v)
2053            {
2054                SootMethodRef m = v.getMethodRef();
2055
2056                emitValue(v.getBase());
2057
2058                for(int i = 0; i < m.parameterTypes().size(); i++)
2059                    emitValue(v.getArg(i));
2060
2061                emit("invokeinterface " + slashify(m.declaringClass().getName()) + "/" +
2062                    m.name() + jasminDescriptorOf(m) + " " + (argCountOf(m) + 1),
2063                    -(argCountOf(m) + 1) + sizeOfType(m.returnType()));
2064            }
2065
2066            public void caseLengthExpr(LengthExpr v)
2067            {
2068                emitValue(v.getOp());
2069                emit("arraylength", 0);
2070            }
2071
2072            public void caseLocal(Local v)
2073            {
2074                emitLocal(v);
2075            }
2076
2077            public void caseLongConstant(LongConstant v)
2078            {
2079                if(v.value == 0)
2080                    emit("lconst_0", 2);
2081                else if(v.value == 1)
2082                    emit("lconst_1", 2);
2083                else
2084                    emit("ldc2_w " + v.toString(), 2);
2085            }
2086
2087
2088            public void caseMulExpr(MulExpr v)
2089            {
2090                emitValue(v.getOp1());
2091                emitValue(v.getOp2());
2092
2093                v.getType().apply(new TypeSwitch()
2094                {
2095                    private void handleIntCase()
2096                    {
2097                        emit("imul", -1);
2098                    }
2099
2100                    public void caseIntType(IntType t) { handleIntCase(); }
2101                    public void caseBooleanType(BooleanType t) { handleIntCase(); }
2102                    public void caseShortType(ShortType t) { handleIntCase(); }
2103                    public void caseCharType(CharType t) { handleIntCase(); }
2104                    public void caseByteType(ByteType t) { handleIntCase(); }
2105
2106                    public void caseLongType(LongType t)
2107                    {
2108                        emit("lmul", -2);
2109                    }
2110
2111                    public void caseDoubleType(DoubleType t)
2112                    {
2113                        emit("dmul", -2);
2114                    }
2115
2116                    public void caseFloatType(FloatType t)
2117                    {
2118                        emit("fmul", -1);
2119                    }
2120
2121                    public void defaultCase(Type t)
2122                    {
2123                        throw new RuntimeException JavaDoc("Invalid argument type for mul");
2124                    }
2125                });
2126            }
2127
2128            public void caseLtExpr(LtExpr v)
2129            {
2130                emitValue(v.getOp1());
2131                emitValue(v.getOp2());
2132
2133                v.getOp1().getType().apply(new TypeSwitch()
2134                {
2135                    public void caseDoubleType(DoubleType t)
2136                    {
2137                        emit("dcmpg", -3);
2138                        emitBooleanBranch("iflt");
2139                    }
2140
2141                    public void caseFloatType(FloatType t)
2142                    {
2143                        emit("fcmpg", -1);
2144                        emitBooleanBranch("iflt");
2145                    }
2146
2147                    private void handleIntCase()
2148                    {
2149                        emit("if_icmplt", -2);
2150                    }
2151
2152
2153                    public void caseIntType(IntType t) { handleIntCase(); }
2154                    public void caseBooleanType(BooleanType t) { handleIntCase(); }
2155                    public void caseShortType(ShortType t) { handleIntCase(); }
2156                    public void caseCharType(CharType t) { handleIntCase(); }
2157                    public void caseByteType(ByteType t) { handleIntCase(); }
2158
2159                    public void caseLongType(LongType t)
2160                    {
2161                        emit("lcmp", -3);
2162                        emitBooleanBranch("iflt");
2163                    }
2164
2165                    public void defaultCase(Type t)
2166                    {
2167                        throw new RuntimeException JavaDoc("invalid type");
2168                    }
2169                });
2170            }
2171
2172            public void caseLeExpr(LeExpr v)
2173            {
2174                emitValue(v.getOp1());
2175                emitValue(v.getOp2());
2176
2177                v.getOp1().getType().apply(new TypeSwitch()
2178                {
2179                    public void caseDoubleType(DoubleType t)
2180                    {
2181                        emit("dcmpg", -3);
2182                        emitBooleanBranch("ifle");
2183                    }
2184
2185                    public void caseFloatType(FloatType t)
2186                    {
2187                        emit("fcmpg", -1);
2188                        emitBooleanBranch("ifle");
2189                    }
2190
2191                    private void handleIntCase()
2192                    {
2193                        emit("if_icmple", -2);
2194                    }
2195
2196                    public void caseIntType(IntType t) { handleIntCase(); }
2197                    public void caseBooleanType(BooleanType t) { handleIntCase(); }
2198                    public void caseShortType(ShortType t) { handleIntCase(); }
2199                    public void caseCharType(CharType t) { handleIntCase(); }
2200                    public void caseByteType(ByteType t) { handleIntCase(); }
2201
2202                    public void caseLongType(LongType t)
2203                    {
2204                        emit("lcmp", -3);
2205                        emitBooleanBranch("ifle");
2206                    }
2207
2208                    public void defaultCase(Type t)
2209                    {
2210                        throw new RuntimeException JavaDoc("invalid type");
2211                    }
2212                });
2213            }
2214
2215            public void caseGtExpr(GtExpr v)
2216            {
2217                emitValue(v.getOp1());
2218                emitValue(v.getOp2());
2219
2220                v.getOp1().getType().apply(new TypeSwitch()
2221                {
2222                    public void caseDoubleType(DoubleType t)
2223                    {
2224                        emit("dcmpg", -3);
2225                        emitBooleanBranch("ifgt");
2226                    }
2227
2228                    public void caseFloatType(FloatType t)
2229                    {
2230                        emit("fcmpg", -1);
2231                        emitBooleanBranch("ifgt");
2232                    }
2233
2234                    private void handleIntCase()
2235                    {
2236                        emit("if_icmpgt", -2);
2237                    }
2238
2239                    public void caseIntType(IntType t) { handleIntCase(); }
2240                    public void caseBooleanType(BooleanType t) { handleIntCase(); }
2241                    public void caseShortType(ShortType t) { handleIntCase(); }
2242                    public void caseCharType(CharType t) { handleIntCase(); }
2243                    public void caseByteType(ByteType t) { handleIntCase(); }
2244
2245                    public void caseLongType(LongType t)
2246                    {
2247                        emit("lcmp", -3);
2248                        emitBooleanBranch("ifgt");
2249                    }
2250
2251                    public void defaultCase(Type t)
2252                    {
2253                        throw new RuntimeException JavaDoc("invalid type");
2254                    }
2255                });
2256            }
2257
2258            public void caseGeExpr(GeExpr v)
2259            {
2260                emitValue(v.getOp1());
2261                emitValue(v.getOp2());
2262
2263                v.getOp1().getType().apply(new TypeSwitch()
2264                {
2265                    public void caseDoubleType(DoubleType t)
2266                    {
2267                        emit("dcmpg", -3);
2268                        emitBooleanBranch("ifge");
2269                    }
2270
2271                    public void caseFloatType(FloatType t)
2272                    {
2273                        emit("fcmpg", -1);
2274                        emitBooleanBranch("ifge");
2275                    }
2276
2277                    private void handleIntCase()
2278                    {
2279                        emit("if_icmpge", -2);
2280                    }
2281
2282                    public void caseIntType(IntType t) { handleIntCase(); }
2283                    public void caseBooleanType(BooleanType t) { handleIntCase(); }
2284                    public void caseShortType(ShortType t) { handleIntCase(); }
2285                    public void caseCharType(CharType t) { handleIntCase(); }
2286                    public void caseByteType(ByteType t) { handleIntCase(); }
2287
2288                    public void caseLongType(LongType t)
2289                    {
2290                        emit("lcmp", -3);
2291                        emitBooleanBranch("ifge");
2292                    }
2293
2294                    public void defaultCase(Type t)
2295                    {
2296                        throw new RuntimeException JavaDoc("invalid type");
2297                    }
2298                });
2299            }
2300
2301            public void caseNeExpr(NeExpr v)
2302            {
2303                emitValue(v.getOp1());
2304                emitValue(v.getOp2());
2305
2306                v.getOp1().getType().apply(new TypeSwitch()
2307                {
2308                    public void caseDoubleType(DoubleType t)
2309                    {
2310                        emit("dcmpg", -3);
2311                        emit("iconst_0", 1);
2312                        emitBooleanBranch("if_icmpne");
2313                    }
2314
2315                    public void caseFloatType(FloatType t)
2316                    {
2317                        emit("fcmpg", -1);
2318                        emit("iconst_0", 1);
2319                        emitBooleanBranch("if_icmpne");
2320                    }
2321
2322                    private void handleIntCase()
2323                    {
2324                        emit("if_icmpne", -2);
2325                    }
2326
2327                    public void caseIntType(IntType t) { handleIntCase(); }
2328                    public void caseBooleanType(BooleanType t) { handleIntCase(); }
2329                    public void caseShortType(ShortType t) { handleIntCase(); }
2330                    public void caseCharType(CharType t) { handleIntCase(); }
2331                    public void caseByteType(ByteType t) { handleIntCase(); }
2332
2333                    public void caseLongType(LongType t)
2334                    {
2335                        emit("lcmp", -3);
2336                        emit("iconst_0", 1);
2337                        emitBooleanBranch("if_icmpne");
2338                    }
2339
2340                    public void caseArrayType(ArrayType t)
2341                    {
2342                        emitBooleanBranch("if_acmpne");
2343                    }
2344
2345                    public void caseRefType(RefType t)
2346                    {
2347                        emitBooleanBranch("if_acmpne");
2348                    }
2349
2350                    public void defaultCase(Type t)
2351                    {
2352                        throw new RuntimeException JavaDoc("invalid type");
2353                    }
2354                });
2355            }
2356
2357            public void caseEqExpr(EqExpr v)
2358            {
2359                emitValue(v.getOp1());
2360                emitValue(v.getOp2());
2361
2362                v.getOp1().getType().apply(new TypeSwitch()
2363                {
2364                    public void caseDoubleType(DoubleType t)
2365                    {
2366                        emit("dcmpg", -3);
2367                        emit("iconst_0", 1);
2368                        emitBooleanBranch("if_icmpeq");
2369                    }
2370
2371                    public void caseFloatType(FloatType t)
2372                    {
2373                        emit("fcmpg", -3);
2374                        emit("iconst_0", 1);
2375                        emitBooleanBranch("if_icmpeq");
2376                    }
2377
2378                    private void handleIntCase()
2379                    {
2380                        emit("if_icmpeq", -2);
2381                    }
2382
2383                    public void caseIntType(IntType t) { handleIntCase(); }
2384                    public void caseBooleanType(BooleanType t) { handleIntCase(); }
2385                    public void caseShortType(ShortType t) { handleIntCase(); }
2386                    public void caseCharType(CharType t) { handleIntCase(); }
2387                    public void caseByteType(ByteType t) { handleIntCase(); }
2388
2389                    public void caseLongType(LongType t)
2390                    {
2391                        emit("lcmp", -3);
2392                        emit("iconst_0", 1);
2393                        emitBooleanBranch("if_icmpeq");
2394                    }
2395
2396                    public void caseArrayType(ArrayType t)
2397                    {
2398                        emitBooleanBranch("if_acmpeq");
2399                    }
2400
2401                    public void casbeRefType(RefType t)
2402                    {
2403                        emitBooleanBranch("if_acmpeq");
2404                    }
2405
2406                    public void defaultCase(Type t)
2407                    {
2408                        throw new RuntimeException JavaDoc("invalid type");
2409                    }
2410                });
2411            }
2412
2413            public void caseNegExpr(final NegExpr v)
2414            {
2415                emitValue(v.getOp());
2416
2417                v.getType().apply(new TypeSwitch()
2418                {
2419                    private void handleIntCase()
2420                    {
2421                        emit("ineg", 0);
2422                    }
2423
2424                    public void caseIntType(IntType t) { handleIntCase(); }
2425                    public void caseBooleanType(BooleanType t) { handleIntCase(); }
2426                    public void caseShortType(ShortType t) { handleIntCase(); }
2427                    public void caseCharType(CharType t) { handleIntCase(); }
2428                    public void caseByteType(ByteType t) { handleIntCase(); }
2429
2430                    public void caseLongType(LongType t)
2431                    {
2432                        emit("lneg", 0);
2433                    }
2434
2435                    public void caseDoubleType(DoubleType t)
2436                    {
2437                        emit("dneg", 0);
2438                    }
2439
2440                    public void caseFloatType(FloatType t)
2441                    {
2442                        emit("fneg", 0);
2443                    }
2444
2445                    public void defaultCase(Type t)
2446                    {
2447                        throw new RuntimeException JavaDoc("Invalid argument type for neg: " + t + ": " + v);
2448                    }
2449                });
2450
2451            }
2452
2453            public void caseNewArrayExpr(NewArrayExpr v)
2454            {
2455                Value size = v.getSize();
2456
2457                emitValue(size);
2458
2459                if(v.getBaseType() instanceof RefType)
2460                    emit("anewarray " + slashify(v.getBaseType().toString()), 0);
2461                else if(v.getBaseType() instanceof ArrayType)
2462                    emit("anewarray " + jasminDescriptorOf(v.getBaseType()), 0);
2463                else
2464                    emit("newarray " + v.getBaseType().toString(), 0);
2465            }
2466
2467            public void caseNewMultiArrayExpr(NewMultiArrayExpr v)
2468            {
2469                List sizes = v.getSizes();
2470
2471                for(int i = 0; i < sizes.size(); i++)
2472                    emitValue((Value) sizes.get(i));
2473
2474                emit("multianewarray " + jasminDescriptorOf(v.getBaseType()) + " " + sizes.size(), -sizes.size() + 1);
2475            }
2476
2477            public void caseNewExpr(NewExpr v)
2478            {
2479                emit("new " + slashify(v.getBaseType().toString()), 1);
2480            }
2481
2482            public void caseNewInvokeExpr(NewInvokeExpr v)
2483            {
2484                emit("new " + slashify(v.getBaseType().toString()), 1);
2485                emit("dup", 1);
2486                
2487                SootMethodRef m = v.getMethodRef();
2488
2489                // emitValue(v.getBase());
2490
// already on the stack
2491

2492                for(int i = 0; i < m.parameterTypes().size(); i++)
2493                    emitValue(v.getArg(i));
2494
2495                emit("invokespecial " + slashify(m.declaringClass().getName()) + "/" +
2496                    m.name() + jasminDescriptorOf(m),
2497                    -(argCountOf(m) + 1) + sizeOfType(m.returnType()));
2498            }
2499
2500            public void caseNullConstant(NullConstant v)
2501            {
2502                emit("aconst_null", 1);
2503            }
2504
2505            public void caseOrExpr(OrExpr v)
2506            {
2507                emitValue(v.getOp1());
2508                emitValue(v.getOp2());
2509
2510                v.getType().apply(new TypeSwitch()
2511                {
2512                    private void handleIntCase()
2513                    {
2514                        emit("ior", -1);
2515                    }
2516
2517                    public void caseIntType(IntType t) { handleIntCase(); }
2518                    public void caseBooleanType(BooleanType t) { handleIntCase(); }
2519                    public void caseShortType(ShortType t) { handleIntCase(); }
2520                    public void caseCharType(CharType t) { handleIntCase(); }
2521                    public void caseByteType(ByteType t) { handleIntCase(); }
2522
2523                    public void caseLongType(LongType t)
2524                    {
2525                        emit("lor", -2);
2526                    }
2527
2528                    public void defaultCase(Type t)
2529                    {
2530                        throw new RuntimeException JavaDoc("Invalid argument type for or");
2531                    }
2532                });
2533            }
2534
2535            public void caseRemExpr(RemExpr v)
2536            {
2537                emitValue(v.getOp1());
2538                emitValue(v.getOp2());
2539
2540                v.getType().apply(new TypeSwitch()
2541                {
2542                    private void handleIntCase()
2543                    {
2544                        emit("irem", -1);
2545                    }
2546
2547                    public void caseIntType(IntType t) { handleIntCase(); }
2548                    public void caseBooleanType(BooleanType t) { handleIntCase(); }
2549                    public void caseShortType(ShortType t) { handleIntCase(); }
2550                    public void caseCharType(CharType t) { handleIntCase(); }
2551                    public void caseByteType(ByteType t) { handleIntCase(); }
2552
2553                    public void caseLongType(LongType t)
2554                    {
2555                        emit("lrem", -2);
2556                    }
2557
2558                    public void caseDoubleType(DoubleType t)
2559                    {
2560                        emit("drem", -2);
2561                    }
2562
2563                    public void caseFloatType(FloatType t)
2564                    {
2565                        emit("frem", -1);
2566                    }
2567
2568                    public void defaultCase(Type t)
2569                    {
2570                        throw new RuntimeException JavaDoc("Invalid argument type for rem");
2571                    }
2572                });
2573            }
2574
2575            public void caseShlExpr(ShlExpr v)
2576            {
2577                emitValue(v.getOp1());
2578                emitValue(v.getOp2());
2579
2580                v.getType().apply(new TypeSwitch()
2581                {
2582                    private void handleIntCase()
2583                    {
2584                        emit("ishl", -1);
2585                    }
2586
2587                    public void caseIntType(IntType t) { handleIntCase(); }
2588                    public void caseBooleanType(BooleanType t) { handleIntCase(); }
2589                    public void caseShortType(ShortType t) { handleIntCase(); }
2590                    public void caseCharType(CharType t) { handleIntCase(); }
2591                    public void caseByteType(ByteType t) { handleIntCase(); }
2592
2593                    public void caseLongType(LongType t)
2594                    {
2595                        emit("lshl", -1);
2596                    }
2597
2598                    public void defaultCase(Type t)
2599                    {
2600                        throw new RuntimeException JavaDoc("Invalid argument type for shl");
2601                    }
2602                });
2603            }
2604
2605            public void caseShrExpr(ShrExpr v)
2606            {
2607                emitValue(v.getOp1());
2608                emitValue(v.getOp2());
2609
2610                v.getType().apply(new TypeSwitch()
2611                {
2612                    private void handleIntCase()
2613                    {
2614                        emit("ishr", -1);
2615                    }
2616
2617                    public void caseIntType(IntType t) { handleIntCase(); }
2618                    public void caseBooleanType(BooleanType t) { handleIntCase(); }
2619                    public void caseShortType(ShortType t) { handleIntCase(); }
2620                    public void caseCharType(CharType t) { handleIntCase(); }
2621                    public void caseByteType(ByteType t) { handleIntCase(); }
2622
2623                    public void caseLongType(LongType t)
2624                    {
2625                        emit("lshr", -1);
2626                    }
2627
2628                    public void defaultCase(Type t)
2629                    {
2630                        throw new RuntimeException JavaDoc("Invalid argument type for shr");
2631                    }
2632                });
2633            }
2634
2635            public void caseSpecialInvokeExpr(SpecialInvokeExpr v)
2636            {
2637                SootMethodRef m = v.getMethodRef();
2638
2639                emitValue(v.getBase());
2640
2641                for(int i = 0; i < m.parameterTypes().size(); i++)
2642                    emitValue(v.getArg(i));
2643
2644                emit("invokespecial " + slashify(m.declaringClass().getName()) + "/" +
2645                    m.name() + jasminDescriptorOf(m),
2646                    -(argCountOf(m) + 1) + sizeOfType(m.returnType()));
2647            }
2648
2649            public void caseStaticInvokeExpr(StaticInvokeExpr v)
2650            {
2651                SootMethodRef m = v.getMethodRef();
2652
2653                for(int i = 0; i < m.parameterTypes().size(); i++)
2654                    emitValue(v.getArg(i));
2655
2656                emit("invokestatic " + slashify(m.declaringClass().getName()) + "/" +
2657                    m.name() + jasminDescriptorOf(m),
2658                    -(argCountOf(m)) + sizeOfType(m.returnType()));
2659            }
2660
2661            public void caseStaticFieldRef(StaticFieldRef v)
2662            {
2663                emit("getstatic " + slashify(v.getFieldRef().declaringClass().getName()) + "/" +
2664                    v.getFieldRef().name() + " " + jasminDescriptorOf(v.getFieldRef().type()),
2665                    sizeOfType(v.getFieldRef().type()));
2666            }
2667
2668            public void caseStringConstant(StringConstant v)
2669            {
2670                emit("ldc " + v.toString(), 1);
2671            }
2672
2673            public void caseClassConstant(ClassConstant v)
2674            {
2675                emit("ldc_w " + v.getValue(), 1);
2676            }
2677
2678            public void caseSubExpr(SubExpr v)
2679            {
2680                emitValue(v.getOp1());
2681                emitValue(v.getOp2());
2682
2683                v.getType().apply(new TypeSwitch()
2684                {
2685                    private void handleIntCase()
2686                    {
2687                        emit("isub", -1);
2688                    }
2689
2690                    public void caseIntType(IntType t) { handleIntCase(); }
2691                    public void caseBooleanType(BooleanType t) { handleIntCase(); }
2692                    public void caseShortType(ShortType t) { handleIntCase(); }
2693                    public void caseCharType(CharType t) { handleIntCase(); }
2694                    public void caseByteType(ByteType t) { handleIntCase(); }
2695
2696                    public void caseLongType(LongType t)
2697                    {
2698                        emit("lsub", -2);
2699                    }
2700
2701                    public void caseDoubleType(DoubleType t)
2702                    {
2703                        emit("dsub", -2);
2704                    }
2705
2706                    public void caseFloatType(FloatType t)
2707                    {
2708                        emit("fsub", -1);
2709                    }
2710
2711                    public void defaultCase(Type t)
2712                    {
2713                        throw new RuntimeException JavaDoc("Invalid argument type for sub");
2714                    }
2715                });
2716
2717            }
2718
2719            public void caseUshrExpr(UshrExpr v)
2720            {
2721                emitValue(v.getOp1());
2722                emitValue(v.getOp2());
2723
2724                v.getType().apply(new TypeSwitch()
2725                {
2726                    private void handleIntCase()
2727                    {
2728                        emit("iushr", -1);
2729                    }
2730
2731                    public void caseIntType(IntType t) { handleIntCase(); }
2732                    public void caseBooleanType(BooleanType t) { handleIntCase(); }
2733                    public void caseShortType(ShortType t) { handleIntCase(); }
2734                    public void caseCharType(CharType t) { handleIntCase(); }
2735                    public void caseByteType(ByteType t) { handleIntCase(); }
2736
2737                    public void caseLongType(LongType t)
2738                    {
2739                        emit("lushr", -1);
2740                    }
2741
2742                    public void defaultCase(Type t)
2743                    {
2744                        throw new RuntimeException JavaDoc("Invalid argument type for ushr");
2745                    }
2746                });
2747            }
2748
2749            public void caseVirtualInvokeExpr(VirtualInvokeExpr v)
2750            {
2751                SootMethodRef m = v.getMethodRef();
2752
2753                emitValue(v.getBase());
2754
2755                for(int i = 0; i < m.parameterTypes().size(); i++)
2756                    emitValue(v.getArg(i));
2757
2758                emit("invokevirtual " + slashify(m.declaringClass().getName()) + "/" +
2759                    m.name() + jasminDescriptorOf(m),
2760                    -(argCountOf(m) + 1) + sizeOfType(m.returnType()));
2761            }
2762
2763            public void caseXorExpr(XorExpr v)
2764            {
2765                emitValue(v.getOp1());
2766                emitValue(v.getOp2());
2767
2768                v.getType().apply(new TypeSwitch()
2769                {
2770                    private void handleIntCase()
2771                    {
2772                        emit ("ixor", -1);
2773                    }
2774
2775                    public void caseIntType(IntType t) { handleIntCase(); }
2776                    public void caseBooleanType(BooleanType t) { handleIntCase(); }
2777                    public void caseShortType(ShortType t) { handleIntCase(); }
2778                    public void caseCharType(CharType t) { handleIntCase(); }
2779                    public void caseByteType(ByteType t) { handleIntCase(); }
2780
2781                    public void caseLongType(LongType t)
2782                    {
2783                        emit("lxor", -2);
2784                    }
2785
2786                    public void defaultCase(Type t)
2787                    {
2788                        throw new RuntimeException JavaDoc("Invalid argument type for xor");
2789                    }
2790                });
2791            }
2792        });
2793    }
2794
2795    public void emitBooleanBranch(String JavaDoc s)
2796    {
2797        int count;
2798        
2799        if(s.indexOf("icmp") != -1 || s.indexOf("acmp") != -1)
2800            count = -2;
2801        else
2802            count = -1;
2803            
2804        emit(s + " label" + labelCount, count);
2805        emit("iconst_0", 1);
2806        emit("goto label" + labelCount+1, 0);
2807        emit("label" + labelCount++ + ":");
2808        emit("iconst_1", 1);
2809        emit("label" + labelCount++ + ":");
2810    }
2811
2812}
2813
Popular Tags