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