1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.bcel.util;
19
20 import java.io.PrintWriter;
21 import java.util.ArrayList;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Locale;
25 import java.util.Map;
26
27 import org.apache.bcel.Constants;
28 import org.apache.bcel.classfile.Utility;
29 import org.apache.bcel.generic.AllocationInstruction;
30 import org.apache.bcel.generic.ArrayInstruction;
31 import org.apache.bcel.generic.ArrayType;
32 import org.apache.bcel.generic.BranchHandle;
33 import org.apache.bcel.generic.BranchInstruction;
34 import org.apache.bcel.generic.CHECKCAST;
35 import org.apache.bcel.generic.CPInstruction;
36 import org.apache.bcel.generic.CodeExceptionGen;
37 import org.apache.bcel.generic.ConstantPoolGen;
38 import org.apache.bcel.generic.ConstantPushInstruction;
39 import org.apache.bcel.generic.EmptyVisitor;
40 import org.apache.bcel.generic.FieldInstruction;
41 import org.apache.bcel.generic.IINC;
42 import org.apache.bcel.generic.INSTANCEOF;
43 import org.apache.bcel.generic.Instruction;
44 import org.apache.bcel.generic.InstructionConstants;
45 import org.apache.bcel.generic.InstructionHandle;
46 import org.apache.bcel.generic.InvokeInstruction;
47 import org.apache.bcel.generic.LDC;
48 import org.apache.bcel.generic.LDC2_W;
49 import org.apache.bcel.generic.LocalVariableInstruction;
50 import org.apache.bcel.generic.MULTIANEWARRAY;
51 import org.apache.bcel.generic.MethodGen;
52 import org.apache.bcel.generic.NEWARRAY;
53 import org.apache.bcel.generic.ObjectType;
54 import org.apache.bcel.generic.RET;
55 import org.apache.bcel.generic.ReturnInstruction;
56 import org.apache.bcel.generic.Select;
57 import org.apache.bcel.generic.Type;
58
59
60
61
62
63
64
65
66
67 class BCELFactory extends EmptyVisitor {
68
69 private final MethodGen _mg;
70 private final PrintWriter _out;
71 private final ConstantPoolGen _cp;
72
73
74 BCELFactory(MethodGen mg, PrintWriter out) {
75 _mg = mg;
76 _cp = mg.getConstantPool();
77 _out = out;
78 }
79
80 private final Map<Instruction, InstructionHandle> branch_map = new HashMap<Instruction, InstructionHandle>();
81
82
83 public void start() {
84 if (!_mg.isAbstract() && !_mg.isNative()) {
85 for (InstructionHandle ih = _mg.getInstructionList().getStart(); ih != null; ih = ih
86 .getNext()) {
87 Instruction i = ih.getInstruction();
88 if (i instanceof BranchInstruction) {
89 branch_map.put(i, ih);
90 }
91 if (ih.hasTargeters()) {
92 if (i instanceof BranchInstruction) {
93 _out.println(" InstructionHandle ih_" + ih.getPosition() + ";");
94 } else {
95 _out.print(" InstructionHandle ih_" + ih.getPosition() + " = ");
96 }
97 } else {
98 _out.print(" ");
99 }
100 if (!visitInstruction(i)) {
101 i.accept(this);
102 }
103 }
104 updateBranchTargets();
105 updateExceptionHandlers();
106 }
107 }
108
109
110 private boolean visitInstruction( Instruction i ) {
111 short opcode = i.getOpcode();
112 if ((InstructionConstants.INSTRUCTIONS[opcode] != null)
113 && !(i instanceof ConstantPushInstruction) && !(i instanceof ReturnInstruction)) {
114 _out.println("il.append(InstructionConstants."
115 + i.getName().toUpperCase(Locale.ENGLISH) + ");");
116 return true;
117 }
118 return false;
119 }
120
121
122 @Override
123 public void visitLocalVariableInstruction( LocalVariableInstruction i ) {
124 short opcode = i.getOpcode();
125 Type type = i.getType(_cp);
126 if (opcode == Constants.IINC) {
127 _out.println("il.append(new IINC(" + i.getIndex() + ", " + ((IINC) i).getIncrement()
128 + "));");
129 } else {
130 String kind = (opcode < Constants.ISTORE) ? "Load" : "Store";
131 _out.println("il.append(_factory.create" + kind + "(" + BCELifier.printType(type)
132 + ", " + i.getIndex() + "));");
133 }
134 }
135
136
137 @Override
138 public void visitArrayInstruction( ArrayInstruction i ) {
139 short opcode = i.getOpcode();
140 Type type = i.getType(_cp);
141 String kind = (opcode < Constants.IASTORE) ? "Load" : "Store";
142 _out.println("il.append(_factory.createArray" + kind + "(" + BCELifier.printType(type)
143 + "));");
144 }
145
146
147 @Override
148 public void visitFieldInstruction( FieldInstruction i ) {
149 short opcode = i.getOpcode();
150 String class_name = i.getClassName(_cp);
151 String field_name = i.getFieldName(_cp);
152 Type type = i.getFieldType(_cp);
153 _out.println("il.append(_factory.createFieldAccess(\"" + class_name + "\", \"" + field_name
154 + "\", " + BCELifier.printType(type) + ", " + "Constants."
155 + Constants.OPCODE_NAMES[opcode].toUpperCase(Locale.ENGLISH) + "));");
156 }
157
158
159 @Override
160 public void visitInvokeInstruction( InvokeInstruction i ) {
161 short opcode = i.getOpcode();
162 String class_name = i.getClassName(_cp);
163 String method_name = i.getMethodName(_cp);
164 Type type = i.getReturnType(_cp);
165 Type[] arg_types = i.getArgumentTypes(_cp);
166 _out.println("il.append(_factory.createInvoke(\"" + class_name + "\", \"" + method_name
167 + "\", " + BCELifier.printType(type) + ", "
168 + BCELifier.printArgumentTypes(arg_types) + ", " + "Constants."
169 + Constants.OPCODE_NAMES[opcode].toUpperCase(Locale.ENGLISH) + "));");
170 }
171
172
173 @Override
174 public void visitAllocationInstruction( AllocationInstruction i ) {
175 Type type;
176 if (i instanceof CPInstruction) {
177 type = ((CPInstruction) i).getType(_cp);
178 } else {
179 type = ((NEWARRAY) i).getType();
180 }
181 short opcode = ((Instruction) i).getOpcode();
182 int dim = 1;
183 switch (opcode) {
184 case Constants.NEW:
185 _out.println("il.append(_factory.createNew(\"" + ((ObjectType) type).getClassName()
186 + "\"));");
187 break;
188 case Constants.MULTIANEWARRAY:
189 dim = ((MULTIANEWARRAY) i).getDimensions();
190
191 case Constants.ANEWARRAY:
192 case Constants.NEWARRAY:
193 if (type instanceof ArrayType) {
194 type = ((ArrayType) type).getBasicType();
195 }
196 _out.println("il.append(_factory.createNewArray(" + BCELifier.printType(type)
197 + ", (short) " + dim + "));");
198 break;
199 default:
200 throw new RuntimeException("Oops: " + opcode);
201 }
202 }
203
204
205 private void createConstant( Object value ) {
206 String embed = value.toString();
207 if (value instanceof String) {
208 embed = '"' + Utility.convertString(embed) + '"';
209 } else if (value instanceof Character) {
210 embed = "(char)0x" + Integer.toHexString(((Character) value).charValue());
211 } else if (value instanceof Float) {
212 embed += "f";
213 } else if (value instanceof Long) {
214 embed += "L";
215 } else if (value instanceof ObjectType){
216 ObjectType ot = (ObjectType) value;
217 embed = "new ObjectType(\""+ot.getClassName()+"\")";
218 }
219
220 _out.println("il.append(new PUSH(_cp, " + embed + "));");
221 }
222
223
224 @Override
225 public void visitLDC( LDC i ) {
226 createConstant(i.getValue(_cp));
227 }
228
229
230 @Override
231 public void visitLDC2_W( LDC2_W i ) {
232 createConstant(i.getValue(_cp));
233 }
234
235
236 @Override
237 public void visitConstantPushInstruction( ConstantPushInstruction i ) {
238 createConstant(i.getValue());
239 }
240
241
242 @Override
243 public void visitINSTANCEOF( INSTANCEOF i ) {
244 Type type = i.getType(_cp);
245 _out.println("il.append(new INSTANCEOF(_cp.addClass(" + BCELifier.printType(type) + ")));");
246 }
247
248
249 @Override
250 public void visitCHECKCAST( CHECKCAST i ) {
251 Type type = i.getType(_cp);
252 _out.println("il.append(_factory.createCheckCast(" + BCELifier.printType(type) + "));");
253 }
254
255
256 @Override
257 public void visitReturnInstruction( ReturnInstruction i ) {
258 Type type = i.getType(_cp);
259 _out.println("il.append(_factory.createReturn(" + BCELifier.printType(type) + "));");
260 }
261
262
263 private final List<BranchInstruction> branches = new ArrayList<BranchInstruction>();
264
265
266 @Override
267 public void visitBranchInstruction( BranchInstruction bi ) {
268 BranchHandle bh = (BranchHandle) branch_map.get(bi);
269 int pos = bh.getPosition();
270 String name = bi.getName() + "_" + pos;
271 if (bi instanceof Select) {
272 Select s = (Select) bi;
273 branches.add(bi);
274 StringBuffer args = new StringBuffer("new int[] { ");
275 int[] matchs = s.getMatchs();
276 for (int i = 0; i < matchs.length; i++) {
277 args.append(matchs[i]);
278 if (i < matchs.length - 1) {
279 args.append(", ");
280 }
281 }
282 args.append(" }");
283 _out.print("Select " + name + " = new " + bi.getName().toUpperCase(Locale.ENGLISH)
284 + "(" + args + ", new InstructionHandle[] { ");
285 for (int i = 0; i < matchs.length; i++) {
286 _out.print("null");
287 if (i < matchs.length - 1) {
288 _out.print(", ");
289 }
290 }
291 _out.println(" }, null);");
292 } else {
293 int t_pos = bh.getTarget().getPosition();
294 String target;
295 if (pos > t_pos) {
296 target = "ih_" + t_pos;
297 } else {
298 branches.add(bi);
299 target = "null";
300 }
301 _out.println(" BranchInstruction " + name + " = _factory.createBranchInstruction("
302 + "Constants." + bi.getName().toUpperCase(Locale.ENGLISH) + ", " + target
303 + ");");
304 }
305 if (bh.hasTargeters()) {
306 _out.println(" ih_" + pos + " = il.append(" + name + ");");
307 } else {
308 _out.println(" il.append(" + name + ");");
309 }
310 }
311
312
313 @Override
314 public void visitRET( RET i ) {
315 _out.println("il.append(new RET(" + i.getIndex() + ")));");
316 }
317
318
319 private void updateBranchTargets() {
320 for (BranchInstruction bi : branches) {
321 BranchHandle bh = (BranchHandle) branch_map.get(bi);
322 int pos = bh.getPosition();
323 String name = bi.getName() + "_" + pos;
324 int t_pos = bh.getTarget().getPosition();
325 _out.println(" " + name + ".setTarget(ih_" + t_pos + ");");
326 if (bi instanceof Select) {
327 InstructionHandle[] ihs = ((Select) bi).getTargets();
328 for (int j = 0; j < ihs.length; j++) {
329 t_pos = ihs[j].getPosition();
330 _out.println(" " + name + ".setTarget(" + j + ", ih_" + t_pos + ");");
331 }
332 }
333 }
334 }
335
336
337 private void updateExceptionHandlers() {
338 CodeExceptionGen[] handlers = _mg.getExceptionHandlers();
339 for (int i = 0; i < handlers.length; i++) {
340 CodeExceptionGen h = handlers[i];
341 String type = (h.getCatchType() == null) ? "null" : BCELifier.printType(h
342 .getCatchType());
343 _out.println(" method.addExceptionHandler(" + "ih_" + h.getStartPC().getPosition()
344 + ", " + "ih_" + h.getEndPC().getPosition() + ", " + "ih_"
345 + h.getHandlerPC().getPosition() + ", " + type + ");");
346 }
347 }
348 }