History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/tools (38 of 18352 files). Show all

Unified · Split

38 files
  1. java/tools/genpkg/GenerateMkfile.class +0 −0
  2. java/tools/genpkg/GenerateMkfile.java +32 −0
  3. java/tools/j2d/asm.c +344 −0
  4. java/tools/j2d/bb.c +643 −0
  5. java/tools/j2d/datarloc.c +188 −0
  6. java/tools/j2d/desc.c +117 −0
  7. java/tools/j2d/dis.c +336 −0
  8. java/tools/j2d/entry.c +40 −0
  9. java/tools/j2d/finally.c +132 −0
  10. java/tools/j2d/frame.c +514 −0
  11. java/tools/j2d/java.h +452 −0
  12. java/tools/j2d/javadas.c +596 −0
  13. java/tools/j2d/javaisa.h +221 −0
  14. java/tools/j2d/javatbl.c +232 −0
  15. java/tools/j2d/links.c +172 −0
  16. java/tools/j2d/loader.c +673 −0
  17. java/tools/j2d/ltreloc.c +404 −0
  18. java/tools/j2d/main.c +196 −0
  19. java/tools/j2d/mdata.c +513 −0
  20. java/tools/j2d/mkfile +45 −0
  21. java/tools/j2d/module.c +21 −0
  22. java/tools/j2d/patch.c +132 −0
  23. java/tools/j2d/reloc.h +123 −0
  24. java/tools/j2d/rtreloc.c +409 −0
  25. java/tools/j2d/sbl.c +46 −0
  26. java/tools/j2d/simjvm.c +1509 −0
  27. java/tools/j2d/unify.c +106 −0
  28. java/tools/j2d/util.c +372 −0
  29. java/tools/j2d/xlate.c +3094 −0
  30. java/tools/javal/FileMerge.class +0 −0
  31. java/tools/javal/FileMerge.java +108 −0
  32. java/tools/javal/LimboGen.class +0 −0
  33. java/tools/javal/LimboGen.java +677 −0
  34. java/tools/javal/TargetLoader.class +0 −0
  35. java/tools/javal/javal.class +0 −0
  36. java/tools/javal/javal.java +244 −0
  37. java/tools/javal/mkfile +21 −0
  38. java/tools/mkfile +7 −0
java/tools/genpkg/GenerateMkfile.class+0−0

Binary file not shown.

java/tools/genpkg/GenerateMkfile.java+32−0
@@ -0,0 +1,32 @@
1
2import java.io.*;
3
4public class GenerateMkfile {
5
6 public static void main(String[] args) {
7 if (args.length == 0) {
8 System.out.println("Generates or updates the mkfile for java");
9 System.out.println("package in inferno java subsystem.");
10 System.out.println();
11 System.out.println("Usage: specify the package dir");
12 return;
13 }
14
15 File dir = new File(args[0]);
16 if (!dir.exists() || !dir.isDirectory()) {
17 System.out.println("The path must be existing directory");
18 return;
19 }
20
21 StringBuilder result = new StringBuilder();
22 result.append("TARG=\\").append('\n');
23
24 File[] files = dir.listFiles();
25 for (File f: files) {
26 if (f.isFile() && f.getName().endsWith(".java"))
27 result.append('\t').append(f.getName()).append("\\\n");
28 }
29 }
30
31}
32
java/tools/j2d/asm.c+344−0
@@ -0,0 +1,344 @@
1#include "java.h"
2
3static char *instname[MAXDIS];
4
5/*
6 * %A format conversion.
7 */
8
9int
10Aconv(va_list *addr, Fconv *f)
11{
12 Addr *a;
13 char buf[512];
14
15 a = va_arg(*addr, Addr*);
16
17 switch(a->mode) {
18 case Anone:
19 sprint(buf, "none");
20 break;
21 case Aimm:
22 sprint(buf, "$%d", a->u.ival);
23 break;
24 case Afp:
25 sprint(buf, "%d(fp)", a->u.offset);
26 break;
27 case Amp:
28 sprint(buf, "%d(mp)", a->u.offset);
29 break;
30 case Afpind:
31 sprint(buf, "%d(%d(fp))", a->u.b.si, a->u.b.fi);
32 break;
33 case Ampind:
34 sprint(buf, "%d(%d(mp))", a->u.b.si, a->u.b.fi);
35 break;
36 }
37 strconv(buf, f);
38 return sizeof(Addr*);
39}
40
41/*
42 * %I format conversion.
43 */
44
45int
46Iconv(va_list *inst, Fconv *f)
47{
48 int n;
49 Inst *in;
50 char buf[512], *p;
51 char *op, *comma;
52
53 in = va_arg(*inst, Inst*);
54 if(in->op >= 0 && in->op < MAXDIS)
55 op = instname[in->op];
56 else
57 op = "??";
58 buf[0] = '\0';
59 n = sprint(buf, "\t%s\t", op);
60 p = buf+n;
61
62 comma = "";
63 if(in->s.mode != Anone) {
64 n = sprint(p, "%A", &in->s);
65 p += n;
66 comma = ",";
67 }
68 if(in->m.mode != Anone) {
69 n = sprint(p, "%s%A", comma, &in->m);
70 p += n;
71 comma = ",";
72 }
73 if(in->d.mode != Anone)
74 sprint(p, "%s%A", comma, &in->d);
75
76 strconv(buf, f);
77 return sizeof(Inst*);
78}
79
80static void
81ehtable(Code *c)
82{
83 int i;
84 char *s;
85 Handler *h;
86
87 if(c->nex == 0)
88 return;
89 Bprint(bout, "#\tException Table\n");
90 for(i = 0; i < c->nex; i++) {
91 h = c->ex[i];
92 if(h->catch_type == 0)
93 s = "*";
94 else
95 s = CLASSNAME(h->catch_type);
96 Bprint(bout, "#\t%d %d %d %s\n", h->start_pc, h->end_pc,
97 h->handler_pc, s);
98 }
99}
100
101static void
102putinst(Inst *i)
103{
104 while(i) {
105 if(i->pc % 10 == 0)
106 Bprint(bout, "#%d\n", i->pc);
107 Bprint(bout, "%I\n", i);
108 i = i->next;
109 }
110}
111
112Inst *clinitclone; /* generated <clinit>, <clone> methods */
113
114/*
115 * Emit assembly instructions for a method.
116 */
117
118void
119asminst(void)
120{
121 Inst *i;
122 Jinst *j, *je;
123 int n;
124
125 if(verbose == 0) {
126 putinst(ihead);
127 return;
128 }
129
130 /* -v option */
131
132 for(n = 0; n < class->methods_count; n++) {
133 Bprint(bout, "#Method: %s%s\n", pcode[n].name, pcode[n].sig);
134 if(pcode[n].code == nil)
135 continue;
136 ehtable(pcode[n].code);
137 j = &pcode[n].code->j[0];
138 je = j + pcode[n].code->code_length;
139 while(j < je) {
140 Bprint(bout, "#J%d\t%J\n", j->pc, j);
141 for(i = j->dis; i && i->j == j; i = i->next) {
142 if(i->pc % 10 == 0)
143 Bprint(bout, "#%d\n", i->pc);
144 Bprint(bout, "%I\n", i);
145 }
146 j += j->size;
147 }
148 }
149
150 if(clinitclone) {
151 Bprint(bout, "#Method: <clinit|clone>()V\n");
152 putinst(clinitclone);
153 }
154}
155
156void
157sblinst(Biobuf *bsym)
158{
159 Inst *i;
160 int curline, lastline, lastchar, blockid;
161
162 Bprint(bsym, "%d\n", itail ? itail->pc + 1 : 0);
163 curline = 1;
164 lastline = -1;
165 lastchar = 6;
166 blockid = -1;
167 for(i = ihead; i; i = i->next) {
168 if(i->j)
169 curline = i->j->line;
170 if(curline != lastline) {
171 lastline = curline;
172 lastchar = 6;
173 blockid++;
174 Bprint(bsym, "%d.", curline);
175 }
176 Bprint(bsym, "1,%d %d\n", lastchar++, blockid);
177 }
178}
179
180/*
181 * Dis opcode mnemonics. Keep in sync with interp/tab.h!
182 */
183
184static char *instname[MAXDIS] =
185{
186 "nop",
187 "alt",
188 "nbalt",
189 "goto",
190 "call",
191 "frame",
192 "spawn",
193 "runt",
194 "load",
195 "mcall",
196 "mspawn",
197 "mframe",
198 "ret",
199 "jmp",
200 "case",
201 "exit",
202 "new",
203 "newa",
204 "newcb",
205 "newcw",
206 "newcf",
207 "newcp",
208 "newcm",
209 "newcmp",
210 "send",
211 "recv",
212 "consb",
213 "consw",
214 "consp",
215 "consf",
216 "consm",
217 "consmp",
218 "headb",
219 "headw",
220 "headp",
221 "headf",
222 "headm",
223 "headmp",
224 "tail",
225 "lea",
226 "indx",
227 "movp",
228 "movm",
229 "movmp",
230 "movb",
231 "movw",
232 "movf",
233 "cvtbw",
234 "cvtwb",
235 "cvtfw",
236 "cvtwf",
237 "cvtca",
238 "cvtac",
239 "cvtwc",
240 "cvtcw",
241 "cvtfc",
242 "cvtcf",
243 "addb",
244 "addw",
245 "addf",
246 "subb",
247 "subw",
248 "subf",
249 "mulb",
250 "mulw",
251 "mulf",
252 "divb",
253 "divw",
254 "divf",
255 "modw",
256 "modb",
257 "andb",
258 "andw",
259 "orb",
260 "orw",
261 "xorb",
262 "xorw",
263 "shlb",
264 "shlw",
265 "shrb",
266 "shrw",
267 "insc",
268 "indc",
269 "addc",
270 "lenc",
271 "lena",
272 "lenl",
273 "beqb",
274 "bneb",
275 "bltb",
276 "bleb",
277 "bgtb",
278 "bgeb",
279 "beqw",
280 "bnew",
281 "bltw",
282 "blew",
283 "bgtw",
284 "bgew",
285 "beqf",
286 "bnef",
287 "bltf",
288 "blef",
289 "bgtf",
290 "bgef",
291 "beqc",
292 "bnec",
293 "bltc",
294 "blec",
295 "bgtc",
296 "bgec",
297 "slicea",
298 "slicela",
299 "slicec",
300 "indw",
301 "indf",
302 "indb",
303 "negf",
304 "movl",
305 "addl",
306 "subl",
307 "divl",
308 "modl",
309 "mull",
310 "andl",
311 "orl",
312 "xorl",
313 "shll",
314 "shrl",
315 "bnel",
316 "bltl",
317 "blel",
318 "bgtl",
319 "bgel",
320 "beql",
321 "cvtlf",
322 "cvtfl",
323 "cvtlw",
324 "cvtwl",
325 "cvtlc",
326 "cvtcl",
327 "headl",
328 "consl",
329 "newcl",
330 "casec",
331 "indl",
332 "movpc",
333 "tcmp",
334 "mnewz",
335 "cvtrf",
336 "cvtfr",
337 "cvtws",
338 "cvtsw",
339 "lsrw",
340 "lsrl",
341 "eclr",
342 "newz",
343 "newaz",
344};
java/tools/j2d/bb.c+643−0
@@ -0,0 +1,643 @@
1#include "java.h"
2#include "javaisa.h"
3#include "reloc.h"
4
5static BB **roots; /* root basic blocks */
6static int nr; /* number of root basic blocks */
7static int maxr; /* maximum number of roots */
8
9static BB **bbtbl; /* basic blocks */
10static int nbb; /* number of basic blocks */
11
12static void
13setflags(int pc, uchar flags)
14{
15 Jinst *j;
16
17 j = &code->j[pc];
18 if(j->bb == nil) {
19 j->bb = Mallocz(sizeof(BB));
20 j->bb->id = -1;
21 j->bb->js = j;
22 j->bb->state = BB_PRESIM;
23 nbb += 1;
24 /* record root basic blocks */
25 if(flags & (BB_ENTRY | BB_FINALLY | BB_HANDLER)) {
26 if(nr >= maxr) {
27 maxr += ALLOCINCR;
28 roots = Realloc(roots, maxr*sizeof(BB*));
29 }
30 roots[nr] = j->bb;
31 nr += 1;
32 }
33 }
34 j->bb->flags |= flags;
35}
36
37/*
38 * Verify that the target of a jump is valid.
39 */
40
41static void
42verifyjump(Jinst *j, int offset)
43{
44 int dst;
45
46 dst = j->pc + offset;
47 if(dst < 0 || dst >= code->code_length || code->j[dst].size == 0)
48 verifyerror(j);
49}
50
51/*
52 * Mark the instructions of a method that are basic block leaders.
53 */
54
55static void
56markldrs(void)
57{
58 Jinst *j;
59 int i;
60 int pc, pcnext;
61
62 /* first instruction is a leader */
63 setflags(0, BB_LDR | BB_ENTRY);
64
65 /* exception handler entry points are leaders */
66 for(i = 0; i < code->nex; i++)
67 setflags(code->ex[i]->handler_pc, BB_LDR | BB_HANDLER);
68
69 pc = 0;
70 while(pc < code->code_length) {
71 j = &code->j[pc];
72 pcnext = pc+j->size;
73 switch(j->op) {
74 case Jwide:
75 if(j->u.w.op != Jret)
76 break;
77 case Jret:
78 case Jireturn:
79 case Jlreturn:
80 case Jfreturn:
81 case Jdreturn:
82 case Jareturn:
83 case Jreturn:
84 case Jathrow:
85 if(pcnext < code->code_length)
86 setflags(pcnext, BB_LDR);
87 break;
88 case Jifeq:
89 case Jifne:
90 case Jiflt:
91 case Jifge:
92 case Jifgt:
93 case Jifle:
94 case Jif_icmpeq:
95 case Jif_icmpne:
96 case Jif_icmplt:
97 case Jif_icmpge:
98 case Jif_icmpgt:
99 case Jif_icmple:
100 case Jif_acmpeq:
101 case Jif_acmpne:
102 case Jifnull:
103 case Jifnonnull:
104 verifyjump(j, j->u.i);
105 setflags(pc+j->u.i, BB_LDR);
106 setflags(pcnext, BB_LDR);
107 break;
108 case Jgoto:
109 case Jgoto_w:
110 verifyjump(j, j->u.i);
111 setflags(pc+j->u.i, BB_LDR);
112 if(pcnext < code->code_length)
113 setflags(pcnext, BB_LDR);
114 break;
115 case Jjsr:
116 case Jjsr_w:
117 /* target of jsr is leader, jsr successor isn't */
118 verifyjump(j, j->u.i);
119 setflags(pc+j->u.i, BB_LDR | BB_FINALLY);
120 finallyentry(pc+j->u.i);
121 break;
122 case Jtableswitch:
123 for(i = 0; i < j->u.t1.hb - j->u.t1.lb + 1; i++) {
124 verifyjump(j, j->u.t1.tbl[i]);
125 setflags(pc+j->u.t1.tbl[i], BB_LDR);
126 }
127 verifyjump(j, j->u.t1.dflt);
128 setflags(pc+j->u.t1.dflt, BB_LDR);
129 if(pcnext < code->code_length)
130 setflags(pcnext, BB_LDR);
131 break;
132 case Jlookupswitch:
133 for(i = 0; i < j->u.t2.np; i++) {
134 verifyjump(j, j->u.t2.tbl[2*i+1]);
135 setflags(pc+j->u.t2.tbl[2*i+1], BB_LDR);
136 }
137 verifyjump(j, j->u.t2.dflt);
138 setflags(pc+j->u.t2.dflt, BB_LDR);
139 if(pcnext < code->code_length)
140 setflags(pcnext, BB_LDR);
141 break;
142 }
143 pc = pcnext;
144 }
145}
146
147/*
148 * b2 is a successor of b1; add appropriate links.
149 */
150
151static void
152addedges(BB *b1, BB *b2)
153{
154 BBList *l;
155
156 /* add successor link from b1 to b2 */
157 l = Malloc(sizeof(BBList));
158 l->bb = b2;
159 l->next = b1->succ;
160 b1->succ = l;
161
162 /* add predecessor link from b2 to b1 */
163 l = Malloc(sizeof(BBList));
164 l->bb = b1;
165 l->next = b2->pred;
166 b2->pred = l;
167}
168
169/*
170 * Connect basic blocks to their successors and predecessors.
171 */
172
173static void
174connect(BB *bb)
175{
176 int i;
177 Jinst *je;
178 int pc;
179
180 je = bb->je;
181 pc = je->pc;
182 switch(je->op) {
183 case Jwide:
184 if(je->u.w.op == Jret)
185 break;
186 default:
187 if(pc+je->size < code->code_length)
188 addedges(bb, code->j[pc+je->size].bb);
189 break;
190 case Jret:
191 case Jireturn:
192 case Jlreturn:
193 case Jfreturn:
194 case Jdreturn:
195 case Jareturn:
196 case Jreturn:
197 case Jathrow:
198 break;
199 case Jifeq:
200 case Jifne:
201 case Jiflt:
202 case Jifge:
203 case Jifgt:
204 case Jifle:
205 case Jif_icmpeq:
206 case Jif_icmpne:
207 case Jif_icmplt:
208 case Jif_icmpge:
209 case Jif_icmpgt:
210 case Jif_icmple:
211 case Jif_acmpeq:
212 case Jif_acmpne:
213 case Jifnull:
214 case Jifnonnull:
215 addedges(bb, code->j[pc+je->u.i].bb); /* branch target */
216 addedges(bb, code->j[pc+je->size].bb); /* fall through */
217 break;
218 case Jgoto:
219 case Jgoto_w:
220 addedges(bb, code->j[pc+je->u.i].bb);
221 break;
222 case Jtableswitch:
223 for(i = 0; i < je->u.t1.hb - je->u.t1.lb + 1; i++)
224 addedges(bb, code->j[pc+je->u.t1.tbl[i]].bb);
225 addedges(bb, code->j[pc+je->u.t1.dflt].bb);
226 break;
227 case Jlookupswitch:
228 for(i = 0; i < je->u.t2.np; i++)
229 addedges(bb, code->j[pc+je->u.t2.tbl[2*i+1]].bb);
230 addedges(bb, code->j[pc+je->u.t2.dflt].bb);
231 break;
232 }
233}
234
235static void dominators(void);
236
237/*
238 * Build the basic block control flow graph.
239 */
240
241void
242flowgraph(void)
243{
244 Jinst *js, *je;
245 int pc, pcnext;
246
247 markldrs();
248
249 pc = 0;
250 while(pc < code->code_length) {
251 js = &code->j[pc];
252 if(js->bb == nil)
253 fatal("flowgraph: nil bb\n");
254 /* find last instruction in basic block */
255 je = js;
256 while(1) {
257 pcnext = je->pc + je->size;
258 if(pcnext >= code->code_length
259 || code->j[pcnext].bb != nil) /* hence a leader */
260 break;
261 je += je->size;
262 je->bb = js->bb;
263 }
264 js->bb->je = je;
265 connect(js->bb);
266 pc = pcnext;
267 }
268
269 dominators();
270 finallyalloc();
271}
272
273/*
274 * Free basic block structures after each method is translated.
275 */
276
277static void
278bblistfree(BBList *l)
279{
280 BBList *l2;
281
282 while(l) {
283 l2 = l->next;
284 free(l);
285 l = l2;
286 }
287}
288
289void
290bbfree(void)
291{
292 int i;
293 BB *bb;
294
295 for(i = 0; i < nbb; i++) {
296 bb = bbtbl[i];
297 if(bb) {
298 bblistfree(bb->succ);
299 bblistfree(bb->pred);
300 free(bb->dom);
301 free(bb->entrystk);
302 free(bb->exitstk);
303 free(bb);
304 }
305 }
306 free(roots);
307 roots = nil;
308 nr = 0;
309 maxr = 0;
310 free(bbtbl);
311 bbtbl = nil;
312 nbb = 0;
313}
314
315/*
316 * The following stuff is used during method simulation.
317 */
318
319#define SSIZE 256
320static BB *bbstack[SSIZE];
321static int bbtos;
322
323void
324bbput(BB *bb)
325{
326 if(bbtos == SSIZE)
327 fatal("bbstack overflow\n");
328 bb->state = BB_ACTIVE;
329 bb->flags |= BB_REACHABLE;
330 bbstack[bbtos++] = bb;
331}
332
333BB*
334bbget(void)
335{
336 return (bbtos == 0) ? nil : bbstack[--bbtos];
337}
338
339void
340bbinit(void)
341{
342 int i;
343
344 bbtos = 0;
345 for(i = 0; i < nr; i++)
346 bbput(roots[i]);
347}
348
349static void
350bbinit2(void)
351{
352 bbtos = 0;
353}
354
355static void
356bbput2(BB *bb)
357{
358 if(bbtos == SSIZE)
359 fatal("bbstack overflow\n");
360 bbstack[bbtos++] = bb;
361}
362
363static void
364intersect(uchar *doml, uchar *domr, int domsz)
365{
366 int i;
367
368 for(i = 0; i < domsz; i++)
369 doml[i] &= domr[i];
370}
371
372#define IBIT2UCHAR 8
373static uchar mask[IBIT2UCHAR] = {
374 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01
375};
376
377static void
378setdombit(uchar *dom, int n)
379{
380 dom[n/IBIT2UCHAR] |= mask[n%IBIT2UCHAR];
381}
382
383static int
384getdombit(uchar *dom, int n)
385{
386 return dom[n/IBIT2UCHAR] & mask[n%IBIT2UCHAR];
387}
388
389/*
390 * Determine dominators for the basic blocks of a sub-graph.
391 * rid is the id of the root basic block.
392 * n basic blocks are reachable from rid.
393 * Algorithm 10.16 from Aho, Sethi, Ullman.
394 */
395
396static void
397dom(int rid, int n)
398{
399 int changes, i, domsz;
400 uchar *dom;
401 BB *bb;
402 BBList *l;
403
404 domsz = (nbb-1)/IBIT2UCHAR + 1;
405 dom = Mallocz(domsz);
406 setdombit(dom, rid);
407 bbtbl[rid]->dom = dom;
408
409 dom = Mallocz(domsz);
410 for(i = rid; i < rid+n; i++)
411 setdombit(dom, i);
412 for(i = rid+1; i < rid+n; i++) {
413 bb = bbtbl[i];
414 /* this bb may have been seen in another sub-graph */
415 if(bb->dom == nil)
416 bb->dom = Malloc(domsz);
417 memcpy(bb->dom, dom, domsz);
418 }
419
420 do {
421 changes = 0;
422 for(i = rid+1; i < rid+n; i++) {
423 bb = bbtbl[i];
424 memcpy(dom, bb->dom, domsz);
425 memset(bb->dom, 0, domsz);
426 for(l = bb->pred; l; l = l->next) {
427 /*
428 * If predecessor is out of range of the
429 * sub-graph being considered, then mark
430 * this bb as undominable.
431 */
432 if(l->bb->id < rid || l->bb->id >= rid+n) {
433 memset(bb->dom, 0, domsz);
434 break;
435 }
436 if(l == bb->pred)
437 memcpy(bb->dom, l->bb->dom, domsz);
438 else
439 intersect(bb->dom, l->bb->dom, domsz);
440 }
441 setdombit(bb->dom, i);
442 if(memcmp(dom, bb->dom, domsz) != 0)
443 changes = 1;
444 }
445 } while(changes);
446 free(dom);
447}
448
449/*
450 * Determine dominators of the basic blocks in the flow graph.
451 */
452
453static void
454dominators(void)
455{
456 int i, id, rid;
457 BB *bb;
458 BBList *l;
459
460 bbtbl = Malloc(nbb*sizeof(BB*));
461 id = 0;
462
463 bbinit2();
464 for(i = 0; i < nr; i++) {
465 if(roots[i]->id != -1)
466 continue;
467 rid = id;
468 bbput2(roots[i]);
469 while(bb = bbget()) {
470 if(bb->id == -1) {
471 bb->id = id;
472 bbtbl[id] = bb;
473 id += 1;
474 }
475 for(l = bb->succ; l; l = l->next) {
476 if(l->bb->id == -1)
477 bbput2(l->bb);
478 }
479 }
480 dom(rid, id - rid);
481 }
482}
483
484typedef struct CRef CRef;
485typedef struct Hash Hash;
486
487struct CRef {
488 char *name; /* class name */
489 int kind; /* LTCODE or RTCODE */
490 int last; /* most recent basic block in which rtload() */
491 /* called for this class */
492 BBList *l; /* basic blocks in which class is referenced */
493};
494
495struct Hash {
496 CRef *cr;
497 Hash *next;
498};
499
500static Hash *crtbl[Hashsize]; /* hash table of referenced classes */
501
502enum {
503 LOOKONLY,
504 LOOKENTER
505};
506
507static CRef*
508creflook(char *classname, int enter)
509{
510 int i;
511 Hash *h;
512 CRef *cr;
513
514 i = hashval(classname);
515 for(h = crtbl[i]; h; h = h->next) {
516 if(strcmp(classname, h->cr->name) == 0)
517 return h->cr;
518 }
519 if(enter == LOOKONLY)
520 return nil;
521 cr = Mallocz(sizeof(CRef));
522 cr->name = classname;
523 cr->last = -1;
524 h = Malloc(sizeof(Hash));
525 h->cr = cr;
526 h->next = crtbl[i];
527 crtbl[i] = h;
528 return cr;
529}
530
531/*
532 * Seed hash table with classes to be resolved at link-time.
533 */
534
535static char *ltload[] = {
536 nil, /* THISCLASS */
537 nil, /* SUPERCLASS */
538 "inferno/vm/Array",
539 "java/lang/Class",
540 "java/lang/Object",
541 "java/lang/String",
542 "java/lang/StringBuffer",
543 "java/io/Serializable"
544};
545
546void
547crefseed(void)
548{
549 CRef *cr;
550 int i;
551
552 ltload[0] = THISCLASS;
553 ltload[1] = SUPERCLASS;
554 for(i = 0; i < sizeof(ltload)/sizeof(char*); i++) {
555 if(ltload[i]) { /* SUPERCLASS == nil for Object */
556 cr = creflook(ltload[i], LOOKENTER);
557 cr->kind = LTCODE;
558 }
559 }
560}
561
562void
563crefenter(char *name, BB *bb)
564{
565 CRef *cr;
566 BBList *l;
567
568 cr = creflook(name, LOOKENTER);
569 if(cr->kind == LTCODE)
570 return;
571
572 /* cr->kind == RTCODE */
573 for(l = cr->l; l; l = l->next) {
574 if(bb->id == l->bb->id)
575 return;
576 }
577 l = Malloc(sizeof(BBList));
578 l->bb = bb;
579 l->next = cr->l;
580 cr->l = l;
581}
582
583/*
584 * Class name referenced in basic block bb.
585 * Should it be resolved at load-time (LTCODE) or run-time (RTCODE)?
586 * Must rtload() be called (RTCALL)?
587 */
588
589int
590crefstate(char *name, BB *bb, int handler)
591{
592 CRef *cr;
593 BBList *l;
594
595 cr = creflook(name, LOOKONLY);
596 /*
597 * Class not directly referenced in bytecode.
598 * So assume it is referenced in an exception table.
599 */
600 if(cr == nil)
601 return RTCODE | RTCALL;
602
603 if(cr->kind == LTCODE)
604 return LTCODE;
605
606 if(cr->last == bb->id) /* rtload() already called in this bb */
607 return RTCODE;
608
609 for(l = cr->l; l; l = l->next) {
610 if(bb->id == l->bb->id)
611 continue;
612 if(getdombit(bb->dom, l->bb->id))
613 return RTCODE;
614 }
615
616 /*
617 * When setting up exception handlers, class names in catch clauses
618 * (i.e., class names in exception tables) should not be marked as
619 * having been rtloaded for the current basic block. rtload()
620 * must be called separately in the try block for those classes
621 * (if referenced therein).
622 */
623 if(!handler)
624 cr->last = bb->id;
625 return RTCODE | RTCALL;
626}
627
628void
629creffree(void)
630{
631 int i;
632 Hash *h;
633 CRef *cr;
634
635 for(i = 0; i < Hashsize; i++) {
636 for(h = crtbl[i]; h; h = h->next) {
637 cr = h->cr;
638 cr->last = -1;
639 bblistfree(cr->l);
640 cr->l = nil;
641 }
642 }
643}
java/tools/j2d/datarloc.c+188−0
@@ -0,0 +1,188 @@
1#include "java.h"
2#include "reloc.h"
3
4/*
5 * Manage module data relocation and instruction patch information.
6 */
7
8static Ipatch *dreloc;
9static int Ipatchtid;
10
11void
12setIpatchtid(void)
13{
14 Ipatchtid = descid(1, 0, (uchar*)"");
15}
16
17/*
18 * Add an instruction patch directive to ip.
19 * (flag == SAVEINST) <=> runtime relocation: Inst* needed later
20 * (flag == !SAVEINST) <=> other: pinfo expected in sequential order
21 */
22
23void
24addIpatch(Ipatch *ip, Inst *i, int operand, int patchkind, int flag)
25{
26
27 if(ip->n >= ip->max) {
28 ip->max += ALLOCINCR;
29 ip->pinfo = Realloc(ip->pinfo, ip->max * sizeof(int));
30 if(flag == SAVEINST)
31 ip->i = Realloc(ip->i, ip->max * sizeof(Inst*));
32 }
33 ip->pinfo[ip->n] = (i->pc << 8) | operand | patchkind;
34 if(flag == SAVEINST)
35 ip->i[ip->n] = i;
36 ip->n += 1;
37}
38
39static char *operand[] = {
40 "?",
41 "src", /* PSRC >> 2 */
42 "dst", /* PDST >> 2 */
43 "mid" /* PMID >> 2 */
44};
45
46static char *mode[] = {
47 "$x", /* PIMM */
48 "x(reg)", /* PSIND */
49 "n(x(reg))", /* PDIND1 */
50 "x(n(reg))" /* PDIND2 */
51};
52
53static schar *ba;
54static int nba;
55static int szba;
56
57static void
58sizeba(int sz)
59{
60 if(sz > szba) {
61 szba = sz;
62 ba = Realloc(ba, szba * sizeof(schar));
63 }
64}
65
66static void
67fillba(Ipatch *ip)
68{
69 int i;
70 int pclast, pcnext, delta, skip;
71
72 sizeba(2*ip->n);
73 pclast = 0;
74 for(i = 0; i < ip->n; i++) {
75 pcnext = ip->pinfo[i] >> 8;
76 delta = pcnext-pclast;
77 sizeba(nba + delta/1024 + 2);
78 while(delta > 7) {
79 skip = (delta > 1024) ? 1024 : delta & 0xfffffff8;
80 ba[nba++] = -(skip >> 3);
81 delta -= skip;
82 }
83 ba[nba++] = (delta << 4) | (ip->pinfo[i] & 0xf);
84 pclast = pcnext;
85 }
86}
87
88/*
89 * Write Ipatch information to .s file.
90 */
91
92void
93asmIpatch(int off, Ipatch *ip)
94{
95 int i;
96 int reloff; /* relative offset for array elements */
97 int pc;
98
99 if(ip == nil || ip->n == 0)
100 return;
101
102 fillba(ip);
103
104 reloff = 0;
105 asmarray(off, Ipatchtid, nba, reloff);
106 pc = 0;
107 for(i = 0; i < nba; i++) {
108 Bprint(bout, "\tbyte\t@mp+%d,%d", reloff, (uchar)ba[i]);
109 if(ba[i] < 0)
110 pc += -ba[i] << 3;
111 else
112 pc += ba[i] >> 4;
113 Bprint(bout, "\t# %d", pc);
114 if(ba[i] > 0) {
115 Bprint(bout, ", %s, %s", operand[(ba[i] >> 2) & 0x3],
116 mode[ba[i] & 0x3]);
117 }
118 Bputc(bout, '\n');
119 reloff += 1;
120 }
121 Bprint(bout, "\tapop\n");
122
123 free(ba);
124 ba = nil;
125 nba = 0;
126 szba = 0;
127}
128
129/*
130 * Write Ipatch information to .dis file.
131 */
132
133void
134disIpatch(int off, Ipatch *ip)
135{
136 int i;
137 int reloff; /* relative offset for array elements */
138
139 if(ip == nil || ip->n == 0)
140 return;
141
142 fillba(ip);
143
144 disarray(off, Ipatchtid, nba);
145 reloff = 0;
146 for(i = 0; i < nba; i++) {
147 disbyte(reloff, (uchar)ba[i]);
148 reloff += 1;
149 }
150 disapop();
151
152 free(ba);
153 ba = nil;
154 nba = 0;
155 szba = 0;
156}
157
158/*
159 * Add instruction patch information to dreloc.
160 */
161
162void
163addDreloc(Inst *i, int operand, int patchkind)
164{
165 if(dreloc == nil)
166 dreloc = Mallocz(sizeof(Ipatch));
167 addIpatch(dreloc, i, operand, patchkind, !SAVEINST);
168}
169
170/*
171 * Write Dreloc information to .s file.
172 */
173
174void
175asmDreloc(int off)
176{
177 asmIpatch(off, dreloc);
178}
179
180/*
181 * Write Dreloc information to .dis file.
182 */
183
184void
185disDreloc(int off)
186{
187 disIpatch(off, dreloc);
188}
java/tools/j2d/desc.c+117−0
@@ -0,0 +1,117 @@
1#include "java.h"
2
3/*
4 * 'desc' assembly directives.
5 */
6
7typedef struct Desc Desc;
8
9struct Desc
10{
11 int id; /* Dis type identifier */
12 int ln; /* length, in bytes, of mapped object */
13 uchar *map; /* bit map of pointers */
14 int nmap; /* number of bytes in map */
15 Desc *next;
16};
17
18static Desc *dlist = nil;
19static Desc *dtail = nil;
20static int id = 0; /* reserve id == 0 for Module Data type descriptor */
21
22/*
23 * Allocate a Desc structure.
24 */
25
26static Desc*
27newDesc(int id, int ln, int nmap, uchar *map)
28{
29 Desc *d;
30
31 d = Malloc(sizeof(Desc));
32 d->id = id;
33 d->ln = ln;
34 d->nmap = nmap;
35 d->map = map;
36 d->next = nil;
37 return d;
38}
39
40/*
41 * Save a type descriptor; reuse existing descriptor if identical.
42 */
43
44int
45descid(int ln, int nmap, uchar *map)
46{
47 Desc *d;
48
49 for(d = dlist; d; d = d->next) {
50 if(d->ln == ln && d->nmap == nmap
51 && (memcmp(d->map, map, nmap) == 0)) {
52 return d->id;
53 }
54 }
55
56 id += 1;
57 d = newDesc(id, ln, nmap, map);
58 if(dlist == nil)
59 dlist = d;
60 else
61 dtail->next = d;
62 dtail = d;
63
64 return d->id;
65}
66
67/*
68 * Save type descriptor for module data.
69 */
70
71void
72mpdescid(int ln, int nmap, uchar *map)
73{
74 Desc *d;
75
76 d = newDesc(0, ln, nmap, map);
77 d->next = dlist;
78 dlist = d;
79}
80
81/*
82 * Emit assembly 'desc' directives.
83 */
84
85void
86asmdesc(void)
87{
88 Desc *d;
89 uchar *m, *e;
90
91 for(d = dlist; d; d = d->next) {
92 Bprint(bout, "\tdesc\t$%d,%d,\"", d->id, d->ln);
93 e = d->map + d->nmap;
94 for(m = d->map; m < e; m++)
95 Bprint(bout, "%.2x", *m);
96 Bprint(bout, "\"\n");
97 }
98}
99
100void
101disndesc(void)
102{
103 discon(id+1);
104}
105
106void
107disdesc(void)
108{
109 Desc *d;
110
111 for(d = dlist; d; d = d->next) {
112 discon(d->id);
113 discon(d->ln);
114 discon(d->nmap);
115 Bwrite(bout, d->map, d->nmap);
116 }
117}
java/tools/j2d/dis.c+336−0
@@ -0,0 +1,336 @@
1#include "java.h"
2
3Inst *ihead; /* first instruction generated for .class file */
4Inst *itail; /* last instruction (for appending to list) */
5
6static uchar *cache; /* module data cache */
7static int ncached; /* number of bytes in cache */
8static int ndatum; /* number of non-string basic datums in cache */
9static int startoff; /* offset of first datum in cache */
10static int lastoff; /* 1 past last byte offset in cache */
11static int lastkind = -1; /* last kind of datum put in cache */
12static int lencache; /* capacity of cache */
13
14/*
15 * Generate Dis object file (.dis).
16 */
17
18void
19discon(int val)
20{
21 if(val >= -64 && val <= 63) {
22 Bputc(bout, val & ~0x80);
23 return;
24 }
25 if(val >= -8192 && val <= 8191) {
26 Bputc(bout, ((val>>8) & ~0xC0) | 0x80);
27 Bputc(bout, val);
28 return;
29 }
30 if(notimmable(val))
31 fatal("discon: overflow 16r%ux\n", val);
32 Bputc(bout, (val>>24) | 0xC0);
33 Bputc(bout, val>>16);
34 Bputc(bout, val>>8);
35 Bputc(bout, val);
36}
37
38void
39disword(int w)
40{
41 Bputc(bout, w >> 24);
42 Bputc(bout, w >> 16);
43 Bputc(bout, w >> 8);
44 Bputc(bout, w);
45}
46
47void
48disdata(int kind, int n)
49{
50 if(n < DMAX && n != 0)
51 Bputc(bout, DBYTE(kind, n));
52 else{
53 Bputc(bout, DBYTE(kind, 0));
54 discon(n);
55 }
56}
57
58void
59disflush(int kind, int off, int size)
60{
61 if(kind != lastkind || off != lastoff){
62 if(lastkind != -1 && ncached){
63 disdata(lastkind, ndatum);
64 discon(startoff);
65 Bwrite(bout, cache, ncached);
66 }
67 startoff = off;
68 lastkind = kind;
69 ncached = 0;
70 ndatum = 0;
71 }
72 lastoff = off + size;
73 while(kind >= 0 && ncached + size >= lencache){
74 lencache = ncached+1024;
75 cache = Realloc(cache, lencache);
76 }
77}
78
79void
80disbyte(int off, int v)
81{
82 disflush(DEFB, off, 1);
83 cache[ncached++] = v;
84 ndatum++;
85}
86
87void
88disint(int off, int v)
89{
90 disflush(DEFW, off, IBY2WD);
91 cache[ncached++] = v >> 24;
92 cache[ncached++] = v >> 16;
93 cache[ncached++] = v >> 8;
94 cache[ncached++] = v;
95 ndatum++;
96}
97
98void
99dislong(int off, vlong v)
100{
101 uint iv;
102
103 disflush(DEFL, off, IBY2LG);
104 iv = v >> 32;
105 cache[ncached++] = iv >> 24;
106 cache[ncached++] = iv >> 16;
107 cache[ncached++] = iv >> 8;
108 cache[ncached++] = iv;
109 iv = v;
110 cache[ncached++] = iv >> 24;
111 cache[ncached++] = iv >> 16;
112 cache[ncached++] = iv >> 8;
113 cache[ncached++] = iv;
114 ndatum++;
115}
116
117static void
118dtocanon(double f, uint v[])
119{
120 union { double d; uint ui[2]; } a;
121
122 a.d = 1.;
123 if(a.ui[0]) {
124 a.d = f;
125 v[0] = a.ui[0];
126 v[1] = a.ui[1];
127 } else {
128 a.d = f;
129 v[0] = a.ui[1];
130 v[1] = a.ui[0];
131 }
132}
133
134void
135disreal(int off, double v)
136{
137 uint bv[2];
138 uint iv;
139
140 disflush(DEFF, off, IBY2LG);
141 dtocanon(v, bv);
142 iv = bv[0];
143 cache[ncached++] = iv >> 24;
144 cache[ncached++] = iv >> 16;
145 cache[ncached++] = iv >> 8;
146 cache[ncached++] = iv;
147 iv = bv[1];
148 cache[ncached++] = iv >> 24;
149 cache[ncached++] = iv >> 16;
150 cache[ncached++] = iv >> 8;
151 cache[ncached++] = iv;
152 ndatum++;
153}
154
155void
156disstring(int offset, char *s)
157{
158 int n, src, dst;
159 char *a;
160
161 /* null char represented as 0xC080 in String literals */
162 n = strlen(s);
163 a = Malloc(n);
164 src = 0;
165 dst = 0;
166 while(src < n) {
167 if(src+1 < n && (uchar)s[src] == 0xC0 && (uchar)s[src+1] == 0x80) {
168 a[dst] = '\0';
169 src++;
170 } else
171 a[dst] = s[src];
172 src++;
173 dst++;
174 }
175 disflush(-1, -1, 0);
176 disdata(DEFS, dst);
177 discon(offset);
178 Bwrite(bout, a, dst);
179 free(a);
180}
181
182/*
183 * Begin an array initializer.
184 */
185
186void
187disarray(int off, int tid, int nelt)
188{
189 disflush(-1, -1, 0);
190 disdata(DEFA, 1); /* 1 is ignored */
191 discon(off);
192 disword(tid);
193 disword(nelt);
194 disdata(DIND, 1); /* 1 is ignored */
195 discon(off);
196 disword(0);
197}
198
199/*
200 * Terminate an array initializer.
201 */
202
203void
204disapop(void)
205{
206 disflush(-1, -1, 0);
207 disdata(DAPOP, 1); /* 1 is ignored */
208 discon(0);
209}
210
211/*
212 * Put number of instructions into .dis Header.
213 */
214
215void
216disninst(void)
217{
218 discon(itail ? itail->pc + 1 : 0);
219}
220
221static int dismode[Aend] = {
222 /* Anone */ AXXX,
223 /* Aimm */ AIMM,
224 /* Amp */ AMP,
225 /* Ampind */ AMP|AIND,
226 /* Afp */ AFP,
227 /* Afpind */ AFP|AIND
228};
229
230static int disregmode[Aend] = {
231 /* Anone */ AXNON,
232 /* Aimm */ AXIMM,
233 /* Amp */ AXINM,
234 /* Ampind */ AXNON,
235 /* Afp */ AXINF,
236 /* Afpind */ AXNON
237};
238
239enum
240{
241 MAXCON = 4,
242 MAXADDR = 2*MAXCON,
243 MAXINST = 3*MAXCON+2,
244 NIBUF = 1024
245};
246
247static uchar *ibuf;
248static int nibuf;
249
250static void
251disbcon(int val)
252{
253 if(val >= -64 && val <= 63){
254 ibuf[nibuf++] = val & ~0x80;
255 return;
256 }
257 if(val >= -8192 && val <= 8191){
258 ibuf[nibuf++] = val>>8 & ~0xC0 | 0x80;
259 ibuf[nibuf++] = val;
260 return;
261 }
262 if(notimmable(val))
263 fatal("disbcon: overflow 16r%x\n", val);
264 ibuf[nibuf++] = val>>24 | 0xC0;
265 ibuf[nibuf++] = val>>16;
266 ibuf[nibuf++] = val>>8;
267 ibuf[nibuf++] = val;
268}
269
270static void
271disaddr(Addr *a)
272{
273 int val;
274
275 val = 0;
276 switch(a->mode){
277 case Aimm:
278 val = a->u.ival;
279 break;
280 case Afp:
281 case Amp:
282 val = a->u.offset;
283 break;
284 case Afpind:
285 case Ampind:
286 disbcon(a->u.b.fi);
287 val = a->u.b.si;
288 break;
289 }
290 disbcon(val);
291}
292
293static void
294disinst(void)
295{
296 Inst *i;
297
298 ibuf = Malloc(NIBUF);
299 nibuf = 0;
300 for(i = ihead; i; i = i->next){
301 if(nibuf >= NIBUF-MAXINST){
302 Bwrite(bout, ibuf, nibuf);
303 nibuf = 0;
304 }
305 ibuf[nibuf++] = i->op;
306 ibuf[nibuf++] = SRC(dismode[i->s.mode])
307 | DST(dismode[i->d.mode]) | disregmode[i->m.mode];
308 if(i->m.mode != Anone)
309 disaddr(&i->m);
310 if(i->s.mode != Anone)
311 disaddr(&i->s);
312 if(i->d.mode != Anone)
313 disaddr(&i->d);
314 }
315 if(nibuf > 0)
316 Bwrite(bout, ibuf, nibuf);
317 free(ibuf);
318}
319
320void
321disout(void)
322{
323 discon(XMAGIC);
324 discon(DONTCOMPILE); /* runtime "hints" */
325 disstackext(); /* minimum stack extent size */
326 disninst();
327 disnvar();
328 disndesc();
329 disnlinks();
330 disentry();
331 disinst();
332 disdesc();
333 disvar();
334 dismod();
335 dislinks();
336}
java/tools/j2d/entry.c+40−0
@@ -0,0 +1,40 @@
1#include "java.h"
2
3/*
4 * 'entry' assembly directive.
5 */
6
7static int pc = -1;
8static int tid = -1;
9
10/*
11 * Set the entry point; entry is the beginning of "main".
12 */
13
14void
15setentry(int l, int i)
16{
17 if(pc != -1)
18 verifyerrormess("main overloaded");
19 pc = l;
20 tid = i;
21}
22
23/*
24 * Emit 'entry' assembly directive.
25 */
26
27void
28asmentry(void)
29{
30 if(pc == -1)
31 return;
32 Bprint(bout, "\tentry\t%d, %d\n", pc, tid);
33}
34
35void
36disentry(void)
37{
38 discon(pc);
39 discon(tid);
40}
java/tools/j2d/finally.c+132−0
@@ -0,0 +1,132 @@
1#include "java.h"
2
3/*
4 * Maintain information about 'finally' blocks.
5 */
6
7typedef struct Finally Finally;
8
9static Finally *finally; /* linked list of finally block records */
10
11struct Finally {
12 int npc; /* Java pc of finally entry (jsr target) */
13 int xpc; /* Java pc of finally exit (ret) */
14 int n; /* number of jsr slots in gototbl */
15 int *gototbl; /* goto jump table */
16 int off; /* mp offset to gototbl */
17 Finally *next;
18};
19
20/*
21 * Get record for finally block whose entry point is pc.
22 */
23
24static Finally*
25getfinally(int pc)
26{
27 Finally *f;
28
29 for(f = finally; f; f = f->next) {
30 if(f->npc == pc)
31 return f;
32 }
33 return nil;
34}
35
36/*
37 * Count jsr's to the finally block whose entry point is pc.
38 */
39
40void
41finallyentry(int pc)
42{
43 Finally *f;
44
45 f = getfinally(pc);
46 if(f == nil) {
47 f = Malloc(sizeof(Finally));
48 f->npc = pc;
49 f->xpc = 0;
50 f->n = 0;
51 f->next = finally;
52 finally = f;
53 }
54 f->n += 1;
55}
56
57/*
58 * Allocate the gototbl's and pass them to mdata.c.
59 */
60
61void
62finallyalloc(void)
63{
64 Finally *f;
65
66 for(f = finally; f; f = f->next) {
67 f->gototbl = Mallocz(f->n*sizeof(int));
68 f->off = mpgoto(f->n, f->gototbl);
69 }
70}
71
72/*
73 * Fix up operands of a Dis movw that implements Java jsr/jsr_w.
74 */
75
76void
77jsrfixup(Addr *s, Addr *d, int dispc, int javapc)
78{
79 Finally *f;
80 int i;
81
82 f = getfinally(javapc);
83 for(i = 0; i < f->n; i++) {
84 if(f->gototbl[i] == 0) {
85 f->gototbl[i] = dispc;
86 break;
87 }
88 }
89 if(i == f->n)
90 fatal("jsrfixup: %d, %d\n", dispc, javapc);
91 s->u.ival = i;
92 d->u.offset = f->off + f->n*IBY2WD;
93}
94
95/*
96 * Fix up operands of a Dis goto that implements Java ret.
97 */
98
99void
100retfixup(Addr *s, Addr *d, int retpc)
101{
102 Finally *fi, *f;
103
104 f = nil;
105 for(fi = finally; fi; fi = fi->next) {
106 if(fi->xpc == 0 && fi->npc < retpc
107 && (f == nil || f->npc < fi->npc)) {
108 f = fi;
109 }
110 }
111 if(f == nil)
112 fatal("retfixup: %d\n", retpc);
113 f->xpc = retpc; /* claim this finally block for this 'ret' */
114 s->u.offset = f->off + f->n*IBY2WD;
115 d->u.offset = f->off;
116}
117
118/*
119 * Free finally information after each method is translated.
120 */
121
122void
123finallyfree(void)
124{
125 Finally *f, *f2;
126
127 for(f = finally; f; f = f2) {
128 f2 = f->next;
129 free(f);
130 }
131 finally = nil;
132}
java/tools/j2d/frame.c+514−0
@@ -0,0 +1,514 @@
1#include "java.h"
2#include "javaisa.h"
3
4/*
5 * Manage method frame.
6 */
7
8/*
9 * Local variables (including function parameters).
10 */
11
12typedef struct Local Local;
13
14struct Local { /* local variable */
15 uchar dtype; /* type of local (DIS_[BWLP]) */
16 int offset; /* fp offset of this local */
17 Local *next; /* for locals that are reused */
18};
19
20static int frameoff; /* tracks growth of frame */
21static int maxframe; /* size of largest frame */
22static Local *locals; /* local variables */
23static int nlocals; /* number of locals (in the Java sense) */
24
25/*
26 * fp temporaries.
27 */
28
29typedef struct Fp Fp;
30
31struct Fp {
32 uchar dtype;
33 int refcnt;
34};
35
36static int tmpslwm; /* lowest temporary fp offset */
37static int tmpssz; /* size of tmps array */
38static Fp *tmps; /* temporary arena */
39
40/*
41 * Resize the locals array.
42 *
43 * Since the Java VM reuses local variables (e.g., perhaps using
44 * the same slot for an int and an Object reference), max_locals
45 * doesn't always give the number of Dis locals to allow for.
46 */
47
48static void
49resizelocals(int ix)
50{
51 int oldsz;
52
53 oldsz = nlocals;
54 while(ix >= nlocals)
55 nlocals += ALLOCINCR;
56 locals = Realloc(locals, nlocals*sizeof(Local));
57 memset(&locals[oldsz], 0, ALLOCINCR*sizeof(Local));
58}
59
60/*
61 * Reserve a frame cell for a local variable of the given type.
62 * The Java VM reuses local variables.
63 */
64
65static void
66reservelocal(uchar dtype, int ix)
67{
68 Local *l;
69
70 if(ix >= nlocals)
71 resizelocals(ix);
72 if(locals[ix].dtype == dtype)
73 return;
74 if(locals[ix].dtype == DIS_X) /* not yet reserved */
75 l = &locals[ix];
76 else { /* check reuse list */
77 for(l = locals[ix].next; l; l = l->next) {
78 if(dtype == l->dtype)
79 return;
80 }
81 l = Malloc(sizeof(Local));
82 l->next = locals[ix].next;
83 locals[ix].next = l;
84 }
85 l->dtype = dtype;
86 frameoff = align(frameoff, cellsize[dtype]);
87 l->offset = frameoff;
88 frameoff += cellsize[dtype];
89}
90
91/*
92 * Map the signature parameter types into 'locals' array.
93 */
94
95static void
96mapmethodsig(char *sig, int isstatic)
97{
98 int index;
99
100 index = 0;
101 if(isstatic == 0) {
102 reservelocal(DIS_P, index); /* this pointer */
103 index += 1;
104 }
105 sig++; /* skip '(' */
106 while(sig[0] != ')') {
107 switch(sig[0]) {
108 case 'Z':
109 case 'B':
110 case 'C':
111 case 'S':
112 case 'I':
113 reservelocal(DIS_W, index);
114 index += 1;
115 break;
116 case 'F':
117 reservelocal(DIS_L, index);
118 index += 1;
119 break;
120 case 'J':
121 case 'D':
122 reservelocal(DIS_L, index);
123 index += 2;
124 break;
125 case 'L':
126 case '[':
127 reservelocal(DIS_P, index);
128 index += 1;
129 break;
130 }
131 sig = nextjavatype(sig);
132 }
133}
134
135/*
136 * Map references to local variables in the Java bytecode into 'locals' array.
137 */
138
139static void
140maplocalrefs(void)
141{
142 Jinst *j, *je;
143
144 j = &code->j[0];
145 je = j + code->code_length;
146 while(j < je) {
147 switch(j->op) {
148 case Jiinc:
149 reservelocal(DIS_W, j->u.x1c.ix);
150 break;
151 case Jiload:
152 case Jistore:
153 reservelocal(DIS_W, j->u.i);
154 break;
155 case Jiload_0:
156 case Jistore_0:
157 reservelocal(DIS_W, 0);
158 break;
159 case Jiload_1:
160 case Jistore_1:
161 reservelocal(DIS_W, 1);
162 break;
163 case Jiload_2:
164 case Jistore_2:
165 reservelocal(DIS_W, 2);
166 break;
167 case Jiload_3:
168 case Jistore_3:
169 reservelocal(DIS_W, 3);
170 break;
171 case Jlload:
172 case Jlstore:
173 case Jfload:
174 case Jfstore:
175 case Jdload:
176 case Jdstore:
177 reservelocal(DIS_L, j->u.i);
178 break;
179 case Jlload_0:
180 case Jlstore_0:
181 case Jfload_0:
182 case Jfstore_0:
183 case Jdload_0:
184 case Jdstore_0:
185 reservelocal(DIS_L, 0);
186 break;
187 case Jlload_1:
188 case Jlstore_1:
189 case Jfload_1:
190 case Jfstore_1:
191 case Jdload_1:
192 case Jdstore_1:
193 reservelocal(DIS_L, 1);
194 break;
195 case Jlload_2:
196 case Jlstore_2:
197 case Jfload_2:
198 case Jfstore_2:
199 case Jdload_2:
200 case Jdstore_2:
201 reservelocal(DIS_L, 2);
202 break;
203 case Jlload_3:
204 case Jlstore_3:
205 case Jfload_3:
206 case Jfstore_3:
207 case Jdload_3:
208 case Jdstore_3:
209 reservelocal(DIS_L, 3);
210 break;
211 case Jret:
212 case Jaload:
213 case Jastore:
214 reservelocal(DIS_P, j->u.i);
215 break;
216 case Jaload_0:
217 case Jastore_0:
218 reservelocal(DIS_P, 0);
219 break;
220 case Jaload_1:
221 case Jastore_1:
222 reservelocal(DIS_P, 1);
223 break;
224 case Jaload_2:
225 case Jastore_2:
226 reservelocal(DIS_P, 2);
227 break;
228 case Jaload_3:
229 case Jastore_3:
230 reservelocal(DIS_P, 3);
231 break;
232 case Jwide: /* repeat from above */
233 switch(j->u.w.op) {
234 case Jiinc:
235 case Jiload:
236 case Jistore:
237 reservelocal(DIS_W, j->u.w.ix);
238 break;
239 case Jlload:
240 case Jlstore:
241 case Jfload:
242 case Jfstore:
243 case Jdload:
244 case Jdstore:
245 reservelocal(DIS_L, j->u.w.ix);
246 break;
247 case Jaload:
248 case Jastore:
249 case Jret:
250 reservelocal(DIS_P, j->u.w.ix);
251 break;
252 }
253 break;
254 }
255 j += j->size;
256 }
257}
258
259/*
260 * Prepare a method's frame prior to translating its code.
261 */
262
263void
264openframe(char *sig, int isstatic)
265{
266 frameoff = REGSIZE;
267 /* 'code' can == nil; e.g, when generating <clinit> for an interface */
268 if(code)
269 nlocals = code->max_locals;
270 else
271 nlocals = 2;
272 locals = Mallocz(nlocals*sizeof(Local));
273 mapmethodsig(sig, isstatic);
274 if(code)
275 maplocalrefs();
276 frameoff = align(frameoff, IBY2WD);
277 tmpslwm = frameoff;
278 tmpssz = frameoff;
279 tmps = Mallocz(tmpssz*sizeof(Fp));
280}
281
282/*
283 * Return fp index of a local variable.
284 */
285
286int
287localix(uchar dtype, int ix)
288{
289 Local *l;
290
291 if(dtype == locals[ix].dtype)
292 return locals[ix].offset;
293 for(l = locals[ix].next; l; l = l->next) {
294 if(dtype == l->dtype)
295 return l->offset;
296 }
297 fatal("localix: %d, %d\n", dtype, ix);
298 return -1; /* for the compiler */
299}
300
301/* fp temporary management starts here */
302
303static void
304incref(int off)
305{
306 if(off >= tmpslwm) /* if <, then local variable */
307 tmps[off-tmpslwm].refcnt++;
308}
309
310void
311acqreg(Addr *a)
312{
313 switch(a->mode) {
314 case Anone:
315 case Aimm:
316 case Amp:
317 case Ampind:
318 break;
319 case Afp:
320 incref(a->u.offset);
321 break;
322 case Afpind:
323 incref(a->u.b.fi);
324 break;
325 }
326}
327
328/*
329 * Reserve the fp temporaries referenced by a StkSnap of some basic block.
330 */
331
332void
333reservereg(StkSnap *s, int sz)
334{
335 int i;
336
337 for(i = 0; i < sz; i++)
338 acqreg(&code->j[s[i].pc[0]].dst);
339}
340
341/*
342 * Get fp offset of the next available register of the given type.
343 */
344
345static int
346getoff(uchar dtype)
347{
348 int off;
349 int stride;
350
351 if(dtype == DIS_L) {
352 stride = IBY2LG;
353 off = tmpslwm % IBY2LG;
354 } else {
355 stride = IBY2WD;
356 off = 0;
357 }
358 while(off < tmpssz) {
359 if(tmps[off].refcnt == 0
360 && (tmps[off].dtype == dtype || tmps[off].dtype == DIS_X)) {
361 return off;
362 }
363 off += stride;
364 }
365 return off;
366}
367
368/*
369 * Get a register (fp offset thereof) of the appropriate type.
370 */
371
372int
373getreg(uchar dtype)
374{
375 int off;
376 int oldsz;
377
378 off = getoff(dtype);
379 if(off >= tmpssz) { /* increase size of temporary arena */
380 oldsz = tmpssz;
381 tmpssz += ALLOCINCR*IBY2LG;
382 tmps = Realloc(tmps, tmpssz*sizeof(Fp));
383 memset(&tmps[oldsz], 0, (ALLOCINCR*IBY2LG)*sizeof(Fp));
384 }
385 tmps[off].dtype = dtype;
386 if(dtype == DIS_L) /* also reserve next word */
387 tmps[off+IBY2WD].dtype = dtype;
388 tmps[off].refcnt = 1;
389 if(tmpslwm+off+cellsize[dtype] > frameoff)
390 frameoff = tmpslwm+off+cellsize[dtype];
391 return tmpslwm+off;
392}
393
394static void
395decref(int off)
396{
397 if(off >= tmpslwm) { /* if <, then local variable */
398 if(--tmps[off-tmpslwm].refcnt < 0)
399 fatal("decref: refcnt < 0\n");
400 }
401}
402
403/*
404 * "Free" register used by a.
405 */
406
407void
408relreg(Addr *a)
409{
410 /* don't mess with exception object */
411 if(code != nil && a == &code->j[code->code_length].dst)
412 return;
413 switch(a->mode) {
414 case Anone:
415 case Aimm:
416 case Amp:
417 case Ampind:
418 break;
419 case Afp:
420 decref(a->u.offset);
421 break;
422 case Afpind:
423 decref(a->u.b.fi);
424 break;
425 }
426}
427
428/*
429 * Mark all temporary fp registers as available. Leave typing as is.
430 */
431
432void
433clearreg(void)
434{
435 int i;
436
437 i = 0;
438 while(i < frameoff-tmpslwm) {
439 tmps[i].refcnt = 0;
440 i += IBY2WD;
441 }
442}
443
444/*
445 * Calculate the type descriptor for a frame.
446 */
447
448static int
449framedesc(void)
450{
451 int ln, id, i;
452 uchar *map;
453 Local *l;
454
455 ln = frameoff / (8*IBY2WD) + (frameoff % (8*IBY2WD) != 0);
456 map = Mallocz(ln);
457 setbit(map, REFSYSEX); /* slot for 'ref Sys->Exception' */
458 setbit(map, EXOBJ); /* slot for exception object */
459 for(i = 0; i < nlocals; i++) {
460 if(locals[i].dtype == DIS_P)
461 setbit(map, locals[i].offset);
462 for(l = locals[i].next; l; l = l->next) {
463 if(l->dtype == DIS_P)
464 setbit(map, l->offset);
465 }
466 }
467 i = 0;
468 while(i < frameoff-tmpslwm) {
469 if(tmps[i].dtype == DIS_P)
470 setbit(map, tmpslwm+i);
471 i += IBY2WD;
472 }
473 id = descid(frameoff, ln, map);
474 return id;
475}
476
477/*
478 * Dispense with a frame.
479 */
480
481int
482closeframe(void)
483{
484 int tid, i;
485 Local *l, *l2;
486
487 /* frame size is always a multiple of 8 */
488 frameoff = align(frameoff, IBY2LG);
489 if(frameoff > maxframe)
490 maxframe = frameoff;
491 tid = framedesc();
492 for(i = 0; i < nlocals; i++) {
493 for(l = locals[i].next; l; l = l2) {
494 l2 = l->next;
495 free(l);
496 }
497 }
498 free(locals);
499 frameoff = 0;
500 tmpslwm = 0;
501 tmpssz = 0;
502 free(tmps);
503 return tid;
504}
505
506/*
507 * Minimum stack extent size.
508 */
509
510void
511disstackext(void)
512{
513 discon(10*maxframe);
514}
java/tools/j2d/java.h+452−0
@@ -0,0 +1,452 @@
1#include "lib9.h"
2#include "bio.h"
3#include "isa.h"
4
5enum {
6 /* Java constant pool tags */
7
8 CON_Utf8 = 1,
9 /* CON_Unicode = 2, */ /* obsolete */
10 CON_Integer = 3,
11 CON_Float = 4,
12 CON_Long = 5,
13 CON_Double = 6,
14 CON_Class = 7,
15 CON_String = 8,
16 CON_Fieldref = 9,
17 CON_Methodref = 10,
18 CON_InterfaceMref = 11,
19 CON_NameAndType = 12,
20
21 /* Java access flags */
22
23 ACC_PUBLIC = 0x0001,
24 ACC_PRIVATE = 0x0002,
25 ACC_PROTECTED = 0x0004,
26 ACC_STATIC = 0x0008,
27 ACC_FINAL = 0x0010,
28 ACC_SUPER = 0x0020,
29 ACC_SYNCHRONIZED = 0x0020, /* sic */
30 ACC_VOLATILE = 0x0040,
31 ACC_TRANSIENT = 0x0080,
32 ACC_NATIVE = 0x0100,
33 ACC_INTERFACE = 0x0200,
34 ACC_ABSTRACT = 0x0400,
35
36 _MUSTCOMPILE = MUSTCOMPILE<<16,
37 _DONTCOMPILE = DONTCOMPILE<<16,
38
39 /* basic block flags */
40
41 BB_LDR = 1 << 0, /* set for all leaders */
42 BB_ENTRY = 1 << 1, /* method entry point */
43 BB_FINALLY = 1 << 2, /* finally block entry point */
44 BB_HANDLER = 1 << 3, /* EH entry point */
45 BB_REACHABLE = 1 << 4, /* reachable basic block */
46
47 /* basic block states */
48
49 BB_PRESIM = 1 << 0, /* not simulated yet */
50 BB_ACTIVE = 1 << 1, /* simulating or being unified */
51 BB_POSTSIM = 1 << 2, /* simulated */
52 BB_POSTUNIFY = 1 << 3, /* unified */
53
54 /* Dis operand classification */
55
56 Anone = 0,
57 Aimm,
58 Amp,
59 Ampind,
60 Afp,
61 Afpind,
62 Aend,
63
64 /* Dis n(fp) types */
65
66 DIS_X = 0, /* not yet typed */
67 DIS_W, /* 'B', 'Z', 'C', 'S', 'I' */
68 DIS_L, /* 'F', 'J', 'D' */
69 DIS_P, /* 'L', '[' */
70
71 /* inferno/vm/Array */
72
73 ARY_DATA = IBY2WD, /* Array data (Dis array) */
74 ARY_NDIM = 2*IBY2WD, /* number of dimensions */
75 ARY_ADT = 3*IBY2WD, /* 'ref Class' of element type */
76 ARY_ETYPE = 4*IBY2WD, /* primitive element type code */
77
78 /* java/lang/String */
79
80 STR_DISSTR = IBY2WD, /* offset to Dis string in a String */
81
82 /* miscellaneous */
83
84 REFSYSEX = 24, /* 24(fp) is a 'ref Sys->Exception' */
85 EXOBJ = 28, /* 28(fp) is exception object */
86 THISOFF = 32, /* 32(fp) is "this" pointer */
87 REGSIZE = 32, /* 32(fp) is first usable frame cell */
88 Hashsize = 31,
89 ALLOCINCR = 16
90};
91
92typedef struct Attr Attr;
93typedef struct Field Field;
94typedef struct Method Method;
95typedef union Const Const;
96typedef struct Class Class;
97typedef struct Jinst Jinst;
98typedef struct StkSnap StkSnap;
99typedef struct BB BB;
100typedef struct BBList BBList;
101typedef struct Code Code;
102typedef struct PCode PCode;
103typedef struct Handler Handler;
104
105typedef struct Addr Addr;
106typedef struct Inst Inst;
107
108union Const {
109 double tdouble; /* CONSTANT_[Float|Double]_info */
110 vlong tvlong; /* CONSTANT_Long_info */
111 int tint; /* CONSTANT_Integer_info */
112 ushort string_index; /* CONSTANT_String_info */
113 struct { /* CONSTANT_Class_info */
114 ushort name_index;
115 } ci;
116 /* CONSTANT_[Fieldref|Methodref|InterfaceMethodref]_info */
117 struct {
118 ushort class_index;
119 ushort name_type_index;
120 } fmiref;
121 struct { /* CONSTANT_NameAndType */
122 ushort name_index;
123 ushort sig_index;
124 } nat;
125 struct { /* CONSTANT_Utf8_info */
126 ushort ln;
127 char *utf8;
128 } utf8;
129};
130
131struct Attr { /* attribute_info */
132 ushort name;
133 uint ln;
134 uchar *info;
135};
136
137struct Field { /* field_info */
138 ushort access_flags;
139 ushort name_index;
140 ushort sig_index;
141 ushort attr_count;
142 Attr *attr_info; /* ConstantValue attributes */
143};
144
145struct Method { /* method_info */
146 ushort access_flags;
147 ushort name_index;
148 ushort sig_index;
149 ushort attr_count;
150 Attr *attr_info; /* Code, Exceptions attributes */
151};
152
153struct Class { /* ClassFile */
154 /* uint magic; */ /* 0xcafebabe */
155 ushort min;
156 ushort maj;
157 ushort cp_count;
158 Const *cps;
159 char *cts;
160 ushort access_flags;
161 ushort this_class;
162 ushort super_class;
163 ushort interfaces_count;
164 ushort *interfaces;
165 ushort fields_count;
166 Field *fields;
167 ushort methods_count;
168 Method *methods;
169 ushort source_file;
170};
171
172struct Addr { /* Dis operand */
173 uchar mode; /* Anone, Aimm, Amp, etc. */
174 union {
175 int ival; /* immediate, $ival */
176 int offset; /* single indirect, offset(fp) */
177 struct { /* double indirect, si(fi(fp)) */
178 ushort fi;
179 ushort si;
180 } b;
181 } u;
182};
183
184struct Jinst { /* Java instruction */
185 uchar op; /* op code */
186 uchar jtype; /* Java type of dst ('I', '[', etc.) */
187 int pc; /* pc offset */
188 int line; /* source line number */
189 int size; /* size of this instruction */
190 Inst *dis; /* Dis code for this instruction */
191 BB *bb; /* the instruction's basic block */
192 int nsrc; /* 0 or more source operands */
193 int *src;
194 Addr dst; /* usual destination operand */
195 Addr movsrc; /* source operand if mov generated for load */
196 union {
197 int i; /* AT, X1, X2, B2, B4, V1, V2 */
198 struct { /* iinc */
199 uint ix;
200 int icon;
201 } x1c;
202 struct { /* invokeinterface */
203 uint ix;
204 uint narg;
205 uint zero;
206 } x2c0;
207 struct { /* multianewarray */
208 uint ix;
209 uint dim;
210 } x2d;
211 struct { /* tableswitch */
212 int dflt;
213 int lb;
214 int hb;
215 int *tbl;
216 } t1;
217 struct { /* lookupswitch */
218 int dflt;
219 int np;
220 int *tbl;
221 } t2;
222 struct { /* wide */
223 uchar op;
224 uint ix;
225 int icon;
226 } w;
227 } u;
228};
229
230struct Handler { /* exception_table entry */
231 ushort start_pc;
232 ushort end_pc;
233 ushort handler_pc;
234 ushort catch_type;
235};
236
237struct Code { /* one Java method */
238 int max_stack;
239 int max_locals;
240 int code_length;
241 Jinst *j;
242 int nex;
243 Handler **ex;
244};
245
246struct PCode {
247 Code *code;
248 char *name;
249 char *sig;
250};
251
252struct StkSnap { /* snapshot of simulated Java VM stack */
253 uchar jtype;
254 int npc;
255 int *pc;
256};
257
258struct BB { /* basic block */
259 int id; /* unique identifier */
260 Jinst *js; /* first instruction in basic block */
261 Jinst *je; /* last instruction in basic block */
262 BBList *succ; /* successors */
263 BBList *pred; /* predecessors */
264 uchar *dom; /* bit-vector of dominators */
265 uchar flags; /* basic block leader flags */
266 uchar state; /* BB_PRESIM, etc. */
267 int entrysz; /* size of saved entry stack */
268 StkSnap *entrystk; /* snapshot of entry stack */
269 int exitsz; /* size of saved exit stack */
270 StkSnap *exitstk; /* snapshot of exit stack */
271};
272
273struct BBList {
274 BB *bb;
275 BBList *next;
276};
277
278struct Inst { /* Dis instruction */
279 uchar op; /* op code */
280 Addr s; /* source */
281 Addr m; /* middle */
282 Addr d; /* destination */
283 int pc; /* 0-based instruction offset */
284 Jinst *j;
285 Inst *next;
286};
287
288/* asm.c */
289extern int Aconv(va_list*, Fconv*);
290extern int Iconv(va_list*, Fconv*);
291extern void asminst(void);
292extern void sblinst(Biobuf*);
293extern Inst *clinitclone;
294
295/* bb.c */
296extern void flowgraph(void);
297extern void bbfree(void);
298extern void bbinit(void);
299extern void bbput(BB*);
300extern BB *bbget(void);
301extern void crefseed(void);
302extern void crefenter(char*, BB*);
303extern int crefstate(char*, BB*, int);
304extern void creffree(void);
305
306/* desc.c */
307extern int descid(int, int, uchar*);
308extern void mpdescid(int, int, uchar*);
309extern void asmdesc(void);
310extern void disndesc(void);
311extern void disdesc(void);
312
313/* dis.c */
314extern void discon(int);
315extern void disword(int);
316extern void disdata(int, int);
317extern void disflush(int, int, int);
318extern void disbyte(int, int);
319extern void disint(int, int);
320extern void dislong(int, vlong);
321extern void disreal(int, double);
322extern void disstring(int, char*);
323extern void disarray(int, int, int);
324extern void disapop(void);
325extern void disout(void);
326extern Inst *ihead;
327extern Inst *itail;
328
329/* entry.c */
330extern void setentry(int, int);
331extern void asmentry(void);
332extern void disentry(void);
333
334/* finally.c */
335extern void finallyentry(int);
336extern void finallyalloc(void);
337extern void jsrfixup(Addr*, Addr*, int, int);
338extern void retfixup(Addr*, Addr*, int);
339extern void finallyfree(void);
340
341/* frame.c */
342extern void openframe(char*, int);
343extern int closeframe(void);
344extern int localix(uchar, int);
345extern void reservereg(StkSnap*, int);
346extern int getreg(uchar);
347extern void acqreg(Addr*);
348extern void relreg(Addr*);
349extern void clearreg(void);
350extern void disstackext(void);
351
352/* javadas.c */
353extern int Jconv(va_list*, Fconv*);
354extern Code *javadas(Attr*);
355
356/* javatbl.c */
357extern int isload(Jinst*);
358extern int isstore(Jinst*);
359
360/* links.c */
361extern void xtrnlink(int, int, char*, char*);
362extern void addfcpatch(Inst*, Inst*, char*, char*);
363extern void dofcpatch(void);
364extern void asmlinks(void);
365extern void disnlinks(void);
366extern void dislinks(void);
367extern void sbllinks(Biobuf*);
368
369/* loader.c */
370extern void ClassLoader(char*);
371extern void dumpcpool(void);
372extern char *CLASSNAME(int);
373extern char *STRING(int);
374extern Class *class;
375extern PCode *pcode;
376extern char *THISCLASS;
377extern char *SUPERCLASS;
378
379/* main.c */
380extern int compileflag;
381extern int gensbl;
382extern int verbose;
383extern Biobuf *bout;
384extern char *ofile;
385
386/* mdata.c */
387extern int mpint(int);
388extern int mplong(vlong);
389extern int mpreal(double);
390extern int mpstring(char*);
391extern int mpcase(int, int*);
392extern void mpdesc(void);
393extern int mpgoto(int, int*);
394extern void asmarray(int, int, int, int);
395extern void asmint(int, int);
396extern void asmstring(int, char*);
397extern void asmvar(void);
398extern void disnvar(void);
399extern void disvar(void);
400
401/* module.c */
402extern void asmmod(void);
403extern void dismod(void);
404
405/* patch.c */
406extern void patchop(Inst*);
407extern void patchcase(Inst*, int, int*);
408extern void patchmethod(int);
409extern void patchfree(void);
410
411/* sbl.c */
412extern void sblout(char*);
413
414/* simjvm.c */
415extern void simjvm(char*);
416
417/* unify.c */
418extern void unify(void);
419
420/* util.c */
421extern void uSet(uchar*);
422extern void uN(int);
423extern uchar u1(void);
424extern ushort u2(void);
425extern uint u4(void);
426extern void getattr(Attr*);
427extern int CVattrindex(Field*);
428extern char *uPtr(void);
429extern int align(int, int);
430extern void pstring(char*);
431extern void fatal(char*, ...);
432extern void verifycpindex(Jinst*, int, int);
433extern void verifyerror(Jinst*);
434extern void verifyerrormess(char*);
435extern char *nextjavatype(char*);
436extern uchar j2dtype(uchar);
437extern void addrimm(Addr*, int);
438extern int notimmable(int);
439extern void addrsind(Addr*, uchar, int);
440extern void addrdind(Addr*, uchar, uint, uint);
441extern void dstreg(Addr*, uchar);
442extern void setbit(uchar*, int);
443extern int hashval(char*);
444extern void *Malloc(uint);
445extern void *Mallocz(uint);
446extern void *Realloc(void*, uint);
447extern int cellsize[];
448
449/* xlate.c */
450extern void xlate(void);
451extern Code *code;
452#pragma varargck type "A" Addr*
java/tools/j2d/javadas.c+596−0
@@ -0,0 +1,596 @@
1#include "java.h"
2#include "javaisa.h"
3
4/*
5 * Java bytecode disassembler.
6 */
7
8enum /* Java operand classifications */
9{
10 AT, /* unsigned byte (newarray) */
11 B2, /* 2-byte signed branch offset */
12 B4, /* 4-byte signed branch offset */
13 X1, /* 1-byte unsigned index (ldc) */
14 X1C, /* iinc */
15 X2, /* 2-byte unsigned index */
16 X2C0, /* invokeinterface */
17 X2D, /* multianewarray */
18 T1, /* tableswitch */
19 T2, /* lookupswitch */
20 V1, /* 1-byte signed value (bipush) */
21 V2, /* 2-byte signed value (sipush) */
22 W, /* wide */
23 Z /* zero operands */
24};
25
26typedef struct Jmnemon Jmnemon;
27
28struct Jmnemon
29{
30 char *op;
31 uchar kind;
32};
33
34/*
35 * Java bytecode mnemonics.
36 */
37
38static Jmnemon tab[MAXJAVA] =
39{
40 "nop", Z,
41 "aconst_null", Z,
42 "iconst_m1", Z,
43 "iconst_0", Z,
44 "iconst_1", Z,
45 "iconst_2", Z,
46 "iconst_3", Z,
47 "iconst_4", Z,
48 "iconst_5", Z,
49 "lconst_0", Z,
50 "lconst_1", Z,
51 "fconst_0", Z,
52 "fconst_1", Z,
53 "fconst_2", Z,
54 "dconst_0", Z,
55 "dconst_1", Z,
56 "bipush", V1,
57 "sipush", V2,
58 "ldc", X1,
59 "ldc_w", X2,
60 "ldc2_w", X2,
61 "iload", X1,
62 "lload", X1,
63 "fload", X1,
64 "dload", X1,
65 "aload", X1,
66 "iload_0", Z,
67 "iload_1", Z,
68 "iload_2", Z,
69 "iload_3", Z,
70 "lload_0", Z,
71 "lload_1", Z,
72 "lload_2", Z,
73 "lload_3", Z,
74 "fload_0", Z,
75 "fload_1", Z,
76 "fload_2", Z,
77 "fload_3", Z,
78 "dload_0", Z,
79 "dload_1", Z,
80 "dload_2", Z,
81 "dload_3", Z,
82 "aload_0", Z,
83 "aload_1", Z,
84 "aload_2", Z,
85 "aload_3", Z,
86 "iaload", Z,
87 "laload", Z,
88 "faload", Z,
89 "daload", Z,
90 "aaload", Z,
91 "baload", Z,
92 "caload", Z,
93 "saload", Z,
94 "istore", X1,
95 "lstore", X1,
96 "fstore", X1,
97 "dstore", X1,
98 "astore", X1,
99 "istore_0", Z,
100 "istore_1", Z,
101 "istore_2", Z,
102 "istore_3", Z,
103 "lstore_0", Z,
104 "lstore_1", Z,
105 "lstore_2", Z,
106 "lstore_3", Z,
107 "fstore_0", Z,
108 "fstore_1", Z,
109 "fstore_2", Z,
110 "fstore_3", Z,
111 "dstore_0", Z,
112 "dstore_1", Z,
113 "dstore_2", Z,
114 "dstore_3", Z,
115 "astore_0", Z,
116 "astore_1", Z,
117 "astore_2", Z,
118 "astore_3", Z,
119 "iastore", Z,
120 "lastore", Z,
121 "fastore", Z,
122 "dastore", Z,
123 "aastore", Z,
124 "bastore", Z,
125 "castore", Z,
126 "sastore", Z,
127 "pop", Z,
128 "pop2", Z,
129 "dup", Z,
130 "dup_x1", Z,
131 "dup_x2", Z,
132 "dup2", Z,
133 "dup2_x1", Z,
134 "dup2_x2", Z,
135 "swap", Z,
136 "iadd", Z,
137 "ladd", Z,
138 "fadd", Z,
139 "dadd", Z,
140 "isub", Z,
141 "lsub", Z,
142 "fsub", Z,
143 "dsub", Z,
144 "imul", Z,
145 "lmul", Z,
146 "fmul", Z,
147 "dmul", Z,
148 "idiv", Z,
149 "ldiv", Z,
150 "fdiv", Z,
151 "ddiv", Z,
152 "irem", Z,
153 "lrem", Z,
154 "frem", Z,
155 "drem", Z,
156 "ineg", Z,
157 "lneg", Z,
158 "fneg", Z,
159 "dneg", Z,
160 "ishl", Z,
161 "lshl", Z,
162 "ishr", Z,
163 "lshr", Z,
164 "iushr", Z,
165 "lushr", Z,
166 "iand", Z,
167 "land", Z,
168 "ior", Z,
169 "lor", Z,
170 "ixor", Z,
171 "lxor", Z,
172 "iinc", X1C,
173 "i2l", Z,
174 "i2f", Z,
175 "i2d", Z,
176 "l2i", Z,
177 "l2f", Z,
178 "l2d", Z,
179 "f2i", Z,
180 "f2l", Z,
181 "f2d", Z,
182 "d2i", Z,
183 "d2l", Z,
184 "d2f", Z,
185 "i2b", Z,
186 "i2c", Z,
187 "i2s", Z,
188 "lcmp", Z,
189 "fcmpl", Z,
190 "fcmpg", Z,
191 "dcmpl", Z,
192 "dcmpg", Z,
193 "ifeq", B2,
194 "ifne", B2,
195 "iflt", B2,
196 "ifge", B2,
197 "ifgt", B2,
198 "ifle", B2,
199 "if_icmpeq", B2,
200 "if_icmpne", B2,
201 "if_icmplt", B2,
202 "if_icmpge", B2,
203 "if_icmpgt", B2,
204 "if_icmple", B2,
205 "if_acmpeq", B2,
206 "if_acmpne", B2,
207 "goto", B2,
208 "jsr", B2,
209 "ret", X1,
210 "tableswitch", T1,
211 "lookupswitch", T2,
212 "ireturn", Z,
213 "lreturn", Z,
214 "freturn", Z,
215 "dreturn", Z,
216 "areturn", Z,
217 "return", Z,
218 "getstatic", X2,
219 "putstatic", X2,
220 "getfield", X2,
221 "putfield", X2,
222 "invokevirtual",X2,
223 "invokespecial", X2,
224 "invokestatic", X2,
225 "invokeinterface", X2C0,
226 "xxxunusedxxx", Z,
227 "new", X2,
228 "newarray", AT,
229 "anewarray", X2,
230 "arraylength", Z,
231 "athrow", Z,
232 "checkcast", X2,
233 "instanceof", X2,
234 "monitorenter", Z,
235 "monitorexit", Z,
236 "wide", W,
237 "multianewarray", X2D,
238 "ifnull", B2,
239 "ifnonnull", B2,
240 "goto_w", B4,
241 "jsr_w", B4,
242};
243
244/*
245 * %J format conversion.
246 */
247
248int
249Jconv(va_list *jinst, Fconv *f)
250{
251 Jinst *j;
252 Jmnemon *t;
253 int i, k;
254 char buf[2048]; /* not big enough for tableswitch, lookupswitch ??? */
255
256 j = va_arg(*jinst, Jinst*);
257 t = &tab[j->op];
258
259 switch(t->kind) {
260 case Z:
261 sprint(buf, "%s", t->op);
262 break;
263 case X1:
264 case X2:
265 case V1:
266 case V2:
267 case B2:
268 case B4:
269 sprint(buf, "%s %d", t->op, j->u.i);
270 break;
271 case X1C:
272 sprint(buf, "%s %d,%d", t->op, j->u.x1c.ix, j->u.x1c.icon);
273 break;
274 case X2D:
275 sprint(buf, "%s %d,%d", t->op, j->u.x2d.ix, j->u.x2d.dim);
276 break;
277 case AT:
278 sprint(buf, "%s %d", t->op, j->u.i);
279 break;
280 case T1:
281 i = sprint(buf, "%s %d,%d,%d", t->op, j->u.t1.dflt,
282 j->u.t1.lb, j->u.t1.hb);
283 if(j->u.t1.tbl) {
284 for(k = 0; k < j->u.t1.hb - j->u.t1.lb + 1; k++)
285 i += sprint(buf+i, ",%d", j->u.t1.tbl[k]);
286 }
287 break;
288 case T2:
289 i = sprint(buf, "%s %d,%d", t->op, j->u.t2.dflt, j->u.t2.np);
290 if(j->u.t2.tbl) {
291 for(k = 0; k < 2*j->u.t2.np; k++)
292 i += sprint(buf+i, ",%d", j->u.t2.tbl[k]);
293 }
294 break;
295 case W:
296 i = sprint(buf, "%s %d,%d", t->op, j->u.w.op, j->u.w.ix);
297 if(j->u.w.op == Jiinc)
298 sprint(buf+i, ",%d", j->u.w.icon);
299 break;
300 case X2C0:
301 sprint(buf, "%s %d,%d,%d", t->op, j->u.x2c0.ix,
302 j->u.x2c0.narg, j->u.x2c0.zero);
303 break;
304 }
305 strconv(buf, f);
306 return sizeof(char*);
307}
308
309/*
310 * Verify an exception handler.
311 */
312
313static void
314verifyehpc(Code *c, int pc)
315{
316 if(pc >= c->code_length || c->j[pc].size == 0)
317 verifyerrormess("handler pc");
318}
319
320static void
321verifyhandler(Code *c, Handler *h)
322{
323 verifyehpc(c, h->start_pc);
324
325 if(h->end_pc != c->code_length)
326 verifyehpc(c, h->end_pc);
327
328 verifyehpc(c, h->handler_pc);
329
330 if(h->catch_type != 0)
331 verifycpindex(nil, h->catch_type, 1 << CON_Class);
332}
333
334/*
335 * Disassemble code for a method.
336 */
337
338Code*
339javadas(Attr *a)
340{
341 Attr at;
342 Code *c;
343 Handler *h, *h1, *h2;
344 Jinst *j;
345 int pc, codelen;
346 int l, i, k, n, nat, nln, CON_bits;
347
348 uSet(a->info);
349 c = Malloc(sizeof(Code));
350 c->max_stack = u2();
351 c->max_locals = u2();
352 c->code_length = u4();
353 if(c->code_length == 0 || c->code_length > 65535)
354 verifyerrormess("code_length");
355 /* +1 is for exception object */
356 c->j = Mallocz((c->code_length+1)*sizeof(Jinst));
357
358 l = -1;
359 CON_bits = -1;
360 pc = 0;
361 codelen = c->code_length;
362 while(codelen > 0) {
363 j = &c->j[pc];
364 j->op = u1();
365 j->pc = pc;
366 switch(tab[j->op].kind) {
367 case Z:
368 l = 1;
369 j->size = l;
370 break;
371 case V1:
372 j->u.i = (schar)u1();
373 l = 2;
374 j->size = l;
375 break;
376 case B2:
377 case V2:
378 j->u.i = (short)u2();
379 l = 3;
380 j->size = l;
381 break;
382 case B4:
383 j->u.i = (int)u4();
384 l = 5;
385 j->size = l;
386 break;
387 case X1:
388 j->u.i = u1();
389 if(j->op == Jldc) {
390 CON_bits = 1 << CON_Integer | 1 << CON_Float | 1 << CON_String;
391 verifycpindex(j, j->u.i, CON_bits);
392 }
393 l = 2;
394 j->size = l;
395 break;
396 case X2:
397 j->u.i = u2();
398 switch(j->op) {
399 case Jldc_w:
400 CON_bits = 1 << CON_Integer | 1 << CON_Float | 1 << CON_String;
401 break;
402 case Jldc2_w:
403 CON_bits = 1 << CON_Long | 1 << CON_Double;
404 if(j->u.i == class->cp_count-1)
405 verifyerror(j);
406 break;
407 case Jgetstatic:
408 case Jputstatic:
409 case Jgetfield:
410 case Jputfield:
411 CON_bits = 1 << CON_Fieldref;
412 break;
413 case Jinvokevirtual:
414 case Jinvokespecial:
415 case Jinvokestatic:
416 CON_bits = 1 << CON_Methodref;
417 break;
418 case Jnew:
419 case Janewarray:
420 case Jcheckcast:
421 case Jinstanceof:
422 CON_bits = 1 << CON_Class;
423 break;
424 }
425 verifycpindex(j, j->u.i, CON_bits);
426 l = 3;
427 j->size = l;
428 break;
429 case X1C:
430 j->u.x1c.ix = u1();
431 j->u.x1c.icon = (schar)u1();
432 l = 3;
433 j->size = l;
434 break;
435 case X2D:
436 j->u.x2d.ix = u2();
437 j->u.x2d.dim = u1();
438 verifycpindex(j, j->u.x2d.ix, 1 << CON_Class);
439 if(j->u.x2d.dim < 1)
440 verifyerror(j);
441 l = 4;
442 j->size = l;
443 break;
444 case AT:
445 j->u.i = u1();
446 if(j->u.i < T_BOOLEAN || j->u.i > T_LONG)
447 verifyerror(j);
448 l = 2;
449 j->size = l;
450 break;
451 case T1:
452 if((pc+1)%4) /* <0-3 byte pad> */
453 n = 4-(pc+1)%4;
454 else
455 n = 0;
456 l = n;
457 while(n--)
458 u1();
459 j->u.t1.dflt = (int)u4();
460 j->u.t1.lb = (int)u4();
461 j->u.t1.hb = (int)u4();
462 if(j->u.t1.lb > j->u.t1.hb)
463 verifyerror(j);
464 n = j->u.t1.hb - j->u.t1.lb + 1;
465 j->u.t1.tbl = Malloc(n*sizeof(int));
466 for(i = 0; i < n; i++)
467 j->u.t1.tbl[i] = (int)u4();
468 l += 13 + n * 4;
469 j->size = l;
470 break;
471 case T2:
472 if((pc+1)%4) /* <0-3 byte pad> */
473 n = 4-(pc+1)%4;
474 else
475 n = 0;
476 l = n;
477 while(n--)
478 u1();
479 j->u.t2.dflt = (int)u4();
480 j->u.t2.np = (int)u4();
481 n = j->u.t2.np;
482 if(n < 0)
483 verifyerror(j);
484 j->u.t2.tbl = Malloc(n*2*sizeof(int));
485 for(i = 0; i < n*2; i++)
486 j->u.t2.tbl[i] = (int)u4();
487 for(i = 2; i < n*2; i += 2) {
488 if(j->u.t2.tbl[i-2] > j->u.t2.tbl[i])
489 verifyerror(j);
490 }
491 l += 9 + n * 8;
492 j->size = l;
493 break;
494 case W:
495 j->u.w.op = u1();
496 j->u.w.ix = u2();
497 switch(j->u.w.op) {
498 case Jiload:
499 case Jlload:
500 case Jfload:
501 case Jdload:
502 case Jaload:
503 case Jistore:
504 case Jlstore:
505 case Jfstore:
506 case Jdstore:
507 case Jastore:
508 case Jret:
509 l = 4;
510 break;
511 case Jiinc:
512 j->u.w.icon = (short)u2();
513 l = 6;
514 break;
515 default:
516 verifyerror(j);
517 }
518 j->size = l;
519 break;
520 case X2C0:
521 j->u.x2c0.ix = u2();
522 j->u.x2c0.narg = u1();
523 j->u.x2c0.zero = u1(); /* must be 0 */
524 verifycpindex(j, j->u.x2c0.ix, 1 << CON_InterfaceMref);
525 if(j->u.x2c0.narg < 1 || j->u.x2c0.zero != 0)
526 verifyerror(j);
527 l = 5;
528 j->size = l;
529 break;
530 default:
531 verifyerrormess("illegal opcode");
532 return nil; /* for compiler */
533 }
534 codelen -= l;
535 pc += l;
536 }
537 if(codelen != 0)
538 verifyerrormess("code_length");
539
540 c->nex = u2();
541 if(c->nex == 0)
542 c->ex = nil;
543 else {
544 c->ex = Malloc(c->nex*sizeof(Handler*));
545 for(i = 0; i < c->nex; i++) {
546 h = Malloc(sizeof(Handler));
547 h->start_pc = u2();
548 h->end_pc = u2();
549 h->handler_pc = u2();
550 h->catch_type = u2();
551 c->ex[i] = h;
552 verifyhandler(c, h);
553 /*
554 * sort nested try blocks that have same start_pc,
555 * outer-most go first (see cvtehinfo() [xlate.c])
556 */
557 for(k = i; k > 0; k--) {
558 h1 = c->ex[k];
559 h2 = c->ex[k-1];
560 if(h1->start_pc == h2->start_pc
561 && h1->end_pc > h2->end_pc) {
562 c->ex[k] = h2;
563 c->ex[k-1] = h1;
564 }
565 }
566 }
567 }
568
569 if(gensbl == 0)
570 return c;
571
572 /* interpret LineNumberTable attributes */
573 nat = u2();
574 for(i = 0; i < nat; i++) {
575 getattr(&at);
576 if(strcmp(STRING(at.name), "LineNumberTable") == 0) {
577 nln = (at.info[0] << 8) | at.info[1];
578 for(k = 2; k < nln*4+2; k += 4) {
579 pc = (at.info[k] << 8) | at.info[k+1];
580 c->j[pc].line = (at.info[k+2] << 8) | at.info[k+3];
581 }
582 }
583 free(at.info);
584 }
585 pc = 0;
586 n = 0;
587 while(pc < c->code_length) {
588 if(c->j[pc].line == 0)
589 c->j[pc].line = n;
590 else
591 n = c->j[pc].line;
592 pc += c->j[pc].size;
593 }
594
595 return c;
596}
java/tools/j2d/javaisa.h+221−0
@@ -0,0 +1,221 @@
1/*
2 * Java VM instruction set
3 */
4
5enum {
6 Jnop = 0,
7 Jaconst_null = 1,
8 Jiconst_m1 = 2,
9 Jiconst_0 = 3,
10 Jiconst_1 = 4,
11 Jiconst_2 = 5,
12 Jiconst_3 = 6,
13 Jiconst_4 = 7,
14 Jiconst_5 = 8,
15 Jlconst_0 = 9,
16 Jlconst_1 = 10,
17 Jfconst_0 = 11,
18 Jfconst_1 = 12,
19 Jfconst_2 = 13,
20 Jdconst_0 = 14,
21 Jdconst_1 = 15,
22 Jbipush = 16,
23 Jsipush = 17,
24 Jldc = 18,
25 Jldc_w = 19,
26 Jldc2_w = 20,
27 Jiload = 21,
28 Jlload = 22,
29 Jfload = 23,
30 Jdload = 24,
31 Jaload = 25,
32 Jiload_0 = 26,
33 Jiload_1 = 27,
34 Jiload_2 = 28,
35 Jiload_3 = 29,
36 Jlload_0 = 30,
37 Jlload_1 = 31,
38 Jlload_2 = 32,
39 Jlload_3 = 33,
40 Jfload_0 = 34,
41 Jfload_1 = 35,
42 Jfload_2 = 36,
43 Jfload_3 = 37,
44 Jdload_0 = 38,
45 Jdload_1 = 39,
46 Jdload_2 = 40,
47 Jdload_3 = 41,
48 Jaload_0 = 42,
49 Jaload_1 = 43,
50 Jaload_2 = 44,
51 Jaload_3 = 45,
52 Jiaload = 46,
53 Jlaload = 47,
54 Jfaload = 48,
55 Jdaload = 49,
56 Jaaload = 50,
57 Jbaload = 51,
58 Jcaload = 52,
59 Jsaload = 53,
60 Jistore = 54,
61 Jlstore = 55,
62 Jfstore = 56,
63 Jdstore = 57,
64 Jastore = 58,
65 Jistore_0 = 59,
66 Jistore_1 = 60,
67 Jistore_2 = 61,
68 Jistore_3 = 62,
69 Jlstore_0 = 63,
70 Jlstore_1 = 64,
71 Jlstore_2 = 65,
72 Jlstore_3 = 66,
73 Jfstore_0 = 67,
74 Jfstore_1 = 68,
75 Jfstore_2 = 69,
76 Jfstore_3 = 70,
77 Jdstore_0 = 71,
78 Jdstore_1 = 72,
79 Jdstore_2 = 73,
80 Jdstore_3 = 74,
81 Jastore_0 = 75,
82 Jastore_1 = 76,
83 Jastore_2 = 77,
84 Jastore_3 = 78,
85 Jiastore = 79,
86 Jlastore = 80,
87 Jfastore = 81,
88 Jdastore = 82,
89 Jaastore = 83,
90 Jbastore = 84,
91 Jcastore = 85,
92 Jsastore = 86,
93 Jpop = 87,
94 Jpop2 = 88,
95 Jdup = 89,
96 Jdup_x1 = 90,
97 Jdup_x2 = 91,
98 Jdup2 = 92,
99 Jdup2_x1 = 93,
100 Jdup2_x2 = 94,
101 Jswap = 95,
102 Jiadd = 96,
103 Jladd = 97,
104 Jfadd = 98,
105 Jdadd = 99,
106 Jisub = 100,
107 Jlsub = 101,
108 Jfsub = 102,
109 Jdsub = 103,
110 Jimul = 104,
111 Jlmul = 105,
112 Jfmul = 106,
113 Jdmul = 107,
114 Jidiv = 108,
115 Jldiv = 109,
116 Jfdiv = 110,
117 Jddiv = 111,
118 Jirem = 112,
119 Jlrem = 113,
120 Jfrem = 114,
121 Jdrem = 115,
122 Jineg = 116,
123 Jlneg = 117,
124 Jfneg = 118,
125 Jdneg = 119,
126 Jishl = 120,
127 Jlshl = 121,
128 Jishr = 122,
129 Jlshr = 123,
130 Jiushr = 124,
131 Jlushr = 125,
132 Jiand = 126,
133 Jland = 127,
134 Jior = 128,
135 Jlor = 129,
136 Jixor = 130,
137 Jlxor = 131,
138 Jiinc = 132,
139 Ji2l = 133,
140 Ji2f = 134,
141 Ji2d = 135,
142 Jl2i = 136,
143 Jl2f = 137,
144 Jl2d = 138,
145 Jf2i = 139,
146 Jf2l = 140,
147 Jf2d = 141,
148 Jd2i = 142,
149 Jd2l = 143,
150 Jd2f = 144,
151 Ji2b = 145,
152 Ji2c = 146,
153 Ji2s = 147,
154 Jlcmp = 148,
155 Jfcmpl = 149,
156 Jfcmpg = 150,
157 Jdcmpl = 151,
158 Jdcmpg = 152,
159 Jifeq = 153,
160 Jifne = 154,
161 Jiflt = 155,
162 Jifge = 156,
163 Jifgt = 157,
164 Jifle = 158,
165 Jif_icmpeq = 159,
166 Jif_icmpne = 160,
167 Jif_icmplt = 161,
168 Jif_icmpge = 162,
169 Jif_icmpgt = 163,
170 Jif_icmple = 164,
171 Jif_acmpeq = 165,
172 Jif_acmpne = 166,
173 Jgoto = 167,
174 Jjsr = 168,
175 Jret = 169,
176 Jtableswitch = 170,
177 Jlookupswitch = 171,
178 Jireturn = 172,
179 Jlreturn = 173,
180 Jfreturn = 174,
181 Jdreturn = 175,
182 Jareturn = 176,
183 Jreturn = 177,
184 Jgetstatic = 178,
185 Jputstatic = 179,
186 Jgetfield = 180,
187 Jputfield = 181,
188 Jinvokevirtual = 182,
189 Jinvokespecial = 183,
190 Jinvokestatic = 184,
191 Jinvokeinterface = 185,
192 Jxxxunusedxxx = 186,
193 Jnew = 187,
194 Jnewarray = 188,
195 Janewarray = 189,
196 Jarraylength = 190,
197 Jathrow = 191,
198 Jcheckcast = 192,
199 Jinstanceof = 193,
200 Jmonitorenter = 194,
201 Jmonitorexit = 195,
202 Jwide = 196,
203 Jmultianewarray = 197,
204 Jifnull = 198,
205 Jifnonnull = 199,
206 Jgoto_w = 200,
207 Jjsr_w = 201,
208
209 MAXJAVA = Jjsr_w+1,
210
211 /* newarray element types (Java VM Specification page 320) */
212
213 T_BOOLEAN = 4,
214 T_CHAR = 5,
215 T_FLOAT = 6,
216 T_DOUBLE = 7,
217 T_BYTE = 8,
218 T_SHORT = 9,
219 T_INT = 10,
220 T_LONG = 11
221};
java/tools/j2d/javatbl.c+232−0
@@ -0,0 +1,232 @@
1#include "java.h"
2#include "javaisa.h"
3
4enum {
5 XLOAD = 0x1 << 0,
6 XSTORE = 0x1 << 1
7};
8
9static uchar javatbl[MAXJAVA];
10
11static int
12opcode(Jinst *j)
13{
14 return (j->op == Jwide) ? j->u.w.op : j->op;
15}
16
17int
18isload(Jinst *j)
19{
20 return javatbl[opcode(j)] & XLOAD;
21}
22
23int
24isstore(Jinst *j)
25{
26 return javatbl[opcode(j)] & XSTORE;
27}
28
29static uchar javatbl[MAXJAVA] = {
30 0, /* Jnop */
31 XLOAD, /* Jaconst_null */
32 XLOAD, /* Jiconst_m1 */
33 XLOAD, /* Jiconst_0 */
34 XLOAD, /* Jiconst_1 */
35 XLOAD, /* Jiconst_2 */
36 XLOAD, /* Jiconst_3 */
37 XLOAD, /* Jiconst_4 */
38 XLOAD, /* Jiconst_5 */
39 XLOAD, /* Jlconst_0 */
40 XLOAD, /* Jlconst_1 */
41 XLOAD, /* Jfconst_0 */
42 XLOAD, /* Jfconst_1 */
43 XLOAD, /* Jfconst_2 */
44 XLOAD, /* Jdconst_0 */
45 XLOAD, /* Jdconst_1 */
46 XLOAD, /* Jbipush */
47 XLOAD, /* Jsipush */
48 XLOAD, /* Jldc */
49 XLOAD, /* Jldc_w */
50 XLOAD, /* Jldc2_w */
51 XLOAD, /* Jiload */
52 XLOAD, /* Jlload */
53 XLOAD, /* Jfload */
54 XLOAD, /* Jdload */
55 XLOAD, /* Jaload */
56 XLOAD, /* Jiload_0 */
57 XLOAD, /* Jiload_1 */
58 XLOAD, /* Jiload_2 */
59 XLOAD, /* Jiload_3 */
60 XLOAD, /* Jlload_0 */
61 XLOAD, /* Jlload_1 */
62 XLOAD, /* Jlload_2 */
63 XLOAD, /* Jlload_3 */
64 XLOAD, /* Jfload_0 */
65 XLOAD, /* Jfload_1 */
66 XLOAD, /* Jfload_2 */
67 XLOAD, /* Jfload_3 */
68 XLOAD, /* Jdload_0 */
69 XLOAD, /* Jdload_1 */
70 XLOAD, /* Jdload_2 */
71 XLOAD, /* Jdload_3 */
72 XLOAD, /* Jaload_0 */
73 XLOAD, /* Jaload_1 */
74 XLOAD, /* Jaload_2 */
75 XLOAD, /* Jaload_3 */
76 0, /* Jiaload */
77 0, /* Jlaload */
78 0, /* Jfaload */
79 0, /* Jdaload */
80 0, /* Jaaload */
81 0, /* Jbaload */
82 0, /* Jcaload */
83 0, /* Jsaload */
84 XSTORE, /* Jistore */
85 XSTORE, /* Jlstore */
86 XSTORE, /* Jfstore */
87 XSTORE, /* Jdstore */
88 XSTORE, /* Jastore */
89 XSTORE, /* Jistore_0 */
90 XSTORE, /* Jistore_1 */
91 XSTORE, /* Jistore_2 */
92 XSTORE, /* Jistore_3 */
93 XSTORE, /* Jlstore_0 */
94 XSTORE, /* Jlstore_1 */
95 XSTORE, /* Jlstore_2 */
96 XSTORE, /* Jlstore_3 */
97 XSTORE, /* Jfstore_0 */
98 XSTORE, /* Jfstore_1 */
99 XSTORE, /* Jfstore_2 */
100 XSTORE, /* Jfstore_3 */
101 XSTORE, /* Jdstore_0 */
102 XSTORE, /* Jdstore_1 */
103 XSTORE, /* Jdstore_2 */
104 XSTORE, /* Jdstore_3 */
105 XSTORE, /* Jastore_0 */
106 XSTORE, /* Jastore_1 */
107 XSTORE, /* Jastore_2 */
108 XSTORE, /* Jastore_3 */
109 0, /* Jiastore */
110 0, /* Jlastore */
111 0, /* Jfastore */
112 0, /* Jdastore */
113 0, /* Jaastore */
114 0, /* Jbastore */
115 0, /* Jcastore */
116 0, /* Jsastore */
117 0, /* Jpop */
118 0, /* Jpop2 */
119 0, /* Jdup */
120 0, /* Jdup_x1 */
121 0, /* Jdup_x2 */
122 0, /* Jdup2 */
123 0, /* Jdup2_x1 */
124 0, /* Jdup2_x2 */
125 0, /* Jswap */
126 0, /* Jiadd */
127 0, /* Jladd */
128 0, /* Jfadd */
129 0, /* Jdadd */
130 0, /* Jisub */
131 0, /* Jlsub */
132 0, /* Jfsub */
133 0, /* Jdsub */
134 0, /* Jimul */
135 0, /* Jlmul */
136 0, /* Jfmul */
137 0, /* Jdmul */
138 0, /* Jidiv */
139 0, /* Jldiv */
140 0, /* Jfdiv */
141 0, /* Jddiv */
142 0, /* Jirem */
143 0, /* Jlrem */
144 0, /* Jfrem */
145 0, /* Jdrem */
146 0, /* Jineg */
147 0, /* Jlneg */
148 0, /* Jfneg */
149 0, /* Jdneg */
150 0, /* Jishl */
151 0, /* Jlshl */
152 0, /* Jishr */
153 0, /* Jlshr */
154 0, /* Jiushr */
155 0, /* Jlushr */
156 0, /* Jiand */
157 0, /* Jland */
158 0, /* Jior */
159 0, /* Jlor */
160 0, /* Jixor */
161 0, /* Jlxor */
162 0, /* Jiinc */
163 0, /* Ji2l */
164 0, /* Ji2f */
165 0, /* Ji2d */
166 0, /* Jl2i */
167 0, /* Jl2f */
168 0, /* Jl2d */
169 0, /* Jf2i */
170 0, /* Jf2l */
171 0, /* Jf2d */
172 0, /* Jd2i */
173 0, /* Jd2l */
174 0, /* Jd2f */
175 0, /* Ji2b */
176 0, /* Ji2c */
177 0, /* Ji2s */
178 0, /* Jlcmp */
179 0, /* Jfcmpl */
180 0, /* Jfcmpg */
181 0, /* Jdcmpl */
182 0, /* Jdcmpg */
183 0, /* Jifeq */
184 0, /* Jifne */
185 0, /* Jiflt */
186 0, /* Jifge */
187 0, /* Jifgt */
188 0, /* Jifle */
189 0, /* Jif_icmpeq */
190 0, /* Jif_icmpne */
191 0, /* Jif_icmplt */
192 0, /* Jif_icmpge */
193 0, /* Jif_icmpgt */
194 0, /* Jif_icmple */
195 0, /* Jif_acmpeq */
196 0, /* Jif_acmpne */
197 0, /* Jgoto */
198 0, /* Jjsr */
199 0, /* Jret */
200 0, /* Jtableswitch */
201 0, /* Jlookupswitch */
202 0, /* Jireturn */
203 0, /* Jlreturn */
204 0, /* Jfreturn */
205 0, /* Jdreturn */
206 0, /* Jareturn */
207 0, /* Jreturn */
208 0, /* Jgetstatic */
209 0, /* Jputstatic */
210 0, /* Jgetfield */
211 0, /* Jputfield */
212 0, /* Jinvokevirtual */
213 0, /* Jinvokespecial */
214 0, /* Jinvokestatic */
215 0, /* Jinvokeinterface*/
216 0, /* Jxxxunusedxxx */
217 0, /* Jnew */
218 0, /* Jnewarray */
219 0, /* Janewarray */
220 0, /* Jarraylength */
221 0, /* Jathrow */
222 0, /* Jcheckcast */
223 0, /* Jinstanceof */
224 0, /* Jmonitorenter */
225 0, /* Jmonitorexit */
226 0, /* Jwide */
227 0, /* Jmultianewarray */
228 0, /* Jifnull */
229 0, /* Jifnonnull */
230 0, /* Jgoto_w */
231 0, /* Jjsr_w */
232};
java/tools/j2d/links.c+172−0
@@ -0,0 +1,172 @@
1#include "java.h"
2
3/*
4 * Manage .dis Link Section.
5 */
6
7typedef struct Link Link;
8
9struct Link
10{
11 int id; /* dis type identifier */
12 int pc; /* method entry pc */
13 uint sig; /* MD5 signature */
14 char *name; /* method name */
15 Link *next;
16};
17
18static Link *links = nil;
19static Link *last = nil;
20static int nlinks;
21
22/*
23 * Create a Link entry; one for each method defined in the class.
24 */
25
26void
27xtrnlink(int id, int pc, char *name, char *sig)
28{
29 Link *l;
30 char *n;
31
32 l = Malloc(sizeof(Link));
33 l->id = id;
34 l->pc = pc;
35 if(strcmp(name, "main") == 0)
36 setentry(pc, id);
37 l->sig = 1247901281;
38 n = Malloc(strlen(name) + strlen(sig) + 1);
39 strcpy(n, name);
40 strcat(n, sig);
41 l->name = n;
42 l->next = nil;
43 if(links == nil)
44 links = l;
45 else
46 last->next = l;
47 last = l;
48 nlinks += 1;
49}
50
51/*
52 * Functions for patching frame & call instructions.
53 */
54
55typedef struct FCPatch FCPatch;
56
57struct FCPatch {
58 Inst *frame;
59 Inst *call;
60 char *name;
61 char *sig;
62 FCPatch *next;
63};
64
65static FCPatch *fcplist;
66
67/*
68 * Record a frame/call pair for later patching.
69 */
70
71void
72addfcpatch(Inst *frame, Inst *call, char *name, char *sig)
73{
74 FCPatch *fcp;
75
76 fcp = Malloc(sizeof(FCPatch));
77 fcp->frame = frame;
78 fcp->call = call;
79 fcp->name = name;
80 fcp->sig = sig;
81 fcp->next = fcplist;
82 fcplist = fcp;
83}
84
85static Link*
86getLink(char *name, char *sig)
87{
88 Link *l;
89 int nlen;
90
91 nlen = strlen(name);
92 l = links;
93 while(l) {
94 if(strncmp(l->name, name, nlen) == 0
95 && strncmp(l->name+nlen, sig, strlen(sig)) == 0) {
96 return l;
97 }
98 l = l->next;
99 }
100 fatal("getLink: %s, %s\n", name, sig);
101 return nil; /* for compiler */
102}
103
104/*
105 * Patch frame/call pairs.
106 */
107
108void
109dofcpatch(void)
110{
111 FCPatch *fcp, *fcp2;
112 Link *l;
113
114 fcp = fcplist;
115 while(fcp) {
116 l = getLink(fcp->name, fcp->sig);
117 fcp->frame->s.u.ival = l->id;
118 fcp->call->d.u.ival = l->pc;
119 fcp2 = fcp->next;
120 free(fcp);
121 fcp = fcp2;
122 }
123}
124
125/*
126 * Emit assembly 'link' directives.
127 */
128
129void
130asmlinks(void)
131{
132 Link *l;
133
134 for(l = links; l; l = l->next) {
135 Bprint(bout, "\tlink\t%d,%d,0x%x,\"%s\"\n",
136 l->id, l->pc, l->sig, l->name);
137 }
138}
139
140void
141sbllinks(Biobuf *bsym)
142{
143 Link *l;
144
145 Bprint(bsym, "%d\n", nlinks);
146 for(l = links; l; l = l->next) {
147 Bprint(bsym, "%d:%s\n", l->pc, l->name);
148 Bprint(bsym, "0\n"); /* args */
149 Bprint(bsym, "0\n"); /* locals */
150 Bprint(bsym, "n\n"); /* return type */
151 }
152}
153
154void
155disnlinks(void)
156{
157 discon(nlinks);
158}
159
160void
161dislinks(void)
162{
163 Link *l;
164
165 for(l = links; l; l = l->next) {
166 discon(l->pc);
167 discon(l->id);
168 disword(l->sig);
169 Bprint(bout, "%s", l->name);
170 Bputc(bout, '\0');
171 }
172}
java/tools/j2d/loader.c+673−0
@@ -0,0 +1,673 @@
1#include "java.h"
2
3/*
4 * Class loader.
5 */
6
7Class *class; /* class under translation */
8PCode *pcode; /* pointers to byte code of defined methods */
9char *THISCLASS;
10char *SUPERCLASS;
11
12char*
13CLASSNAME(int i)
14{
15 return class->cps[class->cps[i].ci.name_index].utf8.utf8;
16}
17
18char*
19STRING(int i)
20{
21 return class->cps[i].utf8.utf8;
22}
23
24typedef union Fc Fc;
25
26union Fc
27{
28 float f;
29 uint ival;
30};
31
32static double
33canontod(uint v[])
34{
35 union { double d; uint ui[2]; } a;
36
37 a.d = 1.;
38 if(a.ui[0]) {
39 a.ui[0] = v[0];
40 a.ui[1] = v[1];
41 } else {
42 a.ui[0] = v[1];
43 a.ui[1] = v[0];
44 }
45 return a.d;
46}
47
48/*
49 * Bytecode verification.
50 */
51
52static void
53verifyutf8index(int index)
54{
55 verifycpindex(nil, index, 1 << CON_Utf8);
56 if(STRING(index) == nil)
57 verifyerrormess("nil name or descriptor");
58}
59
60static void
61verifyclassindex(int index)
62{
63 verifycpindex(nil, index, 1 << CON_Class);
64 verifyutf8index(class->cps[index].ci.name_index);
65}
66
67static void
68verifyfielddesc(int name_index, int sig_index)
69{
70 char *sig;
71 char ftype;
72
73 verifyutf8index(name_index);
74 verifyutf8index(sig_index);
75 sig = STRING(sig_index);
76 ftype = sig[0];
77 sig = nextjavatype(sig);
78 if(ftype == 'V' || sig[0] != '\0')
79 verifyerrormess("field descriptor");
80}
81
82static void
83verifymethoddesc(int name_index, int sig_index)
84{
85 char *name, *sig;
86 char rtype;
87 int wargs;
88
89 verifyutf8index(name_index);
90 name = STRING(name_index);
91 verifyutf8index(sig_index);
92 sig = STRING(sig_index);
93
94 /* check special <method> names */
95 if(name[0] == '<') {
96 if(strcmp(name, "<init>") == 0)
97 ;
98 else if(strcmp(name, "<clinit>") == 0) {
99 if(strcmp(sig, "()V") != 0)
100 verifyerrormess("<clinit> signature");
101 return;
102 } else
103 verifyerrormess("<method> name");
104 }
105
106 /* check signature */
107 if(sig[0] != '(')
108 goto bad;
109 sig++;
110 wargs = 0;
111 while(sig[0] != ')') {
112 wargs++;
113 if(sig[0] == 'J' || sig[0] == 'D')
114 wargs++;
115 sig = nextjavatype(sig);
116 }
117 sig++;
118 rtype = sig[0];
119 sig = nextjavatype(sig);
120 if(wargs > 255 || sig[0] != '\0' || (name[0] == '<' && rtype != 'V'))
121bad: verifyerrormess("method descriptor");
122}
123
124static void
125verifycpindexes(void)
126{
127 int i;
128 Const *cp;
129 int nameindex, sigindex, natindex;
130
131 for(i = 1; i < class->cp_count; i++) {
132 cp = &class->cps[i];
133 switch(class->cts[i]) {
134 case CON_Class:
135 verifyutf8index(cp->ci.name_index);
136 break;
137 case CON_Fieldref:
138 case CON_Methodref:
139 case CON_InterfaceMref:
140 verifyclassindex(cp->fmiref.class_index);
141 natindex = cp->fmiref.name_type_index;
142 verifycpindex(nil, natindex, 1 << CON_NameAndType);
143 nameindex = class->cps[natindex].nat.name_index;
144 sigindex = class->cps[natindex].nat.sig_index;
145 if(class->cts[i] == CON_Fieldref)
146 verifyfielddesc(nameindex, sigindex);
147 else
148 verifymethoddesc(nameindex, sigindex);
149 break;
150 case CON_String:
151 verifycpindex(nil, cp->string_index, 1 << CON_Utf8);
152 break;
153 case CON_Integer:
154 case CON_Float:
155 case CON_NameAndType:
156 /*
157 * CON_NameAndType is verified through
158 * CON_Fieldref, CON_Methodref, CON_InterfaceMref
159 */
160 case CON_Utf8:
161 break;
162 case CON_Long:
163 case CON_Double:
164 i++;
165 break;
166 }
167 }
168}
169
170#define CLASSMUTEX (ACC_FINAL|ACC_ABSTRACT)
171
172static void
173verifyclassflags(void)
174{
175 int bad;
176
177 if(class->access_flags & ACC_INTERFACE) {
178 if(strcmp(SUPERCLASS, "java/lang/Object") != 0)
179 verifyerrormess("superclass");
180 /* java bug: ACC_ABSTRACT should be set ???
181 bad = (class->access_flags & ACC_ABSTRACT) != ACC_ABSTRACT;
182 */
183 bad = 0;
184 bad += (class->access_flags & ACC_FINAL) != 0;
185 } else {
186 bad = (class->access_flags & CLASSMUTEX) == CLASSMUTEX;
187 }
188 if(bad)
189 verifyerrormess("access_flags");
190}
191
192static int
193multippp(int flag)
194{
195 int ret;
196
197 switch(flag & (ACC_PUBLIC|ACC_PRIVATE|ACC_PROTECTED)) {
198 case 0:
199 case ACC_PUBLIC:
200 case ACC_PRIVATE:
201 case ACC_PROTECTED:
202 ret = 0;
203 break;
204 default:
205 ret = 1;
206 break;
207 }
208 return ret;
209}
210
211#define IFACEFIELD (ACC_PUBLIC|ACC_STATIC|ACC_FINAL)
212#define _IFACEFIELD (ACC_PRIVATE|ACC_PROTECTED|ACC_VOLATILE|ACC_TRANSIENT)
213#define FIELDMUTEX (ACC_FINAL|ACC_VOLATILE)
214#define CVATTRTAGS ((1<<CON_Integer)|(1<<CON_Long)|(1<<CON_Float)|(1<<CON_Double)|(1<<CON_String))
215
216static void
217verifyfield(Field *fp)
218{
219 int bad, n;
220 char c;
221
222 verifyfielddesc(fp->name_index, fp->sig_index);
223 if(class->access_flags & ACC_INTERFACE) {
224 bad = (fp->access_flags & _IFACEFIELD) != 0;
225 bad += (fp->access_flags & IFACEFIELD) != IFACEFIELD;
226 } else {
227 bad = multippp(fp->access_flags);
228 bad += (fp->access_flags & FIELDMUTEX) == FIELDMUTEX;
229 }
230 if(bad)
231 verifyerrormess("access_flags");
232
233 /* verify ConstantValue attribute */
234 n = CVattrindex(fp);
235 if(n == 0)
236 return;
237 verifycpindex(nil, n, CVATTRTAGS);
238 c = STRING(fp->sig_index)[0];
239 switch(class->cts[n]) {
240 case CON_Integer:
241 switch(c) {
242 case 'Z':
243 case 'B':
244 case 'C':
245 case 'S':
246 case 'I':
247 bad = 0;
248 break;
249 default:
250 bad = 1;
251 break;
252 }
253 break;
254 case CON_Long:
255 bad = (c != 'J');
256 break;
257 case CON_Float:
258 bad = (c != 'F');
259 break;
260 case CON_Double:
261 bad = (c != 'D');
262 break;
263 case CON_String:
264 bad = (c != 'L');
265 break;
266 }
267 if(bad)
268 verifyerrormess("ConstantValue attribute");
269}
270
271#define IFACEMETHOD (ACC_PUBLIC|ACC_ABSTRACT)
272#define _IFACEMETHOD (ACC_PRIVATE|ACC_PROTECTED|ACC_STATIC|ACC_FINAL|ACC_SYNCHRONIZED|ACC_NATIVE)
273#define _INITFLAGS (ACC_STATIC|ACC_FINAL|ACC_SYNCHRONIZED|ACC_NATIVE|ACC_ABSTRACT)
274/* java bug: ACC_SYNCHRONIZED wrongly allowed with ACC_ABSTRACT ???
275#define METHODMUTEX (ACC_PRIVATE|ACC_STATIC|ACC_FINAL|ACC_SYNCHRONIZED|ACC_NATIVE)
276*/
277#define METHODMUTEX (ACC_PRIVATE|ACC_STATIC|ACC_FINAL|ACC_NATIVE)
278
279static void
280verifymethod(Method *mp)
281{
282 int bad;
283 char *name;
284
285 verifymethoddesc(mp->name_index, mp->sig_index);
286 name = STRING(mp->name_index);
287 if(strcmp(name, "<clinit>") == 0)
288 return;
289 if(class->access_flags & ACC_INTERFACE) {
290 bad = (mp->access_flags & _IFACEMETHOD) != 0;
291 bad += (mp->access_flags & IFACEMETHOD) != IFACEMETHOD;
292 } else {
293 bad = multippp(mp->access_flags);
294 if(strcmp(name, "<init>") == 0)
295 bad += (mp->access_flags & _INITFLAGS) != 0;
296 if(mp->access_flags & ACC_ABSTRACT)
297 bad += (mp->access_flags & METHODMUTEX) != 0;
298 }
299 if(bad)
300 verifyerrormess("access_flags");
301 /*
302 * Code attribute verified during disassembly
303 * ignore Exceptions attribute for now
304 */
305}
306
307/*
308 * Parse a byte stream into a Class stucture.
309 */
310
311static void
312byte2Class(uchar *text)
313{
314 Fc fc;
315 uint v[2];
316 int i, j;
317 Field *fp;
318 Method *mp;
319 Const *cp;
320 Attr a;
321
322 uSet(text);
323 class = Malloc(sizeof(Class));
324
325 if(u4() != 0xCAFEBABE)
326 verifyerrormess("magic");
327
328 class->min = u2();
329 class->maj = u2();
330
331 class->cp_count = u2();
332 class->cps = Mallocz(class->cp_count*sizeof(Const));
333 class->cts = Mallocz(class->cp_count);
334
335 for(i = 1; i < class->cp_count; i++) {
336 cp = &class->cps[i];
337 class->cts[i] = u1();
338 switch(class->cts[i]) {
339 case CON_Class:
340 cp->ci.name_index = u2();
341 break;
342 case CON_Fieldref:
343 case CON_Methodref:
344 case CON_InterfaceMref:
345 cp->fmiref.class_index = u2();
346 cp->fmiref.name_type_index = u2();
347 break;
348 case CON_String:
349 cp->string_index = u2();
350 break;
351 case CON_Integer:
352 cp->tint = u4();
353 break;
354 case CON_Float:
355 fc.ival = (uint)u4();
356 cp->tdouble = fc.f;
357 break;
358 case CON_Long:
359 cp->tvlong = ((vlong)u4()<<32) | (vlong)u4();
360 i++;
361 break;
362 case CON_Double:
363 v[0] = (uint)u4();
364 v[1] = (uint)u4();
365 cp->tdouble = canontod(v);
366 i++;
367 break;
368 case CON_NameAndType:
369 cp->nat.name_index = u2();
370 cp->nat.sig_index = u2();
371 break;
372 case CON_Utf8:
373 cp->utf8.ln = u2();
374 cp->utf8.utf8 = Malloc(cp->utf8.ln+1);
375 memmove(cp->utf8.utf8, uPtr(), cp->utf8.ln);
376 cp->utf8.utf8[cp->utf8.ln] = '\0';
377 uN(cp->utf8.ln);
378 break;
379 default:
380 verifyerrormess("constant pool tag");
381 }
382 }
383
384 verifycpindexes(); /* verify after all are established */
385
386 class->access_flags = u2(); /* verify after [THIS|SUPER]CLASS set */
387
388 class->this_class = u2();
389 verifyclassindex(class->this_class);
390 THISCLASS = CLASSNAME(class->this_class);
391
392 class->super_class = u2();
393 if(class->super_class != 0) {
394 verifyclassindex(class->super_class);
395 SUPERCLASS = CLASSNAME(class->super_class);
396 } else if(strcmp(THISCLASS, "java/lang/Object") != 0)
397 verifyerrormess("superclass");
398
399 verifyclassflags();
400
401 /* for compatibility with JavaSoft VM */
402 if(strncmp(THISCLASS, "inferno/vm/", sizeof("inferno/vm/")-1) == 0) {
403 /*
404 * ACC_ABSTRACT & ACC_FINAL are both set in JVM,
405 * but a class can't be declared that way
406 */
407 class->access_flags |= ACC_ABSTRACT;
408 /*
409 * ACC_SUPER not set in JVM, but javac sets it
410 * for inferno/vm/Array
411 */
412 class->access_flags &= ~ACC_SUPER;
413 } else if(class->access_flags & ACC_INTERFACE) {
414 /* interfaces are implicitly abstract */
415 class->access_flags |= ACC_ABSTRACT;
416 }
417
418 class->interfaces_count = u2();
419 if(class->interfaces_count > 0)
420 class->interfaces = Malloc(class->interfaces_count*sizeof(ushort));
421 for(i = 0; i < class->interfaces_count; i++) {
422 class->interfaces[i] = u2();
423 verifyclassindex(class->interfaces[i]);
424 }
425
426 class->fields_count = u2();
427 if(class->fields_count > 0)
428 class->fields = Malloc(class->fields_count*sizeof(Field));
429 for(i = 0, fp = class->fields; i < class->fields_count; i++, fp++) {
430 fp->access_flags = u2();
431 fp->name_index = u2();
432 fp->sig_index = u2();
433 fp->attr_count = u2();
434 if(fp->attr_count > 0)
435 fp->attr_info = Malloc(fp->attr_count*sizeof(Attr));
436 for(j = 0; j < fp->attr_count; j++)
437 getattr(&fp->attr_info[j]);
438 verifyfield(fp);
439 }
440
441 class->methods_count = u2();
442 if(class->methods_count > 0) {
443 class->methods = Malloc(class->methods_count*sizeof(Method));
444 pcode = Mallocz(class->methods_count*sizeof(PCode));
445 }
446 for(i = 0, mp = class->methods; i < class->methods_count; i++, mp++) {
447 mp->access_flags = u2();
448 mp->name_index = u2();
449 mp->sig_index = u2();
450 mp->attr_count = u2();
451 if(mp->attr_count > 0)
452 mp->attr_info = Malloc(mp->attr_count*sizeof(Attr));
453 for(j = 0; j < mp->attr_count; j++)
454 getattr(&mp->attr_info[j]);
455 verifymethod(mp);
456 }
457
458 /* get SourceFile attribute */
459 class->source_file = 0;
460 i = u2();
461 for(j = 0; j < i; j++) {
462 getattr(&a);
463 if(strcmp(STRING(a.name), "SourceFile") == 0) {
464 class->source_file = (a.info[0] << 8) | a.info[1];
465 verifyutf8index(class->source_file);
466 free(a.info);
467 break;
468 }
469 free(a.info);
470 }
471}
472
473/*
474 * Return Class structure for named class.
475 */
476
477void
478ClassLoader(char *name)
479{
480 int fd;
481 Dir dir;
482 uchar *bytecode;
483
484 fd = open(name, OREAD);
485 if(fd < 0)
486 fatal("ClassLoader: can't open %s: %r\n", name);
487
488 if(dirfstat(fd, &dir) < 0)
489 fatal("ClassLoader: can't stat %s: %r\n", name);
490
491 bytecode = Malloc(dir.length);
492 if(read(fd, bytecode, dir.length) != dir.length)
493 fatal("ClassLoader: read %s: %r\n", name);
494
495 byte2Class(bytecode);
496
497 close(fd);
498 free(bytecode);
499}
500
501/*
502 * Print access flag mnemonics.
503 */
504
505static void
506accessflags(int flags, int isclass)
507{
508 if(flags == 0)
509 return;
510 Bputc(bout, '\t');
511 if(flags & ACC_PUBLIC)
512 Bprint(bout, "|public");
513 if(flags & ACC_PRIVATE)
514 Bprint(bout, "|private");
515 if(flags & ACC_PROTECTED)
516 Bprint(bout, "|protected");
517 if(flags & ACC_STATIC)
518 Bprint(bout, "|static");
519 if(flags & ACC_FINAL)
520 Bprint(bout, "|final");
521 if(flags & ACC_SUPER) { /* ACC_SYNCHRONIZED == ACC_SUPER */
522 if(isclass)
523 Bprint(bout, "|super");
524 else
525 Bprint(bout, "|synchronized");
526 }
527 if(flags & ACC_VOLATILE)
528 Bprint(bout, "|volatile");
529 if(flags & ACC_TRANSIENT)
530 Bprint(bout, "|transient");
531 if(flags & ACC_NATIVE)
532 Bprint(bout, "|native");
533 if(flags & ACC_INTERFACE)
534 Bprint(bout, "|interface");
535 if(flags & ACC_ABSTRACT)
536 Bprint(bout, "|abstract");
537 Bputc(bout, '|');
538}
539
540/*
541 * Print out the constant pool (-c option).
542 */
543
544void
545dumpcpool(void)
546{
547 int i, n;
548 Field *fp;
549 Method *mp;
550 Const *cp;
551
552 Bprint(bout, "# -- Constant Pool Start --\n");
553 Bprint(bout, "# minor: %d\n", class->min);
554 Bprint(bout, "# major: %d\n", class->maj);
555
556 Bprint(bout, "# constant pool count: %d\n", class->cp_count);
557
558 for(i = 1; i < class->cp_count; i++) {
559 Bprint(bout, "# %d ", i);
560 cp = &class->cps[i];
561 switch(class->cts[i]) {
562 case CON_Class:
563 Bprint(bout, "Class %d", cp->ci.name_index);
564 Bprint(bout, "\t\"%s\"\n",
565 STRING(cp->ci.name_index));
566 break;
567 case CON_Fieldref:
568 Bprint(bout, "Field Ref %d %d\n",
569 cp->fmiref.class_index, cp->fmiref.name_type_index);
570 break;
571 case CON_Methodref:
572 Bprint(bout, "Method Ref %d %d\n",
573 cp->fmiref.class_index, cp->fmiref.name_type_index);
574 break;
575 case CON_InterfaceMref:
576 Bprint(bout, "InterfaceMethod Ref %d %d\n",
577 cp->fmiref.class_index, cp->fmiref.name_type_index);
578 break;
579 case CON_String:
580 Bprint(bout, "String %d", cp->string_index);
581 Bprint(bout, "\t\"");
582 pstring(STRING(cp->string_index));
583 Bprint(bout, "\"\n");
584 break;
585 case CON_Integer:
586 Bprint(bout, "Int %d\n", cp->tint);
587 break;
588 case CON_Float:
589 Bprint(bout, "Float %g\n", cp->tdouble);
590 break;
591 case CON_Long:
592 Bprint(bout, "Long %lld\n", cp->tvlong);
593 i++;
594 break;
595 case CON_Double:
596 Bprint(bout, "Double %g\n", cp->tdouble);
597 i++;
598 break;
599 case CON_NameAndType:
600 Bprint(bout, "N&T %d %d",
601 cp->nat.name_index, cp->nat.sig_index);
602 Bprint(bout, "\t\"%s\", \"%s\"\n",
603 STRING(cp->nat.name_index),
604 STRING(cp->nat.sig_index));
605 break;
606 case CON_Utf8:
607 Bprint(bout, "utf8 \"");
608 pstring(cp->utf8.utf8);
609 Bprint(bout, "\"\n");
610 break;
611 }
612 }
613
614 Bprint(bout, "# access flags: %d", class->access_flags);
615 accessflags(class->access_flags, 1);
616 Bputc(bout, '\n');
617
618 Bprint(bout, "# this_class: %d\t\"%s\"\n",
619 class->this_class, THISCLASS);
620 Bprint(bout, "# super_class: %d", class->super_class);
621 if(SUPERCLASS)
622 Bprint(bout, "\t\"%s\"", SUPERCLASS);
623 Bputc(bout, '\n');
624
625 Bprint(bout, "# interfaces: %d\n", class->interfaces_count);
626 for(i = 0; i < class->interfaces_count; i++) {
627 Bprint(bout, "#\t%s\n", CLASSNAME(class->interfaces[i]));
628 }
629
630 Bprint(bout, "# fields: %d\n", class->fields_count);
631 for(i = 0, fp = class->fields; i < class->fields_count; i++, fp++) {
632 Bprint(bout, "#\t%s: %s", STRING(fp->name_index),
633 STRING(fp->sig_index));
634 accessflags(fp->access_flags, 0);
635 Bputc(bout, '\n');
636 n = CVattrindex(fp);
637 if(n == 0)
638 continue;
639 Bprint(bout, "#\t\tConstantValue: ");
640 cp = &class->cps[n];
641 switch(class->cts[n]) {
642 case CON_Integer:
643 Bprint(bout, "Int %d\n", cp->tint);
644 break;
645 case CON_Long:
646 Bprint(bout, "Long %lld\n", cp->tvlong);
647 break;
648 case CON_Float:
649 Bprint(bout, "Float %g\n", cp->tdouble);
650 break;
651 case CON_Double:
652 Bprint(bout, "Double %g\n", cp->tdouble);
653 break;
654 case CON_String:
655 Bprint(bout, "String \"%s\"\n",
656 STRING(cp->ci.name_index));
657 break;
658 }
659 }
660
661 Bprint(bout, "# methods: %d\n", class->methods_count);
662 for(i = 0, mp = class->methods; i < class->methods_count; i++, mp++) {
663 Bprint(bout, "# %d Method %d sig %d",
664 i, mp->name_index, mp->sig_index);
665 Bprint(bout, "\t%s%s", STRING(mp->name_index),
666 STRING(mp->sig_index));
667 accessflags(mp->access_flags, 0);
668 Bputc(bout, '\n');
669 }
670
671 Bprint(bout, "# class attribute ignored\n");
672 Bprint(bout, "# -- Constant Pool End --\n");
673}
java/tools/j2d/ltreloc.c+404−0
@@ -0,0 +1,404 @@
1#include "java.h"
2#include "reloc.h"
3
4/*
5 * Manage load-time resolution information.
6 */
7
8typedef struct LTHash LTHash;
9
10struct LTHash
11{
12 Creloc *cr;
13 LTHash *next;
14};
15
16 int doclinitinits;
17static LTHash *lttbl[Hashsize]; /* hash table of referenced classes */
18static Creloc *thisclass; /* class under translation */
19static int nltclasses; /* no. of classes referenced */
20
21/*
22 * Allocate a Creloc structure.
23 */
24
25static Creloc*
26newCreloc(char *s)
27{
28 Creloc *cr;
29
30 cr = Malloc(sizeof(Creloc));
31 cr->classname = s;
32 cr->fr = nil;
33 cr->tail = nil;
34 cr->n = 0;
35 nltclasses += 1;
36 return cr;
37}
38
39static void
40ltappend(Creloc *cr, Freloc *fr)
41{
42 if(cr->fr == nil)
43 cr->fr = fr;
44 else
45 cr->tail->next = fr;
46 cr->tail = fr;
47}
48
49static void
50ltprepend(Creloc *cr, Freloc *fr)
51{
52 if(cr->fr == nil)
53 cr->tail = fr;
54 fr->next = cr->fr;
55 cr->fr = fr;
56}
57
58/*
59 * Add Freloc entry.
60 */
61
62static Freloc*
63addFreloc(Creloc *cr, char *field, char *sig, uint flags)
64{
65 Freloc *fr;
66
67 fr = Malloc(sizeof(Freloc));
68 fr->field = field;
69 fr->sig = sig;
70 fr->flags = flags;
71 fr->ipatch = Mallocz(sizeof(Ipatch));
72 fr->next = nil;
73 if(field[0] == '@') /* these must go first in the list ! */
74 ltprepend(cr, fr);
75 else
76 ltappend(cr, fr);
77 cr->n += 1;
78 return fr;
79}
80
81/*
82 * Add Creloc entry for classname.
83 */
84
85static Creloc*
86addCreloc(char *classname)
87{
88 uint h;
89 LTHash *he;
90
91 h = hashval(classname);
92 he = Malloc(sizeof(LTHash));
93 he->cr = newCreloc(classname);
94 he->next = lttbl[h];
95 lttbl[h] = he;
96 return he->cr;
97}
98
99/*
100 * Get Creloc entry for classname.
101 */
102
103Creloc*
104getCreloc(char *classname)
105{
106 LTHash *he;
107
108 for(he = lttbl[hashval(classname)]; he; he = he->next) {
109 if(strcmp(classname, he->cr->classname) == 0)
110 return he->cr;
111 }
112 return addCreloc(classname);
113}
114
115/*
116 * Get Freloc entry. Ignore signature if nil.
117 */
118
119Freloc*
120getFreloc(Creloc *cr, char *field, char *sig, uint flags)
121{
122 Freloc *fr;
123 uint lowflags;
124
125 lowflags = 0;
126 for(fr = cr->fr; fr; fr = fr->next) {
127 if(strcmp(fr->field, field) == 0
128 && (sig == nil || strcmp(fr->sig, sig) == 0)) {
129 if(fr->flags >> 16 == 0) {
130 fr->flags |= flags;
131 return fr;
132 } else if(fr->flags >> 16 == flags >> 16)
133 return fr;
134 lowflags = fr->flags & 0xffff;
135 }
136 }
137
138 return addFreloc(cr, field, sig, flags|lowflags);
139}
140
141/*
142 * Seed Creloc for this class.
143 */
144
145void
146thisCreloc(void)
147{
148 int i, haveclinit;
149 Field *fp;
150 Method *mp;
151
152 thisclass = addCreloc(THISCLASS);
153
154 /* class access_flags here for the benefit of interfaces */
155 addFreloc(thisclass, RCLASS, nil, class->access_flags|compileflag);
156
157 /* data */
158 for(i = 0, fp = class->fields; i < class->fields_count; i++, fp++) {
159 addFreloc(thisclass, STRING(fp->name_index),
160 STRING(fp->sig_index), fp->access_flags);
161 if((fp->access_flags & ACC_STATIC) && CVattrindex(fp))
162 doclinitinits = 1;
163 }
164
165 /* methods */
166 haveclinit = 0;
167 for(i = 0, mp = class->methods; i < class->methods_count; i++, mp++) {
168 addFreloc(thisclass, STRING(mp->name_index),
169 STRING(mp->sig_index), mp->access_flags);
170 if(strcmp(STRING(mp->name_index), "<clinit>") == 0)
171 haveclinit = 1;
172 }
173 if(doclinitinits && haveclinit == 0)
174 addFreloc(thisclass, "<clinit>", "()V", ACC_STATIC);
175 if((class->access_flags & (ACC_INTERFACE | ACC_ABSTRACT)) == 0)
176 addFreloc(thisclass, "<clone>", "()V", ACC_STATIC);
177}
178
179/*
180 * Add instruction patch information to Freloc fr.
181 */
182
183void
184LTIpatch(Freloc *fr, Inst *i, int operand, int patchkind)
185{
186 addIpatch(fr->ipatch, i, operand, patchkind, !SAVEINST);
187}
188
189/*
190 * Size of Module Data space taken by load-time relocation information.
191 * Includes nil terminator.
192 */
193
194int
195LTrelocsize(void)
196{
197 return align((9 + 2*(nltclasses-1)) * IBY2WD, 32);
198}
199
200/*
201 * Fix type descriptor for relocation information.
202 */
203
204static int Freloctid, Ifacetid;
205
206void
207LTrelocdesc(uchar *map)
208{
209 int i, bit;
210
211 Freloctid = descid(4*IBY2WD, 1, (uchar*)"\xd0");
212 setIpatchtid(); /* force type id for patch info */
213 Ifacetid = descid(IBY2WD, 1, (uchar*)"\x80");
214
215 setbit(map, 8); /* Class name */
216 setbit(map, 12); /* Superclass name */
217 setbit(map, 16); /* Interfaces */
218 setbit(map, 20); /* Class relocation */
219 setbit(map, 28); /* Data relocation */
220 /*
221 * even i: Class name
222 * odd i: Class relocation
223 */
224 bit = 32;
225 for(i = 0; i < (nltclasses-1)*2; i++) {
226 setbit(map, bit);
227 bit += 4;
228 }
229 setbit(map, bit); /* nil */
230}
231
232/*
233 * Write Freloc array to .s file.
234 */
235
236static void
237asmFreloc(int off, Creloc *cr)
238{
239 Freloc *fr;
240 int reloff; /* relative offset for array elements */
241
242 reloff = 0;
243 asmarray(off, Freloctid, cr->n, reloff); /* cr->n != 0, always */
244 for(fr = cr->fr; fr; fr = fr->next) {
245 asmstring(reloff, fr->field);
246 reloff += IBY2WD;
247 if(fr->sig)
248 asmstring(reloff, fr->sig);
249 reloff += IBY2WD;
250 asmint(reloff, fr->flags);
251 reloff += IBY2WD;
252 asmIpatch(reloff, fr->ipatch);
253 reloff += IBY2WD;
254 }
255 Bprint(bout, "\tapop\n");
256}
257
258/*
259 * Write Creloc's (except for this_class) to .s file.
260 */
261
262int
263asmCreloc(int off)
264{
265 LTHash *he;
266 int i;
267
268 for(i = 0; i < Hashsize; i++) {
269 for(he = lttbl[i]; he; he = he->next) {
270 if(he->cr == thisclass)
271 continue;
272 asmstring(off, he->cr->classname);
273 off += IBY2WD;
274 asmFreloc(off, he->cr);
275 off += IBY2WD;
276 }
277 }
278 off += IBY2WD; /* skip past nil */
279 return off;
280}
281
282enum {
283 JVNO = '4',
284 JMAGIC = ('J'<<24)|('a'<<16)|('v'<<8)|'a',
285 JVERSION = ('S'<<24)|('u'<<16)|('x'<<8)|JVNO
286};
287
288/*
289 * Write Creloc for this_class to .s file.
290 */
291
292int
293asmthisCreloc(int off)
294{
295 int i;
296 int reloff; /* relative offset for array elements */
297
298 asmint(off, JMAGIC);
299 off += IBY2WD;
300 asmint(off, JVERSION);
301 off += IBY2WD;
302 asmstring(off, THISCLASS);
303 off += IBY2WD;
304 if(SUPERCLASS) /* Object has no superclass */
305 asmstring(off, SUPERCLASS);
306 off += IBY2WD;
307 if(class->interfaces_count > 0) {
308 reloff = 0;
309 asmarray(off, Ifacetid, class->interfaces_count, reloff);
310 for(i = 0; i < class->interfaces_count; i++) {
311 asmstring(reloff, CLASSNAME(class->interfaces[i]));
312 reloff += IBY2WD;
313 }
314 Bprint(bout, "\tapop\n");
315 }
316 off += IBY2WD;
317 asmFreloc(off, thisclass);
318 off += IBY2WD;
319 return off;
320}
321
322/*
323 * Write Freloc array to .dis file.
324 */
325
326static void
327disFreloc(int off, Creloc *cr)
328{
329 Freloc *fr;
330 int reloff; /* relative offset for array elements */
331
332 reloff = 0;
333 disarray(off, Freloctid, cr->n);
334 for(fr = cr->fr; fr; fr = fr->next) {
335 disstring(reloff, fr->field);
336 reloff += IBY2WD;
337 if(fr->sig)
338 disstring(reloff, fr->sig);
339 reloff += IBY2WD;
340 disint(reloff, fr->flags);
341 reloff += IBY2WD;
342 disIpatch(reloff, fr->ipatch);
343 reloff += IBY2WD;
344 }
345 disapop();
346}
347
348/*
349 * Write Creloc's (except for this_class) to .dis file.
350 */
351
352int
353disCreloc(int off)
354{
355 LTHash *he;
356 int i;
357
358 for(i = 0; i < Hashsize; i++) {
359 for(he = lttbl[i]; he; he = he->next) {
360 if(he->cr == thisclass)
361 continue;
362 disstring(off, he->cr->classname);
363 off += IBY2WD;
364 disFreloc(off, he->cr);
365 off += IBY2WD;
366 }
367 }
368 off += IBY2WD; /* skip past nil */
369 return off;
370}
371
372/*
373 * Write Creloc for this_class to .dis file.
374 */
375
376int
377disthisCreloc(int off)
378{
379 int i;
380 int reloff; /* relative offset for array elements */
381
382 disint(off, JMAGIC);
383 off += IBY2WD;
384 disint(off, JVERSION);
385 off += IBY2WD;
386 disstring(off, THISCLASS);
387 off += IBY2WD;
388 if(SUPERCLASS) /* Object has no superclass */
389 disstring(off, SUPERCLASS);
390 off += IBY2WD;
391 if(class->interfaces_count > 0) {
392 reloff = 0;
393 disarray(off, Ifacetid, class->interfaces_count);
394 for(i = 0; i < class->interfaces_count; i++) {
395 disstring(reloff, CLASSNAME(class->interfaces[i]));
396 reloff += IBY2WD;
397 }
398 disapop();
399 }
400 off += IBY2WD;
401 disFreloc(off, thisclass);
402 off += IBY2WD;
403 return off;
404}
java/tools/j2d/main.c+196−0
@@ -0,0 +1,196 @@
1#include "java.h"
2//#include "libcrypt.h"
3#include "reloc.h"
4
5static int gendis; /* generate .dis rather than .s (default) */
6static int emitcpool; /* -p: emit constant pool (with -S only) */
7 int gensbl; /* -g: generate .sbl file */
8 int compileflag; /* -c (MUSTCOMPILE) & -C (DONTCOMPILE) */
9 int verbose; /* -v: emit Java instructions (with -S only) */
10 Biobuf *bout;
11 char *ofile;
12
13static void
14usage(void)
15{
16 print("usage: j2d [-cgpvCS] [-o outfile] file.class\n");
17 exits("usage");
18}
19
20/*
21 * Translate .class file (in) into .s or .dis (out).
22 */
23
24static void
25translate(char *in, char *out)
26{
27 ClassLoader(in);
28
29 bout = Bopen(out, OWRITE);
30 if(bout == nil)
31 fatal("can't open %s: %r\n", out);
32
33 if(emitcpool != 0)
34 dumpcpool();
35
36 thisCreloc();
37 crefseed();
38 xlate();
39 mpdesc();
40 /* Patch frame/call for invokespecial/invokestatic. */
41 dofcpatch();
42 /* Patch instructions for run-time resolution. */
43 doRTpatch();
44
45 if(gendis == 0) { /* generate .s file */
46 asminst();
47 asmentry();
48 asmdesc();
49 asmvar();
50 asmmod();
51 asmlinks();
52 } else
53 disout(); /* generate .dis file */
54
55 if(gensbl) /* generate .sbl file */
56 sblout(out);
57
58 Bterm(bout);
59}
60
61enum {
62 MAXUNENCODED = NAMELEN - 7,
63 ENCODEDLEN = 21
64};
65
66static char encoding[] = {
67 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
68 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
69 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
70 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
71 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
72 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
73 'w', 'x', 'y', 'z', '0', '1', '2', '3',
74 '4', '5', '6', '7', '8', '9', '+', '-',
75};
76
77static char*
78encodename(char *name, int ln)
79{
80 char *e;
81 int i, n, r, v;
82 uchar d[MD5dlen];
83
84 md5((uchar*)name, ln, d, nil);
85 e = Malloc(ENCODEDLEN+1);
86 n = 0;
87 r = 0;
88 v = 0;
89 for(i = 0; i < ENCODEDLEN; i++) {
90 if(r < 6) {
91 v |= d[n++] << r;
92 r += 8;
93 }
94 e[i] = encoding[v & 0x3F];
95 v >>= 6;
96 r -= 6;
97 }
98 e[ENCODEDLEN] = '\0';
99 return e;
100}
101
102/*
103 * Construct output filename.
104 */
105
106static char*
107mkfileext(char *file, char *ext)
108{
109 char *s;
110 int n;
111
112 n = strlen(file);
113 if(n <= 6 || strcmp(&file[n-6], ".class") != 0)
114 usage();
115 else
116 n -= 6;
117 if(n > MAXUNENCODED) {
118 file = encodename(file, n);
119 n = ENCODEDLEN;
120 }
121 s = Malloc(n + strlen(ext) + 1);
122 memmove(s, file, n);
123 strcpy(s+n, ext);
124 print("%s\n", s); /* print filename for [mk|make]file's */
125 return s;
126}
127
128extern int gfltconv(va_list*, Fconv*);
129
130void
131main(int argc, char *argv[])
132{
133 char *ext, *s;
134
135 fmtinstall('A', Aconv);
136 fmtinstall('I', Iconv);
137 fmtinstall('J', Jconv);
138 fmtinstall('g', gfltconv);
139
140 gendis = 1;
141
142 ARGBEGIN{
143 case 'C':
144 compileflag |= _DONTCOMPILE;
145 break;
146 case 'S':
147 gendis = 0;
148 break;
149 case 'c':
150 compileflag |= _MUSTCOMPILE;
151 break;
152 case 'g':
153 gensbl = 1;
154 break;
155 case 'p':
156 emitcpool = 1;
157 break;
158 case 'o':
159 ofile = ARGF();
160 break;
161 case 'v':
162 verbose = 1;
163 break;
164 default:
165 usage();
166 break;
167 }ARGEND
168
169 if(argc != 1)
170 usage();
171 if(compileflag == (_MUSTCOMPILE|_DONTCOMPILE)) {
172 print("j2d: warning: -c and -C are mutually exclusive, ignoring\n");
173 compileflag = 0;
174 }
175 if((verbose != 0 || emitcpool != 0) && gendis != 0) {
176 print("j2d: warning: -p/-v only allowed with -S, ignoring\n");
177 emitcpool = 0;
178 verbose = 0;
179 }
180 if(ofile)
181 translate(argv[0], ofile);
182 else {
183 if(gendis == 0)
184 ext = ".s";
185 else
186 ext = ".dis";
187 s = strrchr(argv[0], '/');
188 if(s == nil)
189 s = argv[0];
190 else
191 s++;
192 ofile = mkfileext(s, ext);
193 translate(argv[0], ofile);
194 }
195 exits(nil);
196}
java/tools/j2d/mdata.c+513−0
@@ -0,0 +1,513 @@
1#include "java.h"
2#include "reloc.h"
3
4/*
5 * Manage module Data Section.
6 */
7
8enum {
9 MP_INT,
10 MP_LONG,
11 MP_REAL,
12 MP_STRING,
13 MP_CASE,
14 MP_GOTO
15};
16
17typedef struct Hentry Hentry;
18typedef struct Datum Datum;
19
20struct Datum {
21 uchar kind; /* MP_INT, etc. */
22 int offset; /* byte offset in Data Section */
23 union {
24 struct {
25 union {
26 vlong ival; /* MP_INT, MP_LONG */
27 double rval; /* MP_REAL */
28 } u;
29 Datum *next;
30 } v;
31 char *s; /* MP_STRING */
32 struct { /* MP_CASE */
33 int n; /* number of cases in jmptbl */
34 int *jmptbl;/* 3 words per case, plus default */
35 } c;
36 struct { /* MP_GOTO (for finally blocks) */
37 int n; /* number of entries in gototbl */
38 int *gototbl;
39 } g;
40 } u;
41 Datum *next;
42};
43
44struct Hentry
45{
46 Datum *md;
47 Hentry *next;
48};
49
50static Hentry *htable[Hashsize];
51static int mpoff;
52
53static Datum *mplist = nil;
54static Datum *mptail = nil;
55static Datum *llist = nil;
56static Datum *rlist = nil;
57
58/*
59 * Allocate a Datum structure.
60 */
61
62static Datum*
63newDatum(uchar kind)
64{
65 Datum *md;
66
67 md = Malloc(sizeof(Datum));
68 md->kind = kind;
69 md->next = nil;
70 md->u.v.next = nil;
71 return md;
72}
73
74/*
75 * Append a module datum to mplist.
76 */
77
78static void
79append(Datum *md)
80{
81 if(mplist == nil)
82 mplist = md;
83 else
84 mptail->next = md;
85 mptail = md;
86}
87
88/*
89 * Add a 'byte', int 'word', or 'long'.
90 */
91
92static int
93mpintegral(uchar kind, vlong ival)
94{
95 Datum *md;
96 int size;
97
98 md = newDatum(kind);
99 md->u.v.u.ival = ival;
100 switch(kind) {
101 case MP_INT:
102 size = IBY2WD;
103 mpoff = align(mpoff, IBY2WD);
104 break;
105 case MP_LONG:
106 size = IBY2LG;
107 mpoff = align(mpoff, IBY2LG);
108 md->u.v.next = llist;
109 llist = md;
110 break;
111 default:
112 SET(size); /* not reached */
113 }
114 md->offset = mpoff;
115 mpoff += size;
116 append(md);
117 return md->offset;
118}
119
120/*
121 * Add a 'word' (int).
122 */
123
124int
125mpint(int ival)
126{
127 return mpintegral(MP_INT, ival);
128}
129
130/*
131 * Add a 'long'.
132 */
133
134int
135mplong(vlong lval)
136{
137 Datum *md;
138
139 for(md = llist; md; md = md->u.v.next) {
140 if(lval == md->u.v.u.ival)
141 return md->offset;
142 }
143 return mpintegral(MP_LONG, lval);
144}
145
146/*
147 * Add a 'real'.
148 */
149
150/* from math/dtoa.c */
151#ifdef __LITTLE_ENDIAN
152#define word0(x) ((unsigned long*)&x)[1]
153#else
154#define word0(x) ((unsigned long*)&x)[0]
155#endif
156#define Sign_bit 0x80000000
157
158int
159mpreal(double rval)
160{
161 Datum *md;
162
163 for(md = rlist; md; md = md->u.v.next) {
164 /* distinguish 0.0 from -0.0 */
165 if(rval == md->u.v.u.rval &&
166 (word0(rval) & Sign_bit) == (word0(md->u.v.u.rval) & Sign_bit))
167 return md->offset;
168 }
169 md = newDatum(MP_REAL);
170 md->u.v.u.rval = rval;
171 md->u.v.next = rlist;
172 rlist = md;
173 mpoff = align(mpoff, IBY2FT);
174 md->offset = mpoff;
175 mpoff += IBY2FT;
176 append(md);
177 return md->offset;
178}
179
180/*
181 * Add a 'case' jump table.
182 */
183
184int
185mpcase(int sz, int *jt)
186{
187 Datum *md;
188
189 md = newDatum(MP_CASE);
190 mpoff = align(mpoff, IBY2WD);
191 md->offset = mpoff;
192 mpoff += (sz*3+2)*IBY2WD;
193 md->u.c.n = sz;
194 md->u.c.jmptbl = jt;
195 append(md);
196 return md->offset;
197}
198
199/*
200 * Add a 'goto' jump table; used for implementing finally blocks.
201 */
202
203int
204mpgoto(int n, int *gototbl)
205{
206 Datum *md;
207
208 md = newDatum(MP_GOTO);
209 mpoff = align(mpoff, IBY2WD);
210 md->offset = mpoff;
211 mpoff += (n+2)*IBY2WD;
212 md->u.g.n = n;
213 md->u.g.gototbl = gototbl;
214 append(md);
215 return md->offset+IBY2WD;
216}
217
218/*
219 * Hash table lookup function.
220 */
221
222static Hentry*
223htlook(char *s)
224{
225 Hentry *he;
226
227 for(he = htable[hashval(s)]; he; he = he->next)
228 if(strcmp(s, he->md->u.s) == 0)
229 return he;
230 return nil;
231}
232
233/*
234 * Hash table enter function.
235 */
236
237static Hentry*
238htenter(Datum *md)
239{
240 uint h;
241 Hentry *he;
242
243 h = hashval(md->u.s);
244 he = Malloc(sizeof(Hentry));
245 he->md = md;
246 he->next = htable[h];
247 htable[h] = he;
248 return he;
249}
250
251/*
252 * Add a 'string'.
253 */
254
255int
256mpstring(char *s)
257{
258 Hentry *he;
259 Datum *md;
260
261 if(he = htlook(s))
262 return he->md->offset;
263 md = newDatum(MP_STRING);
264 md->u.s = s;
265 mpoff = align(mpoff, IBY2WD);
266 md->offset = mpoff;
267 mpoff += IBY2WD;
268 append(md);
269 htenter(md);
270 return md->offset;
271}
272
273/*
274 * Calculate the type descriptor for the Module Data section.
275 */
276
277void
278mpdesc(void)
279{
280 Datum *md;
281 int ltsize, rtsize, ln, mdsize;
282 uchar *map;
283
284 ltsize = LTrelocsize(); /* link-time reloc data */
285 mpoff = align(mpoff, IBY2WD);
286 rtsize = RTrelocsize(); /* run-time reloc data */
287 mdsize = ltsize + mpoff + rtsize;
288 ln = mdsize / (8*IBY2WD) + (mdsize % (8*IBY2WD) != 0);
289 map = Mallocz(ln);
290 LTrelocdesc(map);
291 for(md = mplist; md; md = md->next) {
292 if(md->kind == MP_STRING)
293 setbit(map, ltsize + md->offset);
294 }
295 RTrelocdesc(map, ltsize + mpoff);
296 RTfixoff(ltsize + mpoff);
297 mpdescid(mdsize, ln, map);
298}
299
300static void
301asmprefix(int off, char *s)
302{
303 Bprint(bout, "\t%s\t@mp+%d,", s, off);
304}
305
306/*
307 * Begin an array initializer.
308 */
309
310void
311asmarray(int off, int tid, int nelt, int reloff)
312{
313 asmprefix(off, "array");
314 Bprint(bout, "$%d,%d\n", tid, nelt);
315 asmprefix(off, "indir");
316 Bprint(bout, "%d\n", reloff);
317}
318
319void
320asmint(int off, int val)
321{
322 asmprefix(off, "word");
323 Bprint(bout, "%d\n", val);
324}
325
326static void
327asmlong(int off, vlong val)
328{
329 asmprefix(off, "long");
330 Bprint(bout, "%lld\n", val);
331}
332
333static void
334asmreal(int off, double val)
335{
336 asmprefix(off, "real");
337 Bprint(bout, "%g\n", val);
338}
339
340void
341asmstring(int off, char *s)
342{
343 asmprefix(off, "string");
344 Bputc(bout, '"');
345 pstring(s);
346 Bprint(bout, "\"\n");
347}
348
349static void
350asmcase(int off, Datum *md)
351{
352 int i;
353
354 asmprefix(off, "word");
355 Bprint(bout, "%d", md->u.c.n);
356 for(i = 0; i < md->u.c.n; i++) {
357 Bprint(bout, ",%d", md->u.c.jmptbl[i*3]);
358 Bprint(bout, ",%d", md->u.c.jmptbl[i*3+1]);
359 Bprint(bout, ",%d", md->u.c.jmptbl[i*3+2]);
360 }
361 Bprint(bout, ",%d\n", md->u.c.jmptbl[md->u.c.n*3]);
362}
363
364static void
365asmgoto(int off, Datum *md)
366{
367 int i;
368
369 asmprefix(off, "word");
370 Bprint(bout, "%d", md->u.g.n);
371 for(i = 0; i < md->u.g.n; i++)
372 Bprint(bout, ",%d", md->u.g.gototbl[i]);
373 Bputc(bout, '\n');
374}
375
376/*
377 * Write Module Data to .s file.
378 */
379
380void
381asmvar(void)
382{
383 Datum *md;
384 int ltsize, rtsize, off;
385
386 ltsize = LTrelocsize();
387 rtsize = RTrelocsize();
388 Bprint(bout, "\tvar\t@mp,%d\n", ltsize + mpoff + rtsize);
389 off = asmthisCreloc(0);
390 asmint(off, mpoff + rtsize);
391 off += IBY2WD;
392 asmDreloc(off);
393 off += IBY2WD;
394 off = asmCreloc(off);
395 off = align(off, 32);
396 if(off != ltsize)
397 fatal("asmvar: off %d, ltsize %d\n", off, ltsize);
398
399 for(md = mplist; md; md = md->next) {
400 off = ltsize + md->offset;
401 switch(md->kind) {
402 case MP_INT:
403 asmint(off, md->u.v.u.ival);
404 break;
405 case MP_LONG:
406 asmlong(off, md->u.v.u.ival);
407 break;
408 case MP_REAL:
409 asmreal(off, md->u.v.u.rval);
410 break;
411 case MP_STRING:
412 asmstring(off, md->u.s);
413 break;
414 case MP_CASE:
415 asmcase(off, md);
416 break;
417 case MP_GOTO:
418 asmgoto(off, md);
419 break;
420 }
421 }
422 asmRTClass(ltsize + mpoff);
423}
424
425/*
426 * Put Module Data size into .dis Header.
427 */
428
429void
430disnvar(void)
431{
432 discon(LTrelocsize() + mpoff + RTrelocsize());
433}
434
435static void
436discase(int off, Datum *md)
437{
438 int i;
439
440 disint(off, md->u.c.n);
441 off += IBY2WD;
442 for(i = 0; i < md->u.c.n; i++) {
443 disint(off, md->u.c.jmptbl[i*3]);
444 off += IBY2WD;
445 disint(off, md->u.c.jmptbl[i*3+1]);
446 off += IBY2WD;
447 disint(off, md->u.c.jmptbl[i*3+2]);
448 off += IBY2WD;
449 }
450 disint(off, md->u.c.jmptbl[md->u.c.n*3]);
451}
452
453static void
454disgoto(int off, Datum *md)
455{
456 int i;
457
458 disint(off, md->u.g.n);
459 for(i = 0; i < md->u.g.n; i++) {
460 off += IBY2WD;
461 disint(off, md->u.g.gototbl[i]);
462 }
463}
464
465/*
466 * Write Module Data to .dis file.
467 */
468
469void
470disvar(void)
471{
472 Datum *md;
473 int ltsize, rtsize, off;
474
475 ltsize = LTrelocsize();
476 rtsize = RTrelocsize();
477 off = disthisCreloc(0);
478 disint(off, mpoff + rtsize);
479 off += IBY2WD;
480 disDreloc(off);
481 off += IBY2WD;
482 off = disCreloc(off);
483 off = align(off, 32);
484 if(off != ltsize)
485 fatal("disvar: off %d, ltsize %d\n", off, ltsize);
486
487 for(md = mplist; md; md = md->next) {
488 off = ltsize + md->offset;
489 switch(md->kind) {
490 case MP_INT:
491 disint(off, md->u.v.u.ival);
492 break;
493 case MP_LONG:
494 dislong(off, md->u.v.u.ival);
495 break;
496 case MP_REAL:
497 disreal(off, md->u.v.u.rval);
498 break;
499 case MP_STRING:
500 disstring(off, md->u.s);
501 break;
502 case MP_CASE:
503 discase(off, md);
504 break;
505 case MP_GOTO:
506 disgoto(off, md);
507 break;
508 }
509 }
510 disRTClass(ltsize + mpoff);
511 disflush(-1, -1, 0);
512 Bputc(bout, 0);
513}
java/tools/j2d/mkfile+45−0
@@ -0,0 +1,45 @@
1<../../../mkconfig
2
3LIBS=\
4 bio\
5 crypt\
6 math\
7 9
8
9TARG=j2d
10
11OFILES=\
12 asm.$O\
13 bb.$O\
14 datarloc.$O\
15 desc.$O\
16 dis.$O\
17 entry.$O\
18 finally.$O\
19 frame.$O\
20 javadas.$O\
21 javatbl.$O\
22 links.$O\
23 loader.$O\
24 ltreloc.$O\
25 main.$O\
26 mdata.$O\
27 module.$O\
28 patch.$O\
29 rtreloc.$O\
30 sbl.$O\
31 simjvm.$O\
32 unify.$O\
33 util.$O\
34 xlate.$O
35
36HFILES=\
37 java.h\
38 $ROOT/include/bio.h\
39 $ROOT/include/isa.h\
40# $ROOT/include/libcrypt.h\
41 $ROOT/$OBJDIR/include/lib9.h
42
43BIN=$ROOT/$OBJDIR/bin
44
45<$ROOT/mkfiles/mkone-$SHELLTYPE
java/tools/j2d/module.c+21−0
@@ -0,0 +1,21 @@
1#include "java.h"
2
3/*
4 * Emit 'module' assembly directive.
5 */
6
7void
8asmmod(void)
9{
10 Bprint(bout, "\tmodule\t%s\n", THISCLASS);
11}
12
13void
14dismod(void)
15{
16 char name[NAMELEN];
17
18 strncpy(name, THISCLASS, NAMELEN);
19 name[NAMELEN-1] = '\0';
20 Bwrite(bout, name, strlen(name)+1);
21}
java/tools/j2d/patch.c+132−0
@@ -0,0 +1,132 @@
1#include "java.h"
2
3/*
4 * Patch operands, etc. that reference pc offsets.
5 */
6
7enum {
8 P_CASE = 1,
9 P_OTHER
10};
11
12typedef struct Patch Patch;
13
14struct Patch {
15 uchar kind; /* P_xxx */
16 Inst *i;
17 int n; /* number of cases in ... */
18 int *jmptbl; /* ... case jump table */
19 Patch *next;
20};
21
22static Patch *plist;
23
24/*
25 * Allocate a Patch structure.
26 */
27
28static Patch*
29newPatch(uchar kind, Inst *i)
30{
31 Patch *p;
32
33 p = Malloc(sizeof(Patch));
34 p->kind = kind;
35 p->i = i;
36 p->next = plist;
37 plist = p;
38 return p;
39}
40
41/*
42 * Record non-case branch instruction for later patching.
43 */
44
45void
46patchop(Inst *i)
47{
48 newPatch(P_OTHER, i);
49}
50
51/*
52 * Record case jump table for later patching.
53 */
54
55void
56patchcase(Inst *i, int n, int *jmptbl)
57{
58 Patch *p;
59
60 p = newPatch(P_CASE, i);
61 p->n = n;
62 p->jmptbl = jmptbl;
63}
64
65/*
66 * Calculate patch address; Java branches are relative.
67 */
68
69static int
70patchaddr(Inst *i, int pc)
71{
72 Jinst *j;
73 int span, srcjpc, dstjpc;
74
75 span = pc;
76 srcjpc = i->j->pc;
77 dstjpc = srcjpc + span;
78 j = &code->j[dstjpc];
79
80 /* account for no-op's (dup, swap, pop, etc.), elided loads/stores */
81 while(j->dis == nil)
82 j += j->size;
83
84 return j->dis->pc;
85}
86
87/*
88 * Patch branch instructions and case jump tables of a method.
89 */
90
91void
92patchmethod(int startpc)
93{
94 Patch *p;
95 Inst *i;
96 int *jt;
97 int n;
98
99 for(p = plist; p; p = p->next) {
100 i = p->i;
101 if(p->kind == P_CASE) {
102 jt = p->jmptbl;
103 for(n = 0; n < p->n; n++)
104 jt[n*3+2] = patchaddr(i, jt[n*3+2]);
105 jt[p->n*3] = patchaddr(i, jt[p->n*3]);
106 } else { /* P_OTHER */
107 i->d.u.ival = patchaddr(i, i->d.u.ival);
108 /*
109 * jmp $start_of_method -> jmp $start_of_method+1
110 * skip (re-)allocation of Sys->Exception object
111 */
112 if(i->d.u.ival == startpc && i->op == IJMP && code->nex != 0)
113 i->d.u.ival += 1;
114 }
115 }
116}
117
118/*
119 * Clear the patch list after each method.
120 */
121
122void
123patchfree(void)
124{
125 Patch *p, *p2;
126
127 for(p = plist; p; p = p2) {
128 p2 = p->next;
129 free(p);
130 }
131 plist = nil;
132}
java/tools/j2d/reloc.h+123−0
@@ -0,0 +1,123 @@
1enum {
2 Rgetputfield = 0x1 << 16,
3 Rgetputstatic = 0x2 << 16,
4 Rinvokeinterface = 0x3 << 16,
5 Rinvokespecial = 0x4 << 16,
6 Rinvokestatic = 0x5 << 16,
7 Rinvokevirtual = 0x6 << 16,
8
9 Rstaticmp = 0x8 << 16,
10 Rspecialmp = 0x10 << 16,
11
12 PSRC = 0x1 << 2, /* patch source operand */
13 PDST = 0x2 << 2, /* destination */
14 PMID = 0x3 << 2, /* middle */
15
16 PIMM = 0x0, /* patch immediate operand */
17 PSIND = 0x1, /* single indirect offset */
18 PDIND1 = 0x2, /* 1st offset of double indirect */
19 PDIND2 = 0x3, /* 2nd offset */
20
21 SAVEINST = 1, /* save Inst* for patching */
22
23 LTCODE = 0x1, /* load-time resolution code */
24 RTCODE = 0x2, /* run-time resolution code */
25 RTCALL = 0x4 /* call rtload() */
26};
27
28/* special fields */
29#define RCLASS "@Class"
30#define RADT "@adt"
31#define RJEX "@jex"
32#define RMP "@mp"
33#define RNP "@np"
34#define ROBJ "@obj"
35#define RSYS "@sys"
36
37/* special class name */
38#define RLOADER "@Loader"
39
40typedef struct Ipatch Ipatch;
41typedef struct Freloc Freloc;
42typedef struct Creloc Creloc;
43typedef struct RTReloc RTReloc;
44typedef struct RTClass RTClass;
45
46struct Ipatch {
47 int n; /* no. of significant elts. in pinfo & i */
48 int max; /* number of elements pinfo & i can hold */
49 int *pinfo; /* operand patch directives */
50 Inst **i; /* instructions to patch (runtime relocation) */
51};
52
53/*
54 * Load-time relocation.
55 */
56
57struct Freloc {
58 char *field; /* field name */
59 char *sig; /* Java type signature */
60 uint flags; /* access flags */
61 Ipatch *ipatch; /* instruction patch information */
62 Freloc *next;
63};
64
65struct Creloc {
66 char *classname;
67 Freloc *fr;
68 Freloc *tail;
69 int n; /* number of elements in 'fr' */
70};
71
72/*
73 * Run-time relocation.
74 */
75
76struct RTReloc {
77 char *field; /* field name */
78 char *sig; /* Java type signature */
79 uint flags; /* access flags */
80 Ipatch *ipatch; /* instruction patch information */
81 RTReloc *next;
82};
83
84struct RTClass {
85 char *classname;
86 RTReloc *rtr;
87 RTReloc *tail;
88 int n; /* number of elements in 'rtr' */
89 int off; /* Module Data offset */
90};
91
92/* datarloc.c */
93extern void addDreloc(Inst*, int, int);
94extern void asmDreloc(int);
95extern void disDreloc(int);
96extern void addIpatch(Ipatch*, Inst*, int, int, int);
97extern void setIpatchtid(void);
98extern void asmIpatch(int, Ipatch*);
99extern void disIpatch(int, Ipatch*);
100
101/* ltreloc.c */
102extern void thisCreloc(void);
103extern Creloc *getCreloc(char*);
104extern Freloc *getFreloc(Creloc*, char*, char*, uint);
105extern void LTIpatch(Freloc*, Inst*, int, int);
106extern int LTrelocsize(void);
107extern void LTrelocdesc(uchar*);
108extern int asmCreloc(int);
109extern int disCreloc(int);
110extern int asmthisCreloc(int);
111extern int disthisCreloc(int);
112extern int doclinitinits;
113
114/* rtreloc.c */
115extern RTClass *getRTClass(char*);
116extern RTReloc *getRTReloc(RTClass*, char*, char*, uint);
117extern void RTIpatch(RTReloc*, Inst*, int, int);
118extern void RTfixoff(int);
119extern void doRTpatch(void);
120extern int RTrelocsize(void);
121extern void RTrelocdesc(uchar*, int);
122extern int asmRTClass(int);
123extern int disRTClass(int);
java/tools/j2d/rtreloc.c+409−0
@@ -0,0 +1,409 @@
1#include "java.h"
2#include "reloc.h"
3
4/*
5 * Manage run-time resolution information.
6 */
7
8typedef struct RTHash RTHash;
9
10struct RTHash
11{
12 RTClass *rtc;
13 RTHash *next;
14};
15
16static RTHash *rttbl[Hashsize]; /* hash table of referenced classes */
17static int nrtclasses; /* no. of classes referenced */
18
19static void
20rtappend(RTClass *rtc, RTReloc *rtr)
21{
22 if(rtc->rtr == nil)
23 rtc->rtr = rtr;
24 else
25 rtc->tail->next = rtr;
26 rtc->tail = rtr;
27}
28
29static void
30rtprepend(RTClass *rtc, RTReloc *rtr)
31{
32 if(rtc->rtr == nil)
33 rtc->tail = rtr;
34 rtr->next = rtc->rtr;
35 rtc->rtr = rtr;
36}
37
38/*
39 * Add RTReloc entry.
40 */
41
42static RTReloc*
43addRTReloc(RTClass *rtc, char *field, char *sig, uint flags)
44{
45 RTReloc *rtr;
46
47 rtr = Malloc(sizeof(RTReloc));
48 rtr->field = field;
49 rtr->sig = sig;
50 rtr->flags = flags;
51 rtr->ipatch = Mallocz(sizeof(Ipatch));
52 rtr->next = nil;
53 if(field[0] == '@') /* these must go first in the list ! */
54 rtprepend(rtc, rtr);
55 else
56 rtappend(rtc, rtr);
57 rtc->n += 1;
58 return rtr;
59}
60
61/*
62 * Allocate a RTClass structure.
63 */
64
65static RTClass*
66newRTClass(char *s)
67{
68 RTClass *rtc;
69
70 rtc = Malloc(sizeof(RTClass));
71 rtc->classname = s;
72 rtc->rtr = nil;
73 rtc->tail = nil;
74 rtc->n = 0;
75 rtc->off = 0;
76 nrtclasses += 1;
77 /* want the order: @mp, @np, @adt, @Class */
78 addRTReloc(rtc, RCLASS, nil, 0);
79 addRTReloc(rtc, RADT, nil, 0);
80 addRTReloc(rtc, RNP, nil, 0);
81 addRTReloc(rtc, RMP, nil, 0);
82 return rtc;
83}
84
85/*
86 * Add RTClass entry for classname.
87 */
88
89static RTClass*
90addRTClass(char *classname)
91{
92 uint h;
93 RTHash *he;
94
95 h = hashval(classname);
96 he = Malloc(sizeof(RTHash));
97 he->rtc = newRTClass(classname);
98 he->next = rttbl[h];
99 rttbl[h] = he;
100 return he->rtc;
101}
102
103/*
104 * Get RTClass entry for classname.
105 */
106
107RTClass*
108getRTClass(char *classname)
109{
110 RTHash *he;
111
112 for(he = rttbl[hashval(classname)]; he; he = he->next) {
113 if(strcmp(classname, he->rtc->classname) == 0)
114 return he->rtc;
115 }
116 return addRTClass(classname);
117}
118
119/*
120 * Get RTReloc entry. Ignore signature if nil.
121 */
122
123RTReloc*
124getRTReloc(RTClass *rtc, char *field, char *sig, uint flags)
125{
126 RTReloc *rtr;
127 uint lowflags;
128
129 lowflags = 0;
130 for(rtr = rtc->rtr; rtr; rtr = rtr->next) {
131 if(strcmp(rtr->field, field) == 0
132 && (sig == nil || strcmp(rtr->sig, sig) == 0)) {
133 if(rtr->flags >> 16 == 0) {
134 rtr->flags |= flags;
135 return rtr;
136 } else if(rtr->flags >> 16 == flags >> 16)
137 return rtr;
138 lowflags = rtr->flags & 0xffff;
139 }
140 }
141
142 return addRTReloc(rtc, field, sig, flags|lowflags);
143}
144
145/*
146 * Add instruction patch information to RTReloc rtr.
147 */
148
149void
150RTIpatch(RTReloc *rtr, Inst *i, int operand, int patchkind)
151{
152 addDreloc(i, operand, patchkind);
153 addIpatch(rtr->ipatch, i, operand, patchkind, SAVEINST);
154}
155
156/*
157 * Fix RTClass and RTReloc 'off' fields to prepare for instruction patch.
158 */
159
160void
161RTfixoff(int off)
162{
163 RTHash *he;
164 int i;
165
166 if(nrtclasses > 0) {
167 for(i = 0; i < Hashsize; i++) {
168 for(he = rttbl[i]; he; he = he->next) {
169 he->rtc->off = off;
170 off += he->rtc->n * IBY2WD;
171 }
172 }
173 }
174}
175
176/*
177 * Patch instructions for run-time relocation.
178 */
179
180void
181doRTpatch(void)
182{
183 Addr *a;
184 RTHash *he;
185 Ipatch *ip;
186 RTReloc *rtr;
187 int i, j;
188 int off, ltsize;
189
190 if(nrtclasses == 0)
191 return;
192
193 ltsize = LTrelocsize();
194 a = nil;
195 for(i = 0; i < Hashsize; i++) {
196 for(he = rttbl[i]; he; he = he->next) {
197 off = he->rtc->off - ltsize;
198 for(rtr = he->rtc->rtr; rtr; rtr = rtr->next) {
199 ip = rtr->ipatch;
200 for(j = 0; j < ip->n; j++) {
201 switch(ip->pinfo[j] & (0x3 << 2)) {
202 case PSRC:
203 a = &ip->i[j]->s;
204 break;
205 case PDST:
206 a = &ip->i[j]->d;
207 break;
208 case PMID:
209 a = &ip->i[j]->m;
210 break;
211 }
212 switch(ip->pinfo[j] & 0x3) {
213 case PIMM:
214 a->u.ival = off;
215 break;
216 case PSIND:
217 a->u.offset = off;
218 break;
219 case PDIND1:
220 a->u.b.fi = off;
221 break;
222 case PDIND2:
223 a->u.b.si = off;
224 break;
225 }
226 }
227 off += IBY2WD;
228 }
229 }
230 }
231}
232
233/*
234 * Size of Module Data space taken by run-time relocation information.
235 */
236
237int
238RTrelocsize(void)
239{
240 int i;
241 int n;
242 RTHash *he;
243
244 n = 0;
245 if(nrtclasses > 0) {
246 for(i = 0; i < Hashsize; i++) {
247 for(he = rttbl[i]; he; he = he->next)
248 n += he->rtc->n;
249 }
250 }
251 return n * IBY2WD;
252}
253
254/*
255 * Fix type descriptor for run-time relocation information.
256 */
257
258static int RTReloctid;
259
260void
261RTrelocdesc(uchar *map, int off)
262{
263 int i;
264 RTHash *he;
265 RTReloc *rtr;
266
267 if(nrtclasses == 0)
268 return;
269
270 RTReloctid = descid(3*IBY2WD, 1, (uchar*)"\xc0");
271
272 for(i = 0; i < Hashsize; i++) {
273 for(he = rttbl[i]; he; he = he->next) {
274 setbit(map, off); /* @mp cell */
275 off += 4;
276 setbit(map, off); /* @np cell */
277 off += 4;
278 setbit(map, off); /* @adt cell */
279 off += 8;
280 rtr = he->rtc->rtr->next->next->next->next;
281 while(rtr) {
282 if(rtr->flags & (Rspecialmp | Rstaticmp))
283 setbit(map, off);
284 off += 4;
285 rtr = rtr->next;
286 }
287 }
288 }
289}
290
291/*
292 * Write RTReloc array to .s file.
293 */
294
295static void
296asmRTReloc(int off, RTClass *rtc)
297{
298 RTReloc *rtr;
299 int reloff; /* relative offset for array elements */
300
301 if(rtc->n <= 4)
302 return;
303
304 reloff = 0;
305 asmarray(off, RTReloctid, rtc->n - 4, reloff);
306 /* skip @mp @np @adt @Class */
307 rtr = rtc->rtr->next->next->next->next;
308 while(rtr) {
309 asmstring(reloff, rtr->field);
310 reloff += IBY2WD;
311 if(rtr->sig)
312 asmstring(reloff, rtr->sig);
313 reloff += IBY2WD;
314 asmint(reloff, rtr->flags);
315 reloff += IBY2WD;
316 rtr = rtr->next;
317 }
318 Bprint(bout, "\tapop\n");
319}
320
321/*
322 * Write RTClass information to .s file.
323 */
324
325int
326asmRTClass(int off)
327{
328 RTHash *he;
329 int i;
330 int ltsize;
331
332 if(nrtclasses > 0) {
333 ltsize = LTrelocsize();
334 for(i = 0; i < Hashsize; i++) {
335 for(he = rttbl[i]; he; he = he->next) {
336 off += IBY2WD; /* @mp cell */
337 asmstring(off, he->rtc->classname);
338 off += IBY2WD;
339 asmRTReloc(off, he->rtc);
340 off += IBY2WD;
341 asmint(off, he->rtc->off - ltsize);
342 off += IBY2WD;
343 /* account for fields beyond @Class */
344 off += (he->rtc->n - 4) * IBY2WD;
345 }
346 }
347 }
348 return off;
349}
350
351/*
352 * Write RTReloc array to .dis file.
353 */
354
355static void
356disRTReloc(int off, RTClass *rtc)
357{
358 RTReloc *rtr;
359 int reloff; /* relative offset for array elements */
360
361 if(rtc->n <= 4)
362 return;
363
364 reloff = 0;
365 disarray(off, RTReloctid, rtc->n - 4);
366 /* skip @mp @np @adt @Class */
367 rtr = rtc->rtr->next->next->next->next;
368 while(rtr) {
369 disstring(reloff, rtr->field);
370 reloff += IBY2WD;
371 if(rtr->sig)
372 disstring(reloff, rtr->sig);
373 reloff += IBY2WD;
374 disint(reloff, rtr->flags);
375 reloff += IBY2WD;
376 rtr = rtr->next;
377 }
378 disapop();
379}
380
381/*
382 * Write RTClass information to .dis file.
383 */
384
385int
386disRTClass(int off)
387{
388 RTHash *he;
389 int i;
390 int ltsize;
391
392 if(nrtclasses > 0) {
393 ltsize = LTrelocsize();
394 for(i = 0; i < Hashsize; i++) {
395 for(he = rttbl[i]; he; he = he->next) {
396 off += IBY2WD; /* @mp cell */
397 disstring(off, he->rtc->classname);
398 off += IBY2WD;
399 disRTReloc(off, he->rtc);
400 off += IBY2WD;
401 disint(off, he->rtc->off - ltsize);
402 off += IBY2WD;
403 /* account for fields beyond @Class */
404 off += (he->rtc->n - 4) * IBY2WD;
405 }
406 }
407 }
408 return off;
409}
java/tools/j2d/sbl.c+46−0
@@ -0,0 +1,46 @@
1#include "java.h"
2
3/*
4 * Generate symbol table file (.sbl).
5 */
6
7#define SBLVERSION "limbo .sbl 2.0"
8#define EXT ".sbl"
9
10void
11sblout(char *out)
12{
13 int n;
14 char *sym;
15 Biobuf *bsym;
16
17 n = strlen(out);
18 if(n > 2 && out[n-1] == 's') { /* .s or .dis file ? */
19 if(out[n-2] == '.')
20 n -= 2;
21 else if(n > 4 && out[n-2] == 'i'
22 && out[n-3] == 'd' && out[n-4] == '.')
23 n -= 4;
24 }
25 sym = Malloc(n + strlen(EXT) + 1);
26 memmove(sym, out, n);
27 strcpy(sym+n, EXT);
28
29 bsym = Bopen(sym, OWRITE);
30 if(bsym == nil)
31 fatal("can't open %s: %r\n", sym);
32
33 Bprint(bsym, "%s\n", SBLVERSION);
34 Bprint(bsym, "%s\n", THISCLASS);
35 Bprint(bsym, "1\n");
36 if(class->source_file)
37 Bprint(bsym, "%s\n", STRING(class->source_file));
38 else
39 Bprint(bsym, "%s.java\n", THISCLASS);
40 sblinst(bsym); /* Dis instructions */
41 Bprint(bsym, "0\n"); /* adts */
42 sbllinks(bsym); /* functions */
43 Bprint(bsym, "0\n"); /* globals */
44
45 Bterm(bsym);
46}
java/tools/j2d/simjvm.c+1509−0
@@ -0,0 +1,1509 @@
1#include "java.h"
2#include "javaisa.h"
3
4/*
5 * "Simulate" the Java VM on a method.
6 */
7
8typedef struct Result Result;
9
10struct Result {
11 uchar jtype;
12 int pc;
13};
14
15static Result *jvmstack; /* simulated JVM stack */
16static int jvmtos; /* number of items in jvmstack */
17static int jvmwords; /* number of words that would be on JVM stack */
18static uchar rettype; /* return type of simulated method */
19
20static Result
21jvmpop(void)
22{
23 Result r;
24
25 if(jvmtos == 0)
26 goto bad;
27 r = jvmstack[--jvmtos];
28 if(r.jtype == 'J' || r.jtype == 'D')
29 jvmwords -= 2;
30 else
31 jvmwords -= 1;
32 if(jvmwords < 0)
33bad: verifyerrormess("stack underflow");
34 return r;
35}
36
37static void
38jvmpush(Result r)
39{
40 if(r.jtype == 'J' || r.jtype == 'D')
41 jvmwords += 2;
42 else
43 jvmwords += 1;
44 if(jvmwords > code->max_stack)
45 verifyerrormess("stack overflow");
46 jvmstack[jvmtos++] = r;
47}
48
49/*
50 * Initialize jvmstack to process basic block bb.
51 */
52
53static void
54jvminit(BB *bb)
55{
56 int i;
57 Result r;
58 StkSnap *s;
59
60 jvmtos = 0;
61 jvmwords = 0;
62 if(bb->flags & (BB_FINALLY | BB_HANDLER)) {
63 r.jtype = 'L';
64 r.pc = code->code_length;
65 jvmpush(r); /* push a dummy */
66 return;
67 }
68
69 /* set jvmstack to bb->entrystk */
70 s = bb->entrystk;
71 for(i = 0; i < bb->entrysz; i++) {
72 r.jtype = s[i].jtype;
73 r.pc = s[i].pc[0];
74 jvmpush(r);
75 }
76}
77
78static void
79typecheck(Result *r, uchar jtype)
80{
81 /* assumes 'L' and '[' are interchangeable */
82 if(r->jtype != jtype && r->jtype + jtype != 'L' + '[')
83 verifyerror(&code->j[r->pc]);
84}
85
86static uchar
87jvmtype(uchar jtype)
88{
89 switch(jtype) {
90 case 'Z':
91 case 'B':
92 case 'C':
93 case 'S':
94 jtype = 'I';
95 break;
96 }
97 return jtype;
98}
99
100static void
101setresult(Result *r, uchar jtype, Jinst *j)
102{
103 r->jtype = jtype;
104 r->pc = j->pc;
105 j->jtype = jtype;
106}
107
108static void
109srcalloc(Jinst *j, int n)
110{
111 j->nsrc = n;
112 j->src = Malloc(n*sizeof(int));
113}
114
115static void
116iconst(Jinst *j, int ival)
117{
118 Result r;
119
120 addrimm(&j->dst, ival);
121 setresult(&r, 'I', j);
122 jvmpush(r);
123}
124
125static void
126mpconst(Jinst *j, uchar jtype, int off)
127{
128 Result r;
129
130 addrsind(&j->dst, Amp, off);
131 setresult(&r, jtype, j);
132 jvmpush(r);
133}
134
135static void
136verifyindex(Jinst *j, uchar jtype, int ix)
137{
138 int n;
139
140 switch(jtype) {
141 case 'I':
142 case 'F':
143 case 'L':
144 n = code->max_locals-1;
145 break;
146 case 'J':
147 case 'D':
148 n = code->max_locals-2;
149 break;
150 default:
151 fatal("verifyindex: invalid jtype");
152 return;
153 }
154 if(ix > n)
155 verifyerror(j);
156}
157
158static int
159getfpoff(uchar jtype, int ix)
160{
161 int off;
162
163 switch(jtype) {
164 case 'I':
165 off = localix(DIS_W, ix);
166 break;
167 case 'J':
168 case 'F':
169 case 'D':
170 off = localix(DIS_L, ix);
171 break;
172 case 'L':
173 off = localix(DIS_P, ix);
174 break;
175 default:
176 fatal("getfpoff: invalid jtype");
177 return -1;
178 }
179 return off;
180}
181
182static void
183javaload(Jinst *j, uchar jtype, int ix)
184{
185 Result r;
186
187 verifyindex(j, jtype, ix);
188 addrsind(&j->dst, Afp, getfpoff(jtype, ix));
189 setresult(&r, jtype, j);
190 jvmpush(r);
191}
192
193static void
194javastore(Jinst *j, uchar jtype, int ix)
195{
196 Result r;
197
198 verifyindex(j, jtype, ix);
199
200 srcalloc(j, 1);
201
202 r = jvmpop();
203 typecheck(&r, jtype);
204 j->src[0] = r.pc;
205
206 addrsind(&j->dst, Afp, getfpoff(jtype, ix));
207}
208
209static void
210arrayload(Jinst *j, uchar jtype)
211{
212 Result r;
213
214 srcalloc(j, 2);
215
216 r = jvmpop();
217 typecheck(&r, 'I');
218 j->src[1] = r.pc;
219
220 r = jvmpop();
221 typecheck(&r, '[');
222 j->src[0] = r.pc;
223
224 addrsind(&j->dst, Afp, -1);
225 setresult(&r, jtype, j);
226 jvmpush(r);
227}
228
229static void
230arraystore(Jinst *j, uchar jtype)
231{
232 Result r;
233
234 srcalloc(j, 3);
235
236 r = jvmpop();
237 typecheck(&r, jtype);
238 j->src[2] = r.pc;
239
240 r = jvmpop();
241 typecheck(&r, 'I');
242 j->src[1] = r.pc;
243
244 r = jvmpop();
245 typecheck(&r, '[');
246 j->src[0] = r.pc;
247
248}
249
250static void
251binop(Jinst *j, uchar loptype, uchar roptype, uchar dsttype)
252{
253 Result r;
254
255 srcalloc(j, 2);
256
257 r = jvmpop();
258 typecheck(&r, roptype);
259 j->src[1] = r.pc;
260
261 r = jvmpop();
262 typecheck(&r, loptype);
263 j->src[0] = r.pc;
264
265 addrsind(&j->dst, Afp, -1);
266 setresult(&r, dsttype, j);
267 jvmpush(r);
268}
269
270static void
271unop(Jinst *j, uchar srctype, uchar dsttype)
272{
273 Result r;
274
275 srcalloc(j, 1);
276
277 r = jvmpop();
278 typecheck(&r, srctype);
279 j->src[0] = r.pc;
280
281 addrsind(&j->dst, Afp, -1);
282 setresult(&r, dsttype, j);
283 jvmpush(r);
284}
285
286/*
287 * If the local variable being stored into corresponds to a local
288 * that is on the stack, then an explicit mov_ MUST be generated
289 * for the load instruction that put it on the stack.
290 */
291
292static void
293storechk(int six, uchar stype)
294{
295 int i, lix;
296 uchar ltype;
297 Jinst *j;
298
299 for(i = 0; i < jvmtos; i++) {
300 j = &code->j[jvmstack[i].pc];
301 lix = -1;
302 switch(j->op) {
303 case Jiload:
304 case Jlload:
305 case Jfload:
306 case Jdload:
307 case Jaload:
308 lix = j->u.i;
309 break;
310 case Jiload_0:
311 case Jlload_0:
312 case Jfload_0:
313 case Jdload_0:
314 case Jaload_0:
315 lix = 0;
316 break;
317 case Jiload_1:
318 case Jlload_1:
319 case Jfload_1:
320 case Jdload_1:
321 case Jaload_1:
322 lix = 1;
323 break;
324 case Jiload_2:
325 case Jlload_2:
326 case Jfload_2:
327 case Jdload_2:
328 case Jaload_2:
329 lix = 2;
330 break;
331 case Jiload_3:
332 case Jlload_3:
333 case Jfload_3:
334 case Jdload_3:
335 case Jaload_3:
336 lix = 3;
337 break;
338 case Jwide:
339 switch(j->u.w.op) {
340 case Jiload:
341 case Jlload:
342 case Jfload:
343 case Jdload:
344 case Jaload:
345 lix = j->u.w.ix;
346 }
347 break;
348 }
349 ltype = '-';
350 switch(j->op) {
351 case Jiload:
352 case Jiload_0:
353 case Jiload_1:
354 case Jiload_2:
355 case Jiload_3:
356 ltype = 'I';
357 break;
358 case Jlload:
359 case Jlload_0:
360 case Jlload_1:
361 case Jlload_2:
362 case Jlload_3:
363 ltype = 'J';
364 break;
365 case Jfload:
366 case Jfload_0:
367 case Jfload_1:
368 case Jfload_2:
369 case Jfload_3:
370 ltype = 'F';
371 break;
372 case Jdload:
373 case Jdload_0:
374 case Jdload_1:
375 case Jdload_2:
376 case Jdload_3:
377 ltype = 'D';
378 break;
379 case Jaload:
380 case Jaload_0:
381 case Jaload_1:
382 case Jaload_2:
383 case Jaload_3:
384 ltype = 'L';
385 break;
386 case Jwide:
387 switch(j->u.w.op) {
388 case Jiload:
389 ltype = 'I';
390 break;
391 case Jlload:
392 ltype = 'J';
393 break;
394 case Jfload:
395 ltype = 'F';
396 break;
397 case Jdload:
398 ltype = 'D';
399 break;
400 case Jaload:
401 ltype = 'L';
402 break;
403 }
404 break;
405 }
406 if(lix == six && ltype == stype && j->movsrc.mode == Anone) {
407 j->movsrc = j->dst;
408 addrsind(&j->dst, Afp, -1);
409 }
410 }
411}
412
413static void
414useone(Jinst *j, uchar jtype)
415{
416 Result r;
417
418 srcalloc(j, 1);
419
420 r = jvmpop();
421 typecheck(&r, jtype);
422 j->src[0] = r.pc;
423}
424
425static void
426usetwo(Jinst *j, uchar loptype, uchar roptype)
427{
428 Result r;
429
430 srcalloc(j, 2);
431
432 r = jvmpop();
433 typecheck(&r, roptype);
434 j->src[1] = r.pc;
435
436 r = jvmpop();
437 typecheck(&r, loptype);
438 j->src[0] = r.pc;
439}
440
441static void
442javanew(Jinst *j)
443{
444 Result r;
445 char *name;
446
447 name = CLASSNAME(j->u.i);
448 if(name[0] == '[')
449 verifyerror(j);
450
451 addrsind(&j->dst, Afp, -1);
452 setresult(&r, 'L', j);
453 jvmpush(r);
454 crefenter(name, j->bb);
455}
456
457static int
458checkdim(Jinst *j, int ix)
459{
460 int ndim;
461 char *name;
462
463 ndim = 0;
464 name = CLASSNAME(ix);
465 while(name[0] == '[') {
466 ndim++;
467 name++;
468 }
469 if(ndim > 255)
470 verifyerror(j);
471 crefenter(name, j->bb);
472 return ndim;
473}
474
475static void
476anewarray(Jinst *j)
477{
478 checkdim(j, j->u.i);
479 unop(j, 'I', '[');
480}
481
482static void
483multianewarray(Jinst *j)
484{
485 Result r;
486 int i, ndim;
487
488 ndim = checkdim(j, j->u.x2d.ix);
489 if(ndim == 0 || j->u.x2d.dim > ndim)
490 verifyerror(j);
491
492 srcalloc(j, j->u.x2d.dim);
493
494 for(i = j->u.x2d.dim-1; i >= 0; i--) {
495 r = jvmpop();
496 typecheck(&r, 'I');
497 j->src[i] = r.pc;
498 }
499
500 addrsind(&j->dst, Afp, -1);
501 setresult(&r, '[', j);
502 jvmpush(r);
503}
504
505static char*
506getclassname(Jinst *j)
507{
508 Const *c;
509 int ix;
510
511 if(j->op == Jinvokeinterface)
512 ix = j->u.x2c0.ix;
513 else
514 ix = j->u.i;
515 c = &class->cps[ix];
516 return CLASSNAME(c->fmiref.class_index);
517}
518
519static char*
520getname(Jinst *j)
521{
522 Const *c, *n;
523 int ix;
524
525 if(j->op == Jinvokeinterface)
526 ix = j->u.x2c0.ix;
527 else
528 ix = j->u.i;
529 c = &class->cps[ix];
530 n = &class->cps[c->fmiref.name_type_index];
531 return STRING(n->nat.name_index);
532}
533
534static char*
535getsig(Jinst *j)
536{
537 Const *c, *n;
538 int ix;
539
540 if(j->op == Jinvokeinterface)
541 ix = j->u.x2c0.ix;
542 else
543 ix = j->u.i;
544 c = &class->cps[ix];
545 n = &class->cps[c->fmiref.name_type_index];
546 return STRING(n->nat.sig_index);
547}
548
549static void
550getfs(Jinst *j)
551{
552 Result r;
553 char *sig;
554
555 sig = getsig(j);
556 if(j->op == Jgetfield)
557 useone(j, 'L');
558 addrsind(&j->dst, Afp, -1);
559 setresult(&r, jvmtype(sig[0]), j);
560 jvmpush(r);
561 crefenter(getclassname(j), j->bb);
562}
563
564static void
565putfs(Jinst *j)
566{
567 char *sig;
568
569 sig = getsig(j);
570 if(j->op == Jputstatic)
571 useone(j, jvmtype(sig[0]));
572 else
573 usetwo(j, 'L', jvmtype(sig[0]));
574 crefenter(getclassname(j), j->bb);
575}
576
577static void
578invoke(Jinst *j)
579{
580 char *name, *sig, *savesig;
581 int i, nargs, wargs;
582 Result *args;
583 Result rv;
584
585 name = getname(j);
586 if(name[0] == '<'
587 && (strcmp(name, "<init>") != 0 || j->op != Jinvokespecial))
588 verifyerror(j);
589
590 /* count arguments */
591 sig = getsig(j);
592 nargs = 0; /* number of arguments */
593 wargs = 0; /* width of arguments (number of Java words) */
594 sig++; /* skip '(' */
595 savesig = sig;
596 while(sig[0] != ')') {
597 nargs++;
598 wargs++;
599 if(sig[0] == 'J' || sig[0] == 'D')
600 wargs++;
601 sig = nextjavatype(sig);
602 }
603 if(j->op != Jinvokestatic) {
604 nargs++;
605 wargs++;
606 }
607 if(wargs > 255 || (j->op == Jinvokeinterface && j->u.x2c0.narg != wargs))
608 verifyerror(j);
609
610 /* collect and typecheck arguments */
611 if(nargs > 0) {
612 srcalloc(j, nargs);
613 args = Malloc(nargs*sizeof(Result));
614 for(i = nargs-1; i >= 0; i--) {
615 args[i] = jvmpop();
616 j->src[i] = args[i].pc;
617 }
618 i = 0;
619 if(j->op != Jinvokestatic) {
620 typecheck(&args[0], 'L');
621 i++;
622 }
623 sig = savesig;
624 while(sig[0] != ')') {
625 typecheck(&args[i], jvmtype(sig[0]));
626 i++;
627 sig = nextjavatype(sig);
628 }
629 free(args);
630 }
631
632 /* return type */
633 if(sig[1] != 'V') { /* skip ')' */
634 addrsind(&j->dst, Afp, -1);
635 setresult(&rv, jvmtype(sig[1]), j);
636 jvmpush(rv);
637 }
638 crefenter(getclassname(j), j->bb);
639}
640
641static void
642javareturn(Jinst *j)
643{
644 uchar jtype;
645
646 switch(j->op) {
647 case Jireturn:
648 jtype = 'I';
649 break;
650 case Jlreturn:
651 jtype = 'J';
652 break;
653 case Jfreturn:
654 jtype = 'F';
655 break;
656 case Jdreturn:
657 jtype = 'D';
658 break;
659 case Jareturn:
660 jtype = 'L';
661 break;
662 case Jreturn:
663 jtype = 'V';
664 break;
665 default:
666 fatal("javareturn: invalid j->op");
667 return;
668 }
669 if(jtype != rettype && jtype + rettype != 'L' + '[')
670 verifyerror(j);
671 if(j->op != Jreturn)
672 useone(j, jtype);
673}
674
675static void
676ldc(Jinst *j)
677{
678 Const *c;
679
680 c = &class->cps[j->u.i];
681 switch(class->cts[j->u.i]) {
682 case CON_Integer:
683 if(notimmable(c->tint))
684 mpconst(j, 'I', mpint(c->tint));
685 else
686 iconst(j, c->tint);
687 break;
688 case CON_Float:
689 mpconst(j, 'F', mpreal(c->tdouble));
690 break;
691 case CON_Double:
692 mpconst(j, 'D', mpreal(c->tdouble));
693 break;
694 case CON_Long:
695 mpconst(j, 'J', mplong(c->tvlong));
696 break;
697 case CON_String:
698 mpconst(j, 'L', mpstring(STRING(c->string_index)));
699 j->movsrc = j->dst;
700 addrsind(&j->dst, Afp, -1);
701 break;
702 }
703}
704
705static void
706oneword(Jinst *j, uchar jtype)
707{
708 if(jtype == 'J' || jtype == 'D')
709 verifyerror(j);
710}
711
712static void
713javapop(Jinst *j)
714{
715 Result r1, r2;
716 int n;
717
718 r1 = jvmpop();
719 n = 1;
720 switch(j->op) {
721 case Jpop:
722 oneword(j, r1.jtype);
723 break;
724 case Jpop2:
725 if(r1.jtype != 'J' && r1.jtype != 'D') {
726 r2 = jvmpop();
727 n = 2;
728 oneword(j, r2.jtype);
729 }
730 break;
731 }
732 srcalloc(j, n);
733 j->src[0] = r1.pc;
734 if(n == 2) /* pop2 */
735 j->src[1] = r2.pc;
736}
737
738static void
739javadup(Jinst *j)
740{
741 Result w1, w2, w3, w4;
742 int n; /* number of stack items duplicated */
743
744 n = 1;
745 switch(j->op) {
746 case Jdup:
747 w1 = jvmpop();
748 oneword(j, w1.jtype);
749 jvmpush(w1);
750 jvmpush(w1);
751 break;
752 case Jdup_x1:
753 w1 = jvmpop();
754 oneword(j, w1.jtype);
755 w2 = jvmpop();
756 oneword(j, w2.jtype);
757 jvmpush(w1);
758 jvmpush(w2);
759 jvmpush(w1);
760 break;
761 case Jdup_x2:
762 w1 = jvmpop();
763 oneword(j, w1.jtype);
764 w2 = jvmpop();
765 if(w2.jtype == 'J' || w2.jtype == 'D') {
766 jvmpush(w1);
767 } else {
768 w3 = jvmpop();
769 oneword(j, w3.jtype);
770 jvmpush(w1);
771 jvmpush(w3);
772 }
773 jvmpush(w2);
774 jvmpush(w1);
775 break;
776 case Jdup2:
777 w1 = jvmpop();
778 if(w1.jtype == 'J' || w1.jtype == 'D') {
779 jvmpush(w1);
780 } else {
781 n = 2;
782 w2 = jvmpop();
783 oneword(j, w2.jtype);
784 jvmpush(w2);
785 jvmpush(w1);
786 jvmpush(w2);
787 }
788 jvmpush(w1);
789 break;
790 case Jdup2_x1:
791 w1 = jvmpop();
792 if(w1.jtype == 'J' || w1.jtype == 'D') {
793 w3 = jvmpop();
794 oneword(j, w3.jtype);
795 jvmpush(w1);
796 jvmpush(w3);
797 } else {
798 n = 2;
799 w2 = jvmpop();
800 oneword(j, w2.jtype);
801 w3 = jvmpop();
802 oneword(j, w3.jtype);
803 jvmpush(w2);
804 jvmpush(w1);
805 jvmpush(w3);
806 jvmpush(w2);
807 }
808 jvmpush(w1);
809 break;
810 case Jdup2_x2:
811 w1 = jvmpop();
812 if(w1.jtype != 'J' && w1.jtype != 'D') {
813 n = 2;
814 w2 = jvmpop();
815 oneword(j, w2.jtype);
816 }
817 w3 = jvmpop();
818 if(w3.jtype != 'J' && w3.jtype != 'D') {
819 w4 = jvmpop();
820 oneword(j, w4.jtype);
821 }
822
823 if(w1.jtype != 'J' && w1.jtype != 'D')
824 jvmpush(w2);
825 jvmpush(w1);
826 if(w3.jtype != 'J' && w3.jtype != 'D')
827 jvmpush(w4);
828 jvmpush(w3);
829 if(w1.jtype != 'J' && w1.jtype != 'D')
830 jvmpush(w2);
831 jvmpush(w1);
832 break;
833 }
834 srcalloc(j, n);
835 j->src[0] = w1.pc;
836 if(n == 2)
837 j->src[1] = w2.pc;
838}
839
840static void
841javaswap(Jinst *j)
842{
843 Result w1, w2;
844
845 w1 = jvmpop();
846 oneword(j, w1.jtype);
847 w2 = jvmpop();
848 oneword(j, w2.jtype);
849 jvmpush(w1);
850 jvmpush(w2);
851}
852
853static void
854simjinst(Jinst *j)
855{
856 switch(j->op) {
857 case Jnop:
858 break;
859 case Jaconst_null:
860 mpconst(j, 'L', 0);
861 break;
862 case Jiconst_m1:
863 iconst(j, -1);
864 break;
865 case Jiconst_0:
866 iconst(j, 0);
867 break;
868 case Jiconst_1:
869 iconst(j, 1);
870 break;
871 case Jiconst_2:
872 iconst(j, 2);
873 break;
874 case Jiconst_3:
875 iconst(j, 3);
876 break;
877 case Jiconst_4:
878 iconst(j, 4);
879 break;
880 case Jiconst_5:
881 iconst(j, 5);
882 break;
883 case Jlconst_0:
884 mpconst(j, 'J', mplong(0));
885 break;
886 case Jlconst_1:
887 mpconst(j, 'J', mplong(1));
888 break;
889 case Jfconst_0:
890 mpconst(j, 'F', mpreal(0.0));
891 break;
892 case Jfconst_1:
893 mpconst(j, 'F', mpreal(1.0));
894 break;
895 case Jfconst_2:
896 mpconst(j, 'F', mpreal(2.0));
897 break;
898 case Jdconst_0:
899 mpconst(j, 'D', mpreal(0.0));
900 break;
901 case Jdconst_1:
902 mpconst(j, 'D', mpreal(1.0));
903 break;
904 case Jbipush:
905 case Jsipush:
906 iconst(j, j->u.i);
907 break;
908 case Jldc:
909 case Jldc_w:
910 case Jldc2_w:
911 ldc(j);
912 break;
913 case Jiload:
914 javaload(j, 'I', j->u.i);
915 break;
916 case Jlload:
917 javaload(j, 'J', j->u.i);
918 break;
919 case Jfload:
920 javaload(j, 'F', j->u.i);
921 break;
922 case Jdload:
923 javaload(j, 'D', j->u.i);
924 break;
925 case Jaload:
926 javaload(j, 'L', j->u.i);
927 break;
928 case Jiload_0:
929 javaload(j, 'I', 0);
930 break;
931 case Jiload_1:
932 javaload(j, 'I', 1);
933 break;
934 case Jiload_2:
935 javaload(j, 'I', 2);
936 break;
937 case Jiload_3:
938 javaload(j, 'I', 3);
939 break;
940 case Jlload_0:
941 javaload(j, 'J', 0);
942 break;
943 case Jlload_1:
944 javaload(j, 'J', 1);
945 break;
946 case Jlload_2:
947 javaload(j, 'J', 2);
948 break;
949 case Jlload_3:
950 javaload(j, 'J', 3);
951 break;
952 case Jfload_0:
953 javaload(j, 'F', 0);
954 break;
955 case Jfload_1:
956 javaload(j, 'F', 1);
957 break;
958 case Jfload_2:
959 javaload(j, 'F', 2);
960 break;
961 case Jfload_3:
962 javaload(j, 'F', 3);
963 break;
964 case Jdload_0:
965 javaload(j, 'D', 0);
966 break;
967 case Jdload_1:
968 javaload(j, 'D', 1);
969 break;
970 case Jdload_2:
971 javaload(j, 'D', 2);
972 break;
973 case Jdload_3:
974 javaload(j, 'D', 3);
975 break;
976 case Jaload_0:
977 javaload(j, 'L', 0);
978 break;
979 case Jaload_1:
980 javaload(j, 'L', 1);
981 break;
982 case Jaload_2:
983 javaload(j, 'L', 2);
984 break;
985 case Jaload_3:
986 javaload(j, 'L', 3);
987 break;
988 case Jbaload:
989 case Jcaload:
990 case Jsaload:
991 case Jiaload:
992 arrayload(j, 'I');
993 break;
994 case Jlaload:
995 arrayload(j, 'J');
996 break;
997 case Jfaload:
998 arrayload(j, 'F');
999 break;
1000 case Jdaload:
1001 arrayload(j, 'D');
1002 break;
1003 case Jaaload:
1004 arrayload(j, 'L');
1005 break;
1006 case Jistore:
1007 storechk(j->u.i, 'I');
1008 javastore(j, 'I', j->u.i);
1009 break;
1010 case Jlstore:
1011 storechk(j->u.i, 'J');
1012 javastore(j, 'J', j->u.i);
1013 break;
1014 case Jfstore:
1015 storechk(j->u.i, 'F');
1016 javastore(j, 'F', j->u.i);
1017 break;
1018 case Jdstore:
1019 storechk(j->u.i, 'D');
1020 javastore(j, 'D', j->u.i);
1021 break;
1022 case Jastore: /* could be start of finally block or handler */
1023 storechk(j->u.i, 'L');
1024 javastore(j, 'L', j->u.i);
1025 break;
1026 case Jistore_0:
1027 storechk(0, 'I');
1028 javastore(j, 'I', 0);
1029 break;
1030 case Jistore_1:
1031 storechk(1, 'I');
1032 javastore(j, 'I', 1);
1033 break;
1034 case Jistore_2:
1035 storechk(2, 'I');
1036 javastore(j, 'I', 2);
1037 break;
1038 case Jistore_3:
1039 storechk(3, 'I');
1040 javastore(j, 'I', 3);
1041 break;
1042 case Jlstore_0:
1043 storechk(0, 'J');
1044 javastore(j, 'J', 0);
1045 break;
1046 case Jlstore_1:
1047 storechk(1, 'J');
1048 javastore(j, 'J', 1);
1049 break;
1050 case Jlstore_2:
1051 storechk(2, 'J');
1052 javastore(j, 'J', 2);
1053 break;
1054 case Jlstore_3:
1055 storechk(3, 'J');
1056 javastore(j, 'J', 3);
1057 break;
1058 case Jfstore_0:
1059 storechk(0, 'F');
1060 javastore(j, 'F', 0);
1061 break;
1062 case Jfstore_1:
1063 storechk(1, 'F');
1064 javastore(j, 'F', 1);
1065 break;
1066 case Jfstore_2:
1067 storechk(2, 'F');
1068 javastore(j, 'F', 2);
1069 break;
1070 case Jfstore_3:
1071 storechk(3, 'F');
1072 javastore(j, 'F', 3);
1073 break;
1074 case Jdstore_0:
1075 storechk(0, 'D');
1076 javastore(j, 'D', 0);
1077 break;
1078 case Jdstore_1:
1079 storechk(1, 'D');
1080 javastore(j, 'D', 1);
1081 break;
1082 case Jdstore_2:
1083 storechk(2, 'D');
1084 javastore(j, 'D', 2);
1085 break;
1086 case Jdstore_3:
1087 storechk(3, 'D');
1088 javastore(j, 'D', 3);
1089 break;
1090 case Jastore_0: /* could be start of finally block or handler */
1091 storechk(0, 'L');
1092 javastore(j, 'L', 0);
1093 break;
1094 case Jastore_1:
1095 storechk(1, 'L');
1096 javastore(j, 'L', 1);
1097 break;
1098 case Jastore_2:
1099 storechk(2, 'L');
1100 javastore(j, 'L', 2);
1101 break;
1102 case Jastore_3:
1103 storechk(3, 'L');
1104 javastore(j, 'L', 3);
1105 break;
1106 case Jbastore:
1107 case Jcastore:
1108 case Jsastore:
1109 case Jiastore:
1110 arraystore(j, 'I');
1111 break;
1112 case Jlastore:
1113 arraystore(j, 'J');
1114 break;
1115 case Jfastore:
1116 arraystore(j, 'F');
1117 break;
1118 case Jdastore:
1119 arraystore(j, 'D');
1120 break;
1121 case Jaastore:
1122 arraystore(j, 'L');
1123 break;
1124 case Jpop:
1125 case Jpop2:
1126 javapop(j);
1127 break;
1128 case Jdup:
1129 case Jdup_x1:
1130 case Jdup_x2:
1131 case Jdup2:
1132 case Jdup2_x1:
1133 case Jdup2_x2:
1134 javadup(j);
1135 break;
1136 case Jswap:
1137 javaswap(j);
1138 break;
1139 case Jiadd:
1140 case Jisub:
1141 case Jimul:
1142 case Jidiv:
1143 case Jirem:
1144 case Jishl:
1145 case Jishr:
1146 case Jiushr:
1147 case Jiand:
1148 case Jior:
1149 case Jixor:
1150 binop(j, 'I', 'I', 'I');
1151 break;
1152 case Jladd:
1153 case Jlsub:
1154 case Jlmul:
1155 case Jldiv:
1156 case Jlrem:
1157 case Jland:
1158 case Jlor:
1159 case Jlxor:
1160 binop(j, 'J', 'J', 'J');
1161 break;
1162 case Jfadd:
1163 case Jfsub:
1164 case Jfmul:
1165 case Jfdiv:
1166 case Jfrem:
1167 binop(j, 'F', 'F', 'F');
1168 break;
1169 case Jdadd:
1170 case Jdsub:
1171 case Jdmul:
1172 case Jddiv:
1173 case Jdrem:
1174 binop(j, 'D', 'D', 'D');
1175 break;
1176 case Jineg:
1177 unop(j, 'I', 'I');
1178 break;
1179 case Jlneg:
1180 unop(j, 'J', 'J');
1181 break;
1182 case Jfneg:
1183 unop(j, 'F', 'F');
1184 break;
1185 case Jdneg:
1186 unop(j, 'D', 'D');
1187 break;
1188 case Jlshl:
1189 case Jlshr:
1190 case Jlushr:
1191 binop(j, 'J', 'I', 'J');
1192 break;
1193 case Jiinc:
1194 verifyindex(j, 'I', j->u.x1c.ix);
1195 storechk(j->u.x1c.ix, 'I');
1196 break;
1197 case Ji2l:
1198 unop(j, 'I', 'J');
1199 break;
1200 case Ji2f:
1201 unop(j, 'I', 'F');
1202 break;
1203 case Ji2d:
1204 unop(j, 'I', 'D');
1205 break;
1206 case Jl2i:
1207 unop(j, 'J', 'I');
1208 break;
1209 case Jl2f:
1210 unop(j, 'J', 'F');
1211 break;
1212 case Jl2d:
1213 unop(j, 'J', 'D');
1214 break;
1215 case Jf2i:
1216 unop(j, 'F', 'I');
1217 break;
1218 case Jf2l:
1219 unop(j, 'F', 'J');
1220 break;
1221 case Jf2d:
1222 unop(j, 'F', 'D');
1223 break;
1224 case Jd2i:
1225 unop(j, 'D', 'I');
1226 break;
1227 case Jd2l:
1228 unop(j, 'D', 'J');
1229 break;
1230 case Jd2f:
1231 unop(j, 'D', 'F');
1232 break;
1233 case Ji2b:
1234 case Ji2c:
1235 case Ji2s:
1236 unop(j, 'I', 'I');
1237 break;
1238 case Jlcmp:
1239 binop(j, 'J', 'J', 'I');
1240 break;
1241 case Jfcmpl:
1242 case Jfcmpg:
1243 binop(j, 'F', 'F', 'I');
1244 break;
1245 case Jdcmpl:
1246 case Jdcmpg:
1247 binop(j, 'D', 'D', 'I');
1248 break;
1249 case Jifeq:
1250 case Jifne:
1251 case Jiflt:
1252 case Jifge:
1253 case Jifgt:
1254 case Jifle:
1255 useone(j, 'I');
1256 break;
1257 case Jif_icmpeq:
1258 case Jif_icmpne:
1259 case Jif_icmplt:
1260 case Jif_icmpge:
1261 case Jif_icmpgt:
1262 case Jif_icmple:
1263 usetwo(j, 'I', 'I');
1264 break;
1265 case Jif_acmpeq:
1266 case Jif_acmpne:
1267 usetwo(j, 'L', 'L');
1268 break;
1269 case Jgoto:
1270 case Jgoto_w:
1271 case Jjsr: /* no push; not following ... */
1272 case Jjsr_w: /* ... these branches */
1273 break;
1274 case Jret:
1275 verifyindex(j, 'L', j->u.i);
1276 break;
1277 case Jtableswitch:
1278 case Jlookupswitch:
1279 useone(j, 'I');
1280 break;
1281 case Jireturn:
1282 case Jlreturn:
1283 case Jfreturn:
1284 case Jdreturn:
1285 case Jareturn:
1286 case Jreturn:
1287 javareturn(j);
1288 break;
1289 case Jgetfield:
1290 case Jgetstatic:
1291 getfs(j);
1292 break;
1293 case Jputfield:
1294 case Jputstatic:
1295 putfs(j);
1296 break;
1297 case Jinvokevirtual:
1298 case Jinvokespecial:
1299 case Jinvokestatic:
1300 case Jinvokeinterface:
1301 invoke(j);
1302 break;
1303 case Jxxxunusedxxx:
1304 break;
1305 case Jnew:
1306 javanew(j);
1307 break;
1308 case Jnewarray:
1309 unop(j, 'I', '[');
1310 break;
1311 case Janewarray:
1312 anewarray(j);
1313 break;
1314 case Jarraylength:
1315 unop(j, '[', 'I');
1316 break;
1317 case Jathrow:
1318 useone(j, 'L');
1319 break;
1320 case Jcheckcast:
1321 case Jinstanceof:
1322 unop(j, 'L', (j->op == Jcheckcast) ? 'L' : 'I');
1323 crefenter(CLASSNAME(j->u.i), j->bb);
1324 break;
1325 case Jmonitorenter:
1326 case Jmonitorexit:
1327 useone(j, 'L');
1328 break;
1329 case Jwide:
1330 switch(j->u.w.op) {
1331 case Jiload:
1332 javaload(j, 'I', j->u.w.ix);
1333 break;
1334 case Jlload:
1335 javaload(j, 'J', j->u.w.ix);
1336 break;
1337 case Jfload:
1338 javaload(j, 'F', j->u.w.ix);
1339 break;
1340 case Jdload:
1341 javaload(j, 'D', j->u.w.ix);
1342 break;
1343 case Jaload:
1344 javaload(j, 'L', j->u.w.ix);
1345 break;
1346 case Jistore:
1347 storechk(j->u.w.ix, 'I');
1348 javastore(j, 'I', j->u.w.ix);
1349 break;
1350 case Jlstore:
1351 storechk(j->u.w.ix, 'J');
1352 javastore(j, 'J', j->u.w.ix);
1353 break;
1354 case Jfstore:
1355 storechk(j->u.w.ix, 'F');
1356 javastore(j, 'F', j->u.w.ix);
1357 break;
1358 case Jdstore:
1359 storechk(j->u.w.ix, 'D');
1360 javastore(j, 'D', j->u.w.ix);
1361 break;
1362 case Jastore:
1363 storechk(j->u.w.ix, 'L');
1364 javastore(j, 'L', j->u.w.ix);
1365 break;
1366 case Jret:
1367 verifyindex(j, 'L', j->u.w.ix);
1368 break;
1369 case Jiinc:
1370 verifyindex(j, 'I', j->u.w.ix);
1371 storechk(j->u.w.ix, 'I');
1372 break;
1373 }
1374 break;
1375 case Jmultianewarray:
1376 multianewarray(j);
1377 break;
1378 case Jifnull:
1379 case Jifnonnull:
1380 useone(j, 'L');
1381 break;
1382 }
1383}
1384
1385/*
1386 * Take snapshot of current stack.
1387 */
1388
1389static StkSnap*
1390snapstack(void)
1391{
1392 StkSnap *s;
1393 int i;
1394
1395 s = Malloc(jvmtos*sizeof(StkSnap));
1396 for(i = 0; i < jvmtos; i++) {
1397 s[i].jtype = jvmstack[i].jtype;
1398 s[i].npc = 1;
1399 s[i].pc = Malloc(sizeof(int));
1400 s[i].pc[0] = jvmstack[i].pc;
1401 }
1402 return s;
1403}
1404
1405/*
1406 * Merge current stack into bb.entrystk.
1407 */
1408
1409static void
1410stackmerge(BB *bb)
1411{
1412 StkSnap *s;
1413 int i, j;
1414 int pct;
1415 uchar jtype1, jtype2;
1416
1417 if(jvmtos == 0) {
1418 if(bb->entrysz != 0)
1419 verifyerrormess("stack merge");
1420 return;
1421 }
1422 if(bb->entrystk == nil) {
1423 bb->entrysz = jvmtos;
1424 bb->entrystk = snapstack();
1425 return;
1426 }
1427 /* true stack merge */
1428 if(bb->entrysz != jvmtos)
1429 verifyerrormess("stack merge");
1430 for(i = 0; i < jvmtos; i++) {
1431 jtype1 = jvmstack[i].jtype;
1432 jtype2 = bb->entrystk[i].jtype;
1433 if(jtype1 != jtype2 && jtype1 + jtype2 != 'L' + '[')
1434 verifyerrormess("stack merge");
1435 s = &bb->entrystk[i];
1436 for(j = 0; j < s->npc; j++) {
1437 if(s->pc[j] == jvmstack[i].pc)
1438 goto continue_outer;
1439 }
1440 s->pc = Realloc(s->pc, (s->npc+1)*sizeof(int));
1441 s->pc[s->npc++] = jvmstack[i].pc;
1442 /* percolate into sorted order */
1443 for(j = s->npc-1; j > 0; j--) {
1444 if(s->pc[j-1] > s->pc[j]) {
1445 pct = s->pc[j-1];
1446 s->pc[j-1] = s->pc[j];
1447 s->pc[j] = pct;
1448 } else
1449 break;
1450 }
1451 continue_outer: ;
1452 }
1453}
1454
1455/*
1456 * Simulate the instructions in a basic block.
1457 */
1458
1459static void
1460simbb(BB *bb)
1461{
1462 Jinst *j;
1463 BBList *l;
1464
1465 if(bb->state == BB_POSTSIM)
1466 fatal("simbb: BB_POSTSIM\n");
1467
1468 jvminit(bb);
1469 j = bb->js;
1470 while(j <= bb->je) {
1471 simjinst(j);
1472 j += j->size;
1473 }
1474 bb->state = BB_POSTSIM;
1475
1476 if(jvmtos != 0) {
1477 bb->exitsz = jvmtos;
1478 bb->exitstk = snapstack();
1479 }
1480
1481 for(l = bb->succ; l; l = l->next) {
1482 stackmerge(l->bb);
1483 if(l->bb->state == BB_PRESIM)
1484 bbput(l->bb);
1485 }
1486}
1487
1488/*
1489 * Simulate the Java VM on each of the method's basic blocks.
1490 */
1491
1492void
1493simjvm(char *sig)
1494{
1495 BB *bb;
1496
1497 sig++; /* skip '(' */
1498 while(sig[0] != ')')
1499 sig++;
1500 rettype = jvmtype(sig[1]);
1501
1502 jvmstack = Malloc(code->max_stack*sizeof(Result));
1503
1504 bbinit();
1505 while(bb = bbget())
1506 simbb(bb);
1507
1508 free(jvmstack);
1509}
java/tools/j2d/unify.c+106−0
@@ -0,0 +1,106 @@
1#include "java.h"
2#include "javaisa.h"
3
4/*
5 * "Unify" results that are produced in one basic block and consumed
6 * in another. I.e., ensure that producers and consumers access results
7 * through consistent fp offsets.
8 */
9
10static void
11pushsucc(BB *bb)
12{
13 BBList *l;
14
15 for(l = bb->succ; l; l = l->next) {
16 if(l->bb->state == BB_POSTSIM)
17 bbput(l->bb);
18 }
19}
20
21static int
22pass1(StkSnap *s)
23{
24 Jinst *j;
25 int i;
26 int fpoff;
27
28 fpoff = -1;
29 for(i = 0; i < s->npc; i++) {
30 j = &code->j[s->pc[i]];
31 if((isload(j) && j->movsrc.mode != Anone)
32 || (!isload(j) && j->dst.u.offset != -1)) {
33 if(fpoff == -1)
34 fpoff = j->dst.u.offset;
35 else if(fpoff != j->dst.u.offset)
36 fatal("pass1: can't\n");
37 }
38 }
39 if(fpoff == -1)
40 fpoff = getreg(j2dtype(s->jtype));
41 return fpoff;
42}
43
44static void
45pass2(StkSnap *s, int fpoff)
46{
47 Jinst *j;
48 int i;
49
50 for(i = 0; i < s->npc; i++) {
51 j = &code->j[s->pc[i]];
52 if(isload(j) && j->movsrc.mode == Anone) {
53 j->movsrc = j->dst;
54 j->dst.mode = Afp;
55 }
56 j->dst.u.offset = fpoff;
57 }
58}
59
60static void
61unifybb(BB *bb)
62{
63 StkSnap *s;
64 int n, m;
65
66 if(bb->state == BB_POSTUNIFY)
67 fatal("unifybb: BB_POSTUNIFY\n");
68
69 if(bb->entrystk == nil) {
70 pushsucc(bb);
71 return;
72 }
73
74 clearreg();
75 reservereg(bb->entrystk, bb->entrysz);
76 reservereg(bb->exitstk, bb->exitsz);
77
78 for(n = 0; n < bb->entrysz; n++) {
79 s = &bb->entrystk[n];
80 for(m = 0; m < s->npc; m++) {
81 reservereg(code->j[s->pc[m]].bb->entrystk,
82 code->j[s->pc[m]].bb->entrysz);
83 }
84 }
85
86 for(n = 0; n < bb->entrysz; n++) {
87 s = &bb->entrystk[n];
88 if(s->npc == 1)
89 dstreg(&code->j[s->pc[0]].dst, j2dtype(s->jtype));
90 else
91 pass2(s, pass1(s));
92 }
93
94 bb->state = BB_POSTUNIFY;
95 pushsucc(bb);
96}
97
98void
99unify(void)
100{
101 BB *bb;
102
103 bbinit();
104 while(bb = bbget())
105 unifybb(bb);
106}
java/tools/j2d/util.c+372−0
@@ -0,0 +1,372 @@
1#include "java.h"
2
3/*
4 * Utility functions.
5 */
6
7static uchar *codeix;
8
9void
10uSet(uchar *x)
11{
12 codeix = x;
13}
14
15char*
16uPtr(void)
17{
18 return (char*)codeix;
19}
20
21void
22uN(int i)
23{
24 codeix += i;
25}
26
27uchar
28u1(void)
29{
30 return *codeix++;
31}
32
33ushort
34u2(void)
35{
36 ushort l;
37
38 l = (codeix[0]<<8) | codeix[1];
39 codeix += 2;
40 return l;
41}
42
43uint
44u4(void)
45{
46 uint l;
47
48 l = (codeix[0]<<24) | (codeix[1]<<16) | (codeix[2]<<8) | codeix[3];
49 codeix += 4;
50 return l;
51}
52
53void
54getattr(Attr *a)
55{
56 a->name = u2();
57 verifycpindex(nil, a->name, 1 << CON_Utf8);
58 a->ln = u4();
59 a->info = Malloc(a->ln);
60 memmove(a->info, codeix, a->ln);
61 codeix += a->ln;
62}
63
64/*
65 * Get the constantvalue_index of a ConstantValue attribute.
66 */
67
68int
69CVattrindex(Field *fp)
70{
71 int i;
72 Attr *a;
73
74 for(i = 0, a = fp->attr_info; i < fp->attr_count; i++, a++) {
75 if(strcmp(STRING(a->name), "ConstantValue") != 0)
76 continue;
77 if(a->ln != 2)
78 verifyerrormess("ConstantValue attribute");
79 return (a->info[0]<<8) | a->info[1];
80 }
81 return 0;
82}
83
84/*
85 * Align 'off' on an 'align'-byte boundary ('align' is a power of 2).
86 */
87
88int
89align(int off, int align)
90{
91 align--;
92 return (off + align) & ~align;
93}
94
95/*
96 * Set 'offset' bit in type descriptor 'map'.
97 */
98
99void
100setbit(uchar *map, int offset)
101{
102 uchar *m;
103
104 m = &map[offset / (8*IBY2WD)];
105 *m |= 1 << (7 - (offset / IBY2WD % 8));
106}
107
108/*
109 * Trivial hash function from asm.
110 */
111
112int
113hashval(char *s)
114{
115 int h;
116
117 h = 0;
118 while(*s)
119 h = h*3 + *s++;
120 if(h < 0)
121 h = -h;
122 return h % Hashsize;
123}
124
125/*
126 * Advance to the next Java type in a method descriptor.
127 */
128
129char*
130nextjavatype(char *s)
131{
132 int nlb;
133
134 nlb = 0;
135 for(;;) {
136 switch(s[0]) {
137 case 'L':
138 s = strchr(s, ';');
139 case 'V':
140 case 'Z':
141 case 'B':
142 case 'C':
143 case 'S':
144 case 'I':
145 case 'J':
146 case 'F':
147 case 'D':
148 return s+1;
149 case '[':
150 if(++nlb < 256) {
151 s++;
152 break;
153 }
154 default:
155 verifyerrormess("field/method descriptor");
156 }
157 }
158 return nil; /* for compiler */
159}
160
161uchar
162j2dtype(uchar jtype)
163{
164 uchar dtype;
165
166 switch(jtype) {
167 case 'Z':
168 case 'B':
169 case 'C':
170 case 'S':
171 case 'I':
172 dtype = DIS_W;
173 break;
174 case 'J':
175 case 'F':
176 case 'D':
177 dtype = DIS_L;
178 break;
179 case 'L':
180 case '[':
181 dtype = DIS_P;
182 break;
183 default:
184 verifyerrormess("java data type");
185 return -1;
186 }
187 return dtype;
188}
189
190/*
191 * $i operands
192 */
193
194void
195addrimm(Addr *a, int ival)
196{
197 a->mode = Aimm;
198 a->u.ival = ival;
199}
200
201/*
202 * Is an int too big to be an immediate operand?
203 */
204
205int
206notimmable(int val)
207{
208 return val < 0 && ((val >> 29) & 7) != 7 || val > 0 && (val >> 29) != 0;
209}
210
211/*
212 * i(fp) and i(mp) operands
213 */
214
215void
216addrsind(Addr *a, uchar mode, int off)
217{
218 a->mode = mode;
219 a->u.offset = off;
220}
221
222/*
223 * i(j(fp)) and i(j(mp)) operands
224 */
225
226void
227addrdind(Addr *a, uchar mode, uint fi, uint si)
228{
229 a->mode = mode;
230 a->u.b.fi = fi;
231 a->u.b.si = si;
232}
233
234/*
235 * Assign a register to a destination operand if not already done so.
236 */
237
238void
239dstreg(Addr *a, uchar dtype)
240{
241 if(a->mode == Afp && a->u.offset == -1)
242 a->u.offset = getreg(dtype);
243}
244
245/*
246 * Print a string.
247 */
248
249void
250pstring(char *s)
251{
252 int slen;
253 char *se;
254 char c;
255
256 slen = strlen(s);
257 se = s + slen;
258 for(; s < se; s++) {
259 /* null char represented as 0xC080 in String literals */
260 c = s[0];
261 if(s+1 < se && (uchar)c == 0xC0 && (uchar)s[1] == 0x80) {
262 c = '\0';
263 s++;
264 }
265 if(c == '\n')
266 Bwrite(bout, "\\n", 2);
267 else if(c == '\t')
268 Bwrite(bout, "\\t", 2);
269 else if(c == '"')
270 Bwrite(bout, "\\\"", 2);
271 else if(c == '\\')
272 Bwrite(bout, "\\\\", 2);
273 else
274 Bputc(bout, c);
275 }
276}
277
278void*
279Malloc(uint n)
280{
281 void *p;
282
283 p = malloc(n);
284 if(p == nil)
285 fatal("out of memory\n");
286 return p;
287}
288
289void*
290Mallocz(uint n)
291{
292 void *p;
293
294 p = Malloc(n);
295 memset(p, 0, n);
296 return p;
297}
298
299void*
300Realloc(void *p, uint n)
301{
302 if(p == nil)
303 p = malloc(n);
304 else
305 p = realloc(p, n);
306 if(p == nil)
307 fatal("out of memory\n");
308 return p;
309}
310
311/*
312 * Die.
313 */
314
315void
316fatal(char *fmt, ...)
317{
318 va_list s;
319 char buf[1024], *out;
320
321 va_start(s, fmt);
322 write(2, "fatal j2d error: ", 17);
323 out = doprint(buf, buf+sizeof(buf), fmt, s);
324 va_end(s);
325 write(2, buf, (int)(out-buf));
326 if(bout != nil)
327 remove(ofile);
328 exits("fatal");
329}
330
331/*
332 * Bytecode verification.
333 */
334
335/*
336 * Verify a constant pool index.
337 */
338
339void
340verifycpindex(Jinst *j, int ix, int CON_bits)
341{
342 if(ix > 0 && ix < class->cp_count && ((1 << class->cts[ix]) & CON_bits))
343 return;
344
345 if(j != nil)
346 verifyerror(j);
347 else
348 verifyerrormess("constant pool index");
349}
350
351void
352verifyerror(Jinst *j)
353{
354 fatal("VerifyError: %J\n", j);
355}
356
357void
358verifyerrormess(char *mess)
359{
360 fatal("VerifyError: %s\n", mess);
361}
362
363/*
364 * Size of frame cell of given type.
365 */
366
367int cellsize[DIS_P+1] = {
368 0, /* DIS_X */
369 IBY2WD, /* DIS_W */
370 IBY2LG, /* DIS_L */
371 IBY2WD, /* DIS_P */
372};
java/tools/j2d/xlate.c+3094−0
@@ -0,0 +1,3094 @@
1#include "java.h"
2#include "javaisa.h"
3#include "reloc.h"
4
5static int pcdis;
6static int callunrescue;
7static Jinst *J;
8static Method *M;
9 Code *code; /* method under translation */
10
11static int trylevel(int);
12static void unrescue(int);
13
14/*
15 * Allocate a Dis instruction.
16 */
17
18static Inst*
19newi(uchar op)
20{
21 Inst *i;
22
23 i = Mallocz(sizeof(Inst));
24 i->op = (uchar)op;
25 i->pc = pcdis;
26 pcdis += 1;
27 i->j = J;
28 i->next = nil;
29 if(J && J->dis == nil)
30 J->dis = i;
31 if(ihead == nil)
32 ihead = i;
33 if(itail)
34 itail->next = i;
35 itail = i;
36 return i;
37}
38
39/*
40 * Allocate a Dis instruction and record for branch-address patching.
41 */
42
43static Inst*
44newibap(uchar op)
45{
46 Inst *i;
47
48 i = newi(op);
49 patchop(i);
50 return i;
51}
52
53/*
54 * Turn single indirection off fp into double indirection.
55 */
56
57static void
58sind2dind(Addr *a, int s)
59{
60 if(a->mode == Afp) {
61 a->mode = Afpind;
62 /* check for overflow ??? */
63 a->u.b.fi = a->u.offset;
64 a->u.b.si = s;
65 } else if(a->mode == Amp && a->u.offset == 0)
66 ; /* verifyerror(J); *//* can't reject prior to runtime */
67 else
68 fatal("sind2dind: %d not Afp\n", a->mode);
69}
70
71/*
72 * Middle operands that match destination operands are redundant.
73 */
74
75static void
76middstcmp(Inst *i)
77{
78 Addr *m, *d;
79
80 m = &i->m;
81 d = &i->d;
82 if(m->mode == Afp && m->mode == d->mode && m->u.offset == d->u.offset) {
83 m->mode = Anone;
84 m->u.offset = 0;
85 }
86}
87
88/*
89 * For instructions that may reference Module Data.
90 */
91
92static void
93datareloc(Inst *i)
94{
95 if(i->op == IMOVP && i->s.mode == Amp && i->s.u.offset == 0)
96 return; /* don't relocate reference to nil */
97 if(i->s.mode == Amp)
98 addDreloc(i, PSRC, PSIND);
99 if(i->m.mode == Amp)
100 addDreloc(i, PMID, PSIND);
101}
102
103static uchar
104movinst(uchar jtype)
105{
106 uchar movi;
107
108 switch(jtype) {
109 case 'Z':
110 case 'B':
111 if(J->op == Jgetfield || J->op == Jgetstatic)
112 movi = ICVTBW;
113 else if(J->op == Jputfield || J->op == Jputstatic)
114 movi = ICVTWB;
115 else
116 movi = IMOVW;
117 break;
118 case 'C':
119 case 'S':
120 case 'I':
121 movi = IMOVW;
122 break;
123 case 'J':
124 movi = IMOVL;
125 break;
126 case 'F':
127 case 'D':
128 movi = IMOVF;
129 break;
130 case 'L':
131 case '[':
132 movi = IMOVP;
133 break;
134 default:
135 SET(movi); /* not reached */
136 }
137 return movi;
138}
139
140typedef struct FieldInfo FieldInfo;
141
142struct FieldInfo {
143 char *classname;
144 char *fieldname;
145 char *sig;
146 int flags;
147};
148
149static void
150getfldinfo(FieldInfo *fi)
151{
152 Const *c, *n;
153 int i, ix;
154 Method *m;
155
156 if(J->op == Jinvokeinterface)
157 ix = J->u.x2c0.ix;
158 else
159 ix = J->u.i;
160 c = &class->cps[ix];
161 fi->classname = CLASSNAME(c->fmiref.class_index);
162 n = &class->cps[c->fmiref.name_type_index];
163 fi->fieldname = STRING(n->nat.name_index);
164 fi->sig = STRING(n->nat.sig_index);
165 fi->flags = 0;
166 if(strcmp(fi->classname, THISCLASS) != 0)
167 return;
168 for(i = 0, m = class->methods; i < class->methods_count; i++, m++) {
169 if(strcmp(fi->fieldname, STRING(m->name_index)) == 0
170 && strcmp(fi->sig, STRING(m->sig_index)) == 0) {
171 fi->flags = m->access_flags;
172 break;
173 }
174 }
175}
176
177/*
178 * mframe instruction for a call to a Loader entry point.
179 */
180
181static Inst*
182loadermframe(Freloc *frm, Freloc *frf)
183{
184 Inst *imframe;
185
186 imframe = newi(IMFRAME);
187 addrsind(&imframe->s, Amp, 0);
188 addrimm(&imframe->m, 0);
189 addrsind(&imframe->d, Afp, getreg(DIS_W));
190 LTIpatch(frm, imframe, PSRC, PSIND);
191 LTIpatch(frf, imframe, PMID, PIMM);
192
193 return imframe;
194}
195
196/*
197 * mcall instruction for a call to a Loader entry point.
198 */
199
200static Inst*
201loadermcall(Inst *imframe, Freloc *frf, Freloc *frm)
202{
203 Inst *imcall;
204
205 imcall = newi(IMCALL);
206 imcall->s = imframe->d;
207 imcall->m = imframe->m;
208 imcall->d = imframe->s;
209 LTIpatch(frf, imcall, PMID, PIMM);
210 LTIpatch(frm, imcall, PDST, PSIND);
211
212 return imcall;
213}
214
215/*
216 * Call "rtload" for run-time resolution.
217 */
218
219static void
220callrtload(RTClass *rtc, char *classname)
221{
222 Inst *imframe, *i;
223 Creloc *cr;
224 Freloc *frm, *frf;
225 RTReloc *rtr;
226
227 USED(classname);
228 rtr = getRTReloc(rtc, RMP, nil, 0);
229 cr = getCreloc(RLOADER);
230 frm = getFreloc(cr, RMP, nil, 0);
231 frf = getFreloc(cr, "rtload", nil, 0);
232
233 i = newi(IBNEW);
234 addrsind(&i->s, Amp, 0);
235 addrsind(&i->m, Amp, 0);
236 addrimm(&i->d, i->pc+4);
237 RTIpatch(rtr, i, PSRC, PSIND);
238
239 imframe = loadermframe(frm, frf);
240
241 i = newi(ILEA);
242 addrsind(&i->s, Amp, 0);
243 addrdind(&i->d, Afpind, imframe->d.u.offset, REGSIZE);
244 RTIpatch(rtr, i, PSRC, PSIND);
245
246 loadermcall(imframe, frf, frm);
247 relreg(&imframe->d);
248}
249
250/*
251 * Sign-extend an 8-bit unsigned char (Dis byte) to a 32-bit int.
252 */
253
254static void
255signextend(Addr *dst)
256{
257 Inst *i;
258
259 i = newi(ISHLW);
260 addrimm(&i->s, 24);
261 /*i->m = *dst;*/ /* redundant */
262 i->d = *dst;
263
264 i = newi(ISHRW);
265 addrimm(&i->s, 24);
266 /*i->m = *dst;*/ /* redundant */
267 i->d = *dst;
268}
269
270/*
271 * addw instruction for run-time relocated getstatic & putstatic.
272 */
273
274static Addr*
275rtstaticadd(FieldInfo *fi, RTClass *rtc)
276{
277 Inst *i;
278
279 i = newi(IADDW);
280 addrdind(&i->s, Ampind, 0, 0);
281 addrsind(&i->m, Amp, 0);
282 addrsind(&i->d, Afp, getreg(DIS_W));
283
284 RTIpatch(getRTReloc(rtc, RMP, nil, 0), i, PSRC, PDIND1);
285 RTIpatch(getRTReloc(rtc, fi->fieldname, fi->sig, Rgetputstatic),
286 i, PMID, PSIND);
287
288 return &i->d;
289}
290
291/*
292 * addw instruction for load-time relocated getstatic & putstatic.
293 */
294
295static Addr*
296ltstaticadd(FieldInfo *fi)
297{
298 Inst *i;
299 Creloc *cr;
300
301 i = newi(IADDW);
302 addrdind(&i->s, Ampind, 0, 0);
303 addrimm(&i->m, 0);
304 addrsind(&i->d, Afp, getreg(DIS_W));
305
306 cr = getCreloc(fi->classname);
307 LTIpatch(getFreloc(cr, RMP, nil, 0), i, PSRC, PDIND1);
308 LTIpatch(getFreloc(cr, fi->fieldname, fi->sig, Rgetputstatic),
309 i, PMID, PIMM);
310
311 return &i->d;
312}
313
314/*
315 * Java getstatic.
316 */
317
318static void
319getstatic(void)
320{
321 int state;
322 Inst *i;
323 Addr *a;
324 FieldInfo fi;
325 RTClass *rtc;
326
327 getfldinfo(&fi);
328 state = crefstate(fi.classname, J->bb, 0);
329 if(state & LTCODE) {
330 a = ltstaticadd(&fi);
331 } else {
332 rtc = getRTClass(fi.classname);
333 if(state & RTCALL)
334 callrtload(rtc, fi.classname);
335 a = rtstaticadd(&fi, rtc);
336 }
337
338 i = newi(movinst(fi.sig[0]));
339 i->s = *a;
340 sind2dind(&i->s, 0);
341 relreg(a);
342 dstreg(&J->dst, j2dtype(J->jtype));
343 i->d = J->dst;
344
345 if(fi.sig[0] == 'B')
346 signextend(&i->d);
347}
348
349/*
350 * Java putstatic.
351 */
352
353static void
354putstatic(void)
355{
356 int state;
357 Inst *i;
358 Addr *a;
359 FieldInfo fi;
360 RTClass *rtc;
361
362 getfldinfo(&fi);
363 state = crefstate(fi.classname, J->bb, 0);
364 if(state & LTCODE) {
365 a = ltstaticadd(&fi);
366 } else {
367 rtc = getRTClass(fi.classname);
368 if(state & RTCALL)
369 callrtload(rtc, fi.classname);
370 a = rtstaticadd(&fi, rtc);
371 }
372
373 i = newi(movinst(fi.sig[0]));
374 i->s = code->j[J->src[0]].dst;
375 relreg(&code->j[J->src[0]].dst);
376 i->d = *a;
377 sind2dind(&i->d, 0);
378 relreg(a);
379 datareloc(i);
380}
381
382/*
383 * addw instruction for run-time relocated getfield & putfield.
384 */
385
386static Addr*
387rtfieldadd(FieldInfo *fi, RTClass *rtc, Addr *a)
388{
389 Inst *i;
390
391 i = newi(IADDW);
392 i->s = *a;
393 addrsind(&i->m, Amp, 0);
394 addrsind(&i->d, Afp, getreg(DIS_W));
395
396 RTIpatch(getRTReloc(rtc, fi->fieldname, fi->sig, Rgetputfield),
397 i, PMID, PSIND);
398
399 return &i->d;
400}
401
402/*
403 * Java getfield.
404 */
405
406static void
407getfield(void)
408{
409 int state;
410 Addr *a;
411 Inst *i;
412 FieldInfo fi;
413 Creloc *cr;
414 RTClass *rtc;
415
416 getfldinfo(&fi);
417 state = crefstate(fi.classname, J->bb, 0);
418 if(state & LTCODE) {
419 i = newi(movinst(fi.sig[0]));
420 i->s = code->j[J->src[0]].dst;
421 sind2dind(&i->s, 0);
422 relreg(&code->j[J->src[0]].dst);
423 cr = getCreloc(fi.classname);
424 LTIpatch(getFreloc(cr, fi.fieldname, fi.sig, Rgetputfield),
425 i, PSRC, PDIND2);
426 } else {
427 rtc = getRTClass(fi.classname);
428 if(state & RTCALL)
429 callrtload(rtc, fi.classname);
430 a = rtfieldadd(&fi, rtc, &code->j[J->src[0]].dst);
431 relreg(&code->j[J->src[0]].dst);
432 i = newi(movinst(fi.sig[0]));
433 i->s = *a;
434 sind2dind(&i->s, 0);
435 relreg(a);
436 }
437 dstreg(&J->dst, j2dtype(J->jtype));
438 i->d = J->dst;
439
440 if(fi.sig[0] == 'B')
441 signextend(&i->d);
442
443}
444
445/*
446 * Java putfield.
447 */
448
449static void
450putfield(void)
451{
452 int state;
453 Addr *a;
454 Inst *i;
455 FieldInfo fi;
456 Creloc *cr;
457 RTClass *rtc;
458
459 getfldinfo(&fi);
460 state = crefstate(fi.classname, J->bb, 0);
461 if(state & LTCODE) {
462 i = newi(movinst(fi.sig[0]));
463 i->s = code->j[J->src[1]].dst;
464 relreg(&code->j[J->src[1]].dst);
465 i->d = code->j[J->src[0]].dst;
466 relreg(&code->j[J->src[0]].dst);
467
468 cr = getCreloc(fi.classname);
469 LTIpatch(getFreloc(cr, fi.fieldname, fi.sig, Rgetputfield),
470 i, PDST, PDIND2);
471 } else {
472 rtc = getRTClass(fi.classname);
473 if(state & RTCALL)
474 callrtload(rtc, fi.classname);
475 a = rtfieldadd(&fi, rtc, &code->j[J->src[0]].dst);
476 relreg(&code->j[J->src[0]].dst);
477
478 i = newi(movinst(fi.sig[0]));
479 i->s = code->j[J->src[1]].dst;
480 relreg(&code->j[J->src[1]].dst);
481 i->d = *a;
482 relreg(a);
483 }
484 sind2dind(&i->d, 0);
485 datareloc(i);
486}
487
488/*
489 * Push function arguments.
490 */
491
492static void
493pushargs(int calltype, int calleeframe, char *sig)
494{
495 Inst *i;
496 int frameoff;
497 int arg, size;
498
499 frameoff = REGSIZE;
500 arg = 0;
501 if(calltype != Rinvokestatic) {
502 i = newi(IMOVP); /* this pointer */
503 i->s = code->j[J->src[arg]].dst;
504 addrdind(&i->d, Afpind, calleeframe, frameoff);
505 frameoff += IBY2WD;
506 arg++;
507 }
508
509 sig++; /* skip '(' */
510 while(sig[0] != ')') {
511 i = newi(movinst(sig[0]));
512 i->s = code->j[J->src[arg]].dst;
513 size = cellsize[j2dtype(sig[0])];
514 frameoff = align(frameoff, size);
515 addrdind(&i->d, Afpind, calleeframe, frameoff);
516 datareloc(i);
517 frameoff += size;
518 sig = nextjavatype(sig);
519 arg++;
520 }
521
522 /* return value */
523 if(sig[1] != 'V') { /* skip ')' */
524 i = newi(ILEA);
525 dstreg(&J->dst, j2dtype(J->jtype));
526 i->s = J->dst;
527 addrdind(&i->d, Afpind, calleeframe, REGRET*IBY2WD);
528 }
529}
530
531/*
532 * Run-time relocated invokespecial and invokestatic.
533 */
534
535static void
536rtinvokess(FieldInfo *fi, int calltype, int mpflag, int state)
537{
538 int n;
539 Inst *imframe, *imcall;
540 RTClass *rtc;
541 RTReloc *rtr1, *rtr2;
542
543 rtc = getRTClass(fi->classname);
544 if(state & RTCALL)
545 callrtload(rtc, fi->classname);
546
547 imframe = newi(IMFRAME);
548 addrsind(&imframe->s, Amp, 0);
549 addrsind(&imframe->m, Amp, 0);
550 addrsind(&imframe->d, Afp, getreg(DIS_W));
551
552 rtr1 = getRTReloc(rtc, fi->fieldname, fi->sig, calltype|mpflag);
553 rtr2 = getRTReloc(rtc, fi->fieldname, fi->sig, calltype);
554 RTIpatch(rtr1, imframe, PSRC, PSIND);
555 RTIpatch(rtr2, imframe, PMID, PSIND);
556
557 /* push arguments into callee's frame, handle return type */
558 pushargs(calltype, imframe->d.u.offset, fi->sig);
559
560 imcall = newi(IMCALL);
561 imcall->s = imframe->d;
562 imcall->m = imframe->m;
563 imcall->d = imframe->s;
564
565 RTIpatch(rtr1, imcall, PDST, PSIND);
566 RTIpatch(rtr2, imcall, PMID, PSIND);
567
568 for(n = 0; n < J->nsrc; n++)
569 relreg(&code->j[J->src[n]].dst);
570 relreg(&imframe->d);
571}
572
573/*
574 * Load-time relocated invokespecial and invokestatic.
575 */
576
577static void
578invokess(int calltype, int mpflag)
579{
580 int n, state;
581 Inst *imframe, *imcall;
582 Creloc *cr;
583 Freloc *frf, *frm;
584 FieldInfo fi;
585
586 frf = nil;
587 getfldinfo(&fi);
588 state = crefstate(fi.classname, J->bb, 0);
589 if(state & RTCODE) {
590 rtinvokess(&fi, calltype, mpflag, state);
591 return;
592 }
593 cr = getCreloc(fi.classname);
594 /* fi.flags set only if fi.classname == this_class */
595 if(fi.flags & (ACC_PRIVATE | ACC_STATIC)) {
596 if(fi.flags & ACC_NATIVE)
597 frm = getFreloc(cr, RNP, nil, 0);
598 else
599 frm = nil; /* frame/call */
600 } else {
601 /* force @mp, @np into the list for cr */
602 getFreloc(cr, RMP, nil, 0);
603 getFreloc(cr, RNP, nil, 0);
604 frm = getFreloc(cr, fi.fieldname, fi.sig, calltype|mpflag);
605 }
606
607 if(frm == nil) {
608 imframe = newi(IFRAME);
609 addrimm(&imframe->s, 0);
610 } else {
611 imframe = newi(IMFRAME);
612 addrsind(&imframe->s, Amp, 0);
613 addrimm(&imframe->m, 0);
614 LTIpatch(frm, imframe, PSRC, PSIND);
615 frf = getFreloc(cr, fi.fieldname, fi.sig, calltype);
616 LTIpatch(frf, imframe, PMID, PIMM);
617 }
618 addrsind(&imframe->d, Afp, getreg(DIS_W));
619
620 /* push arguments into callee's frame, handle return type */
621 pushargs(calltype, imframe->d.u.offset, fi.sig);
622
623 if(frm == nil) {
624 imcall = newi(ICALL);
625 addfcpatch(imframe, imcall, fi.fieldname, fi.sig);
626 } else {
627 imcall = newi(IMCALL);
628 imcall->m = imframe->m;
629 LTIpatch(frf, imcall, PMID, PIMM);
630 LTIpatch(frm, imcall, PDST, PSIND);
631 }
632 imcall->s = imframe->d;
633 imcall->d = imframe->s;
634
635 for(n = 0; n < J->nsrc; n++)
636 relreg(&code->j[J->src[n]].dst);
637 relreg(&imframe->d);
638}
639
640/*
641 * Load-time relocated invokeinterface.
642 * Resolve all interfaces at load-time.
643 */
644
645static void
646invokei(void)
647{
648 int n;
649 Creloc *cr;
650 Freloc *frm, *frf, *frfi;
651 FieldInfo fi;
652 /*
653 * call Loader->getinterface() with these
654 */
655 Inst *imframe1, *imovw1, *imovp, *imovw2, *ilea, *imcall1;
656 /*
657 * call interface method with these
658 */
659 Inst *iaddw, *imovw3, *imframe2, *imcall2;
660
661 cr = getCreloc(RLOADER);
662 frm = getFreloc(cr, RMP, nil, 0);
663 frf = getFreloc(cr, "getinterface", nil, 0);
664
665 /* call Loader->getinterface */
666
667 imframe1 = loadermframe(frm, frf);
668
669 imovw1 = newi(IMOVW);
670 imovw1->s = code->j[J->src[0]].dst; /* this pointer */
671 sind2dind(&imovw1->s, 0);
672 addrsind(&imovw1->d, Afp, getreg(DIS_W));
673
674 imovp = newi(IMOVP);
675 imovp->s = imovw1->d;
676 sind2dind(&imovp->s, 4);
677 addrdind(&imovp->d, Afpind, imframe1->d.u.offset, REGSIZE);
678
679 imovw2 = newi(IMOVW);
680 addrimm(&imovw2->s, 0);
681 addrdind(&imovw2->d, Afpind, imframe1->d.u.offset, REGSIZE+IBY2WD);
682
683 getfldinfo(&fi);
684 frfi = getFreloc(getCreloc(fi.classname), fi.fieldname,
685 fi.sig, Rinvokeinterface);
686 LTIpatch(frfi, imovw2, PSRC, PIMM);
687
688 ilea = newi(ILEA);
689 addrsind(&ilea->s, Afp, getreg(DIS_W));
690 addrdind(&ilea->d, Afpind, imframe1->d.u.offset, REGRET*IBY2WD);
691
692 imcall1 = loadermcall(imframe1, frf, frm);
693 USED(imcall1);
694
695 /* call interface method */
696
697 iaddw = newi(IADDW);
698 iaddw->s = imovw1->d;
699 iaddw->m = ilea->s;
700 iaddw->d = imovw1->d;
701
702 imovw3 = newi(IMOVW);
703 imovw3->s = iaddw->d;
704 sind2dind(&imovw3->s, 4);
705 imovw3->d = ilea->s;
706
707 imframe2 = newi(IMFRAME);
708 imframe2->s = iaddw->d;
709 sind2dind(&imframe2->s, 0);
710 imframe2->m = imovw3->d;
711 imframe2->d = imframe1->d;
712
713 /* push arguments into callee's frame, handle return type */
714 pushargs(Rinvokeinterface, imframe2->d.u.offset, fi.sig);
715
716 imcall2 = newi(IMCALL);
717 imcall2->s = imframe2->d;
718 imcall2->m = imframe2->m;
719 imcall2->d = imframe2->s;
720
721 for(n = 0; n < J->nsrc; n++)
722 relreg(&code->j[J->src[n]].dst);
723 relreg(&imframe1->d);
724 relreg(&imovw1->d);
725 relreg(&ilea->s);
726}
727
728/*
729 * Run-time relocated invokevirtual.
730 */
731
732static void
733rtinvokev(FieldInfo *fi, int state)
734{
735 int n;
736 Inst *iaddw, *imovw1, *imovw2, *imframe, *imcall;
737 RTClass *rtc;
738
739 rtc = getRTClass(fi->classname);
740 if(state & RTCALL)
741 callrtload(rtc, fi->classname);
742
743 imovw1 = newi(IMOVW);
744 imovw1->s = code->j[J->src[0]].dst; /* this pointer */
745 sind2dind(&imovw1->s, 0);
746 addrsind(&imovw1->d, Afp, getreg(DIS_W));
747
748 iaddw = newi(IADDW);
749 iaddw->s = imovw1->d;
750 addrsind(&iaddw->m, Amp, 0);
751 iaddw->d = imovw1->d;
752
753 RTIpatch(getRTReloc(rtc, fi->fieldname, fi->sig, Rinvokevirtual),
754 iaddw, PMID, PSIND);
755
756 imovw2 = newi(IMOVW);
757 imovw2->s = iaddw->d;
758 sind2dind(&imovw2->s, 4);
759 addrsind(&imovw2->d, Afp, getreg(DIS_W));
760
761 imframe = newi(IMFRAME);
762 imframe->s = imovw1->d;
763 sind2dind(&imframe->s, 0);
764 imframe->m = imovw2->d;
765 addrsind(&imframe->d, Afp, getreg(DIS_W));
766
767 /* push arguments into callee's frame, handle return type */
768 pushargs(Rinvokevirtual, imframe->d.u.offset, fi->sig);
769
770 imcall = newi(IMCALL);
771 imcall->s = imframe->d;
772 imcall->m = imframe->m;
773 imcall->d = imframe->s;
774
775 for(n = 0; n < J->nsrc; n++)
776 relreg(&code->j[J->src[n]].dst);
777 relreg(&imovw1->d);
778 relreg(&imovw2->d);
779 relreg(&imframe->d);
780}
781
782/*
783 * Load-time relocated invokevirtual.
784 */
785
786static void
787invokev(void)
788{
789 int n, state;
790 Inst *imovw1, *imovw2, *imframe, *imcall;
791 Creloc *cr;
792 Freloc *fr;
793 FieldInfo fi;
794
795 getfldinfo(&fi);
796 state = crefstate(fi.classname, J->bb, 0);
797 if(state & RTCODE) {
798 rtinvokev(&fi, state);
799 return;
800 }
801 cr = getCreloc(fi.classname);
802 fr = getFreloc(cr, fi.fieldname, fi.sig, Rinvokevirtual);
803
804 imovw1 = newi(IMOVW);
805 imovw1->s = code->j[J->src[0]].dst; /* this pointer */
806 sind2dind(&imovw1->s, 0);
807 addrsind(&imovw1->d, Afp, getreg(DIS_W));
808
809 imovw2 = newi(IMOVW);
810 imovw2->s = imovw1->d;
811 sind2dind(&imovw2->s, 4);
812 addrsind(&imovw2->d, Afp, getreg(DIS_W));
813 LTIpatch(fr, imovw2, PSRC, PDIND2);
814
815 imframe = newi(IMFRAME);
816 imframe->s = imovw1->d;
817 sind2dind(&imframe->s, 0);
818 imframe->m = imovw2->d;
819 addrsind(&imframe->d, Afp, getreg(DIS_W));
820 LTIpatch(fr, imframe, PSRC, PDIND2);
821
822 /* push arguments into callee's frame, handle return type */
823 pushargs(Rinvokevirtual, imframe->d.u.offset, fi.sig);
824
825 imcall = newi(IMCALL);
826 imcall->s = imframe->d;
827 imcall->m = imframe->m;
828 imcall->d = imframe->s;
829 LTIpatch(fr, imcall, PDST, PDIND2);
830
831 for(n = 0; n < J->nsrc; n++)
832 relreg(&code->j[J->src[n]].dst);
833 relreg(&imovw1->d);
834 relreg(&imovw2->d);
835 relreg(&imframe->d);
836}
837
838/*
839 * Run-time relocated new.
840 */
841
842static void
843rtnew(FieldInfo *fi, int state)
844{
845 Inst *i1, *i2;
846 RTClass *rtc;
847 RTReloc *rtr;
848
849 rtc = getRTClass(fi->classname);
850 if(state & RTCALL)
851 callrtload(rtc, fi->classname);
852
853 i1 = newi(IMNEWZ);
854 addrsind(&i1->s, Amp, 0);
855 addrsind(&i1->m, Amp, 0);
856 dstreg(&J->dst, DIS_P);
857 i1->d = J->dst;
858
859 rtr = getRTReloc(rtc, RCLASS, nil, 0);
860 RTIpatch(rtr, i1, PMID, PSIND);
861 rtr = getRTReloc(rtc, RMP, nil, 0);
862 RTIpatch(rtr, i1, PSRC, PSIND);
863
864 i2 = newi(IMOVP);
865 addrdind(&i2->s, Ampind, 0, 0);
866 i2->d = i1->d;
867 sind2dind(&i2->d, 0);
868
869 RTIpatch(rtr, i2, PSRC, PDIND1);
870}
871
872/*
873 * Load-time relocated new.
874 */
875
876static void
877xjavanew(char *name, Addr *a)
878{
879 int state;
880 Inst *i1, *i2;
881 Creloc *cr;
882 Freloc *frc, *frm;
883 FieldInfo fi;
884
885 if(J) { /* kludge: J == nil when called from clinitinits() */
886 state = crefstate(name, J->bb, 0);
887 if(state & RTCODE) {
888 fi.classname = name;
889 rtnew(&fi, state);
890 return;
891 }
892 }
893
894 cr = getCreloc(name);
895 frc = getFreloc(cr, RCLASS, nil, 0);
896 frm = getFreloc(cr, RMP, nil, 0);
897
898 if(strcmp(name, THISCLASS) == 0) {
899 i1 = newi(INEWZ);
900 addrimm(&i1->s, 0);
901 LTIpatch(frc, i1, PSRC, PIMM);
902 } else {
903 i1 = newi(IMNEWZ);
904 addrsind(&i1->s, Amp, 0);
905 LTIpatch(frm, i1, PSRC, PSIND);
906 addrimm(&i1->m, 0);
907 LTIpatch(frc, i1, PMID, PIMM);
908 }
909 dstreg(a, DIS_P);
910 i1->d = *a;
911
912 i2 = newi(IMOVP);
913 addrdind(&i2->s, Ampind, 0, 0);
914 LTIpatch(frm, i2, PSRC, PDIND1);
915 i2->d = i1->d;
916 sind2dind(&i2->d, 0);
917}
918
919/*
920 * Java newarray
921 */
922
923static void
924newarray(void)
925{
926 Inst *i;
927 int n, tid;
928
929 switch(J->u.i) {
930 case T_BOOLEAN:
931 case T_BYTE:
932 n = 1;
933 break;
934 case T_CHAR:
935 case T_SHORT:
936 case T_INT:
937 n = IBY2WD;
938 break;
939 case T_LONG:
940 case T_FLOAT:
941 case T_DOUBLE:
942 n = IBY2LG;
943 break;
944 default:
945 verifyerrormess("newarray data type");
946 return;
947 }
948 if(n == 1)
949 tid = descid(n, 0, (uchar*)"");
950 else
951 tid = descid(n, 1, (uchar*)"\0");
952
953 xjavanew("inferno/vm/Array", &J->dst);
954 i = newi(INEWAZ);
955 i->s = code->j[J->src[0]].dst;
956 relreg(&code->j[J->src[0]].dst);
957 addrimm(&i->m, tid);
958 i->d = J->dst;
959 sind2dind(&i->d, ARY_DATA);
960 datareloc(i);
961
962 i = newi(IMOVW);
963 addrimm(&i->s, 1);
964 i->d = J->dst;
965 sind2dind(&i->d, ARY_NDIM);
966
967 i = newi(IMOVW);
968 addrimm(&i->s, J->u.i);
969 i->d = J->dst;
970 sind2dind(&i->d, ARY_ETYPE);
971}
972
973typedef struct ArrayInfo ArrayInfo;
974
975struct ArrayInfo {
976 int ndim; /* number of dimensions */
977 int etype; /* element type code (if primitive) */
978 char *ename; /* element type name (if non-primitive) */
979};
980
981/*
982 * Glean array information. s may name a Class, Interface, or Array type.
983 * Used by xanewarray, xmultianewarray, checkcast, instanceof.
984 */
985
986static void
987getaryinfo(ArrayInfo *ai, char *s)
988{
989 int n;
990
991 ai->ndim = 0;
992 ai->etype = 0;
993 ai->ename = nil;
994
995 while(s[0] == '[') {
996 ai->ndim++;
997 s++;
998 }
999
1000 if(ai->ndim > 0) {
1001 switch(s[0]) {
1002 case 'Z':
1003 ai->etype = T_BOOLEAN;
1004 break;
1005 case 'B':
1006 ai->etype = T_BYTE;
1007 break;
1008 case 'C':
1009 ai->etype = T_CHAR;
1010 break;
1011 case 'S':
1012 ai->etype = T_SHORT;
1013 break;
1014 case 'I':
1015 ai->etype = T_INT;
1016 break;
1017 case 'F':
1018 ai->etype = T_FLOAT;
1019 break;
1020 case 'J':
1021 ai->etype = T_LONG;
1022 break;
1023 case 'D':
1024 ai->etype = T_DOUBLE;
1025 break;
1026 case 'L':
1027 /* ai->etype = 0; */ /* above */
1028 break;
1029 }
1030 }
1031 if(ai->etype == 0) {
1032 n = strlen(s) + 1;
1033 if(ai->ndim > 0) { /* e.g., s == "LX.Y.Z;" */
1034 s++;
1035 n -= 2;
1036 }
1037 ai->ename = Malloc(n);
1038 strncpy(ai->ename, s, n-1);
1039 ai->ename[n-1] = '\0';
1040 }
1041}
1042
1043/*
1044 * Java anewarray
1045 */
1046
1047static void
1048xanewarray(void)
1049{
1050 Inst *i;
1051 int state;
1052 RTClass *rtc;
1053 ArrayInfo ai;
1054
1055 SET(state);
1056 SET(rtc);
1057 getaryinfo(&ai, CLASSNAME(J->u.i));
1058 if(ai.etype == 0) {
1059 state = crefstate(ai.ename, J->bb, 0);
1060 if(state & RTCODE) {
1061 rtc = getRTClass(ai.ename);
1062 if(state & RTCALL)
1063 callrtload(rtc, ai.ename);
1064 }
1065 }
1066
1067 xjavanew("inferno/vm/Array", &J->dst);
1068 i = newi(INEWA);
1069 i->s = code->j[J->src[0]].dst;
1070 relreg(&code->j[J->src[0]].dst);
1071 addrimm(&i->m, descid(IBY2WD, 1, (uchar*)"\x80"));
1072 i->d = J->dst;
1073 sind2dind(&i->d, ARY_DATA);
1074 datareloc(i);
1075
1076 i = newi(IMOVW);
1077 addrimm(&i->s, ai.ndim+1);
1078 i->d = J->dst;
1079 sind2dind(&i->d, ARY_NDIM);
1080
1081 if(ai.etype == 0) {
1082 i = newi(IMOVP);
1083 addrsind(&i->s, Amp, 0);
1084 if(state & RTCODE) {
1085 RTIpatch(getRTReloc(rtc, RADT, nil, 0), i, PSRC, PSIND);
1086 } else {
1087 LTIpatch(getFreloc(getCreloc(ai.ename), RADT, nil, 0),
1088 i, PSRC, PSIND);
1089 }
1090 i->d = J->dst;
1091 sind2dind(&i->d, ARY_ADT);
1092 } else {
1093 i = newi(IMOVW);
1094 addrimm(&i->s, ai.etype);
1095 i->d = J->dst;
1096 sind2dind(&i->d, ARY_ETYPE);
1097 }
1098}
1099
1100/*
1101 * Java multianewarray
1102 */
1103
1104static void
1105xmultianewarray(void)
1106{
1107 Inst *imframe, *iindw, *i;
1108 int n, state;
1109 RTClass *rtc;
1110 Creloc *cr;
1111 Freloc *frm, *frf;
1112 ArrayInfo ai;
1113
1114 SET(state);
1115 SET(rtc);
1116 getaryinfo(&ai, CLASSNAME(J->u.x2d.ix));
1117 if(ai.etype == 0) {
1118 state = crefstate(ai.ename, J->bb, 0);
1119 if(state & RTCODE) {
1120 rtc = getRTClass(ai.ename);
1121 if(state & RTCALL)
1122 callrtload(rtc, ai.ename);
1123 }
1124 }
1125
1126 cr = getCreloc(RLOADER);
1127 frm = getFreloc(cr, RMP, nil, 0);
1128 frf = getFreloc(cr, "multianewarray", nil, 0);
1129
1130 imframe = loadermframe(frm, frf);
1131
1132 /* 1st arg: number of dimensions */
1133
1134 i = newi(IMOVW);
1135 addrimm(&i->s, ai.ndim);
1136 addrdind(&i->d, Afpind, imframe->d.u.offset, REGSIZE);
1137
1138 /* 2nd arg: @adt reloc if ref element type, nil otherwise */
1139
1140 i = newi(IMOVP);
1141 addrsind(&i->s, Amp, 0);
1142 if(ai.etype == 0) {
1143 if(state & RTCODE) {
1144 RTIpatch(getRTReloc(rtc, RADT, nil, 0), i, PSRC, PSIND);
1145 } else {
1146 LTIpatch(getFreloc(getCreloc(ai.ename), RADT, nil, 0),
1147 i, PSRC, PSIND);
1148 }
1149 }
1150 addrdind(&i->d, Afpind, imframe->d.u.offset, REGSIZE+IBY2WD);
1151
1152 /* 3rd arg: element type */
1153
1154 i = newi(IMOVW);
1155 addrimm(&i->s, ai.etype);
1156 addrdind(&i->d, Afpind, imframe->d.u.offset, REGSIZE+2*IBY2WD);
1157
1158 /* 4th arg: array of dimensionality information */
1159
1160 i = newi(INEWA);
1161 addrimm(&i->s, J->u.x2d.dim);
1162 addrimm(&i->m, descid(IBY2WD, 1, (uchar*)"\0"));
1163 addrdind(&i->d, Afpind, imframe->d.u.offset, REGSIZE+3*IBY2WD);
1164
1165 iindw = newi(IINDW);
1166 addrdind(&iindw->s, Afpind, imframe->d.u.offset, REGSIZE+3*IBY2WD);
1167 addrsind(&iindw->m, Afp, getreg(DIS_W));
1168 addrimm(&iindw->d, 0);
1169
1170 for(n = 0; n < J->u.x2d.dim; n++) {
1171 i = newi(IMOVW);
1172 i->s = code->j[J->src[n]].dst;
1173 relreg(&code->j[J->src[n]].dst);
1174 i->d = iindw->m;
1175 sind2dind(&i->d, n*IBY2WD);
1176 }
1177 relreg(&iindw->m);
1178
1179 i = newi(ILEA);
1180 dstreg(&J->dst, DIS_P);
1181 i->s = J->dst;
1182 addrdind(&i->d, Afpind, imframe->d.u.offset, REGRET*IBY2WD);
1183
1184 loadermcall(imframe, frf, frm);
1185 relreg(&imframe->d);
1186}
1187
1188static void
1189arraylength(void)
1190{
1191 Inst *i;
1192
1193 i = newi(ILENA);
1194 i->s = code->j[J->src[0]].dst;
1195 relreg(&code->j[J->src[0]].dst);
1196 sind2dind(&i->s, ARY_DATA);
1197 dstreg(&J->dst, DIS_W);
1198 i->d = J->dst;
1199}
1200
1201static Addr*
1202arrayindex(uchar index)
1203{
1204 Inst *i;
1205
1206 i = newi(index);
1207 i->s = code->j[J->src[0]].dst;
1208 relreg(&code->j[J->src[0]].dst);
1209 sind2dind(&i->s, ARY_DATA);
1210 i->d = code->j[J->src[1]].dst;
1211 relreg(&code->j[J->src[1]].dst);
1212 addrsind(&i->m, Afp, getreg(DIS_W));
1213
1214 return &i->m;
1215}
1216
1217/*
1218 * Load an array element.
1219 */
1220
1221static void
1222xarrayload(uchar inst1, uchar inst2, uchar dtype)
1223{
1224 Addr *a;
1225 Inst *i;
1226
1227 a = arrayindex(inst1);
1228 i = newi(inst2);
1229 i->s = *a;
1230 sind2dind(&i->s, 0);
1231 relreg(a);
1232 dstreg(&J->dst, dtype);
1233 i->d = J->dst;
1234 if(inst2 == ICVTBW) /* loading from a byte array */
1235 signextend(&i->d);
1236}
1237
1238/*
1239 * Call Loader->aastorecheck() to do runtime checks for aastore.
1240 */
1241
1242static void
1243aastore(void)
1244{
1245 Inst *imframe, *imovp, *imcall;
1246 Creloc *cr;
1247 Freloc *frm, *frf;
1248
1249 cr = getCreloc(RLOADER);
1250 frm = getFreloc(cr, RMP, nil, 0);
1251 frf = getFreloc(cr, "aastorecheck", nil, 0);
1252
1253 imframe = loadermframe(frm, frf);
1254
1255 imovp = newi(IMOVP);
1256 imovp->s = code->j[J->src[2]].dst;
1257 addrdind(&imovp->d, Afpind, imframe->d.u.offset, REGSIZE);
1258
1259 imovp = newi(IMOVP);
1260 imovp->s = code->j[J->src[0]].dst;
1261 addrdind(&imovp->d, Afpind, imframe->d.u.offset, REGSIZE+IBY2WD);
1262
1263 imcall = loadermcall(imframe, frf, frm);
1264 USED(imcall);
1265 relreg(&imframe->d);
1266}
1267
1268/*
1269 * Store an array element.
1270 */
1271
1272static void
1273xarraystore(uchar inst1, uchar inst2)
1274{
1275 Addr *a;
1276 Inst *i;
1277
1278 a = arrayindex(inst1);
1279 i = newi(inst2);
1280 i->s = code->j[J->src[2]].dst;
1281 relreg(&code->j[J->src[2]].dst);
1282 i->d = *a;
1283 sind2dind(&i->d, 0);
1284 relreg(a);
1285 datareloc(i);
1286}
1287
1288/*
1289 * monitorenter, monitorexit, athrow. Also used for synchronized methods.
1290 */
1291
1292static void
1293mon_or_throw(uchar op, int flags, int syncblock)
1294{
1295 char *loaderfn;
1296 Inst *imframe, *i;
1297 Creloc *cr;
1298 Freloc *frm, *frf, *fro;
1299
1300 switch(op) {
1301 case Jathrow:
1302 loaderfn = "throw";
1303 break;
1304 case Jmonitorenter:
1305 loaderfn = "monitorenter";
1306 break;
1307 case Jmonitorexit:
1308 loaderfn = "monitorexit";
1309 break;
1310 default:
1311 verifyerrormess("bad monitor/throw op");
1312 return;
1313 }
1314
1315 cr = getCreloc(RLOADER);
1316 frm = getFreloc(cr, RMP, nil, 0);
1317 frf = getFreloc(cr, loaderfn, nil, 0);
1318
1319 imframe = loadermframe(frm, frf);
1320
1321 i = newi(IMOVP);
1322 if(op == Jathrow || syncblock) { /* throw or synchronized block */
1323 i->s = code->j[J->src[0]].dst;
1324 relreg(&code->j[J->src[0]].dst);
1325 } else if(flags & ACC_STATIC) { /* synchronized class method */
1326 addrsind(&i->s, Amp, 0);
1327 fro = getFreloc(getCreloc(THISCLASS), ROBJ, nil, 0);
1328 LTIpatch(fro, i, PSRC, PSIND);
1329 } else /* synchronized instance method */
1330 addrsind(&i->s, Afp, THISOFF);
1331 addrdind(&i->d, Afpind, imframe->d.u.offset, REGSIZE);
1332
1333 loadermcall(imframe, frf, frm);
1334 relreg(&imframe->d);
1335
1336 /* for jit: so mcall has an instruction for its return address */
1337 if(op == Jathrow && J->pc+1 == code->code_length) {
1338 i = newi(IJMP);
1339 addrimm(&i->d, 0);
1340 }
1341}
1342
1343static void
1344xjavaload(uchar op)
1345{
1346 Inst *i;
1347
1348 if(J->movsrc.mode != Anone) { /* marked for explicit mov */
1349 i = newi(op);
1350 i->s = J->movsrc;
1351 dstreg(&J->dst, j2dtype(J->jtype));
1352 i->d = J->dst;
1353 datareloc(i);
1354 }
1355}
1356
1357static void
1358xjavastore(uchar op)
1359{
1360 Inst *i;
1361
1362 if(op == IMOVP && J->bb->js == J && (J->bb->flags & BB_FINALLY))
1363 ; /* astore instruction at the start of a finally block */
1364 else if(J->dst.mode != Anone) { /* marked for explicit mov */
1365 i = newi(op);
1366 i->s = code->j[J->src[0]].dst;
1367 relreg(&code->j[J->src[0]].dst);
1368 i->d = J->dst;
1369 datareloc(i);
1370 }
1371}
1372
1373/*
1374 * Check immediate middle operands that are too big.
1375 */
1376
1377static void
1378midcheck(Addr *a)
1379{
1380 if(a->mode == Aimm && (a->u.ival > 0x7fff || a->u.ival < -0x8000)) {
1381 a->mode = Amp;
1382 a->u.offset = mpint(a->u.ival);
1383 }
1384}
1385
1386/*
1387 * Coerce a 64-bit real to a 32-bit real (and back).
1388 */
1389
1390static void
1391real64to32(Addr *a)
1392{
1393 Inst *i1, *i2;
1394
1395 i1 = newi(ICVTFR);
1396 i1->s = *a;
1397 addrsind(&i1->d, Afp, getreg(DIS_W));
1398
1399 i2 = newi(ICVTRF);
1400 i2->s = i1->d;
1401 i2->d = i1->s;
1402
1403 relreg(&i1->d);
1404}
1405
1406static void
1407xbinop(uchar op, uchar dtype, int cvtreal)
1408{
1409 Inst *i;
1410
1411 i = newi(op);
1412 i->s = code->j[J->src[1]].dst;
1413 relreg(&code->j[J->src[1]].dst);
1414 i->m = code->j[J->src[0]].dst;
1415 relreg(&code->j[J->src[0]].dst);
1416 midcheck(&i->m);
1417 dstreg(&J->dst, dtype);
1418 i->d = J->dst;
1419 middstcmp(i);
1420 datareloc(i);
1421
1422 if(cvtreal)
1423 real64to32(&i->d);
1424}
1425
1426static void
1427shift(uchar op, uchar dtype)
1428{
1429 Inst *iaddw, *i;
1430
1431 iaddw = newi(IANDW);
1432 iaddw->s = code->j[J->src[1]].dst;
1433 relreg(&code->j[J->src[1]].dst);
1434 if(dtype == DIS_W) /* ishl, ishr, iushr */
1435 addrimm(&iaddw->m, 31);
1436 else /* lshl, lshr, lushr */
1437 addrimm(&iaddw->m, 63);
1438 addrsind(&iaddw->d, Afp, getreg(DIS_W));
1439 datareloc(iaddw);
1440
1441 i = newi(op);
1442 i->s = iaddw->d;
1443 relreg(&iaddw->d);
1444 i->m = code->j[J->src[0]].dst;
1445 relreg(&code->j[J->src[0]].dst);
1446 midcheck(&i->m);
1447 dstreg(&J->dst, dtype);
1448 i->d = J->dst;
1449 middstcmp(i);
1450 datareloc(i);
1451}
1452
1453static void
1454cvt(uchar op, uchar dtype, int cvtreal)
1455{
1456 Inst *i;
1457
1458 i = newi(op);
1459 i->s = code->j[J->src[0]].dst;
1460 relreg(&code->j[J->src[0]].dst);
1461 dstreg(&J->dst, dtype);
1462 i->d = J->dst;
1463 datareloc(i);
1464
1465 if(cvtreal)
1466 real64to32(&i->d);
1467}
1468
1469static void
1470i2c(void)
1471{
1472 Inst *i;
1473
1474 i = newi(IANDW);
1475 i->s = code->j[J->src[0]].dst;
1476 relreg(&code->j[J->src[0]].dst);
1477 addrsind(&i->m, Amp, mpint(0xffff));
1478 dstreg(&J->dst, DIS_W);
1479 i->d = J->dst;
1480 datareloc(i);
1481}
1482
1483/*
1484 * i2b, i2s.
1485 */
1486
1487static void
1488i2bs(int shift)
1489{
1490 Inst *i1, *i2;
1491
1492 i1 = newi(ISHLW);
1493 addrimm(&i1->s, shift);
1494 i1->m = code->j[J->src[0]].dst;
1495 relreg(&code->j[J->src[0]].dst);
1496 midcheck(&i1->m);
1497 dstreg(&J->dst, DIS_W);
1498 i1->d = J->dst;
1499 middstcmp(i1);
1500 datareloc(i1);
1501
1502 i2 = newi(ISHRW);
1503 addrimm(&i2->s, shift);
1504 /* i2->m = i1->d; */ /* redundant */
1505 i2->d = i1->d;
1506}
1507
1508/*
1509 * ineg, lneg, fneg, dneg
1510 */
1511
1512static void
1513neg(uchar op, uchar dtype)
1514{
1515 Inst *i;
1516
1517 i = newi(op);
1518 i->s = code->j[J->src[0]].dst;
1519 relreg(&code->j[J->src[0]].dst);
1520 if(op == ISUBW) /* ineg */
1521 addrimm(&i->m, 0);
1522 else if(op == ISUBL) /* lneg */
1523 addrsind(&i->m, Amp, mplong(0));
1524 dstreg(&J->dst, dtype);
1525 i->d = J->dst;
1526 datareloc(i);
1527}
1528
1529static void
1530iinc(int val, int ix)
1531{
1532 Inst *i;
1533
1534 i = newi(IADDW);
1535 addrimm(&i->s, val);
1536 addrsind(&i->d, Afp, localix(DIS_W, ix));
1537}
1538
1539/*
1540 * For javaif and javagoto, compute difference of try nesting
1541 * level between source PC and destination PC.
1542 * J->pc is source PC
1543 * J->u.i is destination PC (relative from J->pc)
1544 */
1545
1546static int
1547tldiff(void)
1548{
1549 int tls, tld;
1550
1551 tld = 0;
1552 tls = trylevel(J->pc);
1553 if(tls > 0)
1554 tld = trylevel(J->pc+J->u.i);
1555 return tls-tld;
1556}
1557
1558/*
1559 * Java if_acmp<cond>, if_icmp<cond>, if<cond>, ifnonnull, ifnull.
1560 */
1561
1562enum {
1563 CMPNULL = 0, /* compare against null: ifnonnull, ifnull */
1564 CMPZERO, /* compare against 0: if<cond> */
1565 CMP2OP /* general compare: if_acmp<cond>, if_icmp<cond> */
1566};
1567
1568static void
1569javaif(uchar op, uchar cmpkind)
1570{
1571 Inst *i;
1572 int n;
1573
1574 n = tldiff();
1575 if(n > 0) {
1576 /* complement the test when calling Sys->unrescue() */
1577 switch(op) {
1578 case IBEQW:
1579 op = IBNEW;
1580 break;
1581 case IBNEW:
1582 op = IBEQW;
1583 break;
1584 case IBLTW:
1585 op = IBGEW;
1586 break;
1587 case IBLEW:
1588 op = IBGTW;
1589 break;
1590 case IBGTW:
1591 op = IBLEW;
1592 break;
1593 case IBGEW:
1594 op = IBLTW;
1595 break;
1596 }
1597 i = newi(op);
1598 addrimm(&i->d, pcdis + 2*n + 1);
1599 } else {
1600 i = newibap(op);
1601 addrimm(&i->d, J->u.i);
1602 }
1603
1604 i->s = code->j[J->src[0]].dst;
1605 relreg(&code->j[J->src[0]].dst);
1606
1607 switch(cmpkind) {
1608 case CMPNULL:
1609 addrsind(&i->m, Amp, 0);
1610 break;
1611 case CMPZERO:
1612 addrimm(&i->m, 0);
1613 datareloc(i);
1614 break;
1615 case CMP2OP:
1616 i->m = code->j[J->src[1]].dst;
1617 relreg(&code->j[J->src[1]].dst);
1618 midcheck(&i->m);
1619 datareloc(i);
1620 break;
1621 }
1622
1623 if(n > 0) {
1624 unrescue(n);
1625 callunrescue = 0;
1626 i = newibap(IJMP);
1627 addrimm(&i->d, J->u.i);
1628 }
1629}
1630
1631/*
1632 * Java goto and goto_w.
1633 */
1634
1635static void
1636javagoto(void)
1637{
1638 Inst *i;
1639 int n;
1640
1641 n = tldiff();
1642 if(n > 0) {
1643 unrescue(n);
1644 callunrescue = 0;
1645 }
1646 i = newibap(IJMP);
1647 addrimm(&i->d, J->u.i);
1648}
1649
1650/*
1651 * Java return instructions.
1652 */
1653
1654static void
1655xjavareturn(uchar op)
1656{
1657 Inst *i;
1658
1659 if(op != 0) { /* if op == 0, then return void */
1660 i = newi(op);
1661 i->s = code->j[J->src[0]].dst;
1662 relreg(&code->j[J->src[0]].dst);
1663 addrdind(&i->d, Afpind, REGRET*IBY2WD, 0);
1664 datareloc(i);
1665 }
1666
1667 if(M->access_flags & ACC_SYNCHRONIZED)
1668 mon_or_throw(Jmonitorexit, M->access_flags, 0);
1669
1670 newi(IRET);
1671}
1672
1673/*
1674 * pop & pop2
1675 */
1676
1677static void
1678xjavapop(void)
1679{
1680 relreg(&code->j[J->src[0]].dst);
1681 if(J->nsrc == 2) /* pop2 */
1682 relreg(&code->j[J->src[1]].dst);
1683}
1684
1685/*
1686 * dup, dup2, etc.
1687 */
1688
1689static void
1690xjavadup(void)
1691{
1692 acqreg(&code->j[J->src[0]].dst);
1693 if(J->nsrc == 2)
1694 acqreg(&code->j[J->src[1]].dst);
1695}
1696
1697static void
1698xldc(void)
1699{
1700 Inst *i;
1701
1702 switch(class->cts[J->u.i]) {
1703 case CON_Integer:
1704 xjavaload(IMOVW);
1705 break;
1706 case CON_Float:
1707 case CON_Double:
1708 xjavaload(IMOVF);
1709 break;
1710 case CON_Long:
1711 xjavaload(IMOVL);
1712 break;
1713 case CON_String:
1714 xjavanew("java/lang/String", &J->dst);
1715 i = newi(IMOVP);
1716 i->s = J->movsrc;
1717 i->d = J->dst;
1718 sind2dind(&i->d, STR_DISSTR);
1719 addDreloc(i, PSRC, PSIND);
1720 break;
1721 }
1722}
1723
1724/*
1725 * Java jsr and jsr_w.
1726 * ix is relative Java pc offset of finally block entry point.
1727 */
1728
1729static void
1730jsr(int ix)
1731{
1732 Inst *i;
1733
1734 i = newi(IMOVW);
1735 addrimm(&i->s, 0);
1736 addrsind(&i->d, Amp, 0);
1737 jsrfixup(&i->s, &i->d, i->pc+2, J->pc+ix);
1738 addDreloc(i, PDST, PSIND);
1739
1740 i = newibap(IJMP);
1741 addrimm(&i->d, ix);
1742}
1743
1744/*
1745 * Java ret and wide ret.
1746 */
1747
1748static void
1749ret(void)
1750{
1751 Inst *i;
1752
1753 i = newi(IGOTO);
1754 addrsind(&i->s, Amp, 0);
1755 addrsind(&i->d, Amp, 0);
1756 retfixup(&i->s, &i->d, J->pc);
1757 addDreloc(i, PSRC, PSIND);
1758 addDreloc(i, PDST, PSIND);
1759}
1760
1761static void
1762tableswitch(void)
1763{
1764 Inst *i;
1765 int j, k, n, lb;
1766 int *jt;
1767
1768 n = J->u.t1.hb - J->u.t1.lb + 1;
1769 jt = Malloc((n*3+1)*sizeof(int));
1770 for(j = 0, k = 0, lb = J->u.t1.lb; j < n; j++) {
1771 jt[k++] = lb;
1772 jt[k++] = ++lb;
1773 jt[k++] = J->u.t1.tbl[j];
1774 }
1775 jt[k] = J->u.t1.dflt;
1776 i = newi(ICASE);
1777 i->s = code->j[J->src[0]].dst;
1778 relreg(&code->j[J->src[0]].dst);
1779 addrsind(&i->d, Amp, mpcase(n, jt));
1780 patchcase(i, n, jt);
1781 addDreloc(i, PDST, PSIND);
1782}
1783
1784static void
1785lookupswitch(void)
1786{
1787 Inst *i;
1788 int j, k;
1789 int *jt;
1790
1791 jt = Malloc((J->u.t2.np*3+1)*sizeof(int));
1792 for(j = 0, k = 0; j < J->u.t2.np*2; j += 2) {
1793 jt[k++] = J->u.t2.tbl[j];
1794 jt[k++] = J->u.t2.tbl[j]+1;
1795 jt[k++] = J->u.t2.tbl[j+1];
1796 }
1797 jt[k] = J->u.t2.dflt;
1798 i = newi(ICASE);
1799 i->s = code->j[J->src[0]].dst;
1800 relreg(&code->j[J->src[0]].dst);
1801 addrsind(&i->d, Amp, mpcase(J->u.t2.np, jt));
1802 patchcase(i, J->u.t2.np, jt);
1803 addDreloc(i, PDST, PSIND);
1804}
1805
1806/*
1807 * Call a library routine. Supports lcmp, [df]cmp[gl], [df]rem.
1808 */
1809
1810static void
1811jmath(char *jname, uchar movinst, uchar dtype)
1812{
1813 Inst *imframe, *i;
1814 Creloc *cr;
1815 Freloc *frm, *frf;
1816
1817 cr = getCreloc(RLOADER);
1818 frm = getFreloc(cr, RMP, nil, 0);
1819 frf = getFreloc(cr, jname, nil, 0);
1820
1821 imframe = loadermframe(frm, frf);
1822
1823 i = newi(movinst);
1824 i->s = code->j[J->src[0]].dst;
1825 relreg(&code->j[J->src[0]].dst);
1826 addrdind(&i->d, Afpind, imframe->d.u.offset, REGSIZE);
1827 datareloc(i);
1828
1829 if(jname[1] != '2') { /* d2i or d2l ? */
1830 i = newi(movinst);
1831 i->s = code->j[J->src[1]].dst;
1832 relreg(&code->j[J->src[1]].dst);
1833 addrdind(&i->d, Afpind, imframe->d.u.offset, REGSIZE+IBY2LG);
1834 datareloc(i);
1835 }
1836
1837 i = newi(ILEA);
1838 dstreg(&J->dst, dtype);
1839 i->s = J->dst;
1840 addrdind(&i->d, Afpind, imframe->d.u.offset, REGRET*IBY2WD);
1841
1842 loadermcall(imframe, frf, frm);
1843 relreg(&imframe->d);
1844}
1845
1846/*
1847 * checkcast & instanceof
1848 */
1849
1850static void
1851rtti(void)
1852{
1853 char *loaderfn;
1854 Inst *imframe, *i;
1855 int state;
1856 RTClass *rtc;
1857 Creloc *cr;
1858 Freloc *frm, *frf;
1859 ArrayInfo ai;
1860
1861 SET(state);
1862 SET(rtc);
1863 getaryinfo(&ai, CLASSNAME(J->u.i));
1864 if(ai.etype == 0) {
1865 state = crefstate(ai.ename, J->bb, 0);
1866 if(state & RTCODE) {
1867 rtc = getRTClass(ai.ename);
1868 if(state & RTCALL)
1869 callrtload(rtc, ai.ename);
1870 }
1871 }
1872
1873 if(J->op == Jcheckcast) {
1874 if(ai.ndim > 0) {
1875 if(ai.etype > 0)
1876 loaderfn = "pcheckcast";
1877 else
1878 loaderfn = "acheckcast";
1879 } else
1880 loaderfn = "checkcast";
1881 } else {
1882 if(ai.ndim > 0) {
1883 if(ai.etype > 0)
1884 loaderfn = "pinstanceof";
1885 else
1886 loaderfn = "ainstanceof";
1887 } else
1888 loaderfn = "instanceof";
1889 }
1890
1891 cr = getCreloc(RLOADER);
1892 frm = getFreloc(cr, RMP, nil, 0);
1893 frf = getFreloc(cr, loaderfn, nil, 0);
1894
1895 imframe = loadermframe(frm, frf);
1896
1897 /* pass object as first argument */
1898
1899 i = newi(IMOVP);
1900 i->s = code->j[J->src[0]].dst;
1901 addrdind(&i->d, Afpind, imframe->d.u.offset, REGSIZE);
1902
1903 /* second argument */
1904
1905 if(ai.etype == 0) {
1906 i = newi(IMOVP);
1907 addrsind(&i->s, Amp, 0);
1908 if(state & RTCODE) {
1909 RTIpatch(getRTReloc(rtc, RADT, nil, 0), i, PSRC, PSIND);
1910 } else {
1911 LTIpatch(getFreloc(getCreloc(ai.ename), RADT, nil, 0),
1912 i, PSRC, PSIND);
1913 }
1914 } else {
1915 i = newi(IMOVW);
1916 addrimm(&i->s, ai.etype);
1917 }
1918 addrdind(&i->d, Afpind, imframe->d.u.offset, REGSIZE+IBY2WD);
1919
1920 /* third argument, if present */
1921
1922 if(ai.ndim > 0) {
1923 i = newi(IMOVW);
1924 addrimm(&i->s, ai.ndim);
1925 addrdind(&i->d, Afpind, imframe->d.u.offset, REGSIZE+2*IBY2WD);
1926 }
1927
1928 if(J->op == Jinstanceof) {
1929 i = newi(ILEA);
1930 dstreg(&J->dst, DIS_W);
1931 i->s = J->dst;
1932 addrdind(&i->d, Afpind, imframe->d.u.offset, REGRET*IBY2WD);
1933 }
1934
1935 loadermcall(imframe, frf, frm);
1936 relreg(&imframe->d);
1937
1938 if(J->op == Jcheckcast) {
1939 i = newi(IMOVP);
1940 i->s = code->j[J->src[0]].dst;
1941 relreg(&code->j[J->src[0]].dst);
1942 dstreg(&J->dst, DIS_P);
1943 i->d = J->dst;
1944 datareloc(i);
1945 } else
1946 relreg(&code->j[J->src[0]].dst);
1947}
1948
1949/*
1950 * Exception handling.
1951 */
1952
1953typedef struct Catch Catch;
1954typedef struct Try Try;
1955typedef struct EHInst EHInst;
1956
1957struct Catch {
1958 char *exname;
1959 int handler_pc;
1960 Catch *next;
1961};
1962
1963struct Try {
1964 int start_pc;
1965 int end_pc;
1966 int any_pc;
1967 Catch *catch;
1968 Try *next;
1969};
1970
1971struct EHInst {
1972 Inst *i;
1973 EHInst *next;
1974};
1975
1976static EHInst *ehinst;
1977static Try *trylist;
1978
1979/*
1980 * Save an EH branch instruction for later patching.
1981 */
1982
1983static void
1984saveehinst(Inst *i)
1985{
1986 EHInst *ehi;
1987
1988 ehi = Malloc(sizeof(EHInst));
1989 ehi->i = i;
1990 ehi->next = ehinst;
1991 ehinst = ehi;
1992}
1993
1994/*
1995 * Patch an EH branch instruction.
1996 * Java PCs in exception tables are absolute, not relative.
1997 */
1998
1999static void
2000patchehinst(void)
2001{
2002 EHInst *ehi, *ehi2;
2003 Inst *i;
2004 Jinst *j;
2005
2006 for(ehi = ehinst; ehi; ehi = ehi2) {
2007 i = ehi->i;
2008 j = &code->j[i->d.u.ival];
2009 while(j->dis == nil)
2010 j += j->size;
2011 i->d.u.ival = j->dis->pc;
2012 ehi2 = ehi->next;
2013 free(ehi);
2014 }
2015 ehinst = nil;
2016}
2017
2018/*
2019 * Convert handler information into a more convenient form.
2020 */
2021
2022static void
2023cvtehinfo(void)
2024{
2025 int i;
2026 Try *t;
2027 Catch *c;
2028 Handler *h;
2029
2030 if(code->nex == 0)
2031 return;
2032
2033 /* process in reverse to maintain order of try & catch blocks */
2034 for(i = code->nex-1; i >= 0; i--) {
2035 h = code->ex[i];
2036 if((t = trylist) == nil
2037 || (t->start_pc != h->start_pc || t->end_pc != h->end_pc)) {
2038 t = Mallocz(sizeof(Try));
2039 t->start_pc = h->start_pc;
2040 t->end_pc = h->end_pc;
2041 t->next = trylist;
2042 trylist = t;
2043 }
2044 if(h->catch_type == 0) {
2045 t->any_pc = h->handler_pc;
2046 } else {
2047 c = Malloc(sizeof(Catch));
2048 c->handler_pc = h->handler_pc;
2049 c->exname = CLASSNAME(h->catch_type);
2050 c->next = t->catch;
2051 t->catch = c;
2052 }
2053 }
2054}
2055
2056/*
2057 * At what try nesting level is the given Java pc at.
2058 * 0 means not within a try block.
2059 */
2060
2061static int
2062trylevel(int pc)
2063{
2064 int level;
2065 Try *t;
2066
2067 level = 0;
2068 for(t = trylist; t; t = t->next) {
2069 if(pc >= t->start_pc && pc < t->end_pc)
2070 level += 1;
2071 }
2072 return level;
2073}
2074
2075/*
2076 * Free the handler information.
2077 */
2078
2079static void
2080ehinfofree(void)
2081{
2082 Try *t, *t2;
2083 Catch *c, *c2;
2084
2085 for(t = trylist; t; t = t2) {
2086 for(c = t->catch; c; c = c2) {
2087 c2 = c->next;
2088 free(c);
2089 }
2090 t2 = t->next;
2091 free(t);
2092 }
2093 trylist = nil;
2094}
2095
2096/*
2097 * Install an exception handler: call sys->rescue("*", nil).
2098 */
2099
2100static Addr*
2101rescue(void)
2102{
2103 Inst *imframe, *i;
2104 Creloc *cr;
2105 Freloc *frm, *frf;
2106
2107 cr = getCreloc(RLOADER);
2108 frm = getFreloc(cr, RSYS, nil, 0);
2109 frf = getFreloc(cr, "rescue", nil, 0);
2110
2111 imframe = loadermframe(frm, frf);
2112
2113 i = newi(IMOVP);
2114 addrsind(&i->s, Amp, mpstring("*"));
2115 addrdind(&i->d, Afpind, imframe->d.u.offset, REGSIZE);
2116 addDreloc(i, PSRC, PSIND);
2117
2118 i = newi(IMOVP);
2119 addrsind(&i->s, Afp, REFSYSEX);
2120 addrdind(&i->d, Afpind, imframe->d.u.offset, REGSIZE+IBY2WD);
2121
2122 i = newi(ILEA);
2123 addrsind(&i->s, Afp, getreg(DIS_W));
2124 addrdind(&i->d, Afpind, imframe->d.u.offset, REGRET*IBY2WD);
2125
2126 loadermcall(imframe, frf, frm);
2127 relreg(&imframe->d);
2128
2129 return &i->s;
2130}
2131
2132/*
2133 * Uninstall one or more exception handlers: call sys->unrescue() n times.
2134 */
2135
2136static void
2137unrescue(int n)
2138{
2139 Inst *imframe;
2140 Creloc *cr;
2141 Freloc *frm, *frf;
2142
2143 cr = getCreloc(RLOADER);
2144 frm = getFreloc(cr, RSYS, nil, 0);
2145 frf = getFreloc(cr, "unrescue", nil, 0);
2146
2147 while(n > 0) {
2148 imframe = loadermframe(frm, frf);
2149 loadermcall(imframe, frf, frm);
2150 relreg(&imframe->d);
2151 n--;
2152 }
2153}
2154
2155/*
2156 * Current handler doesn't catch current exception.
2157 * Call sys->raise(@jex) to propagate (rethrow) the exception.
2158 */
2159
2160static Inst*
2161rethrow(void)
2162{
2163 Inst *imframe, *i;
2164 Creloc *cr;
2165 Freloc *frm, *frf;
2166
2167 cr = getCreloc(RLOADER);
2168 frm = getFreloc(cr, RSYS, nil, 0);
2169 frf = getFreloc(cr, "raise", nil, 0);
2170
2171 if(M->access_flags & ACC_SYNCHRONIZED && trylevel(J->pc) == 1)
2172 mon_or_throw(Jmonitorexit, M->access_flags, 0);
2173
2174 imframe = loadermframe(frm, frf);
2175
2176 i = newi(IMOVP);
2177 addrsind(&i->s, Amp, 0);
2178 addrdind(&i->d, Afpind, imframe->d.u.offset, REGSIZE);
2179 LTIpatch(getFreloc(cr, RJEX, nil, 0), i, PSRC, PSIND);
2180
2181 i = loadermcall(imframe, frf, frm);
2182 relreg(&imframe->d);
2183
2184 return i;
2185}
2186
2187/*
2188 * Retrieve thrown object prior to jumping to exception handler.
2189 */
2190
2191static void
2192catch(void)
2193{
2194 Inst *imframe, *i;
2195 Creloc *cr;
2196 Freloc *frm, *frf;
2197
2198 cr = getCreloc(RLOADER);
2199 frm = getFreloc(cr, RMP, nil, 0);
2200 frf = getFreloc(cr, "culprit", nil, 0);
2201
2202 imframe = loadermframe(frm, frf);
2203
2204 i = newi(IMOVP);
2205 addrsind(&i->s, Afp, REFSYSEX);
2206 addrdind(&i->d, Afpind, imframe->d.u.offset, REGSIZE);
2207
2208 i = newi(ILEA);
2209 addrsind(&i->s, Afp, EXOBJ); /* put in known location */
2210 addrdind(&i->d, Afpind, imframe->d.u.offset, REGRET*IBY2WD);
2211
2212 loadermcall(imframe, frf, frm);
2213 relreg(&imframe->d);
2214}
2215
2216/*
2217 * Does thrown object match handler for exception class exname ?
2218 */
2219
2220static Addr*
2221chkhandler(char *exname)
2222{
2223 int state;
2224 Inst *imframe, *i;
2225 RTClass *rtc;
2226 Creloc *cr;
2227 Freloc *frm, *frf;
2228
2229 SET(rtc);
2230 state = crefstate(exname, J->bb, 1);
2231 if(state & RTCODE) {
2232 rtc = getRTClass(exname);
2233 if(state & RTCALL)
2234 callrtload(rtc, exname);
2235
2236 }
2237
2238 cr = getCreloc(RLOADER);
2239 frm = getFreloc(cr, RMP, nil, 0);
2240 frf = getFreloc(cr, "instanceof", nil, 0);
2241
2242 imframe = loadermframe(frm, frf);
2243
2244 i = newi(IMOVP);
2245 addrsind(&i->s, Afp, EXOBJ);
2246 addrdind(&i->d, Afpind, imframe->d.u.offset, REGSIZE);
2247
2248 i = newi(IMOVP);
2249 addrsind(&i->s, Amp, 0);
2250 if(state & RTCODE)
2251 RTIpatch(getRTReloc(rtc, RADT, nil, 0), i, PSRC, PSIND);
2252 else
2253 LTIpatch(getFreloc(getCreloc(exname), RADT, nil, 0), i, PSRC, PSIND);
2254 addrdind(&i->d, Afpind, imframe->d.u.offset, REGSIZE+IBY2WD);
2255
2256 i = newi(ILEA);
2257 addrsind(&i->s, Afp, getreg(DIS_W));
2258 addrdind(&i->d, Afpind, imframe->d.u.offset, REGRET*IBY2WD);
2259
2260 loadermcall(imframe, frf, frm);
2261 relreg(&imframe->d);
2262
2263 return &i->s;
2264}
2265
2266/*
2267 * Start of a try block. Install exception handler for try block t.
2268 */
2269
2270static void
2271trystart(Try *t)
2272{
2273 Inst *ibeqw, *i;
2274 Addr *a;
2275 Catch *c;
2276
2277 a = rescue();
2278
2279 ibeqw = newi(IBEQW);
2280 ibeqw->s = *a;
2281 relreg(a);
2282 addrimm(&ibeqw->m, 0); /* Sys->HANDLER == 0 */
2283 addrimm(&ibeqw->d, 0);
2284
2285 /* code executed when sys->rescue() "returns" Sys->EXCEPTION */
2286
2287 unrescue(1);
2288
2289 catch();
2290
2291 for(c = t->catch; c; c = c->next) {
2292 a = chkhandler(c->exname);
2293 i = newi(IBEQW);
2294 i->s = *a;
2295 relreg(a);
2296 addrimm(&i->m, 1);
2297 addrimm(&i->d, c->handler_pc);
2298 saveehinst(i);
2299 }
2300
2301 if(t->any_pc > 0) {
2302 i = newi(IJMP);
2303 addrimm(&i->d, t->any_pc);
2304 saveehinst(i);
2305 } else
2306 i = rethrow();
2307
2308 ibeqw->d.u.ival = i->pc+1;
2309}
2310
2311/*
2312 * At the start or end of a try block ?
2313 */
2314
2315static void
2316tryhandling(void)
2317{
2318 Try *t;
2319
2320 for(t = trylist; t; t = t->next) {
2321 /* > 1 try block can have the same start_pc */
2322 if(t->start_pc == J->pc)
2323 trystart(t);
2324 /* try block may consist of just 1 bytecode */
2325 if(t->end_pc == J->pc+J->size)
2326 callunrescue = 1;
2327 }
2328}
2329
2330/*
2331 * Generate Dis assembly code for one method.
2332 */
2333
2334static void
2335java2dis(void)
2336{
2337 Jinst *jnext, *je;
2338
2339 je = J + code->code_length;
2340 while(J < je) {
2341 if(J->bb->js == J) { /* start of a basic block ? */
2342 /* ignore unreachable code */
2343 if((J->bb->flags & BB_REACHABLE) == 0) {
2344 J = J->bb->je + J->bb->je->size;
2345 continue;
2346 }
2347 /* initialize fp temporary pool */
2348 clearreg();
2349 reservereg(J->bb->entrystk, J->bb->entrysz);
2350 reservereg(J->bb->exitstk, J->bb->exitsz);
2351 }
2352
2353 /* start of a synchronized method ? */
2354 if(J->pc == 0 && M->access_flags & ACC_SYNCHRONIZED)
2355 mon_or_throw(Jmonitorenter, M->access_flags, 0);
2356
2357 tryhandling();
2358
2359 jnext = J+J->size;
2360 if(jnext >= je)
2361 jnext = nil;
2362 /* "optimize" loads and stores */
2363 if(jnext && isstore(jnext) && jnext->bb->js != jnext) {
2364 if(J->dst.mode == Afp && J->dst.u.offset == -1) {
2365 J->dst = jnext->dst;
2366 /* mark jnext so mov not generated for it */
2367 jnext->dst.mode = Anone;
2368 } else if(isload(J) && J->movsrc.mode == Anone) {
2369 J->movsrc = J->dst;
2370 J->dst = jnext->dst;
2371 /* mark jnext so mov not generated for it */
2372 jnext->dst.mode = Anone;
2373 }
2374 }
2375
2376 switch(J->op) {
2377 case Jnop:
2378 break;
2379 case Jaconst_null:
2380 xjavaload(IMOVP);
2381 break;
2382 case Jiconst_m1:
2383 case Jiconst_0:
2384 case Jiconst_1:
2385 case Jiconst_2:
2386 case Jiconst_3:
2387 case Jiconst_4:
2388 case Jiconst_5:
2389 case Jbipush:
2390 case Jsipush:
2391 xjavaload(IMOVW);
2392 break;
2393 case Jlconst_0:
2394 case Jlconst_1:
2395 xjavaload(IMOVL);
2396 break;
2397 case Jfconst_0:
2398 case Jdconst_0:
2399 case Jfconst_1:
2400 case Jdconst_1:
2401 case Jfconst_2:
2402 xjavaload(IMOVF);
2403 break;
2404 case Jldc:
2405 case Jldc_w:
2406 case Jldc2_w:
2407 xldc();
2408 break;
2409 case Jiload:
2410 case Jiload_0:
2411 case Jiload_1:
2412 case Jiload_2:
2413 case Jiload_3:
2414 xjavaload(IMOVW);
2415 break;
2416 case Jlload:
2417 case Jlload_0:
2418 case Jlload_1:
2419 case Jlload_2:
2420 case Jlload_3:
2421 xjavaload(IMOVL);
2422 break;
2423 case Jfload:
2424 case Jdload:
2425 case Jfload_0:
2426 case Jdload_0:
2427 case Jfload_1:
2428 case Jdload_1:
2429 case Jfload_2:
2430 case Jdload_2:
2431 case Jfload_3:
2432 case Jdload_3:
2433 xjavaload(IMOVF);
2434 break;
2435 case Jaload:
2436 case Jaload_0:
2437 case Jaload_1:
2438 case Jaload_2:
2439 case Jaload_3:
2440 xjavaload(IMOVP);
2441 break;
2442 case Jbaload:
2443 xarrayload(IINDB, ICVTBW, DIS_W);
2444 break;
2445 case Jcaload:
2446 case Jsaload:
2447 case Jiaload:
2448 xarrayload(IINDW, IMOVW, DIS_W);
2449 break;
2450 case Jlaload:
2451 xarrayload(IINDL, IMOVL, DIS_L);
2452 break;
2453 case Jfaload:
2454 case Jdaload:
2455 xarrayload(IINDF, IMOVF, DIS_L);
2456 break;
2457 case Jaaload:
2458 xarrayload(IINDX, IMOVP, DIS_P);
2459 break;
2460 case Jistore:
2461 case Jistore_0:
2462 case Jistore_1:
2463 case Jistore_2:
2464 case Jistore_3:
2465 xjavastore(IMOVW);
2466 break;
2467 case Jlstore:
2468 case Jlstore_0:
2469 case Jlstore_1:
2470 case Jlstore_2:
2471 case Jlstore_3:
2472 xjavastore(IMOVL);
2473 break;
2474 case Jfstore:
2475 case Jdstore:
2476 case Jfstore_0:
2477 case Jdstore_0:
2478 case Jfstore_1:
2479 case Jdstore_1:
2480 case Jfstore_2:
2481 case Jdstore_2:
2482 case Jfstore_3:
2483 case Jdstore_3:
2484 xjavastore(IMOVF);
2485 break;
2486 case Jastore:
2487 case Jastore_0:
2488 case Jastore_1:
2489 case Jastore_2:
2490 case Jastore_3:
2491 xjavastore(IMOVP);
2492 break;
2493 case Jbastore:
2494 xarraystore(IINDB, ICVTWB);
2495 break;
2496 case Jcastore:
2497 case Jsastore:
2498 case Jiastore:
2499 xarraystore(IINDW, IMOVW);
2500 break;
2501 case Jlastore:
2502 xarraystore(IINDL, IMOVL);
2503 break;
2504 case Jfastore:
2505 case Jdastore:
2506 xarraystore(IINDF, IMOVF);
2507 break;
2508 case Jaastore:
2509 aastore();
2510 xarraystore(IINDX, IMOVP);
2511 break;
2512 case Jpop:
2513 case Jpop2:
2514 xjavapop();
2515 break;
2516 case Jdup:
2517 case Jdup_x1:
2518 case Jdup_x2:
2519 case Jdup2:
2520 case Jdup2_x1:
2521 case Jdup2_x2:
2522 xjavadup();
2523 break;
2524 case Jswap:
2525 break;
2526 case Jiadd:
2527 xbinop(IADDW, DIS_W, 0);
2528 break;
2529 case Jisub:
2530 xbinop(ISUBW, DIS_W, 0);
2531 break;
2532 case Jimul:
2533 xbinop(IMULW, DIS_W, 0);
2534 break;
2535 case Jidiv:
2536 xbinop(IDIVW, DIS_W, 0);
2537 break;
2538 case Jishl:
2539 shift(ISHLW, DIS_W);
2540 break;
2541 case Jishr:
2542 shift(ISHRW, DIS_W);
2543 break;
2544 case Jiushr:
2545 shift(ILSRW, DIS_W);
2546 break;
2547 case Jirem:
2548 xbinop(IMODW, DIS_W, 0);
2549 break;
2550 case Jiand:
2551 xbinop(IANDW, DIS_W, 0);
2552 break;
2553 case Jior:
2554 xbinop(IORW, DIS_W, 0);
2555 break;
2556 case Jixor:
2557 xbinop(IXORW, DIS_W, 0);
2558 break;
2559 case Jladd:
2560 xbinop(IADDL, DIS_L, 0);
2561 break;
2562 case Jlsub:
2563 xbinop(ISUBL, DIS_L, 0);
2564 break;
2565 case Jlmul:
2566 xbinop(IMULL, DIS_L, 0);
2567 break;
2568 case Jldiv:
2569 xbinop(IDIVL, DIS_L, 0);
2570 break;
2571 case Jlrem:
2572 xbinop(IMODL, DIS_L, 0);
2573 break;
2574 case Jland:
2575 xbinop(IANDL, DIS_L, 0);
2576 break;
2577 case Jlor:
2578 xbinop(IORL, DIS_L, 0);
2579 break;
2580 case Jlxor:
2581 xbinop(IXORL, DIS_L, 0);
2582 break;
2583 case Jfadd:
2584 xbinop(IADDF, DIS_L, 1);
2585 break;
2586 case Jdadd:
2587 xbinop(IADDF, DIS_L, 0);
2588 break;
2589 case Jfsub:
2590 xbinop(ISUBF, DIS_L, 1);
2591 break;
2592 case Jdsub:
2593 xbinop(ISUBF, DIS_L, 0);
2594 break;
2595 case Jfmul:
2596 xbinop(IMULF, DIS_L, 1);
2597 break;
2598 case Jdmul:
2599 xbinop(IMULF, DIS_L, 0);
2600 break;
2601 case Jfdiv:
2602 xbinop(IDIVF, DIS_L, 1);
2603 break;
2604 case Jddiv:
2605 xbinop(IDIVF, DIS_L, 0);
2606 break;
2607 case Jfrem:
2608 case Jdrem:
2609 jmath("drem", IMOVF, DIS_L);
2610 break;
2611 case Jineg:
2612 neg(ISUBW, DIS_W);
2613 break;
2614 case Jlneg:
2615 neg(ISUBL, DIS_L);
2616 break;
2617 case Jfneg:
2618 case Jdneg:
2619 neg(INEGF, DIS_L);
2620 break;
2621 case Jlshl:
2622 shift(ISHLL, DIS_L);
2623 break;
2624 case Jlshr:
2625 shift(ISHRL, DIS_L);
2626 break;
2627 case Jlushr:
2628 shift(ILSRL, DIS_L);
2629 break;
2630 case Jiinc:
2631 iinc(J->u.x1c.icon, J->u.x1c.ix);
2632 break;
2633 case Ji2l:
2634 cvt(ICVTWL, DIS_L, 0);
2635 break;
2636 case Ji2f:
2637 cvt(ICVTWF, DIS_L, 1);
2638 break;
2639 case Ji2d:
2640 cvt(ICVTWF, DIS_L, 0);
2641 break;
2642 case Jl2i:
2643 cvt(ICVTLW, DIS_W, 0);
2644 break;
2645 case Jl2f:
2646 cvt(ICVTLF, DIS_L, 1);
2647 break;
2648 case Jl2d:
2649 cvt(ICVTLF, DIS_L, 0);
2650 break;
2651 case Jf2i:
2652 case Jd2i:
2653 jmath("d2i", IMOVF, DIS_W);
2654 break;
2655 case Jf2l:
2656 case Jd2l:
2657 jmath("d2l", IMOVF, DIS_L);
2658 break;
2659 case Jf2d:
2660 cvt(IMOVF, DIS_L, 0);
2661 break;
2662 case Jd2f:
2663 cvt(IMOVF, DIS_L, 1);
2664 break;
2665 case Ji2b:
2666 i2bs(24);
2667 break;
2668 case Ji2c:
2669 i2c();
2670 break;
2671 case Ji2s:
2672 i2bs(16);
2673 break;
2674 case Jlcmp:
2675 jmath("lcmp", IMOVL, DIS_W);
2676 break;
2677 case Jfcmpl:
2678 case Jdcmpl:
2679 jmath("dcmpl", IMOVF, DIS_W);
2680 break;
2681 case Jfcmpg:
2682 case Jdcmpg:
2683 jmath("dcmpg", IMOVF, DIS_W);
2684 break;
2685 case Jifeq:
2686 javaif(IBEQW, CMPZERO);
2687 break;
2688 case Jifne:
2689 javaif(IBNEW, CMPZERO);
2690 break;
2691 case Jiflt:
2692 javaif(IBLTW, CMPZERO);
2693 break;
2694 case Jifge:
2695 javaif(IBGEW, CMPZERO);
2696 break;
2697 case Jifgt:
2698 javaif(IBGTW, CMPZERO);
2699 break;
2700 case Jifle:
2701 javaif(IBLEW, CMPZERO);
2702 break;
2703 case Jif_acmpeq:
2704 case Jif_icmpeq:
2705 javaif(IBEQW, CMP2OP);
2706 break;
2707 case Jif_acmpne:
2708 case Jif_icmpne:
2709 javaif(IBNEW, CMP2OP);
2710 break;
2711 case Jif_icmplt:
2712 javaif(IBLTW, CMP2OP);
2713 break;
2714 case Jif_icmpge:
2715 javaif(IBGEW, CMP2OP);
2716 break;
2717 case Jif_icmpgt:
2718 javaif(IBGTW, CMP2OP);
2719 break;
2720 case Jif_icmple:
2721 javaif(IBLEW, CMP2OP);
2722 break;
2723 case Jgoto:
2724 case Jgoto_w:
2725 javagoto();
2726 break;
2727 case Jjsr:
2728 case Jjsr_w:
2729 jsr(J->u.i);
2730 break;
2731 case Jret:
2732 ret();
2733 break;
2734 case Jtableswitch:
2735 tableswitch();
2736 break;
2737 case Jlookupswitch:
2738 lookupswitch();
2739 break;
2740 case Jireturn:
2741 xjavareturn(IMOVW);
2742 break;
2743 case Jlreturn:
2744 xjavareturn(IMOVL);
2745 break;
2746 case Jfreturn:
2747 case Jdreturn:
2748 xjavareturn(IMOVF);
2749 break;
2750 case Jareturn:
2751 xjavareturn(IMOVP);
2752 break;
2753 case Jreturn:
2754 xjavareturn(0);
2755 break;
2756 case Jgetfield:
2757 getfield();
2758 break;
2759 case Jgetstatic:
2760 getstatic();
2761 break;
2762 case Jputfield:
2763 putfield();
2764 break;
2765 case Jputstatic:
2766 putstatic();
2767 break;
2768 case Jinvokevirtual:
2769 invokev();
2770 break;
2771 case Jinvokespecial:
2772 invokess(Rinvokespecial, Rspecialmp);
2773 break;
2774 case Jinvokestatic:
2775 invokess(Rinvokestatic, Rstaticmp);
2776 break;
2777 case Jinvokeinterface:
2778 invokei();
2779 break;
2780 case Jxxxunusedxxx:
2781 break;
2782 case Jnew:
2783 xjavanew(CLASSNAME(J->u.i), &J->dst);
2784 break;
2785 case Jnewarray:
2786 newarray();
2787 break;
2788 case Janewarray:
2789 xanewarray();
2790 break;
2791 case Jarraylength:
2792 arraylength();
2793 break;
2794 case Jcheckcast:
2795 case Jinstanceof:
2796 rtti();
2797 break;
2798 case Jathrow:
2799 case Jmonitorenter:
2800 case Jmonitorexit:
2801 if(J->op == Jathrow
2802 && M->access_flags & ACC_SYNCHRONIZED
2803 && trylevel(J->pc) == 0) {
2804 mon_or_throw(Jmonitorexit, M->access_flags, 0);
2805 }
2806 mon_or_throw(J->op, 0, 1);
2807 break;
2808 case Jwide:
2809 switch(J->u.w.op) {
2810 case Jiload:
2811 xjavaload(IMOVW);
2812 break;
2813 case Jlload:
2814 xjavaload(IMOVL);
2815 break;
2816 case Jfload:
2817 case Jdload:
2818 xjavaload(IMOVF);
2819 break;
2820 case Jaload:
2821 xjavaload(IMOVP);
2822 break;
2823 case Jistore:
2824 xjavastore(IMOVW);
2825 break;
2826 case Jlstore:
2827 xjavastore(IMOVL);
2828 break;
2829 case Jfstore:
2830 case Jdstore:
2831 xjavastore(IMOVF);
2832 break;
2833 case Jastore:
2834 xjavastore(IMOVP);
2835 break;
2836 case Jret:
2837 ret();
2838 break;
2839 case Jiinc:
2840 iinc(J->u.w.icon, J->u.w.ix);
2841 break;
2842 }
2843 break;
2844 case Jmultianewarray:
2845 xmultianewarray();
2846 break;
2847 case Jifnull:
2848 javaif(IBEQW, CMPNULL);
2849 break;
2850 case Jifnonnull:
2851 javaif(IBNEW, CMPNULL);
2852 break;
2853 }
2854 if(callunrescue == 1) {
2855 unrescue(1);
2856 callunrescue = 0;
2857 }
2858 J += J->size;
2859 }
2860 J = nil;
2861}
2862
2863/*
2864 * If there are exception handlers, then allocate a 'ref Sys->Exception'
2865 * to pass to Sys->rescue() and Loader->culprit().
2866 */
2867
2868static void
2869ref_sys_except(void)
2870{
2871 Inst *i;
2872
2873 if(code->nex == 0)
2874 return;
2875
2876 i = newi(INEW);
2877 addrimm(&i->s, descid(3*IBY2WD, 1, (uchar*)"\xc0"));
2878 addrsind(&i->d, Afp, REFSYSEX);
2879}
2880
2881/*
2882 * Generate initialization code for 'static final' fields that have
2883 * ConstantValue attributes.
2884 */
2885
2886static Inst*
2887clinitinits(void)
2888{
2889 uchar movi;
2890 int j, ix, offset, value;
2891 char *sig;
2892 Addr *a;
2893 Addr as;
2894 Const *c;
2895 Field *fp;
2896 FieldInfo fi;
2897 Inst *i, *reti;
2898
2899 SET(value);
2900 as.mode = Afp;
2901 fi.classname = THISCLASS;
2902 reti = nil;
2903
2904 for(j = 0, fp = class->fields; j < class->fields_count; j++, fp++) {
2905 if((fp->access_flags & ACC_STATIC) && (ix = CVattrindex(fp))) {
2906 sig = STRING(fp->sig_index);
2907 c = &class->cps[ix];
2908 switch(class->cts[ix]) {
2909 case CON_Integer:
2910 if(c->tint == 0)
2911 continue;
2912 if(sig[0] == 'Z' || sig[0] == 'B')
2913 movi = ICVTWB;
2914 else
2915 movi = IMOVW;
2916 if(notimmable(c->tint))
2917 offset = mpint(c->tint);
2918 else {
2919 offset = -1;
2920 value = c->tint;
2921 }
2922 break;
2923 case CON_Long:
2924 if(c->tvlong == 0)
2925 continue;
2926 movi = IMOVL;
2927 offset = mplong(c->tvlong);
2928 break;
2929 case CON_Float:
2930 case CON_Double:
2931 if(c->tdouble == 0.0)
2932 continue;
2933 movi = IMOVF;
2934 offset = mpreal(c->tdouble);
2935 break;
2936 case CON_String:
2937 movi = IMOVP;
2938 offset = mpstring(STRING(c->ci.name_index));
2939 break;
2940 default:
2941 verifyerrormess("clinitinits: constant type");
2942 return nil;
2943 }
2944 fi.fieldname = STRING(fp->name_index);
2945 fi.sig = sig;
2946 a = ltstaticadd(&fi);
2947 if(reti == nil)
2948 reti = itail;
2949 if(movi == IMOVP) {
2950 as.u.offset = -1;
2951 xjavanew("java/lang/String", &as);
2952 i = newi(IMOVP);
2953 addrsind(&i->s, Amp, offset);
2954 i->d = as;
2955 sind2dind(&i->d, STR_DISSTR);
2956 addDreloc(i, PSRC, PSIND);
2957 }
2958 i = newi(movi);
2959 if(movi == IMOVP) {
2960 i->s = as;
2961 relreg(&as);
2962 } else if(offset >= 0) {
2963 addrsind(&i->s, Amp, offset);
2964 addDreloc(i, PSRC, PSIND);
2965 } else
2966 addrimm(&i->s, value);
2967 i->d = *a;
2968 sind2dind(&i->d, 0);
2969 relreg(a);
2970 }
2971 }
2972 return reti;
2973}
2974
2975/*
2976 * Cook up a <clinit> static method.
2977 */
2978
2979static void
2980genclinit(void)
2981{
2982 int savepc;
2983
2984 savepc = pcdis;
2985 openframe("()V", ACC_STATIC);
2986 clinitclone = clinitinits(); /* save for -v option */
2987 newi(IRET);
2988 xtrnlink(closeframe(), savepc, "<clinit>", "()V");
2989}
2990
2991/*
2992 * Cook up link entry and body for <clone> static method.
2993 */
2994
2995static Inst*
2996genclone(void)
2997{
2998 Inst *i, *clone;
2999 Freloc *fr;
3000
3001 xtrnlink(descid(40, 2, (uchar*)"\x0\xc0"), pcdis, "<clone>", "()V");
3002
3003 /*
3004 * new @Class, 36(fp)
3005 * movmp 0(32(fp)), @Class, 0(36(fp))
3006 * movp 36(fp), 0(16(fp))
3007 * ret
3008 */
3009
3010 fr = getFreloc(getCreloc(THISCLASS), RCLASS, nil, 0);
3011
3012 i = newi(INEW);
3013 addrimm(&i->s, 0);
3014 LTIpatch(fr, i, PSRC, PIMM);
3015 addrsind(&i->d, Afp, 36);
3016 clone = i; /* save for -v option */
3017
3018 i = newi(IMOVMP);
3019 addrdind(&i->s, Afpind, 32, 0);
3020 addrimm(&i->m, 0);
3021 LTIpatch(fr, i, PMID, PIMM);
3022 addrdind(&i->d, Afpind, 36, 0);
3023
3024 i = newi(IMOVP);
3025 addrsind(&i->s, Afp, 36);
3026 addrdind(&i->d, Afpind, 16, 0);
3027
3028 newi(IRET);
3029
3030 return clone;
3031}
3032
3033/*
3034 * Translate the methods in class cl.
3035 */
3036
3037void
3038xlate(void)
3039{
3040 int i, j, n;
3041 int savepcdis;
3042 Attr *a;
3043 Inst *clone;
3044 Method *m;
3045 char *name, *sig;
3046
3047 n = 0;
3048 for(i = 0, m = class->methods; i < class->methods_count; i++, m++) {
3049 name = STRING(m->name_index);
3050 pcode[n].name = name;
3051 sig = STRING(m->sig_index);
3052 pcode[n].sig = sig;
3053 for(j = 0, a = m->attr_info; j < m->attr_count; j++, a++) {
3054 if(strcmp(STRING(a->name), "Code") == 0) {
3055 M = m;
3056 code = javadas(a);
3057 pcode[n].code = code;
3058 cvtehinfo();
3059 /* exception object */
3060 addrsind(&code->j[code->code_length].dst, Afp, EXOBJ);
3061 openframe(sig, m->access_flags&ACC_STATIC);
3062 savepcdis = pcdis;
3063 flowgraph();
3064 simjvm(sig);
3065 unify();
3066 J = &code->j[0];
3067 ref_sys_except();
3068 if(doclinitinits && strcmp(name, "<clinit>") == 0) {
3069 clinitinits();
3070 doclinitinits = 0;
3071 }
3072 java2dis();
3073 bbfree();
3074 xtrnlink(closeframe(), savepcdis, name, sig);
3075 patchmethod(savepcdis);
3076 patchehinst();
3077 patchfree();
3078 finallyfree();
3079 ehinfofree();
3080 creffree();
3081 }
3082 }
3083 n += 1;
3084 }
3085
3086 if(doclinitinits)
3087 genclinit();
3088
3089 if((class->access_flags & (ACC_INTERFACE | ACC_ABSTRACT)) == 0) {
3090 clone = genclone();
3091 if(clinitclone == nil)
3092 clinitclone = clone;
3093 }
3094}
java/tools/javal/FileMerge.class+0−0

Binary file not shown.

java/tools/javal/FileMerge.java+108−0
@@ -0,0 +1,108 @@
1package javal;
2
3import java.io.File;
4import java.io.FileOutputStream;
5import java.io.FileInputStream;
6import java.io.DataInputStream;
7import java.io.DataOutputStream;
8import java.io.IOException;
9import java.io.EOFException;
10
11
12class FileMerge
13{
14 /**
15 * open the two files and merge. The "tmpname"
16 * is the newer generated file, name is the older
17 * file and will become the merged file
18 */
19 static void Merge( String name, String tmpname ) throws IOException
20 {
21 // rename 'name'
22 String oldname = "old_"+ name;
23 File old_f = new File(oldname);
24 if ( old_f.exists() )
25 old_f.delete();
26 new File( name ).renameTo( old_f );
27
28 // open output for merged file
29 DataOutputStream merge;
30 DataInputStream ftmp, fold;
31
32 merge = new DataOutputStream(new FileOutputStream( name ) );
33 ftmp = new DataInputStream( new FileInputStream( tmpname ) );
34 fold = new DataInputStream( new FileInputStream( oldname ) );
35
36 while ( true )
37 {
38 try
39 {
40 ReadNWrite( ftmp, merge, "#>>" );
41 Ignore( ftmp, "#<<" );
42 }
43 catch ( EOFException ee )
44 {
45 WriteRest( fold, merge );
46 break;
47 }
48 try
49 {
50 Ignore( fold, "#>>" );
51 ReadNWrite( fold, merge, "#<<" );
52 }
53 catch ( EOFException ee )
54 {
55 WriteRest( ftmp, merge );
56 break;
57 }
58 }
59
60 fold.close();
61 ftmp.close();
62 merge.close();
63 new File( tmpname ).delete();
64
65 }
66
67
68 private static void ReadNWrite( DataInputStream fin, DataOutputStream fout, String pat ) throws IOException
69 {
70 String line;
71
72 do
73 {
74 line = fin.readLine();
75 if ( line == null ) throw new EOFException();
76 fout.writeBytes( line );
77 fout.writeBytes( linesep );
78 }
79 while ( line.indexOf(pat) == -1 );
80 }
81
82
83 private static void Ignore( DataInputStream fin, String pat ) throws IOException
84 {
85 String line;
86 do
87 {
88 line = fin.readLine();
89 if ( line == null ) throw new EOFException();
90 }
91 while ( line.indexOf(pat) == -1 );
92 }
93
94 private static void WriteRest( DataInputStream fin, DataOutputStream fout ) throws IOException
95 {
96 while ( true )
97 {
98 String line = fin.readLine();
99 if (line == null)
100 return;
101 fout.writeBytes(line);
102 fout.writeBytes( linesep );
103 }
104 }
105
106 private static String linesep = System.getProperties().getProperty("line.separator");
107
108}
java/tools/javal/LimboGen.class+0−0

Binary file not shown.

java/tools/javal/LimboGen.java+677−0
@@ -0,0 +1,677 @@
1package javal;
2
3import java.io.File;
4import java.io.DataOutputStream;
5import java.io.FileOutputStream;
6import java.io.IOException;
7
8import java.lang.reflect.*;
9
10
11public
12class LimboGen
13{
14 public LimboGen( Class cl, Field[] fields, Method[] methods, boolean verbose )
15 {
16 theClass = cl;
17 this.fields = fields;
18 this.methods = methods;
19 opt_verbose = verbose;
20
21 // create names
22 String full_name = cl.getName();
23 base_name = ClassBaseName( full_name );
24 mod_name = base_name +"_L";
25 limbo_dotm = mod_name +".m";
26 limbo_dotb = mod_name +".b";
27
28 // some class are "special" to javal
29 // if it is a special class we don't
30 // want to generate adt's for it and
31 // will use a special ADT name
32 special = true; //assume special
33 obj_adt = SpecialClass( full_name );
34
35 if ( obj_adt == null )
36 {
37 special = false;
38 obj_adt = base_name +"_obj";
39 }
40
41 // will only generate skeleton for native methods
42 natives = GetNatives( methods );
43 has_natives = natives.length > 0;
44
45 // need to distinguish between instance and static fields
46 iFields = GetInstanceFields( fields );
47 sFields = GetStaticFields( fields );
48 }
49
50
51 /**
52 * Generate a Limbo Module Declaration
53 * file (.m) for a java class containing
54 * native methods.
55 */
56 public void DotM() throws IOException
57 {
58 // open a file
59 out = MkFile( limbo_dotm );
60
61 // emit the Limbo Module File
62
63 Emit( "# generated file edit with care\n\n" );
64 Emit( mod_name +" : module\n" );
65 Emit( "{\n" );
66
67 GenADT();
68
69 Emit( "\n" );
70
71 GenFct(false);
72
73 Emit( "\n};\n" );
74
75 out.close();
76
77 if ( merge )
78 {
79 // save off existing .m and rename
80 // tmp to .m
81 File f = new File( limbo_dotm );
82 File o = new File("old_"+limbo_dotm);
83 File t = new File( tmpname );
84
85 if ( o.exists() ) o.delete();
86 f.renameTo( o );
87 t.renameTo( f );
88
89 }
90
91 }
92
93
94 /**
95 * Generate a Limbo Module Implementation
96 * Skeleton containing native methods for
97 * a java class.
98 */
99 public void DotB() throws IOException
100 {
101 // don't generate a .b if no natives
102 if ( ! has_natives ) return;
103
104 // open a file
105 out = MkFile( limbo_dotb );
106
107 // generate file prolog
108 Emit("implement "+ mod_name +";\n\n" );
109 Emit("include \"jni.m\";\n" );
110 Emit(T1+"jni : JNI;\n" );
111 Emit(T2+"ClassModule,\n");
112 Emit(T2+ T_JString +",\n");
113 Emit(T2+ T_JArray +",\n");
114 Emit(T2+ T_JArrayI +",\n");
115 Emit(T2+ T_JArrayC +",\n");
116 Emit(T2+ T_JArrayB +",\n");
117 Emit(T2+ T_JArrayS +",\n");
118 Emit(T2+ T_JArrayJ +",\n");
119 Emit(T2+ T_JArrayF +",\n");
120 Emit(T2+ T_JArrayD +",\n");
121 Emit(T2+ T_JArrayZ +",\n");
122 Emit(T2+ T_JArrayJObject +",\n");
123 Emit(T2+ T_JArrayJClass +",\n");
124 Emit(T2+ T_JArrayJString +",\n");
125 Emit(T2+ T_JClass +",\n");
126 Emit(T2+T_JObject +" : import jni;\n\n");
127
128 Emit("#>> extra pre includes here\n\n#<<\n\n");
129
130 Emit("include \""+ limbo_dotm +"\";\n\n" );
131
132 Emit("#>> extra post includes here\n\n#<<\n\n");
133
134 // generate a skeleton for init() and each native method
135 GenFct( true );
136
137 out.close();
138
139 if ( merge )
140 FileMerge.Merge( limbo_dotb, tmpname );
141 }
142
143
144 /**
145 * Generate an ADT declaration for the class
146 * instance fields.
147 */
148 private void GenADT() throws IOException
149 {
150 // don't generate an ADT decl for "special" clases
151 if ( special ) return;
152
153 Emit( T1+ obj_adt +" : adt\n"+ T1+ "{\n" );
154
155 // emit the std object header
156 Emit( T2+ "cl_mod : ClassModule;\n" );
157
158 // walk through instance data emitting Limbo decl
159 for( int x=0; x<iFields.length; x++ )
160 {
161 Emit( T2+ GenFieldDecl( iFields[x] ) +";\n" );
162 }
163
164 Emit( T1+ "};\n" );
165 }
166
167 private void GenFct( boolean skel ) throws IOException
168 {
169 // generate init fct
170 GenInit( skel );
171
172 // walk native methods and generate
173 // a limbo fct
174 for( int x=0; x<natives.length; x++ )
175 {
176 String fct_name = MkFctName( natives[x] );
177 String this_param = "";
178
179 // if fct is virtual generate implicit this param
180 if ( ! Modifier.isStatic( natives[x].getModifiers() ) )
181 {
182 // if this is a special class then don't use ref
183 // because the generated special name is already a ref
184 this_param = ( special ? "this : " : "this : ref " );
185 this_param += obj_adt;
186 }
187
188 // determine fct parameters
189 String params = GenFctParams( natives[x].getParameterTypes() );
190
191 StringBuffer fct_params = new StringBuffer(80);
192 if ( this_param != "" )
193 {
194 fct_params.append( this_param );
195 if ( params != "" )
196 fct_params.append( ", " );
197 }
198
199 fct_params.append( params );
200
201 // determine fct return type...if any
202 String fct_t = LimboType( natives[x].getReturnType() );
203 if ( ! fct_t.equals("") )
204 fct_t = " : "+ fct_t;
205
206 if ( skel )
207 {
208 Emit( fct_name +"( "+
209 fct_params.toString() +")"+
210 fct_t +"\n{#>>\n}#<<\n\n" );
211
212 }
213 else
214 {
215 Emit( T1+ fct_name +" : fn( "+
216 fct_params.toString() +")"+
217 fct_t +";\n" );
218 }
219 }
220 }
221
222
223 /**
224 * every Limbo Native module has a init()
225 * function which the loader will call
226 * when the native mod is loaded. This
227 * method generates that fct.
228 *
229 * @param skel If true gen a fct skel; else fct decl
230 *
231 */
232 private void GenInit( boolean skel ) throws IOException
233 {
234 if ( skel )
235 {
236 Emit( "init( jni_p : JNI )\n{\n" );
237 Emit( T1+"# save java native inteface mod instance\n" );
238 Emit( T1+"jni = jni_p;\n" );
239 Emit( T1+"#>>extra initialization here\n"+T1+"#<<\n" );
240 Emit( "}\n\n" );
241 }
242 else
243 {
244 Emit( T1+"init : fn( jni_p : JNI );\n" );
245 }
246 }
247
248 /**
249 * Given an array of types return a string with
250 * a comma seperated sequence of java method
251 * parameter declarations
252 *
253 * @param ptypes An array of types
254 *
255 * @return A string representing method param decls
256 */
257 private String GenFctParams( Class[] ptypes )
258 {
259 String fct_params = "";
260 for( int x=0; x<ptypes.length; x++ )
261 {
262 fct_params = fct_params +"p"+ x +" : "+ LimboType( ptypes[x] );
263 if ( x <ptypes.length-1 )
264 fct_params = fct_params +",";
265 }
266
267 return( fct_params );
268 }
269
270
271 /**
272 * Take a Java class data-field and
273 * return a string with a coresponding
274 * Limbo adt field declaration.
275 *
276 * @param fi The Java field descriptor
277 *
278 * @return Limbo Declaration
279 */
280 private String GenFieldDecl( Field fi )
281 {
282 String fi_name = fi.getName();
283 Class java_type = fi.getType();
284
285 String limbo_type = LimboType( java_type );
286
287 return( fi_name +" : "+ limbo_type );
288 }
289
290
291 /**
292 * Accept a java Type descriptor and
293 * return a corresponding limbo type
294 * as a string. Return a empty string
295 * if the type is void or an unknown.
296 *
297 * @param java_t Java type
298 *
299 * @return Limbo type
300 */
301 private String LimboType( Class java_t )
302 {
303 String limbo_t;
304
305 if ( java_t.isPrimitive() )
306 {
307 // a java primitive type convert to appropriate limbo type
308 String t_name = java_t.getName();
309 if ( t_name.equals( "short" ) ||
310 t_name.equals( "char" ) ||
311 t_name.equals( "int" ) )
312 limbo_t = "int";
313 else if ( t_name.equals( "long" ) )
314 limbo_t = "big";
315 else if ( t_name.equals( "float" ) ||
316 t_name.equals( "double" ) )
317 limbo_t = "real";
318 else if ( t_name.equals( "byte" ) ||
319 t_name.equals( "boolean" ) )
320 limbo_t = "byte";
321 else
322 limbo_t = ""; // void
323
324 }
325 else
326 {
327 // a java reference (i.e. object or array)
328 String t_name = java_t.getName();
329
330 if ( t_name.startsWith( "[" ) )
331 limbo_t = ArrayType( t_name );
332 else
333 limbo_t = ClassName( t_name );
334 }
335
336 return( limbo_t );
337 }
338
339 private String ArrayType( String name )
340 {
341 StringBuffer aryname = new StringBuffer(20);
342 aryname.append( T_JArray );
343
344 char let = name.charAt(1);
345
346 if ( let == 'L' )
347 {
348 // array of some class, determine Limo name
349 aryname.append( ClassName( name.substring(2, name.length()-1) ) );
350 }
351 else if ( let == '[' )
352 {
353 // array of array...
354 // we only care about first level
355 ;
356 }
357 else
358 aryname.append( name.substring(1) ); //append type
359
360 return( aryname.toString() );
361 }
362
363
364 private String ClassName( String clname )
365 {
366 // we treat some classes special and
367 // use specific Limbo adt's otherwise
368 // use the generic JObject
369 String sp_class = SpecialClass( clname );
370 if ( sp_class != null )
371 return( sp_class );
372 else if ( "java.io.FileDescriptor".equals(clname) )
373 return( T_JFd );
374 else if ( "inferno.vm.FD".equals(clname) )
375 return( T_JInfernoFD );
376 else if ( clname.endsWith( base_name ) )
377 return( "ref "+ obj_adt );
378 return( T_JObject );
379 }
380
381
382 private String SpecialClass( String clname )
383 {
384 if ( "java.lang.String".equals(clname) )
385 return( T_JString );
386 else if ( "java.lang.Class".equals(clname) )
387 return( T_JClass );
388 else if ( "java.lang.Object".equals(clname) )
389 return( T_JObject );
390 else
391 return( null );
392 }
393
394 /**
395 * Scan methods list and return list of
396 * native methods.
397 *
398 * @return Array of native methods, else array of length 0.
399 */
400 private Method[] GetNatives( Method[] methods )
401 {
402 // walk the methods array and count natives
403 int native_count = 0;
404 for( int x=0; x<methods.length; x++ )
405 if ( Modifier.isNative( methods[x].getModifiers() ) )
406 native_count++;
407
408 if ( native_count == 0 ) return( new Method[0] );
409
410 if ( opt_verbose )
411 System.out.println( "Native Methods:" );
412
413 // now create an array to hold natives and fill it
414 Method[] natives = new Method[native_count];
415 native_count = 0;
416 for( int x=0; x<methods.length; x++ )
417 if ( Modifier.isNative( methods[x].getModifiers() ) )
418 {
419 natives[native_count++] = methods[x];
420 if ( opt_verbose )
421 System.out.println( "\t"+ methods[x] );
422 }
423
424 return( natives );
425 }
426
427
428 /**
429 * Scan fields list and return list of
430 * instance fields.
431 *
432 * @return Array of instnace fields, else array oflen 0
433 */
434 private Field[] GetInstanceFields( Field[] fields )
435 {
436 // walk the fields array and count non-statics
437 int count = 0;
438 for( int x=0; x<fields.length; x++ )
439 if ( ! Modifier.isStatic( fields[x].getModifiers() ) )
440 count++;
441
442 if ( count == 0 ) return( new Field[0] );
443
444 if ( opt_verbose )
445 System.out.println( "Instance Fields:" );
446
447 // now create an array to hold instance-fields and fill it
448 Field[] iFields = new Field[count];
449 count = 0;
450 for( int x=0; x<fields.length; x++ )
451 if ( ! Modifier.isStatic( fields[x].getModifiers() ) )
452 {
453 iFields[count++] = fields[x];
454 if ( opt_verbose )
455 System.out.println( "\t"+ fields[x] );
456 }
457
458 return( iFields );
459 }
460
461
462 /**
463 * Scan fields list and return list of
464 * static fields.
465 *
466 * @return Array of static fields, else array oflen 0
467 */
468 private Field[] GetStaticFields( Field[] fields )
469 {
470 // walk the fields array and count non-statics
471 int count = 0;
472 for( int x=0; x<fields.length; x++ )
473 if ( Modifier.isStatic( fields[x].getModifiers() ) )
474 count++;
475
476 if ( count == 0 ) return( new Field[0] );
477
478 if ( opt_verbose )
479 System.out.println( "Instance Fields:" );
480
481 // now create an array to hold instance-fields and fill it
482 Field[] sFields = new Field[count];
483 count = 0;
484 for( int x=0; x<fields.length; x++ )
485 if ( Modifier.isStatic( fields[x].getModifiers() ) )
486 {
487 sFields[count++] = fields[x];
488 if ( opt_verbose )
489 System.out.println( "\t"+ fields[x] );
490 }
491
492 return( sFields );
493 }
494
495
496 private String ClassBaseName( String name )
497 {
498 // for java.lang.Object return Object
499 // if last char is ';' strip it off (arrays)
500
501 int start = name.lastIndexOf( '.' );
502 int end = name.lastIndexOf( ';' );
503
504 // if neither found return name
505 if ( (start == -1) && (end==-1) ) return( name );
506
507 // adjust if ';' not found
508 end = ( (end==-1)? name.length() : end );
509
510 return( name.substring( start+1, end ) );
511 }
512
513
514 private String MkFctName( Method meth )
515 {
516 // build name from java method name
517 // java method param types, and the
518 // java method return type
519
520 StringBuffer encode = new StringBuffer(50);
521 encode.append(meth.getName());
522
523 // append parmeter encoding
524 Class[] jparam = meth.getParameterTypes();
525 for( int x=0; x<jparam.length; x++ )
526 {
527 encode.append( "_" );
528 encode.append( JTypeEncode( jparam[x] ) );
529 }
530
531 // append the method return type encoding
532 encode.append("_");
533 encode.append( JTypeEncode( meth.getReturnType() ) );
534
535 if ( opt_verbose )
536 System.out.println( "--mangled fct name:"+ encode );
537
538 return( encode.toString() );
539 }
540
541
542 private String JTypeEncode( Class jtype )
543 {
544 String t_name; //types name
545 String encode = ""; //limbo encoding
546
547 if ( jtype.isPrimitive() )
548 {
549 // a java primitive type convert to appropriate limbo type
550 t_name = jtype.getName();
551
552 // determine
553 if ( t_name.equals( "int" ) )
554 encode = "I";
555 else if ( t_name.equals( "char" ) )
556 encode = "C";
557 else if ( t_name.equals( "short" ) )
558 encode = "S";
559 else if ( t_name.equals( "long" ) )
560 encode = "J";
561 else if ( t_name.equals( "boolean" ) )
562 encode = "Z";
563 else if ( t_name.equals( "byte" ) )
564 encode = "B";
565 else if ( t_name.equals( "float" ) )
566 encode = "F";
567 else if ( t_name.equals( "double" ) )
568 encode = "D";
569 else
570 encode = "V";
571 }
572 else
573 {
574 // a java reference (i.e. object or array)
575 t_name = jtype.getName();
576
577 if ( t_name.indexOf( '[' ) == -1 )
578 {
579 // just an object reference
580 encode = "r"+ ClassBaseName( t_name );
581 }
582 else
583 {
584 // array
585 int x=0;
586 StringBuffer buf = new StringBuffer(40);
587 while( t_name.charAt(x)== '[' )
588 {
589 buf.append('a');
590 x++;
591 }
592 if ( t_name.charAt(x) == 'L' )
593 buf.append( ClassBaseName(t_name.substring(x+1)) );
594 else
595 buf.append( t_name.substring(x) );
596 encode = buf.toString();
597 }
598 }
599
600 return( encode );
601 }
602
603
604 private DataOutputStream MkFile( String name ) throws IOException
605 {
606 File f = new File( name );
607 FileOutputStream fout;
608
609 tmpname = "tmp_"+ name;
610
611 if ( f.exists() )
612 {
613 fout = new FileOutputStream( tmpname );
614 merge = true;
615 }
616 else
617 fout = new FileOutputStream( name );
618
619 return( new DataOutputStream( fout ) );
620 }
621
622 private void Emit( String info ) throws IOException
623 {
624 out.writeBytes( info );
625 }
626
627
628 // data fields
629 private String base_name; // name of class
630 private String mod_name; // module name of native "peer" module
631 private String limbo_dotm; // name of limbo module decl .m file
632 private String limbo_dotb; // name of limbo module impl .b file
633 private String obj_adt; // adt describing objects instance fields
634 private boolean special; // set true if a special class; a special
635 // class is one known to this tool.
636
637 Class theClass; // class descriptor object
638
639 DataOutputStream out; // current gen output file
640 boolean merge = false; // merge old and new gen'ed files
641 String tmpname;
642
643 Method[] methods; // all methods
644 Method[] natives; // native methods
645
646 Field[] fields; // all fields
647 Field[] iFields; // instance fields
648 Field[] sFields; // static fields
649
650 boolean opt_verbose; // print stuff if true
651 boolean has_natives; // set true if class has native methods
652
653 // consts
654 private static final String T1 = " ";
655 private static final String T2 = " ";
656 private static final String T3 = " ";
657
658 // generated Limbo/Java type names
659 private static final String T_JObject = "JObject";
660 private static final String T_JString = "JString";
661 private static final String T_JClass = "JClass";
662 private static final String T_JArrayI = "JArrayI";
663 private static final String T_JArrayC = "JArrayC";
664 private static final String T_JArrayS = "JArrayS";
665 private static final String T_JArrayB = "JArrayB";
666 private static final String T_JArrayJ = "JArrayJ";
667 private static final String T_JArrayF = "JArrayF";
668 private static final String T_JArrayD = "JArrayD";
669 private static final String T_JArrayZ = "JArrayZ";
670 private static final String T_JArrayJObject = "JArrayJObject";
671 private static final String T_JArrayJClass = "JArrayJClass";
672 private static final String T_JArrayJString = "JArrayJString";
673 private static final String T_JArray = "JArray";
674 private static final String T_JFd = "ref FileDescriptor_obj";
675 private static final String T_JInfernoFD = "ref Sys->FD";
676
677}
java/tools/javal/TargetLoader.class+0−0

Binary file not shown.

java/tools/javal/javal.class+0−0

Binary file not shown.

java/tools/javal/javal.java+244−0
@@ -0,0 +1,244 @@
1package javal;
2// Copyright (c) Lucent Technologies 1997
3// Revisions copyright (c) Vita Nuova Holdings Limited 2004
4
5import java.lang.reflect.*;
6import java.io.FileInputStream;
7import java.io.File;
8import java.io.IOException;
9
10
11public
12class javal
13{
14
15 private static java.io.PrintStream out = System.out;
16
17 private static boolean opt_verbose = false;
18 private static boolean opt_classinfo = false; //dump class info
19 private static boolean opt_module = false; //create Limbo mod (.m)
20 private static boolean opt_impl = false; //create Limbo impl skeleton (.b)
21
22
23 public static void main( String[] args )
24 {
25 int args_len = args.length;
26
27 if ( (args_len < 1) || (args_len > 2) )
28 error( "wrong args", true );
29
30 if ( args_len == 2 )
31 SetArgs( args[0] );
32
33 // class to create limbo module for
34 String targ_name = args[args_len-1];
35 Class targ_class = null;
36
37 try
38 {
39 TargetLoader tl = new TargetLoader( opt_verbose );
40 targ_class = tl.loadClass( targ_name, false );
41 }
42 catch ( NoClassDefFoundError ee )
43 {
44 ee.printStackTrace();
45 error( "ERROR: Class "+ targ_name +" not found.", false );
46 }
47 catch ( ClassNotFoundException ee )
48 {
49 error( "Error: Class "+ targ_name +" not found: "+ ee.getMessage(), false );
50 }
51 catch ( Exception ee )
52 {
53 error( "Error: Could not load class "+ targ_name +".", false );
54 }
55
56 out.println( "Class Name: "+ targ_class );
57
58 Field[] fields = GetFields( targ_class );
59 Method[] methods = GetMethods( targ_class);
60
61 if ( opt_classinfo )
62 {
63 Dump( "Fields", fields );
64 Dump( "Methods", methods );
65 }
66
67 if ( opt_module || opt_impl )
68 {
69 try
70 {
71 LimboGen limbogen = new LimboGen( targ_class, fields, methods, opt_verbose );
72
73 if ( opt_module )
74 limbogen.DotM();
75
76 if ( opt_impl )
77 limbogen.DotB();
78 }
79 catch ( RuntimeException ee )
80 {
81 System.err.println( "Error: internal error: "+ ee );
82 ee.printStackTrace();
83 error( "...too bad.", false );
84 }
85 catch ( Exception ee )
86 {
87 error( "Error: could not generate limbo file: "+ ee, false );
88 }
89
90 }
91
92 }
93
94
95 /**
96 * Get all data fields for the class and
97 * all of his ancestors.
98 */
99 private static Field[] GetFields( Class c )
100 {
101 if ( c == null ) return( new Field[0] );
102
103 Class sup = c.getSuperclass();
104 Field[] sup_f = GetFields( sup );
105
106 Field[] f = c.getDeclaredFields();
107
108 return( (Field[])ConcatArray( sup_f, f ) );
109 }
110
111
112 /**
113 * Get methods for the specified class
114 * only (i.e. don't care about ancestor's)
115 */
116 private static Method[] GetMethods( Class c )
117 {
118 return( c.getDeclaredMethods() );
119 }
120
121
122 private static Object ConcatArray( Object[] a1, Object[] a2 )
123 {
124 if ( (a2 == null) || (a2.length==0) ) return( a1 );
125 if ( (a1 == null) || (a1.length==0) ) return( a2 );
126
127 int[] dim = {a1.length+a2.length};
128 Object a = Array.newInstance( a1[0].getClass(), dim );
129
130 System.arraycopy( a1, 0, a, 0, a1.length );
131 System.arraycopy( a2, 0, a, a1.length, a2.length );
132
133 return( a );
134 }
135
136
137 private static void Dump( String title, Object[] ary )
138 {
139 System.out.println( title );
140 for(int x=0; x<ary.length; x++ )
141 {
142 System.out.println( "\t"+ ary[x] );
143 }
144 }
145
146 private static void SetArgs( String opts )
147 {
148
149 if ( (opts.length() > 5) ||
150 (opts.length() < 2) ||
151 (! opts.startsWith("-")) )
152 error( "Error: bad options", true );
153
154 opt_verbose = opts.indexOf( "v" ) != -1;
155 opt_classinfo = opts.indexOf( "c" ) != -1;
156 opt_module = opts.indexOf( "m" ) != -1;
157 opt_impl = opts.indexOf( "b" ) != -1;
158
159 if ( opt_verbose )
160 Runtime.getRuntime().traceMethodCalls(true);
161 }
162
163
164 private static void error( String msg, boolean usage )
165 {
166 out.println( msg );
167 if ( usage )
168 {
169 out.println( " javal [-vcmb] <class name>" );
170 }
171 System.exit(1);
172 }
173}
174
175/**
176 * This loader simply reads from a disk based
177 * .class file in the "current" directory. It
178 * only accepts the base name of the class,
179 * appends ".class" and reads the file. The
180 * purpose is to allow classes like "String.java"
181 * to be read and queried, where the class
182 * is different then the one used by this
183 * program. This tool is used to develop a
184 * new java class library and this class loader
185 * avoids the conflics of using a java based
186 * tool to develop java classes, etc.
187 */
188class TargetLoader extends ClassLoader
189{
190 private boolean verbose;
191 private String class_name = null;
192
193 TargetLoader( boolean verbose )
194 {
195 this.verbose = verbose;
196 }
197
198 public Class loadClass( String name, boolean resolve ) throws ClassNotFoundException
199 {
200
201 // if we have already been here once
202 // then load all other classes from the system
203 if ( class_name != null )
204 {
205 return( findSystemClass( name ) );
206 }
207
208 // otherwise do our one time load from a disk file
209
210 // read from the current directory the file "name".java
211 class_name = name +".class";
212
213 try
214 {
215 FileInputStream fin = new FileInputStream( class_name );
216
217 int len = fin.available(); // how big is the file
218
219 if ( len == 0 )
220 throw new ClassNotFoundException( class_name );
221
222 byte[] buf = new byte[len];
223
224 fin.read( buf ); //read the .class file
225
226 if ( verbose )
227 {
228 System.out.println( "loading class ["+ class_name +"]("+ len +")" );
229 }
230
231 // create class object and return it
232 return( defineClass( buf, 0, buf.length ) );
233 }
234 catch ( IOException ee )
235 {
236 File f = new File( class_name );
237 throw new ClassNotFoundException( "(path:"+f.getAbsolutePath() +")" );
238 }
239 catch ( Exception ee )
240 {
241 throw new ClassNotFoundException( ee.getMessage() );
242 }
243 }
244}
java/tools/javal/mkfile+21−0
@@ -0,0 +1,21 @@
1<../../../mkconfig
2
3TARG=\
4 FileMerge.class\
5 LimboGen.class\
6 javal.class\
7
8JROOT=$ROOT/java
9JPATH=$JROOT/pkg:$JROOT/tools
10
11all:V: $TARG
12
13install:V: all
14
15%.class: %.java
16 $JAVAC -XDignore.symbol.file -classpath $JPATH $stem.java
17
18clean:V:
19 rm -f *.class
20
21nuke:V: clean
java/tools/mkfile+7−0
@@ -0,0 +1,7 @@
1<../../mkconfig
2
3DIRS=\
4# j2d\
5# javal\
6
7<$ROOT/mkfiles/mksubdirs