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