Showing the changes to java/tools (38 of 18352 files). Show all
Unified · Split
Binary file not shown.
| @@ -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 | + | |
| @@ -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 | +}; | |
| @@ -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 | +} | |
| @@ -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 | +} | |
| @@ -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 | +} | |
| @@ -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 | +} | |
| @@ -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 | +} | |
| @@ -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 | +} | |
| @@ -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 | +} | |
| @@ -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* | |
| @@ -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 | +} | |
| @@ -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 | +}; | |
| @@ -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 | +}; | |
| @@ -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 | +} | |
| @@ -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 | +} | |
| @@ -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 | +} | |
| @@ -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 | +} | |
| @@ -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 | +} | |
| @@ -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 | |
| @@ -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 | +} | |
| @@ -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 | +} | |
| @@ -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); | |
| @@ -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 | +} | |
| @@ -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 | +} | |
| @@ -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 | +} | |
| @@ -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 | +} | |
| @@ -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 | +}; | |
| @@ -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 | +} | |
Binary file not shown.
| @@ -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 | +} | |
Binary file not shown.
| @@ -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 | +} | |
Binary file not shown.
Binary file not shown.
| @@ -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 | +} | |
| @@ -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 | |
| @@ -0,0 +1,7 @@ | ||
| 1 | +<../../mkconfig | |
| 2 | + | |
| 3 | +DIRS=\ | |
| 4 | +# j2d\ | |
| 5 | +# javal\ | |
| 6 | + | |
| 7 | +<$ROOT/mkfiles/mksubdirs | |