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 | ||