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