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+
2+import java.io.*;
3+
4+public 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+
3+static char *instname[MAXDIS];
4+
5+/*
6+ * %A format conversion.
7+ */
8+
9+int
10+Aconv(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+
45+int
46+Iconv(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+
80+static void
81+ehtable(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+
101+static void
102+putinst(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+
112+Inst *clinitclone; /* generated <clinit>, <clone> methods */
113+
114+/*
115+ * Emit assembly instructions for a method.
116+ */
117+
118+void
119+asminst(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+
156+void
157+sblinst(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+
184+static 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+
5+static BB **roots; /* root basic blocks */
6+static int nr; /* number of root basic blocks */
7+static int maxr; /* maximum number of roots */
8+
9+static BB **bbtbl; /* basic blocks */
10+static int nbb; /* number of basic blocks */
11+
12+static void
13+setflags(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+
41+static void
42+verifyjump(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+
55+static void
56+markldrs(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+
151+static void
152+addedges(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+
173+static void
174+connect(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+
235+static void dominators(void);
236+
237+/*
238+ * Build the basic block control flow graph.
239+ */
240+
241+void
242+flowgraph(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+
277+static void
278+bblistfree(BBList *l)
279+{
280+ BBList *l2;
281+
282+ while(l) {
283+ l2 = l->next;
284+ free(l);
285+ l = l2;
286+ }
287+}
288+
289+void
290+bbfree(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
320+static BB *bbstack[SSIZE];
321+static int bbtos;
322+
323+void
324+bbput(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+
333+BB*
334+bbget(void)
335+{
336+ return (bbtos == 0) ? nil : bbstack[--bbtos];
337+}
338+
339+void
340+bbinit(void)
341+{
342+ int i;
343+
344+ bbtos = 0;
345+ for(i = 0; i < nr; i++)
346+ bbput(roots[i]);
347+}
348+
349+static void
350+bbinit2(void)
351+{
352+ bbtos = 0;
353+}
354+
355+static void
356+bbput2(BB *bb)
357+{
358+ if(bbtos == SSIZE)
359+ fatal("bbstack overflow\n");
360+ bbstack[bbtos++] = bb;
361+}
362+
363+static void
364+intersect(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
373+static uchar mask[IBIT2UCHAR] = {
374+ 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01
375+};
376+
377+static void
378+setdombit(uchar *dom, int n)
379+{
380+ dom[n/IBIT2UCHAR] |= mask[n%IBIT2UCHAR];
381+}
382+
383+static int
384+getdombit(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+
396+static void
397+dom(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+
453+static void
454+dominators(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+
484+typedef struct CRef CRef;
485+typedef struct Hash Hash;
486+
487+struct 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+
495+struct Hash {
496+ CRef *cr;
497+ Hash *next;
498+};
499+
500+static Hash *crtbl[Hashsize]; /* hash table of referenced classes */
501+
502+enum {
503+ LOOKONLY,
504+ LOOKENTER
505+};
506+
507+static CRef*
508+creflook(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+
535+static 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+
546+void
547+crefseed(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+
562+void
563+crefenter(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+
589+int
590+crefstate(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+
628+void
629+creffree(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+
8+static Ipatch *dreloc;
9+static int Ipatchtid;
10+
11+void
12+setIpatchtid(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+
23+void
24+addIpatch(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+
39+static char *operand[] = {
40+ "?",
41+ "src", /* PSRC >> 2 */
42+ "dst", /* PDST >> 2 */
43+ "mid" /* PMID >> 2 */
44+};
45+
46+static char *mode[] = {
47+ "$x", /* PIMM */
48+ "x(reg)", /* PSIND */
49+ "n(x(reg))", /* PDIND1 */
50+ "x(n(reg))" /* PDIND2 */
51+};
52+
53+static schar *ba;
54+static int nba;
55+static int szba;
56+
57+static void
58+sizeba(int sz)
59+{
60+ if(sz > szba) {
61+ szba = sz;
62+ ba = Realloc(ba, szba * sizeof(schar));
63+ }
64+}
65+
66+static void
67+fillba(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+
92+void
93+asmIpatch(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+
133+void
134+disIpatch(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+
162+void
163+addDreloc(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+
174+void
175+asmDreloc(int off)
176+{
177+ asmIpatch(off, dreloc);
178+}
179+
180+/*
181+ * Write Dreloc information to .dis file.
182+ */
183+
184+void
185+disDreloc(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+
7+typedef struct Desc Desc;
8+
9+struct 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+
18+static Desc *dlist = nil;
19+static Desc *dtail = nil;
20+static int id = 0; /* reserve id == 0 for Module Data type descriptor */
21+
22+/*
23+ * Allocate a Desc structure.
24+ */
25+
26+static Desc*
27+newDesc(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+
44+int
45+descid(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+
71+void
72+mpdescid(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+
85+void
86+asmdesc(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+
100+void
101+disndesc(void)
102+{
103+ discon(id+1);
104+}
105+
106+void
107+disdesc(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+
3+Inst *ihead; /* first instruction generated for .class file */
4+Inst *itail; /* last instruction (for appending to list) */
5+
6+static uchar *cache; /* module data cache */
7+static int ncached; /* number of bytes in cache */
8+static int ndatum; /* number of non-string basic datums in cache */
9+static int startoff; /* offset of first datum in cache */
10+static int lastoff; /* 1 past last byte offset in cache */
11+static int lastkind = -1; /* last kind of datum put in cache */
12+static int lencache; /* capacity of cache */
13+
14+/*
15+ * Generate Dis object file (.dis).
16+ */
17+
18+void
19+discon(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+
38+void
39+disword(int w)
40+{
41+ Bputc(bout, w >> 24);
42+ Bputc(bout, w >> 16);
43+ Bputc(bout, w >> 8);
44+ Bputc(bout, w);
45+}
46+
47+void
48+disdata(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+
58+void
59+disflush(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+
79+void
80+disbyte(int off, int v)
81+{
82+ disflush(DEFB, off, 1);
83+ cache[ncached++] = v;
84+ ndatum++;
85+}
86+
87+void
88+disint(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+
98+void
99+dislong(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+
117+static void
118+dtocanon(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+
134+void
135+disreal(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+
155+void
156+disstring(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+
186+void
187+disarray(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+
203+void
204+disapop(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+
215+void
216+disninst(void)
217+{
218+ discon(itail ? itail->pc + 1 : 0);
219+}
220+
221+static 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+
230+static int disregmode[Aend] = {
231+ /* Anone */ AXNON,
232+ /* Aimm */ AXIMM,
233+ /* Amp */ AXINM,
234+ /* Ampind */ AXNON,
235+ /* Afp */ AXINF,
236+ /* Afpind */ AXNON
237+};
238+
239+enum
240+{
241+ MAXCON = 4,
242+ MAXADDR = 2*MAXCON,
243+ MAXINST = 3*MAXCON+2,
244+ NIBUF = 1024
245+};
246+
247+static uchar *ibuf;
248+static int nibuf;
249+
250+static void
251+disbcon(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+
270+static void
271+disaddr(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+
293+static void
294+disinst(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+
320+void
321+disout(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+
7+static int pc = -1;
8+static int tid = -1;
9+
10+/*
11+ * Set the entry point; entry is the beginning of "main".
12+ */
13+
14+void
15+setentry(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+
27+void
28+asmentry(void)
29+{
30+ if(pc == -1)
31+ return;
32+ Bprint(bout, "\tentry\t%d, %d\n", pc, tid);
33+}
34+
35+void
36+disentry(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+
7+typedef struct Finally Finally;
8+
9+static Finally *finally; /* linked list of finally block records */
10+
11+struct 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+
24+static Finally*
25+getfinally(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+
40+void
41+finallyentry(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+
61+void
62+finallyalloc(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+
76+void
77+jsrfixup(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+
99+void
100+retfixup(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+
122+void
123+finallyfree(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+
12+typedef struct Local Local;
13+
14+struct 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+
20+static int frameoff; /* tracks growth of frame */
21+static int maxframe; /* size of largest frame */
22+static Local *locals; /* local variables */
23+static int nlocals; /* number of locals (in the Java sense) */
24+
25+/*
26+ * fp temporaries.
27+ */
28+
29+typedef struct Fp Fp;
30+
31+struct Fp {
32+ uchar dtype;
33+ int refcnt;
34+};
35+
36+static int tmpslwm; /* lowest temporary fp offset */
37+static int tmpssz; /* size of tmps array */
38+static 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+
48+static void
49+resizelocals(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+
65+static void
66+reservelocal(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+
95+static void
96+mapmethodsig(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+
139+static void
140+maplocalrefs(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+
263+void
264+openframe(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+
286+int
287+localix(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+
303+static void
304+incref(int off)
305+{
306+ if(off >= tmpslwm) /* if <, then local variable */
307+ tmps[off-tmpslwm].refcnt++;
308+}
309+
310+void
311+acqreg(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+
332+void
333+reservereg(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+
345+static int
346+getoff(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+
372+int
373+getreg(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+
394+static void
395+decref(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+
407+void
408+relreg(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+
432+void
433+clearreg(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+
448+static int
449+framedesc(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+
481+int
482+closeframe(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+
510+void
511+disstackext(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+
5+enum {
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+
92+typedef struct Attr Attr;
93+typedef struct Field Field;
94+typedef struct Method Method;
95+typedef union Const Const;
96+typedef struct Class Class;
97+typedef struct Jinst Jinst;
98+typedef struct StkSnap StkSnap;
99+typedef struct BB BB;
100+typedef struct BBList BBList;
101+typedef struct Code Code;
102+typedef struct PCode PCode;
103+typedef struct Handler Handler;
104+
105+typedef struct Addr Addr;
106+typedef struct Inst Inst;
107+
108+union 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+
131+struct Attr { /* attribute_info */
132+ ushort name;
133+ uint ln;
134+ uchar *info;
135+};
136+
137+struct 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+
145+struct 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+
153+struct 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+
172+struct 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+
184+struct 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+
230+struct Handler { /* exception_table entry */
231+ ushort start_pc;
232+ ushort end_pc;
233+ ushort handler_pc;
234+ ushort catch_type;
235+};
236+
237+struct 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+
246+struct PCode {
247+ Code *code;
248+ char *name;
249+ char *sig;
250+};
251+
252+struct StkSnap { /* snapshot of simulated Java VM stack */
253+ uchar jtype;
254+ int npc;
255+ int *pc;
256+};
257+
258+struct 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+
273+struct BBList {
274+ BB *bb;
275+ BBList *next;
276+};
277+
278+struct 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 */
289+extern int Aconv(va_list*, Fconv*);
290+extern int Iconv(va_list*, Fconv*);
291+extern void asminst(void);
292+extern void sblinst(Biobuf*);
293+extern Inst *clinitclone;
294+
295+/* bb.c */
296+extern void flowgraph(void);
297+extern void bbfree(void);
298+extern void bbinit(void);
299+extern void bbput(BB*);
300+extern BB *bbget(void);
301+extern void crefseed(void);
302+extern void crefenter(char*, BB*);
303+extern int crefstate(char*, BB*, int);
304+extern void creffree(void);
305+
306+/* desc.c */
307+extern int descid(int, int, uchar*);
308+extern void mpdescid(int, int, uchar*);
309+extern void asmdesc(void);
310+extern void disndesc(void);
311+extern void disdesc(void);
312+
313+/* dis.c */
314+extern void discon(int);
315+extern void disword(int);
316+extern void disdata(int, int);
317+extern void disflush(int, int, int);
318+extern void disbyte(int, int);
319+extern void disint(int, int);
320+extern void dislong(int, vlong);
321+extern void disreal(int, double);
322+extern void disstring(int, char*);
323+extern void disarray(int, int, int);
324+extern void disapop(void);
325+extern void disout(void);
326+extern Inst *ihead;
327+extern Inst *itail;
328+
329+/* entry.c */
330+extern void setentry(int, int);
331+extern void asmentry(void);
332+extern void disentry(void);
333+
334+/* finally.c */
335+extern void finallyentry(int);
336+extern void finallyalloc(void);
337+extern void jsrfixup(Addr*, Addr*, int, int);
338+extern void retfixup(Addr*, Addr*, int);
339+extern void finallyfree(void);
340+
341+/* frame.c */
342+extern void openframe(char*, int);
343+extern int closeframe(void);
344+extern int localix(uchar, int);
345+extern void reservereg(StkSnap*, int);
346+extern int getreg(uchar);
347+extern void acqreg(Addr*);
348+extern void relreg(Addr*);
349+extern void clearreg(void);
350+extern void disstackext(void);
351+
352+/* javadas.c */
353+extern int Jconv(va_list*, Fconv*);
354+extern Code *javadas(Attr*);
355+
356+/* javatbl.c */
357+extern int isload(Jinst*);
358+extern int isstore(Jinst*);
359+
360+/* links.c */
361+extern void xtrnlink(int, int, char*, char*);
362+extern void addfcpatch(Inst*, Inst*, char*, char*);
363+extern void dofcpatch(void);
364+extern void asmlinks(void);
365+extern void disnlinks(void);
366+extern void dislinks(void);
367+extern void sbllinks(Biobuf*);
368+
369+/* loader.c */
370+extern void ClassLoader(char*);
371+extern void dumpcpool(void);
372+extern char *CLASSNAME(int);
373+extern char *STRING(int);
374+extern Class *class;
375+extern PCode *pcode;
376+extern char *THISCLASS;
377+extern char *SUPERCLASS;
378+
379+/* main.c */
380+extern int compileflag;
381+extern int gensbl;
382+extern int verbose;
383+extern Biobuf *bout;
384+extern char *ofile;
385+
386+/* mdata.c */
387+extern int mpint(int);
388+extern int mplong(vlong);
389+extern int mpreal(double);
390+extern int mpstring(char*);
391+extern int mpcase(int, int*);
392+extern void mpdesc(void);
393+extern int mpgoto(int, int*);
394+extern void asmarray(int, int, int, int);
395+extern void asmint(int, int);
396+extern void asmstring(int, char*);
397+extern void asmvar(void);
398+extern void disnvar(void);
399+extern void disvar(void);
400+
401+/* module.c */
402+extern void asmmod(void);
403+extern void dismod(void);
404+
405+/* patch.c */
406+extern void patchop(Inst*);
407+extern void patchcase(Inst*, int, int*);
408+extern void patchmethod(int);
409+extern void patchfree(void);
410+
411+/* sbl.c */
412+extern void sblout(char*);
413+
414+/* simjvm.c */
415+extern void simjvm(char*);
416+
417+/* unify.c */
418+extern void unify(void);
419+
420+/* util.c */
421+extern void uSet(uchar*);
422+extern void uN(int);
423+extern uchar u1(void);
424+extern ushort u2(void);
425+extern uint u4(void);
426+extern void getattr(Attr*);
427+extern int CVattrindex(Field*);
428+extern char *uPtr(void);
429+extern int align(int, int);
430+extern void pstring(char*);
431+extern void fatal(char*, ...);
432+extern void verifycpindex(Jinst*, int, int);
433+extern void verifyerror(Jinst*);
434+extern void verifyerrormess(char*);
435+extern char *nextjavatype(char*);
436+extern uchar j2dtype(uchar);
437+extern void addrimm(Addr*, int);
438+extern int notimmable(int);
439+extern void addrsind(Addr*, uchar, int);
440+extern void addrdind(Addr*, uchar, uint, uint);
441+extern void dstreg(Addr*, uchar);
442+extern void setbit(uchar*, int);
443+extern int hashval(char*);
444+extern void *Malloc(uint);
445+extern void *Mallocz(uint);
446+extern void *Realloc(void*, uint);
447+extern int cellsize[];
448+
449+/* xlate.c */
450+extern void xlate(void);
451+extern 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+
8+enum /* 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+
26+typedef struct Jmnemon Jmnemon;
27+
28+struct Jmnemon
29+{
30+ char *op;
31+ uchar kind;
32+};
33+
34+/*
35+ * Java bytecode mnemonics.
36+ */
37+
38+static 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+
248+int
249+Jconv(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+
313+static void
314+verifyehpc(Code *c, int pc)
315+{
316+ if(pc >= c->code_length || c->j[pc].size == 0)
317+ verifyerrormess("handler pc");
318+}
319+
320+static void
321+verifyhandler(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+
338+Code*
339+javadas(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+
5+enum {
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+
4+enum {
5+ XLOAD = 0x1 << 0,
6+ XSTORE = 0x1 << 1
7+};
8+
9+static uchar javatbl[MAXJAVA];
10+
11+static int
12+opcode(Jinst *j)
13+{
14+ return (j->op == Jwide) ? j->u.w.op : j->op;
15+}
16+
17+int
18+isload(Jinst *j)
19+{
20+ return javatbl[opcode(j)] & XLOAD;
21+}
22+
23+int
24+isstore(Jinst *j)
25+{
26+ return javatbl[opcode(j)] & XSTORE;
27+}
28+
29+static 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+
7+typedef struct Link Link;
8+
9+struct 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+
18+static Link *links = nil;
19+static Link *last = nil;
20+static int nlinks;
21+
22+/*
23+ * Create a Link entry; one for each method defined in the class.
24+ */
25+
26+void
27+xtrnlink(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+
55+typedef struct FCPatch FCPatch;
56+
57+struct FCPatch {
58+ Inst *frame;
59+ Inst *call;
60+ char *name;
61+ char *sig;
62+ FCPatch *next;
63+};
64+
65+static FCPatch *fcplist;
66+
67+/*
68+ * Record a frame/call pair for later patching.
69+ */
70+
71+void
72+addfcpatch(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+
85+static Link*
86+getLink(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+
108+void
109+dofcpatch(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+
129+void
130+asmlinks(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+
140+void
141+sbllinks(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+
154+void
155+disnlinks(void)
156+{
157+ discon(nlinks);
158+}
159+
160+void
161+dislinks(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+
7+Class *class; /* class under translation */
8+PCode *pcode; /* pointers to byte code of defined methods */
9+char *THISCLASS;
10+char *SUPERCLASS;
11+
12+char*
13+CLASSNAME(int i)
14+{
15+ return class->cps[class->cps[i].ci.name_index].utf8.utf8;
16+}
17+
18+char*
19+STRING(int i)
20+{
21+ return class->cps[i].utf8.utf8;
22+}
23+
24+typedef union Fc Fc;
25+
26+union Fc
27+{
28+ float f;
29+ uint ival;
30+};
31+
32+static double
33+canontod(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+
52+static void
53+verifyutf8index(int index)
54+{
55+ verifycpindex(nil, index, 1 << CON_Utf8);
56+ if(STRING(index) == nil)
57+ verifyerrormess("nil name or descriptor");
58+}
59+
60+static void
61+verifyclassindex(int index)
62+{
63+ verifycpindex(nil, index, 1 << CON_Class);
64+ verifyutf8index(class->cps[index].ci.name_index);
65+}
66+
67+static void
68+verifyfielddesc(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+
82+static void
83+verifymethoddesc(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'))
121+bad: verifyerrormess("method descriptor");
122+}
123+
124+static void
125+verifycpindexes(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+
172+static void
173+verifyclassflags(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+
192+static int
193+multippp(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+
216+static void
217+verifyfield(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+
279+static void
280+verifymethod(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+
311+static void
312+byte2Class(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+
477+void
478+ClassLoader(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+
505+static void
506+accessflags(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+
544+void
545+dumpcpool(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+
8+typedef struct LTHash LTHash;
9+
10+struct LTHash
11+{
12+ Creloc *cr;
13+ LTHash *next;
14+};
15+
16+ int doclinitinits;
17+static LTHash *lttbl[Hashsize]; /* hash table of referenced classes */
18+static Creloc *thisclass; /* class under translation */
19+static int nltclasses; /* no. of classes referenced */
20+
21+/*
22+ * Allocate a Creloc structure.
23+ */
24+
25+static Creloc*
26+newCreloc(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+
39+static void
40+ltappend(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+
49+static void
50+ltprepend(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+
62+static Freloc*
63+addFreloc(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+
85+static Creloc*
86+addCreloc(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+
103+Creloc*
104+getCreloc(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+
119+Freloc*
120+getFreloc(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+
145+void
146+thisCreloc(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+
183+void
184+LTIpatch(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+
194+int
195+LTrelocsize(void)
196+{
197+ return align((9 + 2*(nltclasses-1)) * IBY2WD, 32);
198+}
199+
200+/*
201+ * Fix type descriptor for relocation information.
202+ */
203+
204+static int Freloctid, Ifacetid;
205+
206+void
207+LTrelocdesc(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+
236+static void
237+asmFreloc(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+
262+int
263+asmCreloc(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+
282+enum {
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+
292+int
293+asmthisCreloc(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+
326+static void
327+disFreloc(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+
352+int
353+disCreloc(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+
376+int
377+disthisCreloc(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+
5+static int gendis; /* generate .dis rather than .s (default) */
6+static 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+
13+static void
14+usage(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+
24+static void
25+translate(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+
61+enum {
62+ MAXUNENCODED = NAMELEN - 7,
63+ ENCODEDLEN = 21
64+};
65+
66+static 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+
77+static char*
78+encodename(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+
106+static char*
107+mkfileext(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+
128+extern int gfltconv(va_list*, Fconv*);
129+
130+void
131+main(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+
8+enum {
9+ MP_INT,
10+ MP_LONG,
11+ MP_REAL,
12+ MP_STRING,
13+ MP_CASE,
14+ MP_GOTO
15+};
16+
17+typedef struct Hentry Hentry;
18+typedef struct Datum Datum;
19+
20+struct 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+
44+struct Hentry
45+{
46+ Datum *md;
47+ Hentry *next;
48+};
49+
50+static Hentry *htable[Hashsize];
51+static int mpoff;
52+
53+static Datum *mplist = nil;
54+static Datum *mptail = nil;
55+static Datum *llist = nil;
56+static Datum *rlist = nil;
57+
58+/*
59+ * Allocate a Datum structure.
60+ */
61+
62+static Datum*
63+newDatum(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+
78+static void
79+append(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+
92+static int
93+mpintegral(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+
124+int
125+mpint(int ival)
126+{
127+ return mpintegral(MP_INT, ival);
128+}
129+
130+/*
131+ * Add a 'long'.
132+ */
133+
134+int
135+mplong(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+
158+int
159+mpreal(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+
184+int
185+mpcase(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+
203+int
204+mpgoto(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+
222+static Hentry*
223+htlook(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+
237+static Hentry*
238+htenter(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+
255+int
256+mpstring(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+
277+void
278+mpdesc(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+
300+static void
301+asmprefix(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+
310+void
311+asmarray(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+
319+void
320+asmint(int off, int val)
321+{
322+ asmprefix(off, "word");
323+ Bprint(bout, "%d\n", val);
324+}
325+
326+static void
327+asmlong(int off, vlong val)
328+{
329+ asmprefix(off, "long");
330+ Bprint(bout, "%lld\n", val);
331+}
332+
333+static void
334+asmreal(int off, double val)
335+{
336+ asmprefix(off, "real");
337+ Bprint(bout, "%g\n", val);
338+}
339+
340+void
341+asmstring(int off, char *s)
342+{
343+ asmprefix(off, "string");
344+ Bputc(bout, '"');
345+ pstring(s);
346+ Bprint(bout, "\"\n");
347+}
348+
349+static void
350+asmcase(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+
364+static void
365+asmgoto(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+
380+void
381+asmvar(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+
429+void
430+disnvar(void)
431+{
432+ discon(LTrelocsize() + mpoff + RTrelocsize());
433+}
434+
435+static void
436+discase(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+
453+static void
454+disgoto(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+
469+void
470+disvar(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+
3+LIBS=\
4+ bio\
5+ crypt\
6+ math\
7+ 9
8+
9+TARG=j2d
10+
11+OFILES=\
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+
36+HFILES=\
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+
43+BIN=$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+
7+void
8+asmmod(void)
9+{
10+ Bprint(bout, "\tmodule\t%s\n", THISCLASS);
11+}
12+
13+void
14+dismod(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+
7+enum {
8+ P_CASE = 1,
9+ P_OTHER
10+};
11+
12+typedef struct Patch Patch;
13+
14+struct 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+
22+static Patch *plist;
23+
24+/*
25+ * Allocate a Patch structure.
26+ */
27+
28+static Patch*
29+newPatch(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+
45+void
46+patchop(Inst *i)
47+{
48+ newPatch(P_OTHER, i);
49+}
50+
51+/*
52+ * Record case jump table for later patching.
53+ */
54+
55+void
56+patchcase(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+
69+static int
70+patchaddr(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+
91+void
92+patchmethod(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+
122+void
123+patchfree(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 @@
1+enum {
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+
40+typedef struct Ipatch Ipatch;
41+typedef struct Freloc Freloc;
42+typedef struct Creloc Creloc;
43+typedef struct RTReloc RTReloc;
44+typedef struct RTClass RTClass;
45+
46+struct 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+
57+struct 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+
65+struct 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+
76+struct 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+
84+struct 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 */
93+extern void addDreloc(Inst*, int, int);
94+extern void asmDreloc(int);
95+extern void disDreloc(int);
96+extern void addIpatch(Ipatch*, Inst*, int, int, int);
97+extern void setIpatchtid(void);
98+extern void asmIpatch(int, Ipatch*);
99+extern void disIpatch(int, Ipatch*);
100+
101+/* ltreloc.c */
102+extern void thisCreloc(void);
103+extern Creloc *getCreloc(char*);
104+extern Freloc *getFreloc(Creloc*, char*, char*, uint);
105+extern void LTIpatch(Freloc*, Inst*, int, int);
106+extern int LTrelocsize(void);
107+extern void LTrelocdesc(uchar*);
108+extern int asmCreloc(int);
109+extern int disCreloc(int);
110+extern int asmthisCreloc(int);
111+extern int disthisCreloc(int);
112+extern int doclinitinits;
113+
114+/* rtreloc.c */
115+extern RTClass *getRTClass(char*);
116+extern RTReloc *getRTReloc(RTClass*, char*, char*, uint);
117+extern void RTIpatch(RTReloc*, Inst*, int, int);
118+extern void RTfixoff(int);
119+extern void doRTpatch(void);
120+extern int RTrelocsize(void);
121+extern void RTrelocdesc(uchar*, int);
122+extern int asmRTClass(int);
123+extern 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+
8+typedef struct RTHash RTHash;
9+
10+struct RTHash
11+{
12+ RTClass *rtc;
13+ RTHash *next;
14+};
15+
16+static RTHash *rttbl[Hashsize]; /* hash table of referenced classes */
17+static int nrtclasses; /* no. of classes referenced */
18+
19+static void
20+rtappend(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+
29+static void
30+rtprepend(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+
42+static RTReloc*
43+addRTReloc(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+
65+static RTClass*
66+newRTClass(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+
89+static RTClass*
90+addRTClass(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+
107+RTClass*
108+getRTClass(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+
123+RTReloc*
124+getRTReloc(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+
149+void
150+RTIpatch(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+
160+void
161+RTfixoff(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+
180+void
181+doRTpatch(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+
237+int
238+RTrelocsize(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+
258+static int RTReloctid;
259+
260+void
261+RTrelocdesc(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+
295+static void
296+asmRTReloc(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+
325+int
326+asmRTClass(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+
355+static void
356+disRTReloc(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+
385+int
386+disRTClass(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+
10+void
11+sblout(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+
8+typedef struct Result Result;
9+
10+struct Result {
11+ uchar jtype;
12+ int pc;
13+};
14+
15+static Result *jvmstack; /* simulated JVM stack */
16+static int jvmtos; /* number of items in jvmstack */
17+static int jvmwords; /* number of words that would be on JVM stack */
18+static uchar rettype; /* return type of simulated method */
19+
20+static Result
21+jvmpop(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)
33+bad: verifyerrormess("stack underflow");
34+ return r;
35+}
36+
37+static void
38+jvmpush(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+
53+static void
54+jvminit(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+
78+static void
79+typecheck(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+
86+static uchar
87+jvmtype(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+
100+static void
101+setresult(Result *r, uchar jtype, Jinst *j)
102+{
103+ r->jtype = jtype;
104+ r->pc = j->pc;
105+ j->jtype = jtype;
106+}
107+
108+static void
109+srcalloc(Jinst *j, int n)
110+{
111+ j->nsrc = n;
112+ j->src = Malloc(n*sizeof(int));
113+}
114+
115+static void
116+iconst(Jinst *j, int ival)
117+{
118+ Result r;
119+
120+ addrimm(&j->dst, ival);
121+ setresult(&r, 'I', j);
122+ jvmpush(r);
123+}
124+
125+static void
126+mpconst(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+
135+static void
136+verifyindex(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+
158+static int
159+getfpoff(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+
182+static void
183+javaload(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+
193+static void
194+javastore(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+
209+static void
210+arrayload(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+
229+static void
230+arraystore(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+
250+static void
251+binop(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+
270+static void
271+unop(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+
292+static void
293+storechk(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+
413+static void
414+useone(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+
425+static void
426+usetwo(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+
441+static void
442+javanew(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+
457+static int
458+checkdim(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+
475+static void
476+anewarray(Jinst *j)
477+{
478+ checkdim(j, j->u.i);
479+ unop(j, 'I', '[');
480+}
481+
482+static void
483+multianewarray(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+
505+static char*
506+getclassname(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+
519+static char*
520+getname(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+
534+static char*
535+getsig(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+
549+static void
550+getfs(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+
564+static void
565+putfs(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+
577+static void
578+invoke(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+
641+static void
642+javareturn(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+
675+static void
676+ldc(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+
705+static void
706+oneword(Jinst *j, uchar jtype)
707+{
708+ if(jtype == 'J' || jtype == 'D')
709+ verifyerror(j);
710+}
711+
712+static void
713+javapop(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+
738+static void
739+javadup(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+
840+static void
841+javaswap(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+
853+static void
854+simjinst(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+
1389+static StkSnap*
1390+snapstack(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+
1409+static void
1410+stackmerge(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+
1459+static void
1460+simbb(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+
1492+void
1493+simjvm(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+
10+static void
11+pushsucc(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+
21+static int
22+pass1(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+
44+static void
45+pass2(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+
60+static void
61+unifybb(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+
98+void
99+unify(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+
7+static uchar *codeix;
8+
9+void
10+uSet(uchar *x)
11+{
12+ codeix = x;
13+}
14+
15+char*
16+uPtr(void)
17+{
18+ return (char*)codeix;
19+}
20+
21+void
22+uN(int i)
23+{
24+ codeix += i;
25+}
26+
27+uchar
28+u1(void)
29+{
30+ return *codeix++;
31+}
32+
33+ushort
34+u2(void)
35+{
36+ ushort l;
37+
38+ l = (codeix[0]<<8) | codeix[1];
39+ codeix += 2;
40+ return l;
41+}
42+
43+uint
44+u4(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+
53+void
54+getattr(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+
68+int
69+CVattrindex(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+
88+int
89+align(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+
99+void
100+setbit(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+
112+int
113+hashval(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+
129+char*
130+nextjavatype(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+
161+uchar
162+j2dtype(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+
194+void
195+addrimm(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+
205+int
206+notimmable(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+
215+void
216+addrsind(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+
226+void
227+addrdind(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+
238+void
239+dstreg(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+
249+void
250+pstring(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+
278+void*
279+Malloc(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+
289+void*
290+Mallocz(uint n)
291+{
292+ void *p;
293+
294+ p = Malloc(n);
295+ memset(p, 0, n);
296+ return p;
297+}
298+
299+void*
300+Realloc(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+
315+void
316+fatal(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+
339+void
340+verifycpindex(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+
351+void
352+verifyerror(Jinst *j)
353+{
354+ fatal("VerifyError: %J\n", j);
355+}
356+
357+void
358+verifyerrormess(char *mess)
359+{
360+ fatal("VerifyError: %s\n", mess);
361+}
362+
363+/*
364+ * Size of frame cell of given type.
365+ */
366+
367+int 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+
5+static int pcdis;
6+static int callunrescue;
7+static Jinst *J;
8+static Method *M;
9+ Code *code; /* method under translation */
10+
11+static int trylevel(int);
12+static void unrescue(int);
13+
14+/*
15+ * Allocate a Dis instruction.
16+ */
17+
18+static Inst*
19+newi(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+
43+static Inst*
44+newibap(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+
57+static void
58+sind2dind(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+
75+static void
76+middstcmp(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+
92+static void
93+datareloc(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+
103+static uchar
104+movinst(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+
140+typedef struct FieldInfo FieldInfo;
141+
142+struct FieldInfo {
143+ char *classname;
144+ char *fieldname;
145+ char *sig;
146+ int flags;
147+};
148+
149+static void
150+getfldinfo(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+
181+static Inst*
182+loadermframe(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+
200+static Inst*
201+loadermcall(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+
219+static void
220+callrtload(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+
254+static void
255+signextend(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+
274+static Addr*
275+rtstaticadd(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+
295+static Addr*
296+ltstaticadd(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+
318+static void
319+getstatic(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+
353+static void
354+putstatic(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+
386+static Addr*
387+rtfieldadd(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+
406+static void
407+getfield(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+
449+static void
450+putfield(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+
492+static void
493+pushargs(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+
535+static void
536+rtinvokess(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+
577+static void
578+invokess(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+
645+static void
646+invokei(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+
732+static void
733+rtinvokev(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+
786+static void
787+invokev(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+
842+static void
843+rtnew(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+
876+static void
877+xjavanew(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+
923+static void
924+newarray(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+
973+typedef struct ArrayInfo ArrayInfo;
974+
975+struct 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+
986+static void
987+getaryinfo(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+
1047+static void
1048+xanewarray(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+
1104+static void
1105+xmultianewarray(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+
1188+static void
1189+arraylength(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+
1201+static Addr*
1202+arrayindex(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+
1221+static void
1222+xarrayload(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+
1242+static void
1243+aastore(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+
1272+static void
1273+xarraystore(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+
1292+static void
1293+mon_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+
1343+static void
1344+xjavaload(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+
1357+static void
1358+xjavastore(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+
1377+static void
1378+midcheck(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+
1390+static void
1391+real64to32(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+
1406+static void
1407+xbinop(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+
1426+static void
1427+shift(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+
1453+static void
1454+cvt(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+
1469+static void
1470+i2c(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+
1487+static void
1488+i2bs(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+
1512+static void
1513+neg(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+
1529+static void
1530+iinc(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+
1546+static int
1547+tldiff(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+
1562+enum {
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+
1568+static void
1569+javaif(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+
1635+static void
1636+javagoto(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+
1654+static void
1655+xjavareturn(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+
1677+static void
1678+xjavapop(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+
1689+static void
1690+xjavadup(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+
1697+static void
1698+xldc(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+
1729+static void
1730+jsr(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+
1748+static void
1749+ret(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+
1761+static void
1762+tableswitch(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+
1784+static void
1785+lookupswitch(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+
1810+static void
1811+jmath(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+
1850+static void
1851+rtti(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+
1953+typedef struct Catch Catch;
1954+typedef struct Try Try;
1955+typedef struct EHInst EHInst;
1956+
1957+struct Catch {
1958+ char *exname;
1959+ int handler_pc;
1960+ Catch *next;
1961+};
1962+
1963+struct Try {
1964+ int start_pc;
1965+ int end_pc;
1966+ int any_pc;
1967+ Catch *catch;
1968+ Try *next;
1969+};
1970+
1971+struct EHInst {
1972+ Inst *i;
1973+ EHInst *next;
1974+};
1975+
1976+static EHInst *ehinst;
1977+static Try *trylist;
1978+
1979+/*
1980+ * Save an EH branch instruction for later patching.
1981+ */
1982+
1983+static void
1984+saveehinst(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+
1999+static void
2000+patchehinst(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+
2022+static void
2023+cvtehinfo(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+
2061+static int
2062+trylevel(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+
2079+static void
2080+ehinfofree(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+
2100+static Addr*
2101+rescue(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+
2136+static void
2137+unrescue(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+
2160+static Inst*
2161+rethrow(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+
2191+static void
2192+catch(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+
2220+static Addr*
2221+chkhandler(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+
2270+static void
2271+trystart(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+
2315+static void
2316+tryhandling(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+
2334+static void
2335+java2dis(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+
2868+static void
2869+ref_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+
2886+static Inst*
2887+clinitinits(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+
2979+static void
2980+genclinit(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+
2995+static Inst*
2996+genclone(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+
3037+void
3038+xlate(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 @@
1+package javal;
2+
3+import java.io.File;
4+import java.io.FileOutputStream;
5+import java.io.FileInputStream;
6+import java.io.DataInputStream;
7+import java.io.DataOutputStream;
8+import java.io.IOException;
9+import java.io.EOFException;
10+
11+
12+class 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 @@
1+package javal;
2+
3+import java.io.File;
4+import java.io.DataOutputStream;
5+import java.io.FileOutputStream;
6+import java.io.IOException;
7+
8+import java.lang.reflect.*;
9+
10+
11+public
12+class 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 @@
1+package javal;
2+// Copyright (c) Lucent Technologies 1997
3+// Revisions copyright (c) Vita Nuova Holdings Limited 2004
4+
5+import java.lang.reflect.*;
6+import java.io.FileInputStream;
7+import java.io.File;
8+import java.io.IOException;
9+
10+
11+public
12+class 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+ */
188+class 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+
3+TARG=\
4+ FileMerge.class\
5+ LimboGen.class\
6+ javal.class\
7+
8+JROOT=$ROOT/java
9+JPATH=$JROOT/pkg:$JROOT/tools
10+
11+all:V: $TARG
12+
13+install:V: all
14+
15+%.class: %.java
16+ $JAVAC -XDignore.symbol.file -classpath $JPATH $stem.java
17+
18+clean:V:
19+ rm -f *.class
20+
21+nuke:V: clean
java/tools/mkfile+7−0
@@ -0,0 +1,7 @@
1+<../../mkconfig
2+
3+DIRS=\
4+# j2d\
5+# javal\
6+
7+<$ROOT/mkfiles/mksubdirs