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