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