KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jbet > SimpleCodeGen


1 /*
2  * JBET - Java Binary Enhancement Tool
3  * Copyright (c) 2003 Networks Associates Technology, Inc.
4  *
5  * This software was developed under DARPA/SPAWAR contract
6  * N66001-00-C-8602 "SPMA" as part of the
7  * DARPA OASIS research program.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */

30
31 /**
32  * This class generates bytecode from a DAG. It is quite inefficient,
33  * especially concerning register allocation.
34  */

35
36 package jbet;
37 import java.util.*;
38 import java.lang.reflect.*;
39
40
41 public class SimpleCodeGen implements CodeGenerator {
42
43     public Snippit codegen (DagSnippit dags) {
44     LocalAccess locals = new JvmLocals();
45     InstrBlock[] outbbs = (InstrBlock[]) codegen (dags, locals, InstrBlock.class);
46     MethodInfo mi = new MethodInfo();
47     Snippit code = new Snippit();
48     Instruction ins;
49
50     for (int i = 0; i < dags.params.length; i++) {
51         if (dags.params[i] == null) continue;
52         code.push( new Instruction().setLoad(dags.params[i].type(), i) );
53         dags.params[i].storeDests(code, locals, -1, false);
54     }
55         
56     // pointers to start of output code for each block
57
Instruction[] outheads = new Instruction [outbbs.length];
58
59     // list of jump targets to fix later
60
Vector fixjumps = new Vector();
61
62     // list of switch instructions to fix later
63
Vector fixswitches = new Vector();
64
65     for (int i = 0; i < outbbs.length; i++) {
66         InstrBlock sb = outbbs[i];
67
68         if ((sb.blflags & Block.Blc_disabled) != 0)
69         continue;
70
71         if (sb.code.head == null) {
72         ins = new Instruction().setNop();
73         code.push (ins);
74         outheads[i] = ins;
75         } else {
76         outheads[i] = sb.code.head;
77         code.append (sb.code);
78         }
79
80         switch (sb.es.op) {
81         case 0:
82         if (i==outbbs.length-1 || sb.es.primary != outbbs[i+1]) {
83             ins = new Instruction();
84             ins.setGoto (sb.es.primary);
85             code.push (ins);
86             fixjumps.addElement (ins);
87         }
88         break;
89
90         case Instruction.OP_JSR:
91         ins = new Instruction();
92         ins.setNop();
93         ins.setOpCode (sb.es.op);
94         ins.setBranchTarget (sb.es.primary);
95         code.push (ins);
96         fixjumps.addElement (ins);
97
98         if (i+1 >= outbbs.length || sb.es.ret != outbbs[i+1]) {
99             ins = new Instruction();
100             ins.setNop();
101             ins.setOpCode (Instruction.OP_GOTO);
102             ins.setBranchTarget (sb.es.ret);
103             code.push(ins);
104             fixjumps.addElement(ins);
105         }
106         break;
107
108
109         case Instruction.OP_RET:
110         ins = new Instruction();
111         ins.setRet (sb.es.retlvt);
112         //ins.setBranchTarget (sb.es.primary);
113
code.push (ins);
114         break;
115
116         case Instruction.OP_TABLESWITCH:
117         case Instruction.OP_LOOKUPSWITCH:
118         ins = new Instruction();
119         ins.setNop();
120
121         ins.setOpCode (sb.es.op);
122         ins.setImmediate (sb.es.swofs);
123         ins.setSwitchArray (sb.es.switches);
124         ins.setBranchTarget (sb.es.primary);
125
126         fixswitches.addElement (ins);
127         code.push (ins);
128         break;
129
130         case Instruction.OP_IFNULL:
131         case Instruction.OP_IFNONNULL:
132         case Instruction.OP_IFEQ:
133         case Instruction.OP_IFNE:
134         case Instruction.OP_IFLE:
135         case Instruction.OP_IFLT:
136         case Instruction.OP_IFGT:
137         case Instruction.OP_IFGE:
138         case Instruction.OP_IF_ACMPEQ:
139         case Instruction.OP_IF_ACMPNE:
140         case Instruction.OP_IF_ICMPEQ:
141         case Instruction.OP_IF_ICMPNE:
142         case Instruction.OP_IF_ICMPLE:
143         case Instruction.OP_IF_ICMPLT:
144         case Instruction.OP_IF_ICMPGT:
145         case Instruction.OP_IF_ICMPGE:
146         ins = new Instruction();
147         ins.setNop();
148         ins.setOpCode (sb.es.op);
149         ins.setBranchTarget (sb.es.jump);
150         code.push (ins);
151         fixjumps.addElement (ins);
152
153         if (i+1 >= outbbs.length || sb.es.primary != outbbs[i+1]) {
154             ins = new Instruction();
155             ins.setNop();
156             ins.setOpCode (Instruction.OP_GOTO);
157             ins.setBranchTarget (sb.es.primary);
158             code.push(ins);
159             fixjumps.addElement(ins);
160         }
161         break;
162
163         default:
164         ins = new Instruction();
165         ins.setNop();
166         ins.setOpCode (sb.es.op);
167
168         code.push (ins);
169         break;
170         }
171     }
172
173     /* Fix forward jump targets */
174     for (int i = 0; i < fixjumps.size(); i++) {
175         ins = (Instruction) fixjumps.elementAt(i);
176         if (ins.usesBranch())
177         ins.setBranchTarget
178             (outheads[ ins.branchTarget().block.swval - 1]);
179     }
180
181     /* Fix switch instructions */
182     for (int i = 0; i < fixswitches.size(); i++) {
183         ins = (Instruction) fixswitches.elementAt(i);
184
185         if (ins.branchTarget() != null) {
186         ins.setBranchTarget (outheads[ ins.branchTarget().block.swval - 1]);
187         }
188
189         BranchTarget[] switches = ins.switchArray();
190
191         for (int j = 0; j < switches.length; j++) {
192         switches[j].instr = outheads[switches[j].block.swval-1];
193         }
194     }
195
196     /* set exception ranges */
197     for (int i = 0; i < outbbs.length; i++) {
198         InstrBlock sb = outbbs[i];
199
200         if (sb.es.exceptions != null) {
201         for (int j = 0; j < sb.es.exceptions.size(); j++) {
202             ExceptionRec er = new ExceptionRec();
203             Block.ExcInfo ei = sb.es.exAt (j);
204
205             er.start = new BranchTarget (outheads[i]);
206             if (i+1 == outbbs.length)
207             er.end = new BranchTarget (code.last());
208             else
209             er.end = new BranchTarget (outheads[i+1].prev);
210             er.handler = new BranchTarget (outheads[ei.handler.swval-1]);
211             er.catchType = ei.type.equals ("java/lang/Throwable") ?
212             null : ei.type;
213
214             code.exVector.addElement (er);
215         }
216         }
217     }
218
219     return code;
220     }
221
222     public class StackAccess {
223     BasicBlock sb;
224     Snippit code;
225     Vector st;
226     LocalAccess locals;
227     int[] tmps;
228
229     protected StackAccess (BasicBlock s, Snippit c, LocalAccess l) {
230         code = c;
231         sb = s;
232         st = new Vector();
233         locals = l;
234     }
235
236     public Node at (int j) {
237         return (Node) (st.elementAt (j));
238     }
239
240     public Node pop() {
241         Node n = (Node) st.elementAt (st.size()-1);
242         st.removeElementAt (st.size()-1);
243         return n;
244     }
245
246     // called after storeDests with leaveonstack set
247
public void push (Node n) {
248         //code.comment ("push " + n);
249
st.addElement (n);
250     }
251
252     // remove nodes from stack when they get used
253
private void checkDUs (Node u) {
254         for (int j = u.numParams()-1; j >= 0; j--) {
255         Node n = pop();
256         if (!u.usesAt (j).type().equals (n.type()))
257             throw new IllegalStateException JavaDoc ("top of stack is wrong type (was " + n.type() + " should be " + u.usesAt(j).type() +
258                              ") in emitting " + u + " #B" + sb.swval);
259         }
260     }
261
262     // save stack to temporary locals, before a goto
263
public void saveStack () {
264         if (tmps != null)
265         throw new IllegalStateException JavaDoc ("didn't load stack after saving");
266
267         tmps = new int[st.size()];
268         for (int j = st.size() - 1; j >= 0; j--) {
269         tmps[j] = locals.alloc (at (j).type());
270         code.comment ("savestack " + j);
271         locals.storeStack (code, tmps[j], at(j).type());
272         }
273     }
274
275     // restore the stack after a label
276
public void loadStack () {
277         if (tmps == null)
278         throw new IllegalStateException JavaDoc ("no saved stack to restore");
279         
280         for (int j = 0; j < tmps.length; j++) {
281         code.comment ("loadstack " + j);
282         locals.load (code, tmps[j], at(j).type());
283         }
284
285         tmps = null;
286     }
287     };
288
289     protected Block[] newBlocks (int n) { return new InstrBlock [n]; }
290
291     protected boolean handleNode (Node n, Block b, LocalAccess locals, StackAccess stack) { return false; }
292
293     /* Translate value dags to JVM instructions
294        @param dags Basic blocks stored as value dags
295        @param outt Type to use for the return value
296        @return Basic blocks with JVM instructions
297     */

298
299     /* A preliminary phase. Generate code for each basic block in the method */
300
301     public Block[] codegen (final DagSnippit dags, final LocalAccess locals, Class JavaDoc stackacct)
302     {
303     Block[] out = newBlocks (dags.bbs.size());
304
305     /* allocate jvm locals for method arguments (including
306        this for virtual methods) */

307     if (dags.method.isVirtual())
308         locals.alloc (0, new Type (dags.method.cr.name(), 0));
309     for (int i = 0; i < dags.method.descriptor.args.length; i++)
310         locals.alloc (1 + i, dags.method.descriptor.args[i]);
311
312
313     /* allocate jvm locals for each input node */
314     for (int i = 0; i < dags.bbs.size(); i++) {
315         BasicBlock sb = (BasicBlock) (dags.bbs.elementAt (i));
316         for (int j = 0; j < sb.inputs.length; j++) {
317         Node.var bas = (Node.var) sb.inputs[j];
318         bas.outlvt = locals.alloc(bas);
319         }
320     }
321
322     for (int i = 0; i < dags.bbs.size(); i++) {
323         final BasicBlock sb = (BasicBlock) (dags.bbs.elementAt (i));
324         Block ob;
325
326         if (sb.es.op == Instruction.AOP_LABEL)
327         continue;
328
329         try {
330         ob = (Block) out.getClass().getComponentType().newInstance();
331         out[i] = ob;
332         } catch (Exception JavaDoc e) { throw new IllegalStateException JavaDoc
333         ("unable to create output block: " + e.toString()); }
334
335         ob.swval = sb.swval;
336         ob.blflags = sb.blflags;
337
338         out[i] = ob;
339         
340         final Snippit code;
341         Vector labels = null;
342         if (ob instanceof InstrBlock) {
343         ((InstrBlock)ob).handler = sb.handler;
344         code = ((InstrBlock) ob).code;
345         } else
346         code = null;
347
348         StackAccess stack = new StackAccess (sb, code, locals);
349
350         code.comment(" BLOCK #" + sb.swval + (sb.bname != null ? " " + sb.bname : ""));
351         code.comment("");
352
353         /* If this block is an exception handler, we need to store the
354            exception object since the JVM leaves it on the stack */

355         if (sb.handler != null) {
356         int j;
357         for (j = 0; j < sb.inputs.length; j++)
358             if (sb.inputs[j] instanceof Node.var) {
359             Node.var var = (Node.var) sb.inputs[j];
360             if (var.v == -1 && var.exobject) {
361                 locals.store (code, var.outlvt, var.type());
362                 break;
363             }
364             }
365         if (j == sb.inputs.length)
366             code.push( new Instruction().setPop() );
367         }
368
369
370         if ((sb.enflags & Block.En_jsr) != 0) {
371         int maxv = 1;
372         Node.var retaddr = null;
373         for (int j = 0; j < sb.inputs.length; j++)
374             if (sb.inputs[j] instanceof Node.var) {
375             if (((Node.var)sb.inputs[j]).v < maxv) {
376                 maxv = ((Node.var)sb.inputs[j]).v;
377                 retaddr = (Node.var) sb.inputs[j];
378             }
379             }
380         locals.store (code, retaddr.outlvt, retaddr.type());
381         }
382
383
384         Node[] nodes = sb.order();
385
386         sb.doRefCount(); //this needs to come after order
387
for (int j = 0; j < nodes.length; j++)
388         nodes[j].count = 0;
389         for (int j = 0; j < nodes.length; j++) {
390         for (int k = 0; k < nodes[j].numParams(); k++) {
391             Node p = (Node) nodes[j].requires.elementAt(k);
392             p.count++;
393         }
394         }
395
396         for (int j = 0; j < nodes.length; j++) {
397         if (nodes[j] instanceof Node.LoadMarker) {
398             Node param = ((Node.LoadMarker)nodes[j]).n;
399             locals.load (code, param.clocal, param.type());
400             stack.push (param);
401             continue;
402         }
403         if (nodes[j] instanceof Node.DupMarker) {
404             code.push( new Instruction().setDup() );
405             continue;
406         }
407         
408         if (nodes[j].destinations == null)
409             code.comment("node " + nodes[j]);
410         else
411             code.comment("node " + nodes[j].destinationString() + " = " +
412                  nodes[j]);
413
414         if (handleNode (nodes[j], ob, locals, stack))
415             continue;
416         
417         if (nodes[j] instanceof Node.var) {
418             if (!nodes[j].hasIndirectUsers && nodes[j].countDests(-1, nodes[j].hasDirectUsers) == 0)
419             continue;
420             locals.load (code, ((Node.var)nodes[j]).outlvt, nodes[j].type());
421         } else if (nodes[j] instanceof Node.param)
422             locals.load (code, ((Node.param)nodes[j]).v, nodes[j].type());
423         else
424             nodes[j].codegen1 (code);
425
426         stack.checkDUs (nodes[j]);
427
428         if (nodes[j].type().equals (Type.VOID)) continue;
429
430         nodes[j].clocal = locals.alloc (nodes[j].type());
431         if (nodes[j].hasIndirectUsers)
432             nodes[j].storeDests(code, locals, nodes[j].clocal,
433                     nodes[j].hasDirectUsers);
434         else
435             nodes[j].storeDests(code, locals, -1, nodes[j].hasDirectUsers);
436
437         if (nodes[j].hasDirectUsers)
438             stack.push (nodes[j]);
439         }
440     }
441
442     for (int i = 0; i < out.length; i++) {
443         BasicBlock sb = (BasicBlock) dags.bbs.elementAt (i);
444         
445         if (sb.es.op == Instruction.AOP_LABEL)
446         continue;
447
448         out[i].es.op = sb.es.op;
449         out[i].es.primary = sb.es.primary != null ?
450         out[sb.es.primary.swval-1] : null;
451         out[i].es.jump = sb.es.jump != null ? out[sb.es.jump.swval-1] : null;
452         out[i].es.ret = sb.es.ret != null ? out[sb.es.ret.swval-1] : null;
453         out[i].es.exflags = sb.es.exflags;
454
455         if (sb.es.op == Instruction.OP_RET)
456         if (sb.esnodes[0] instanceof Node.var)
457             out[i].es.retlvt = ((Node.var)sb.esnodes[0]).outlvt;
458         else
459             throw new IllegalStateException JavaDoc
460             ("non-var retnode " + sb.es.retnode);
461         
462         if (sb.es.switches != null) {
463         BranchTarget[] switches = new BranchTarget[sb.es.switches.length];
464         out[i].es.switches = switches;
465         out[i].es.swofs = sb.es.swofs;
466
467         for (int j = 0; j < switches.length; j++)
468             if (sb.es.switches[j] != null) {
469             switches[j] = new BranchTarget();
470             switches[j].key = sb.es.switches[j].key;
471             switches[j].block = out[sb.es.switches[j].block.swval-1];
472             }
473         }
474
475         if (sb.es.exceptions != null) {
476         out[i].es.exceptions = new Vector();
477
478         for (int j = 0; j < sb.es.exceptions.size(); j++) {
479             Block.ExcInfo eo = sb.es.exAt (j);
480             Block.ExcInfo er = new Block.ExcInfo();
481
482             er.handler = out[eo.handler.swval-1];
483             er.type = eo.type;
484             er.info = eo.info;
485
486             out[i].es.exceptions.addElement (er);
487         }
488         }
489     }
490
491     if (out[0] instanceof SwitchBlock)
492         for (int i = 0; i < out.length; i++) if (out[i] != null) {
493         SwitchBlock sb = (SwitchBlock) out[i];
494         for (int j = 0; j < sb.labels.size(); j++) {
495             Node.Label n = (Node.Label) sb.labels.elementAt (j);
496
497             if (n.ip.next == null) {
498             n.ip.next = new Instruction().setNop();
499             n.ip.next.prev = n.ip;
500             }
501
502             n.ip = n.ip.next;
503             if (n.ip == null)
504             throw new IllegalStateException JavaDoc ("a label points to the end of the code");
505         }
506         }
507
508     return out;
509     }
510
511 }
512
Popular Tags