KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jode > flow > CreateIfThenElseOperator


1 /* CreateIfThenElseOperator Copyright (C) 1998-2002 Jochen Hoenicke.
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU Lesser General Public License as published by
5  * the Free Software Foundation; either version 2, or (at your option)
6  * any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program; see the file COPYING.LESSER. If not, write to
15  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
16  *
17  * $Id: CreateIfThenElseOperator.java,v 4.17.2.1 2002/05/28 17:34:09 hoenicke Exp $
18  */

19
20 package jode.flow;
21 import jode.GlobalOptions;
22 import jode.type.Type;
23 import jode.expr.*;
24
25 import java.util.Enumeration JavaDoc;
26 import java.util.Vector JavaDoc;
27
28 public class CreateIfThenElseOperator {
29
30     /**
31      * This handles the body of createFunny. There are three cases:
32      *
33      * <pre>
34      * --------
35      * IF (c2)
36      * GOTO trueDest -> PUSH c2
37      * PUSH false
38      * --------
39      * PUSH bool -> PUSH bool
40      * --------
41      * if (c2)
42      * (handled recursively) -> PUSH (c2 ? expr1 : expr2)
43      * else
44      * (handled recursively)
45      * --------
46      * </pre>
47      */

48     private static boolean createFunnyHelper(FlowBlock trueDest,
49                                              FlowBlock falseDest,
50                                              StructuredBlock block) {
51
52         if (block instanceof InstructionBlock
53             && !((InstructionBlock)block).getInstruction().isVoid())
54             return true;
55         
56         if (block instanceof IfThenElseBlock) {
57             IfThenElseBlock ifBlock = (IfThenElseBlock) block;
58             Expression expr1, expr2;
59             if (ifBlock.elseBlock == null)
60                 return false;
61
62         /* Next is a non-shortcut "or": simplify both blocks! */
63             if (!createFunnyHelper(trueDest, falseDest, ifBlock.thenBlock)
64                 | !createFunnyHelper(trueDest, falseDest, ifBlock.elseBlock))
65                 return false;
66
67             if (GlobalOptions.verboseLevel > 0)
68                 GlobalOptions.err.print('?');
69
70             Expression iteo = new IfThenElseOperator(Type.tBoolean)
71         .addOperand(((InstructionBlock) ifBlock.elseBlock)
72                 .getInstruction())
73         .addOperand(((InstructionBlock) ifBlock.thenBlock)
74                 .getInstruction())
75         .addOperand(ifBlock.cond);
76             ((InstructionBlock)ifBlock.thenBlock).setInstruction(iteo);
77
78             ifBlock.thenBlock.moveDefinitions(ifBlock, null);
79             ifBlock.thenBlock.replace(ifBlock);
80             return true;
81         }
82
83         if (block instanceof SequentialBlock
84             && block.getSubBlocks()[0] instanceof ConditionalBlock
85             && block.getSubBlocks()[1] instanceof InstructionBlock) {
86
87             ConditionalBlock condBlock =
88                 (ConditionalBlock) block.getSubBlocks()[0];
89             InstructionBlock pushBlock =
90                 (InstructionBlock) block.getSubBlocks()[1];
91             
92             if (!(pushBlock.getInstruction() instanceof ConstOperator))
93                 return false;
94
95             ConstOperator constOp =
96                 (ConstOperator) pushBlock.getInstruction();
97
98             if (condBlock.trueBlock.jump.destination == trueDest
99                 && constOp.getValue().equals(new Integer JavaDoc(0))) {
100
101                 Expression cond = condBlock.getInstruction();
102                 condBlock.flowBlock.removeSuccessor(condBlock.trueBlock.jump);
103                 condBlock.trueBlock.removeJump();
104
105                 pushBlock.setInstruction(cond);
106                 pushBlock.moveDefinitions(block, null);
107                 pushBlock.replace(block);
108                 return true;
109             }
110         }
111         return false;
112     }
113
114     /**
115      * This handles the more complicated form of the ?-:-operator used
116      * in a conditional block. The simplest case is:
117      * <pre>
118      * if (cond)
119      * PUSH e1
120      * else {
121      * IF (c2)
122      * GOTO flow_2_
123      * PUSH false
124      * }
125      * -&gt;IF (stack_0 == 0)
126      * GOTO flow_1_
127      * GOTO flow_2_
128      * </pre>
129      * is transformed to
130      * <pre>
131      * push cond ? e1 : c2
132      * -&gt;IF (stack_0 == 0)
133      * GOTO flow_1_
134      * GOTO flow_2_
135      * </pre>
136      *
137      * The <code>-&gt;</code> points to the lastModified block. Note
138      * that both the if and the then part may contain this
139      * condition+push0-block. There may be even stack if-then-else-blocks
140      * for very complicated nested ?-:-Operators. <p>
141      *
142      * Also note that the produced code is suboptimal: The push-0 could
143      * sometimes be better replaced with a correct jump.
144      * @param flow The FlowBlock that is transformed
145      */

146     public static boolean createFunny(ConditionalBlock cb,
147                                       StructuredBlock last) {
148
149         if (cb.jump == null
150             || !(cb.getInstruction() instanceof CompareUnaryOperator)
151             || !(last.outer instanceof SequentialBlock)
152             || !(last.outer.getSubBlocks()[0] instanceof IfThenElseBlock))
153             return false;
154         
155         CompareUnaryOperator compare =
156             (CompareUnaryOperator) cb.getInstruction();
157
158         FlowBlock trueDestination;
159         FlowBlock falseDestination;
160         if (compare.getOperatorIndex() == compare.EQUALS_OP) {
161             trueDestination = cb.jump.destination;
162             falseDestination = cb.trueBlock.jump.destination;
163         } else if (compare.getOperatorIndex() == compare.NOTEQUALS_OP) {
164             falseDestination = cb.jump.destination;
165             trueDestination = cb.trueBlock.jump.destination;
166         } else
167             return false;
168
169         Expression[] e = new Expression[3];
170         IfThenElseBlock ifBlock;
171
172         SequentialBlock sequBlock = (SequentialBlock) last.outer;
173         return createFunnyHelper(trueDestination, falseDestination,
174                                  sequBlock.subBlocks[0]);
175     }
176
177     /**
178      * This handles the normal form of the ?-:-operator:
179      * <pre>
180      * if (cond)
181      * push e1
182      * GOTO flow_1_
183      * -&gt;push e2
184      * GOTO flow_2
185      * </pre>
186      * is transformed to
187      * <pre>
188      * -&gt;push cond ? e1 : e2
189      * </pre>
190      * The <code>-&gt;</code> points to the lastModified block.
191      * @param flow The FlowBlock that is transformed
192      */

193     public static boolean create(InstructionContainer ic,
194                                  StructuredBlock last) {
195         Expression cond, thenExpr, elseExpr;
196         InstructionBlock thenBlock;
197         if (ic.jump == null
198             || !(last.outer instanceof SequentialBlock))
199             return false;
200         SequentialBlock sequBlock = (SequentialBlock)last.outer;
201         if (!(sequBlock.subBlocks[0] instanceof IfThenElseBlock))
202             return false;
203
204         IfThenElseBlock ifBlock = (IfThenElseBlock)sequBlock.subBlocks[0];
205         if (!(ifBlock.thenBlock instanceof InstructionBlock)
206             || ifBlock.thenBlock.jump == null
207             || ifBlock.thenBlock.jump.destination != ic.jump.destination
208             || ifBlock.elseBlock != null)
209             return false;
210         
211         thenBlock = (InstructionBlock) ifBlock.thenBlock;
212         
213         thenExpr = thenBlock.getInstruction();
214         if (thenExpr.isVoid() || thenExpr.getFreeOperandCount() > 0)
215             return false;
216         elseExpr = ic.getInstruction();
217         if (elseExpr.isVoid() || elseExpr.getFreeOperandCount() > 0)
218             return false;
219         cond = ifBlock.cond;
220         
221         if (GlobalOptions.verboseLevel > 0)
222             GlobalOptions.err.print('?');
223
224         thenBlock.flowBlock.removeSuccessor(thenBlock.jump);
225         thenBlock.removeJump();
226
227         IfThenElseOperator iteo = new IfThenElseOperator
228             (Type.tSuperType(thenExpr.getType())
229              .intersection(Type.tSuperType(elseExpr.getType())));
230     iteo.addOperand(elseExpr);
231     iteo.addOperand(thenExpr);
232     iteo.addOperand(cond);
233         ic.setInstruction(iteo);
234         ic.moveDefinitions(last.outer, last);
235         last.replace(last.outer);
236         return true;
237     }
238 }
239
Popular Tags