11f01a5c352f33860460700076a7ef9f1db5633a
[cacao.git] / src / vm / jit / show.c
1 /* src/vm/jit/show.c - showing the intermediate representation
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    $Id$
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33
34 #include "vm/types.h"
35
36 #include "mm/memory.h"
37
38 #include "threads/lock-common.h"
39
40 #include "vm/global.h"
41 #include "vm/builtin.h"
42 #include "vm/stringlocal.h"
43 #include "vm/vm.h"
44
45 #include "vm/jit/abi.h"
46 #include "vm/jit/jit.h"
47 #include "vm/jit/show.h"
48 #include "vm/jit/disass.h"
49 #include "vm/jit/stack.h"
50 #include "vm/jit/parse.h"
51
52 #include "vmcore/options.h"
53
54 #if defined(ENABLE_DEBUG_FILTER)
55 #       include <sys/types.h>
56 #       include <regex.h>
57 #       if defined(ENABLE_THREADS)
58 #               include "threads/native/threads.h"
59 #       else
60 #               include "threads/none/threads.h"
61 #       endif
62 #endif
63
64 /* global variables ***********************************************************/
65
66 #if defined(ENABLE_THREADS) && !defined(NDEBUG)
67 static java_object_t *show_global_lock;
68 #endif
69
70
71 /* prototypes *****************************************************************/
72
73 #if !defined(NDEBUG)
74 static void show_variable_intern(jitdata *jd, s4 index, int stage);
75 #endif
76
77
78 /* show_init *******************************************************************
79
80    Initialized the show subsystem (called by jit_init).
81
82 *******************************************************************************/
83
84 #if !defined(NDEBUG)
85 bool show_init(void)
86 {
87 #if defined(ENABLE_THREADS)
88         /* initialize the show lock */
89
90         show_global_lock = NEW(java_object_t);
91
92         LOCK_INIT_OBJECT_LOCK(show_global_lock);
93 #endif
94
95 #if defined(ENABLE_DEBUG_FILTER)
96         show_filters_init();
97 #endif
98
99         /* everything's ok */
100
101         return true;
102 }
103 #endif
104
105
106 #if !defined(NDEBUG)
107 char *show_jit_type_names[] = {
108         "INT",
109         "LNG",
110         "FLT",
111         "DBL",
112         "ADR",
113         "??5",
114         "??6",
115         "??7",
116         "RET"
117 };
118 char show_jit_type_letters[] = {
119         'I',
120         'L',
121         'F',
122         'D',
123         'A',
124         '5',
125         '6',
126         '7',
127         'R'
128 };
129 #endif
130
131
132 /* show_method *****************************************************************
133
134    Print the intermediate representation of a method.
135
136    NOTE: Currently this function may only be called after register allocation!
137
138 *******************************************************************************/
139
140 #if !defined(NDEBUG)
141 void show_method(jitdata *jd, int stage)
142 {
143         methodinfo     *m;
144         codeinfo       *code;
145         codegendata    *cd;
146         registerdata   *rd;
147         basicblock     *bptr;
148         basicblock     *lastbptr;
149         exception_entry *ex;
150         s4              i, j;
151         int             irstage;
152 #if defined(ENABLE_DISASSEMBLER)
153         u1             *pc;
154 #endif
155
156         /* get required compiler data */
157
158         m    = jd->m;
159         code = jd->code;
160         cd   = jd->cd;
161         rd   = jd->rd;
162
163         /* We need to enter a lock here, since the binutils disassembler
164            is not reentrant-able and we could not read functions printed
165            at the same time. */
166
167         LOCK_MONITOR_ENTER(show_global_lock);
168
169 #if defined(ENABLE_INTRP)
170         if (opt_intrp)
171                 irstage = SHOW_PARSE;
172         else
173 #endif
174                 irstage = stage;
175
176         /* get the last basic block */
177
178         for (lastbptr = jd->basicblocks; lastbptr->next != NULL; lastbptr = lastbptr->next);
179
180         printf("\n");
181
182         method_println(m);
183
184         if (jd->isleafmethod)
185                 printf("LEAFMETHOD\n");
186
187         printf("\nBasic blocks: %d\n", jd->basicblockcount);
188         if (stage >= SHOW_CODE) {
189                 printf("Code length:  %d\n", (lastbptr->mpc - jd->basicblocks[0].mpc));
190                 printf("Data length:  %d\n", cd->dseglen);
191                 printf("Stub length:  %d\n", (s4) (code->mcodelength -
192                                                                                    ((ptrint) cd->dseglen + lastbptr->mpc)));
193         }
194         printf("Variables:       %d (%d used)\n", jd->varcount, jd->vartop);
195         if (stage >= SHOW_STACK)
196                 printf("Max interfaces:  %d\n", jd->maxinterfaces);
197         printf("Max locals:      %d\n", jd->maxlocals);
198         printf("Max stack:       %d\n", m->maxstack);
199         printf("Linenumbers:     %d\n", m->linenumbercount);
200         printf("Branch to entry: %s\n", (jd->branchtoentry) ? "yes" : "no");
201         printf("Branch to end:   %s\n", (jd->branchtoend) ? "yes" : "no");
202         if (stage >= SHOW_STACK) {
203                 printf("Number of RETURNs: %d", jd->returncount);
204                 if (jd->returncount == 1)
205                         printf(" (block L%03d)", jd->returnblock->nr);
206                 printf("\n");
207         }
208
209         if (stage >= SHOW_PARSE) {
210                 printf("Exceptions (Number: %d):\n", jd->exceptiontablelength);
211                 for (ex = jd->exceptiontable; ex != NULL; ex = ex->down) {
212                         printf("    L%03d ... ", ex->start->nr );
213                         printf("L%03d  = ", ex->end->nr);
214                         printf("L%03d", ex->handler->nr);
215                         printf("  (catchtype: ");
216                         if (ex->catchtype.any)
217                                 if (IS_CLASSREF(ex->catchtype))
218                                         class_classref_print(ex->catchtype.ref);
219                                 else
220                                         class_print(ex->catchtype.cls);
221                         else
222                                 printf("ANY");
223                         printf(")\n");
224                 }
225         }
226         
227         if (irstage >= SHOW_PARSE && rd && jd->localcount > 0) {
228                 printf("Local Table:\n");
229                 for (i = 0; i < jd->localcount; i++) {
230                         printf("   %3d: ", i);
231
232 #if defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER)
233 # if defined(ENABLE_INTRP)
234                         if (!opt_intrp) {
235 # endif
236                                 printf("   (%s) ", show_jit_type_names[VAR(i)->type]);
237                                 if (irstage >= SHOW_REGS)
238                                         show_allocation(VAR(i)->type, VAR(i)->flags, VAR(i)->vv.regoff);
239                                 printf("\n");
240 # if defined(ENABLE_INTRP)
241                         }
242 # endif
243 #endif /* defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER) */
244                 }
245                 printf("\n");
246         }
247
248         if (jd->maxlocals > 0 && jd->local_map != NULL) {
249                 printf("Local Map:\n");
250                 printf("    index ");
251                 for (j = 0; j < jd->maxlocals; j++) {
252                         printf(" [%2d]", j);
253                 }
254                 printf("\n");
255                 for (i = 0; i < 5; i++) {
256                         printf("    %5s ",show_jit_type_names[i]);
257                         for (j = 0; j < jd->maxlocals; j++) {
258                                 if (jd->local_map[j*5+i] == UNUSED)
259                                         printf("  -- ");
260                                 else
261                                         printf("%4i ",jd->local_map[j*5+i]);
262                         }
263                         printf("\n");
264                 }
265                 printf("\n");
266         }
267
268         if (jd->maxinterfaces > 0 && jd->interface_map && irstage >= SHOW_STACK) {
269                 bool exist = false;
270                 interface_info *mapptr = jd->interface_map;
271                 
272                 /* look if there exist any INOUTS */
273                 for (i = 0; (i < (5 * jd->maxinterfaces)) && !exist; i++, mapptr++)
274                         exist = (mapptr->flags != UNUSED);
275
276                 if (exist) {
277                         printf("Interface Table: (In/Outvars)\n");
278                         printf("    depth ");
279                         for (j = 0; j < jd->maxinterfaces; j++) {
280                                 printf("      [%2d]", j);
281                         }
282                         printf("\n");
283
284                         for (i = 0; i < 5; i++) {
285                                 printf("    %5s      ",show_jit_type_names[i]);
286                                 for (j = 0; j < jd->maxinterfaces; j++) {
287                                         s4 flags  = jd->interface_map[j*5+i].flags;
288                                         s4 regoff = jd->interface_map[j*5+i].regoff;
289                                         if (flags == UNUSED)
290                                                 printf("  --      ");
291                                         else {
292                                                 int ch;
293
294                                                 if (irstage >= SHOW_REGS) {
295                                                         if (flags & SAVEDVAR) {
296                                                                 if (flags & INMEMORY)
297                                                                         ch = 'M';
298                                                                 else
299                                                                         ch = 'R';
300                                                         }
301                                                         else {
302                                                                 if (flags & INMEMORY)
303                                                                         ch = 'm';
304                                                                 else
305                                                                         ch = 'r';
306                                                         }
307                                                         printf("%c%03d(", ch, regoff);
308                                                         show_allocation(i, flags, regoff);
309                                                         printf(") ");
310                                                 }
311                                                 else {
312                                                         if (flags & SAVEDVAR)
313                                                                 printf("  I       ");
314                                                         else
315                                                                 printf("  i       ");
316                                                 }
317                                         }
318                                 }
319                                 printf("\n");
320                         }
321                         printf("\n");
322                 }
323         }
324
325         if (rd->memuse && irstage >= SHOW_REGS) {
326                 int max;
327
328                 max = rd->memuse;
329                 printf("Stack slots: (memuse=%d", rd->memuse);
330                 if (irstage >= SHOW_CODE) {
331                         printf(", stackframesize=%d", cd->stackframesize);
332                         max = cd->stackframesize;
333                 }
334                 printf(")\n");
335                 for (i = 0; i < max; ++i) {
336 #if defined(HAS_4BYTE_STACKSLOT)
337                         printf("    M%02d = 0x%02x(sp): ", i, i * 4);
338 #else
339                         printf("    M%02d = 0x%02x(sp): ", i, i * 8);
340 #endif
341                         for (j = 0; j < jd->vartop; ++j) {
342                                 varinfo *v = VAR(j);
343                                 if ((v->flags & INMEMORY) && (v->vv.regoff == i)) {
344                                         show_variable(jd, j, irstage);
345                                         putchar(' ');
346                                 }
347                         }
348
349                         printf("\n");
350
351                 }
352                 printf("\n");
353         }
354
355 #if defined(ENABLE_REPLACEMENT)
356         if (code->rplpoints) {
357                 printf("Replacement Points:\n");
358                 replace_show_replacement_points(code);
359                 printf("\n");
360         }
361 #endif /* defined(ENABLE_REPLACEMENT) */
362
363 #if defined(ENABLE_DISASSEMBLER)
364         /* show code before first basic block */
365
366         if ((stage >= SHOW_CODE) && JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd)) {
367                 pc = (u1 *) ((ptrint) code->mcode + cd->dseglen);
368
369                 for (; pc < (u1 *) ((ptrint) code->mcode + cd->dseglen + jd->basicblocks[0].mpc);)
370                         DISASSINSTR(pc);
371
372                 printf("\n");
373         }
374 #endif
375
376         /* show code of all basic blocks */
377
378         for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next)
379                 show_basicblock(jd, bptr, stage);
380
381 #if defined(ENABLE_DISASSEMBLER)
382         /* show stubs code */
383
384         if (stage >= SHOW_CODE && opt_showdisassemble && opt_showexceptionstubs) {
385                 printf("\nStubs code:\n");
386                 printf("Length: %d\n\n", (s4) (code->mcodelength -
387                                                                            ((ptrint) cd->dseglen + lastbptr->mpc)));
388
389                 pc = (u1 *) ((ptrint) code->mcode + cd->dseglen + lastbptr->mpc);
390
391                 for (; (ptrint) pc < ((ptrint) code->mcode + code->mcodelength);)
392                         DISASSINSTR(pc);
393
394                 printf("\n");
395         }
396 #endif
397
398         LOCK_MONITOR_EXIT(show_global_lock);
399
400         /* finally flush the output */
401
402         fflush(stdout);
403 }
404 #endif /* !defined(NDEBUG) */
405
406
407 #if !defined(NDEBUG) && defined(ENABLE_INLINING)
408 static void show_inline_info(jitdata *jd, insinfo_inline *ii, s4 opcode, s4 stage)
409 {
410         s4 *jl;
411         s4 n;
412
413         printf("(pt %d+%d+%d st ", 
414                         ii->throughcount - (ii->stackvarscount - ii->paramcount),
415                         ii->stackvarscount - ii->paramcount,
416                         ii->paramcount);
417         show_variable_array(jd, ii->stackvars, ii->stackvarscount, stage);
418
419         if (opcode == ICMD_INLINE_START || opcode == ICMD_INLINE_END) {
420                 printf(" jl ");
421                 jl = (opcode == ICMD_INLINE_START) ? ii->javalocals_start : ii->javalocals_end;
422                 n = (opcode == ICMD_INLINE_START) ? ii->method->maxlocals : ii->outer->maxlocals;
423                 show_javalocals_array(jd, jl, n, stage);
424         }
425
426         printf(") ");
427
428 #if 0
429         printf("(");
430         method_print(ii->outer);
431         printf(" ==> ");
432 #endif
433
434         method_print(ii->method);
435 }
436 #endif /* !defined(NDEBUG) && defined(ENABLE_INLINING) */
437
438
439 /* show_basicblock *************************************************************
440
441    Print the intermediate representation of a basic block.
442
443    NOTE: Currently this function may only be called after register allocation!
444
445 *******************************************************************************/
446
447 #if !defined(NDEBUG)
448 void show_basicblock(jitdata *jd, basicblock *bptr, int stage)
449 {
450         codeinfo    *code;
451         codegendata *cd;
452         s4           i;
453         bool         deadcode;
454         instruction *iptr;
455         int          irstage;
456 #if defined(ENABLE_DISASSEMBLER)
457         methodinfo  *m;                     /* this is only a dummy               */
458         u1          *pc;
459         s4           linenumber;
460         s4           currentlinenumber;
461 #endif
462
463         /* get required compiler data */
464
465         code = jd->code;
466         cd   = jd->cd;
467
468         if (bptr->flags != BBDELETED) {
469 #if defined(ENABLE_INTRP)
470                 if (opt_intrp) {
471                         deadcode = false;
472                         irstage = SHOW_PARSE;
473                 }
474                 else
475 #endif
476                 {
477                         deadcode = (bptr->flags < BBREACHED);
478                         irstage = stage;
479                 }
480
481                 printf("======== %sL%03d ======== %s(flags: %d, bitflags: %01x, next: %d, type: ",
482 #if defined(ENABLE_REPLACEMENT)
483                                 (bptr->bitflags & BBFLAG_REPLACEMENT) ? "<REPLACE> " : 
484 #endif
485                                                                                                                 "",
486                            bptr->nr, 
487                            (deadcode && stage >= SHOW_STACK) ? "DEADCODE! " : "",
488                            bptr->flags, bptr->bitflags, 
489                            (bptr->next) ? (bptr->next->nr) : -1);
490
491                 switch (bptr->type) {
492                 case BBTYPE_STD:
493                         printf("STD");
494                         break;
495                 case BBTYPE_EXH:
496                         printf("EXH");
497                         break;
498                 case BBTYPE_SBR:
499                         printf("SBR");
500                         break;
501                 }
502
503                 printf(", icount: %d", bptr->icount);
504
505                 if (irstage >= SHOW_CFG) {
506                         printf(", preds: %d [ ", bptr->predecessorcount);
507
508                         for (i = 0; i < bptr->predecessorcount; i++)
509                                 printf("%d ", bptr->predecessors[i]->nr);
510
511                         printf("]");
512                 }
513
514                 printf("):");
515
516                 if (bptr->original)
517                         printf(" (clone of L%03d)", bptr->original->nr);
518                 else {
519                         basicblock *b = bptr->copied_to;
520                         if (b) {
521                                 printf(" (copied to ");
522                                 for (; b; b = b->copied_to)
523                                         printf("L%03d ", b->nr);
524                                 printf(")");
525                         }
526                 }
527
528                 printf("\n");
529
530                 if (irstage >= SHOW_STACK) {
531                         printf("IN:  ");
532                         show_variable_array(jd, bptr->invars, bptr->indepth, irstage);
533                         printf(" javalocals: ");
534                         show_javalocals_array(jd, bptr->javalocals, bptr->method->maxlocals, irstage);
535                         printf("\n");
536                 }
537
538 #if defined(ENABLE_INLINING)
539                 if (bptr->inlineinfo) {
540                         printf("inlineinfo: ");
541                         show_inline_info(jd, bptr->inlineinfo, -1, irstage);
542                         printf("\n");
543                 }
544 #endif /* defined(ENABLE_INLINING) */
545
546                 iptr = bptr->iinstr;
547
548                 for (i = 0; i < bptr->icount; i++, iptr++) {
549                         printf("%4d:%4d:  ", iptr->line, iptr->flags.bits >> INS_FLAG_ID_SHIFT);
550
551                         show_icmd(jd, iptr, deadcode, irstage);
552                         printf("\n");
553                 }
554
555                 if (irstage >= SHOW_STACK) {
556                         printf("OUT: ");
557                         show_variable_array(jd, bptr->outvars, bptr->outdepth, irstage);
558                         printf("\n");
559                 }
560
561 #if defined(ENABLE_DISASSEMBLER)
562                 if ((stage >= SHOW_CODE) && JITDATA_HAS_FLAG_SHOWDISASSEMBLE(jd) &&
563                         (!deadcode)) 
564                 {
565                         printf("\n");
566                         pc         = (u1 *) (code->mcode + cd->dseglen + bptr->mpc);
567                         linenumber = 0;
568
569                         if (bptr->next != NULL) {
570                                 for (; pc < (u1 *) (code->mcode + cd->dseglen + bptr->next->mpc);) {
571                                         currentlinenumber =
572                                                 dseg_get_linenumber_from_pc(&m, code->entrypoint, pc);
573
574                                         if (currentlinenumber != linenumber) {
575                                                 linenumber = currentlinenumber;
576                                                 printf("%4d:\n", linenumber);
577                                         }
578
579                                         DISASSINSTR(pc);
580                                 }
581                         }
582                         else {
583                                 for (; pc < (u1 *) (code->mcode + code->mcodelength);) {
584                                         currentlinenumber =
585                                                 dseg_get_linenumber_from_pc(&m, code->entrypoint, pc);
586
587                                         if (currentlinenumber != linenumber) {
588                                                 linenumber = currentlinenumber;
589                                                 printf("%4d:\n", linenumber);
590                                         }
591
592                                         DISASSINSTR(pc);
593                                 }
594                         }
595                         printf("\n");
596                 }
597 #endif
598         }
599 }
600 #endif /* !defined(NDEBUG) */
601
602
603 /* show_icmd *******************************************************************
604
605    Print the intermediate representation of an instruction.
606
607    NOTE: Currently this function may only be called after register allocation!
608
609 *******************************************************************************/
610
611 #if !defined(NDEBUG)
612
613 #define SHOW_TARGET(target)                                          \
614         if (stage >= SHOW_PARSE) {                                   \
615             printf("--> L%03d ", (target).block->nr);                \
616         }                                                            \
617         else {                                                       \
618             printf("--> insindex %d ", (target).insindex);           \
619         }
620
621 #define SHOW_INT_CONST(val)                                          \
622         if (stage >= SHOW_PARSE) {                                   \
623             printf("%d (0x%08x) ", (val), (val));                    \
624         }                                                            \
625         else {                                                       \
626             printf("iconst ");                                       \
627         }
628
629 #if SIZEOF_VOID_P == 4
630 #define SHOW_LNG_CONST(val)                                          \
631         if (stage >= SHOW_PARSE)                                     \
632             printf("%lld (0x%016llx) ", (val), (val));               \
633         else                                                         \
634             printf("lconst ");
635 #else
636 #define SHOW_LNG_CONST(val)                                          \
637         if (stage >= SHOW_PARSE)                                     \
638             printf("%ld (0x%016lx) ", (val), (val));                 \
639         else                                                         \
640             printf("lconst ");
641 #endif
642
643 #if SIZEOF_VOID_P == 4
644 #define SHOW_ADR_CONST(val)                                          \
645         if (stage >= SHOW_PARSE)                                     \
646             printf("0x%08x ", (ptrint) (val));                       \
647         else                                                         \
648             printf("aconst ");
649 #else
650 #define SHOW_ADR_CONST(val)                                          \
651         if (stage >= SHOW_PARSE)                                     \
652             printf("0x%016lx ", (ptrint) (val));                     \
653         else                                                         \
654             printf("aconst ");
655 #endif
656
657 #define SHOW_FLT_CONST(val)                                          \
658         if (stage >= SHOW_PARSE) {                                   \
659             imm_union v;                                             \
660             v.f = (val);                                             \
661             printf("%g (0x%08x) ", (val), v.i);                      \
662         }                                                            \
663         else {                                                       \
664             printf("fconst ");                                       \
665         }
666
667 #if SIZEOF_VOID_P == 4
668 #define SHOW_DBL_CONST(val)                                          \
669         if (stage >= SHOW_PARSE) {                                   \
670             imm_union v;                                             \
671             v.d = (val);                                             \
672             printf("%g (0x%016llx) ", (val), v.l);                   \
673         }                                                            \
674         else                                                         \
675             printf("dconst ");
676 #else
677 #define SHOW_DBL_CONST(val)                                          \
678         if (stage >= SHOW_PARSE) {                                   \
679             imm_union v;                                             \
680             v.d = (val);                                             \
681             printf("%g (0x%016lx) ", (val), v.l);                    \
682         }                                                            \
683         else                                                         \
684             printf("dconst ");
685 #endif
686
687 #define SHOW_INDEX(index)                                            \
688         if (stage >= SHOW_PARSE) {                                   \
689             printf("%d ", index);                                    \
690         }                                                            \
691         else {                                                       \
692             printf("index");                                         \
693         }
694
695 #define SHOW_STRING(val)                                             \
696         if (stage >= SHOW_PARSE) {                                   \
697             putchar('"');                                            \
698             utf_display_printable_ascii(                             \
699                javastring_toutf((java_handle_t *)(val), false));     \
700             printf("\" ");                                           \
701         }                                                            \
702         else {                                                       \
703             printf("string ");                                       \
704         }
705
706 #define SHOW_CLASSREF_OR_CLASSINFO(c)                                \
707         if (stage >= SHOW_PARSE) {                                   \
708             if (IS_CLASSREF(c))                                      \
709                 class_classref_print(c.ref);                         \
710             else                                                     \
711                 class_print(c.cls);                                  \
712             putchar(' ');                                            \
713         }                                                            \
714         else {                                                       \
715             printf("class ");                                        \
716         }
717
718 #define SHOW_FIELD(fmiref)                                           \
719         if (stage >= SHOW_PARSE) {                                   \
720             field_fieldref_print(fmiref);                            \
721             putchar(' ');                                            \
722         }                                                            \
723         else {                                                       \
724             printf("field ");                                        \
725         }
726
727 #define SHOW_VARIABLE(v)                                             \
728     show_variable(jd, (v), stage)
729
730 #define SHOW_S1(iptr)                                                \
731         if (stage >= SHOW_STACK) {                                   \
732             SHOW_VARIABLE(iptr->s1.varindex);                        \
733         }
734
735 #define SHOW_S2(iptr)                                                \
736         if (stage >= SHOW_STACK) {                                   \
737             SHOW_VARIABLE(iptr->sx.s23.s2.varindex);                 \
738         }
739
740 #define SHOW_S3(iptr)                                                \
741     if (stage >= SHOW_STACK) {                                       \
742         SHOW_VARIABLE(iptr->sx.s23.s3.varindex);                     \
743     }
744
745 #define SHOW_DST(iptr)                                               \
746     if (stage >= SHOW_STACK) {                                       \
747         printf("=> ");                                               \
748         SHOW_VARIABLE(iptr->dst.varindex);                           \
749     }
750
751 #define SHOW_S1_LOCAL(iptr)                                          \
752     if (stage >= SHOW_STACK) {                                       \
753         printf("L%d ", iptr->s1.varindex);                           \
754     }                                                                \
755     else {                                                           \
756         printf("JavaL%d ", iptr->s1.varindex);                       \
757     }
758
759 #define SHOW_DST_LOCAL(iptr)                                         \
760     if (stage >= SHOW_STACK) {                                       \
761         printf("=> L%d ", iptr->dst.varindex);                       \
762     }                                                                \
763     else {                                                           \
764         printf("=> JavaL%d ", iptr->dst.varindex);                   \
765     }
766
767 void show_allocation(s4 type, s4 flags, s4 regoff)
768 {
769         if (type == TYPE_RET) {
770                 printf("N/A");
771                 return;
772         }
773
774         if (flags & INMEMORY) {
775                 printf("M%02d", regoff);
776                 return;
777         }
778
779 #ifdef HAS_ADDRESS_REGISTER_FILE
780         if (type == TYPE_ADR) {
781                 printf("R%02d", regoff);
782                 return;
783         }
784 #endif
785
786         if (IS_FLT_DBL_TYPE(type)) {
787                 printf("F%02d", regoff);
788                 return;
789         }
790
791 #if defined(SUPPORT_COMBINE_INTEGER_REGISTERS)
792         if (IS_2_WORD_TYPE(type)) {
793 # if defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER)
794 #  if defined(ENABLE_INTRP)
795                 if (opt_intrp)
796                         printf("%3d/%3d", GET_LOW_REG(regoff),
797                                         GET_HIGH_REG(regoff));
798                 else
799 #  endif
800                         printf("%3s/%3s", abi_registers_integer_name[GET_LOW_REG(regoff)],
801                                    abi_registers_integer_name[GET_HIGH_REG(regoff)]);
802 # else
803                 printf("%3d/%3d", GET_LOW_REG(regoff),
804                            GET_HIGH_REG(regoff));
805 # endif
806                 return;
807         } 
808 #endif /* defined(SUPPORT_COMBINE_INTEGER_REGISTERS) */
809
810 #if defined(ENABLE_JIT) && defined(ENABLE_DISASSEMBLER)
811 # if defined(ENABLE_INTRP)
812         if (opt_intrp)
813                 printf("%3d", regoff);
814         else
815 # endif
816                 printf("%3s", abi_registers_integer_name[regoff]);
817 #else
818         printf("%3d", regoff);
819 #endif
820 }
821
822 void show_variable(jitdata *jd, s4 index, int stage)
823 {
824         show_variable_intern(jd, index, stage);
825         putchar(' ');
826 }
827
828 static void show_variable_intern(jitdata *jd, s4 index, int stage)
829 {
830         char type;
831         char kind;
832         varinfo *v;
833
834         if (index < 0 || index >= jd->vartop) {
835                 printf("<INVALID INDEX:%d>", index);
836                 return;
837         }
838
839         v = VAR(index);
840
841         switch (v->type) {
842                 case TYPE_INT: type = 'i'; break;
843                 case TYPE_LNG: type = 'l'; break;
844                 case TYPE_FLT: type = 'f'; break;
845                 case TYPE_DBL: type = 'd'; break;
846                 case TYPE_ADR: type = 'a'; break;
847                 case TYPE_RET: type = 'r'; break;
848                 default:       type = '?';
849         }
850
851         if (index < jd->localcount) {
852                 kind = 'L';
853                 if (v->flags & (PREALLOC | INOUT))
854                                 printf("<INVALID FLAGS!>");
855         }
856         else {
857                 if (v->flags & PREALLOC) {
858                         kind = 'A';
859                         if (v->flags & INOUT) {
860                                 /* PREALLOC is used to avoid allocation of TYPE_RET */
861                                 if (v->type == TYPE_RET)
862                                         kind = 'i';
863                                 else
864                                         printf("<INVALID FLAGS!>");
865                         }
866                 }
867                 else if (v->flags & INOUT)
868                         kind = 'I';
869                 else
870                         kind = 'T';
871         }
872
873         printf("%c%c%d", kind, type, index);
874
875         if (v->flags & SAVEDVAR)
876                 putchar('!');
877
878         if (stage >= SHOW_REGS || (v->flags & PREALLOC)) {
879                 putchar('(');
880                 show_allocation(v->type, v->flags, v->vv.regoff);
881                 putchar(')');
882         }
883
884         if (v->type == TYPE_RET && (v->flags & PREALLOC)) {
885                 printf("(L%03d)", v->vv.retaddr->nr);
886         }
887 }
888
889 static void show_variable_array_intern(jitdata *jd, s4 *vars, int n, int stage,
890                                                                            bool javalocals)
891 {
892         int i;
893         int nr;
894
895         if (vars == NULL) {
896                 printf("<null>");
897                 return;
898         }
899
900         printf("[");
901         for (i=0; i<n; ++i) {
902                 if (i)
903                         putchar(' ');
904                 if (vars[i] < 0) {
905                         if (vars[i] == UNUSED)
906                                 putchar('-');
907                         else if (javalocals) {
908                                 nr = RETADDR_FROM_JAVALOCAL(vars[i]);
909                                 printf("ret(L%03d)", nr);
910                         }
911                         else {
912                                 printf("<INVALID INDEX:%d>", vars[i]);
913                         }
914                 }
915                 else
916                         show_variable_intern(jd, vars[i], stage);
917         }
918         printf("]");
919 }
920
921 void show_variable_array(jitdata *jd, s4 *vars, int n, int stage)
922 {
923         show_variable_array_intern(jd, vars, n, stage, false);
924 }
925
926 void show_javalocals_array(jitdata *jd, s4 *vars, int n, int stage)
927 {
928         show_variable_array_intern(jd, vars, n, stage, true);
929 }
930
931 void show_icmd(jitdata *jd, instruction *iptr, bool deadcode, int stage)
932 {
933         u2                 opcode;
934         branch_target_t   *table;
935         lookup_target_t   *lookup;
936         constant_FMIref   *fmiref;
937         s4                *argp;
938         s4                 i;
939
940         /* get the opcode and the condition */
941
942         opcode    =  iptr->opc;
943
944         printf("%s ", icmd_table[opcode].name);
945
946         if (stage < SHOW_PARSE)
947                 return;
948
949         if (deadcode)
950                 stage = SHOW_PARSE;
951
952         /* Print the condition for conditional instructions. */
953
954         /* XXX print condition from flags */
955
956         if (iptr->flags.bits & INS_FLAG_UNRESOLVED)
957                 printf("(UNRESOLVED) ");
958
959         switch (opcode) {
960
961         case ICMD_POP:
962         case ICMD_CHECKNULL:
963                 SHOW_S1(iptr);
964                 break;
965
966                 /* unary */
967         case ICMD_ARRAYLENGTH:
968         case ICMD_INEG:
969         case ICMD_LNEG:
970         case ICMD_FNEG:
971         case ICMD_DNEG:
972         case ICMD_I2L:
973         case ICMD_I2F:
974         case ICMD_I2D:
975         case ICMD_L2I:
976         case ICMD_L2F:
977         case ICMD_L2D:
978         case ICMD_F2I:
979         case ICMD_F2L:
980         case ICMD_F2D:
981         case ICMD_D2I:
982         case ICMD_D2L:
983         case ICMD_D2F:
984         case ICMD_INT2BYTE:
985         case ICMD_INT2CHAR:
986         case ICMD_INT2SHORT:
987                 SHOW_S1(iptr);
988                 SHOW_DST(iptr);
989                 break;
990
991                 /* binary */
992         case ICMD_IADD:
993         case ICMD_LADD:
994         case ICMD_FADD:
995         case ICMD_DADD:
996         case ICMD_ISUB:
997         case ICMD_LSUB:
998         case ICMD_FSUB:
999         case ICMD_DSUB:
1000         case ICMD_IMUL:
1001         case ICMD_LMUL:
1002         case ICMD_FMUL:
1003         case ICMD_DMUL:
1004         case ICMD_IDIV:
1005         case ICMD_LDIV:
1006         case ICMD_FDIV:
1007         case ICMD_DDIV:
1008         case ICMD_IREM:
1009         case ICMD_LREM:
1010         case ICMD_FREM:
1011         case ICMD_DREM:
1012         case ICMD_ISHL:
1013         case ICMD_LSHL:
1014         case ICMD_ISHR:
1015         case ICMD_LSHR:
1016         case ICMD_IUSHR:
1017         case ICMD_LUSHR:
1018         case ICMD_IAND:
1019         case ICMD_LAND:
1020         case ICMD_IOR:
1021         case ICMD_LOR:
1022         case ICMD_IXOR:
1023         case ICMD_LXOR:
1024         case ICMD_LCMP:
1025         case ICMD_FCMPL:
1026         case ICMD_FCMPG:
1027         case ICMD_DCMPL:
1028         case ICMD_DCMPG:
1029                 SHOW_S1(iptr);
1030                 SHOW_S2(iptr);
1031                 SHOW_DST(iptr);
1032                 break;
1033
1034                 /* binary/const INT */
1035         case ICMD_IADDCONST:
1036         case ICMD_ISUBCONST:
1037         case ICMD_IMULCONST:
1038         case ICMD_IMULPOW2:
1039         case ICMD_IDIVPOW2:
1040         case ICMD_IREMPOW2:
1041         case ICMD_IANDCONST:
1042         case ICMD_IORCONST:
1043         case ICMD_IXORCONST:
1044         case ICMD_ISHLCONST:
1045         case ICMD_ISHRCONST:
1046         case ICMD_IUSHRCONST:
1047         case ICMD_LSHLCONST:
1048         case ICMD_LSHRCONST:
1049         case ICMD_LUSHRCONST:
1050                 SHOW_S1(iptr);
1051                 SHOW_INT_CONST(iptr->sx.val.i); 
1052                 SHOW_DST(iptr);
1053                 break;
1054
1055                 /* ?ASTORECONST (trinary/const INT) */
1056         case ICMD_IASTORECONST:
1057         case ICMD_BASTORECONST:
1058         case ICMD_CASTORECONST:
1059         case ICMD_SASTORECONST:
1060                 SHOW_S1(iptr);
1061                 SHOW_S2(iptr);
1062                 SHOW_INT_CONST(iptr->sx.s23.s3.constval);
1063                 break;
1064
1065                 /* const INT */
1066         case ICMD_ICONST:
1067                 SHOW_INT_CONST(iptr->sx.val.i); 
1068                 SHOW_DST(iptr);
1069                 break;
1070
1071                 /* binary/const LNG */
1072         case ICMD_LADDCONST:
1073         case ICMD_LSUBCONST:
1074         case ICMD_LMULCONST:
1075         case ICMD_LMULPOW2:
1076         case ICMD_LDIVPOW2:
1077         case ICMD_LREMPOW2:
1078         case ICMD_LANDCONST:
1079         case ICMD_LORCONST:
1080         case ICMD_LXORCONST:
1081                 SHOW_S1(iptr);
1082                 SHOW_LNG_CONST(iptr->sx.val.l);
1083                 SHOW_DST(iptr);
1084                 break;
1085
1086                 /* trinary/const LNG (<= pointer size) */
1087         case ICMD_LASTORECONST:
1088                 SHOW_S1(iptr);
1089                 SHOW_S2(iptr);
1090                 SHOW_ADR_CONST(iptr->sx.s23.s3.constval);
1091                 break;
1092
1093                 /* const LNG */
1094         case ICMD_LCONST:
1095                 SHOW_LNG_CONST(iptr->sx.val.l); 
1096                 SHOW_DST(iptr);
1097                 break;
1098
1099                 /* const FLT */
1100         case ICMD_FCONST:
1101                 SHOW_FLT_CONST(iptr->sx.val.f); 
1102                 SHOW_DST(iptr);
1103                 break;
1104
1105                 /* const DBL */
1106         case ICMD_DCONST:
1107                 SHOW_DBL_CONST(iptr->sx.val.d); 
1108                 SHOW_DST(iptr);
1109                 break;
1110
1111                 /* const ADR */
1112         case ICMD_ACONST:
1113                 if (iptr->flags.bits & INS_FLAG_CLASS) {
1114                         SHOW_ADR_CONST(iptr->sx.val.anyptr);
1115                         SHOW_CLASSREF_OR_CLASSINFO(iptr->sx.val.c);
1116                 }
1117                 else if (iptr->sx.val.anyptr == NULL) {
1118                         printf("NULL ");
1119                 }
1120                 else {
1121                         SHOW_ADR_CONST(iptr->sx.val.anyptr);
1122                         SHOW_STRING(iptr->sx.val.stringconst);
1123                 }
1124                 SHOW_DST(iptr);
1125                 break;
1126
1127         case ICMD_AASTORECONST:
1128                 SHOW_S1(iptr);
1129                 SHOW_S2(iptr);
1130                 printf("%p ", (void*) iptr->sx.s23.s3.constval);
1131                 break;
1132
1133         case ICMD_GETFIELD:        /* 1 -> 1 */
1134         case ICMD_PUTFIELD:        /* 2 -> 0 */
1135         case ICMD_PUTSTATIC:       /* 1 -> 0 */
1136         case ICMD_GETSTATIC:       /* 0 -> 1 */
1137         case ICMD_PUTSTATICCONST:  /* 0 -> 0 */
1138         case ICMD_PUTFIELDCONST:   /* 1 -> 0 */
1139                 if (opcode != ICMD_GETSTATIC && opcode != ICMD_PUTSTATICCONST) {
1140                         SHOW_S1(iptr);
1141                         if (opcode == ICMD_PUTFIELD) {
1142                                 SHOW_S2(iptr);
1143                         }
1144                 }
1145                 INSTRUCTION_GET_FIELDREF(iptr, fmiref);
1146                 SHOW_FIELD(fmiref);
1147
1148                 if (opcode == ICMD_GETSTATIC || opcode == ICMD_GETFIELD) {
1149                         SHOW_DST(iptr);
1150                 }
1151                 break;
1152
1153         case ICMD_IINC:
1154                 SHOW_S1_LOCAL(iptr);
1155                 SHOW_INT_CONST(iptr->sx.val.i);
1156                 SHOW_DST_LOCAL(iptr);
1157                 break;
1158
1159         case ICMD_IASTORE:
1160         case ICMD_SASTORE:
1161         case ICMD_BASTORE:
1162         case ICMD_CASTORE:
1163         case ICMD_LASTORE:
1164         case ICMD_DASTORE:
1165         case ICMD_FASTORE:
1166         case ICMD_AASTORE:
1167                 SHOW_S1(iptr);
1168                 SHOW_S2(iptr);
1169                 SHOW_S3(iptr);
1170                 break;
1171
1172         case ICMD_IALOAD:
1173         case ICMD_SALOAD:
1174         case ICMD_BALOAD:
1175         case ICMD_CALOAD:
1176         case ICMD_LALOAD:
1177         case ICMD_DALOAD:
1178         case ICMD_FALOAD:
1179         case ICMD_AALOAD:
1180                 SHOW_S1(iptr);
1181                 SHOW_S2(iptr);
1182                 SHOW_DST(iptr);
1183                 break;
1184
1185         case ICMD_RET:
1186                 SHOW_S1_LOCAL(iptr);
1187                 if (stage >= SHOW_STACK) {
1188                         printf(" ---> L%03d", iptr->dst.block->nr);
1189                 }
1190                 break;
1191
1192         case ICMD_ILOAD:
1193         case ICMD_LLOAD:
1194         case ICMD_FLOAD:
1195         case ICMD_DLOAD:
1196         case ICMD_ALOAD:
1197                 SHOW_S1_LOCAL(iptr);
1198                 SHOW_DST(iptr);
1199                 break;
1200
1201         case ICMD_ISTORE:
1202         case ICMD_LSTORE:
1203         case ICMD_FSTORE:
1204         case ICMD_DSTORE:
1205         case ICMD_ASTORE:
1206                 SHOW_S1(iptr);
1207                 SHOW_DST_LOCAL(iptr);
1208                 if (stage >= SHOW_STACK && iptr->sx.s23.s3.javaindex != UNUSED)
1209                         printf(" (javaindex %d)", iptr->sx.s23.s3.javaindex);
1210                 if (iptr->flags.bits & INS_FLAG_RETADDR) {
1211                         printf(" (retaddr L%03d)", RETADDR_FROM_JAVALOCAL(iptr->sx.s23.s2.retaddrnr));
1212                 }
1213                 break;
1214
1215         case ICMD_NEW:
1216                 SHOW_DST(iptr);
1217                 break;
1218
1219         case ICMD_NEWARRAY:
1220                 SHOW_DST(iptr);
1221                 break;
1222
1223         case ICMD_ANEWARRAY:
1224                 SHOW_DST(iptr);
1225                 break;
1226
1227         case ICMD_MULTIANEWARRAY:
1228                 if (stage >= SHOW_STACK) {
1229                         argp = iptr->sx.s23.s2.args;
1230                         i = iptr->s1.argcount;
1231                         while (i--) {
1232                                 SHOW_VARIABLE(*(argp++));
1233                         }
1234                 }
1235                 else {
1236                         printf("argcount=%d ", iptr->s1.argcount);
1237                 }
1238                 SHOW_DST(iptr);
1239                 break;
1240
1241         case ICMD_CHECKCAST:
1242                 SHOW_S1(iptr);
1243                 putchar(' ');
1244                 class_classref_or_classinfo_print(iptr->sx.s23.s3.c);
1245                 SHOW_DST(iptr);
1246                 break;
1247
1248         case ICMD_INSTANCEOF:
1249                 SHOW_S1(iptr);
1250                 SHOW_DST(iptr);
1251                 break;
1252
1253         case ICMD_INLINE_START:
1254         case ICMD_INLINE_END:
1255         case ICMD_INLINE_BODY:
1256 #if defined(ENABLE_INLINING)
1257                 {
1258                         insinfo_inline *ii = iptr->sx.s23.s3.inlineinfo;
1259                         show_inline_info(jd, ii, opcode, stage);
1260                 }
1261 #endif
1262                 break;
1263
1264         case ICMD_BUILTIN:
1265                 if (stage >= SHOW_STACK) {
1266                         argp = iptr->sx.s23.s2.args;
1267                         i = iptr->s1.argcount;
1268                         while (i--) {
1269                                 if ((iptr->s1.argcount - 1 - i) == iptr->sx.s23.s3.bte->md->paramcount)
1270                                         printf(" pass-through: ");
1271                                 SHOW_VARIABLE(*(argp++));
1272                         }
1273                 }
1274                 printf("%s ", iptr->sx.s23.s3.bte->cname);
1275                 if (iptr->sx.s23.s3.bte->md->returntype.type != TYPE_VOID) {
1276                         SHOW_DST(iptr);
1277                 }
1278                 break;
1279
1280         case ICMD_INVOKEVIRTUAL:
1281         case ICMD_INVOKESPECIAL:
1282         case ICMD_INVOKESTATIC:
1283         case ICMD_INVOKEINTERFACE:
1284                 if (stage >= SHOW_STACK) {
1285                         methoddesc *md;
1286                         INSTRUCTION_GET_METHODDESC(iptr, md);
1287                         argp = iptr->sx.s23.s2.args;
1288                         i = iptr->s1.argcount;
1289                         while (i--) {
1290                                 if ((iptr->s1.argcount - 1 - i) == md->paramcount)
1291                                         printf(" pass-through: ");
1292                                 SHOW_VARIABLE(*(argp++));
1293                         }
1294                 }
1295                 INSTRUCTION_GET_METHODREF(iptr, fmiref);
1296                 method_methodref_print(fmiref);
1297                 if (fmiref->parseddesc.md->returntype.type != TYPE_VOID) {
1298                         putchar(' ');
1299                         SHOW_DST(iptr);
1300                 }
1301                 break;
1302
1303         case ICMD_IFEQ:
1304         case ICMD_IFNE:
1305         case ICMD_IFLT:
1306         case ICMD_IFGE:
1307         case ICMD_IFGT:
1308         case ICMD_IFLE:
1309                 SHOW_S1(iptr);
1310                 SHOW_INT_CONST(iptr->sx.val.i); 
1311                 SHOW_TARGET(iptr->dst);
1312                 break;
1313
1314         case ICMD_IF_LEQ:
1315         case ICMD_IF_LNE:
1316         case ICMD_IF_LLT:
1317         case ICMD_IF_LGE:
1318         case ICMD_IF_LGT:
1319         case ICMD_IF_LLE:
1320                 SHOW_S1(iptr);
1321                 SHOW_LNG_CONST(iptr->sx.val.l); 
1322                 SHOW_TARGET(iptr->dst);
1323                 break;
1324
1325         case ICMD_GOTO:
1326                 SHOW_TARGET(iptr->dst);
1327                 break;
1328
1329         case ICMD_JSR:
1330                 SHOW_TARGET(iptr->sx.s23.s3.jsrtarget);
1331                 SHOW_DST(iptr);
1332                 break;
1333
1334         case ICMD_IFNULL:
1335         case ICMD_IFNONNULL:
1336                 SHOW_S1(iptr);
1337                 SHOW_TARGET(iptr->dst);
1338                 break;
1339
1340         case ICMD_IF_ICMPEQ:
1341         case ICMD_IF_ICMPNE:
1342         case ICMD_IF_ICMPLT:
1343         case ICMD_IF_ICMPGE:
1344         case ICMD_IF_ICMPGT:
1345         case ICMD_IF_ICMPLE:
1346
1347         case ICMD_IF_LCMPEQ:
1348         case ICMD_IF_LCMPNE:
1349         case ICMD_IF_LCMPLT:
1350         case ICMD_IF_LCMPGE:
1351         case ICMD_IF_LCMPGT:
1352         case ICMD_IF_LCMPLE:
1353
1354         case ICMD_IF_FCMPEQ:
1355         case ICMD_IF_FCMPNE:
1356
1357         case ICMD_IF_FCMPL_LT:
1358         case ICMD_IF_FCMPL_GE:
1359         case ICMD_IF_FCMPL_GT:
1360         case ICMD_IF_FCMPL_LE:
1361
1362         case ICMD_IF_FCMPG_LT:
1363         case ICMD_IF_FCMPG_GE:
1364         case ICMD_IF_FCMPG_GT:
1365         case ICMD_IF_FCMPG_LE:
1366
1367         case ICMD_IF_DCMPEQ:
1368         case ICMD_IF_DCMPNE:
1369
1370         case ICMD_IF_DCMPL_LT:
1371         case ICMD_IF_DCMPL_GE:
1372         case ICMD_IF_DCMPL_GT:
1373         case ICMD_IF_DCMPL_LE:
1374
1375         case ICMD_IF_DCMPG_LT:
1376         case ICMD_IF_DCMPG_GE:
1377         case ICMD_IF_DCMPG_GT:
1378         case ICMD_IF_DCMPG_LE:
1379
1380         case ICMD_IF_ACMPEQ:
1381         case ICMD_IF_ACMPNE:
1382                 SHOW_S1(iptr);
1383                 SHOW_S2(iptr);
1384                 SHOW_TARGET(iptr->dst);
1385                 break;
1386
1387         case ICMD_TABLESWITCH:
1388                 SHOW_S1(iptr);
1389                 table = iptr->dst.table;
1390
1391                 i = iptr->sx.s23.s3.tablehigh - iptr->sx.s23.s2.tablelow + 1;
1392
1393                 printf("high=%d low=%d count=%d\n", iptr->sx.s23.s3.tablehigh, iptr->sx.s23.s2.tablelow, i);
1394                 while (--i >= 0) {
1395                         printf("\t\t%d --> ", (int) (table - iptr->dst.table));
1396                         printf("L%03d\n", table->block->nr);
1397                         table++;
1398                 }
1399
1400                 break;
1401
1402         case ICMD_LOOKUPSWITCH:
1403                 SHOW_S1(iptr);
1404
1405                 printf("count=%d, default=L%03d\n",
1406                            iptr->sx.s23.s2.lookupcount,
1407                            iptr->sx.s23.s3.lookupdefault.block->nr);
1408
1409                 lookup = iptr->dst.lookup;
1410                 i = iptr->sx.s23.s2.lookupcount;
1411
1412                 while (--i >= 0) {
1413                         printf("\t\t%d --> L%03d\n",
1414                                    lookup->value,
1415                                    lookup->target.block->nr);
1416                         lookup++;
1417                 }
1418                 break;
1419
1420         case ICMD_FRETURN:
1421         case ICMD_IRETURN:
1422         case ICMD_DRETURN:
1423         case ICMD_LRETURN:
1424                 SHOW_S1(iptr);
1425                 break;
1426
1427         case ICMD_ARETURN:
1428         case ICMD_ATHROW:
1429                 SHOW_S1(iptr);
1430                 if (INSTRUCTION_IS_UNRESOLVED(iptr)) {
1431                         /* XXX this needs more work */
1432 #if 0
1433                         unresolved_class_debug_dump(iptr->sx.s23.s2.uc, stdout);
1434 #endif
1435                 }
1436                 break;
1437
1438         case ICMD_COPY:
1439         case ICMD_MOVE:
1440                 SHOW_S1(iptr);
1441                 SHOW_DST(iptr);
1442                 break;
1443         }
1444         fflush(stdout);
1445 }
1446 #endif /* !defined(NDEBUG) */
1447
1448 /* Debug output filtering */
1449
1450 #if defined(ENABLE_DEBUG_FILTER)
1451
1452 #if !defined(ENABLE_THREADS)
1453 u2 _no_threads_filterverbosecallctr[2] = { 0, 0 };
1454 #endif
1455
1456 struct show_filter {
1457         /* Boolean indicating if filter is enabled. */
1458         u1 enabled;
1459         /* Regular expression the method name is matched against */
1460         regex_t regex;
1461         /* Flag set on m->filtermatches if regex matches */
1462         u1 flag;
1463 };
1464
1465 typedef struct show_filter show_filter_t;
1466
1467 #define SHOW_FILTERS_SIZE 3
1468
1469 /* Array of filters applyed on a method */
1470 static struct show_filter show_filters[SHOW_FILTERS_SIZE];
1471
1472 static void show_filter_init(show_filter_t *cf, const char *str, u1 flag, u1 default_flag, const char *description) {
1473         int err;
1474         char err_buf[128];
1475
1476         if (str) {
1477                 err = regcomp(&cf->regex, str, REG_EXTENDED | REG_NOSUB);
1478                 if (err != 0) {
1479                         regerror(err, &cf->regex, err_buf, sizeof(err_buf));
1480                         vm_abort(
1481                                 "Invalid value given for %s: `%s' (%s).", 
1482                                 description, str, err_buf
1483                         );
1484                 }
1485                 cf->flag = flag;
1486                 cf->enabled = 1;
1487         } else {
1488                 cf->flag = default_flag;
1489                 cf->enabled = 0;
1490         }
1491 }
1492
1493 void show_filters_init(void) {
1494
1495         show_filter_init(
1496                 show_filters + 0,
1497                 opt_filter_verbosecall_include,
1498                 SHOW_FILTER_FLAG_VERBOSECALL_INCLUDE,
1499                 SHOW_FILTER_FLAG_VERBOSECALL_INCLUDE,
1500                 "verbose call include filter"
1501         );
1502
1503         show_filter_init(
1504                 show_filters + 1,
1505                 opt_filter_verbosecall_exclude,
1506                 SHOW_FILTER_FLAG_VERBOSECALL_EXCLUDE,
1507                 0,
1508                 "verbose call exclude filter"
1509         );
1510
1511         show_filter_init(
1512                 show_filters + 2,
1513                 opt_filter_show_method,
1514                 SHOW_FILTER_FLAG_SHOW_METHOD,
1515                 SHOW_FILTER_FLAG_SHOW_METHOD,
1516                 "show method filter"
1517         );
1518 }
1519
1520 /*
1521  
1522  (Pseudo)State machine:
1523
1524  States are INITIAL, INCLUDE1, INCLUDE2, ..., EXCLUDE1, ..., EXCLUDE2, ...
1525
1526                                                         Enter              Enter
1527  Enter                                                  Include            Include
1528  Exclude                                                  | |                | |
1529   | |    Enter              Enter              Enter      | |     Enter      | |
1530   | |    Include            Include            Exclude    | |     Exclude    | |
1531   | v   --------->        ---------->        ---------->  | v   ---------->  | v
1532 INITIAL           INCLUDE1           INCLUDE2           EXCLUDE1           EXCLUDE2
1533   | ^   <---------        <----------        <----------  | ^   <----------  | ^
1534   | |    Exit               Exit               Exit       | |     Exit       | |
1535   | |    Include            Include            Exclude    | |     Exclude    | |
1536   | |                                                     | |                | |
1537  Exit                                                    Exit               Exit
1538  Exclude                                                 Include            Include
1539
1540   Verbose call scope is active if we are in a INCLUDE state.
1541
1542   State encoding:
1543
1544   INITIAL: ctr[0] == 0, ctr[1] == 0
1545   INCLUDEN: ctr[1] == N, ctr[1] == 0
1546   EXCLUDEN: ctr[1] == N
1547 */
1548
1549 void show_filters_apply(methodinfo *m) {
1550         int i;
1551         int res;
1552         char *method_name;
1553         s4 len;
1554         s4 dumpsize;
1555
1556         /* compose full name of method */
1557
1558         len = 
1559                 utf_bytes(m->class->name) +
1560                 1 +
1561                 utf_bytes(m->name) +
1562                 utf_bytes(m->descriptor) +
1563                 1;
1564
1565         dumpsize = dump_size(); /* allocate memory */
1566
1567         method_name = DMNEW(char, len);
1568
1569         utf_cat_classname(method_name, m->class->name);
1570         strcat(method_name, ".");
1571         utf_cat(method_name, m->name);
1572         utf_cat(method_name, m->descriptor);
1573
1574         /* reset all flags */
1575
1576         m->filtermatches = 0;
1577
1578         for (i = 0; i < SHOW_FILTERS_SIZE; ++i) {
1579                 if (show_filters[i].enabled) {
1580
1581                         res = regexec(&show_filters[i].regex, method_name, 0, NULL, 0);
1582
1583                         if (res == 0) {
1584                                 m->filtermatches |= show_filters[i].flag;
1585                         }
1586                 } else {
1587                         /* Default is to show all */
1588                         m->filtermatches |= show_filters[i].flag;
1589                 }
1590         }
1591
1592         /* release memory */
1593
1594         dump_release(dumpsize); 
1595
1596 }
1597
1598 #define STATE_IS_INITIAL() ((FILTERVERBOSECALLCTR[0] == 0) && (FILTERVERBOSECALLCTR[1] == 0))
1599 #define STATE_IS_INCLUDE() ((FILTERVERBOSECALLCTR[0] > 0) && (FILTERVERBOSECALLCTR[1] == 0))
1600 #define STATE_IS_EXCLUDE() (FILTERVERBOSECALLCTR[1] > 0)
1601 #define EVENT_INCLUDE() (m->filtermatches & SHOW_FILTER_FLAG_VERBOSECALL_INCLUDE)
1602 #define EVENT_EXCLUDE() (m->filtermatches & SHOW_FILTER_FLAG_VERBOSECALL_EXCLUDE)
1603 #define TRANSITION_NEXT_INCLUDE() ++FILTERVERBOSECALLCTR[0]
1604 #define TRANSITION_PREV_INCLUDE() --FILTERVERBOSECALLCTR[0]
1605 #define TRANSITION_NEXT_EXCLUDE() ++FILTERVERBOSECALLCTR[1]
1606 #define TRANSITION_PREV_EXCLUDE() --FILTERVERBOSECALLCTR[1]
1607
1608 #if 0
1609 void dump_state() {
1610         if (STATE_IS_INITIAL()) printf("<INITIAL>\n");
1611         else if (STATE_IS_INCLUDE()) printf("<INCLUDE %hd>\n", FILTERVERBOSECALLCTR[0]);
1612         else if (STATE_IS_EXCLUDE()) printf("<EXCLUDE %hd>\n", FILTERVERBOSECALLCTR[1]);
1613 }
1614 #endif
1615
1616 int show_filters_test_verbosecall_enter(methodinfo *m) {
1617
1618         int force_show = 0;
1619
1620         if (STATE_IS_INITIAL()) {
1621                 if (EVENT_INCLUDE()) {
1622                         TRANSITION_NEXT_INCLUDE();
1623                 }
1624         } else if (STATE_IS_INCLUDE()) {
1625                 if (EVENT_EXCLUDE()) {
1626                         TRANSITION_NEXT_EXCLUDE();
1627                         /* just entered exclude, show this method */
1628                         force_show = 1;
1629                 } else if (EVENT_INCLUDE()) {
1630                         TRANSITION_NEXT_INCLUDE();
1631                 }
1632         } else if (STATE_IS_EXCLUDE()) {
1633                 if (EVENT_EXCLUDE()) {
1634                         TRANSITION_NEXT_EXCLUDE();
1635                 }
1636         }
1637
1638         return STATE_IS_INCLUDE() || force_show;
1639 }
1640
1641 int show_filters_test_verbosecall_exit(methodinfo *m) {
1642
1643         int force_show = 0;
1644
1645         if (m) {
1646                 if (STATE_IS_INCLUDE()) {
1647                         if (EVENT_INCLUDE()) {
1648                                 TRANSITION_PREV_INCLUDE();
1649                                 /* just entered initial, show this method */
1650                                 if (STATE_IS_INITIAL()) force_show = 1;
1651                         }
1652             } else if (STATE_IS_EXCLUDE()) {
1653                         if (EVENT_EXCLUDE()) {
1654                                 TRANSITION_PREV_EXCLUDE();
1655                         }
1656                 }
1657         }
1658
1659         return STATE_IS_INCLUDE() || force_show;
1660 }
1661
1662 #endif
1663
1664
1665 /*
1666  * These are local overrides for various environment variables in Emacs.
1667  * Please do not remove this and leave it at the end of the file, where
1668  * Emacs will automagically detect them.
1669  * ---------------------------------------------------------------------
1670  * Local variables:
1671  * mode: c
1672  * indent-tabs-mode: t
1673  * c-basic-offset: 4
1674  * tab-width: 4
1675  * End:
1676  * vim:noexpandtab:sw=4:ts=4:
1677  */