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