2 #include <mruby/irep.h>
3 #include <mruby/debug.h>
4 #include <mruby/opcode.h>
5 #include <mruby/string.h>
6 #include <mruby/proc.h>
7 #include <mruby/dump.h>
8 #include <mruby/internal.h>
12 print_r(mrb_state
*mrb
, const mrb_irep
*irep
, size_t n
, FILE *out
)
15 if (n
>= irep
->nlocals
) return;
16 if (!irep
->lv
[n
-1]) return;
17 fprintf(out
, " R%d:%s", (int)n
, mrb_sym_dump(mrb
, irep
->lv
[n
-1]));
21 print_lv_a(mrb_state
*mrb
, const mrb_irep
*irep
, uint16_t a
, FILE *out
)
23 if (!irep
->lv
|| a
>= irep
->nlocals
|| a
== 0) {
28 print_r(mrb
, irep
, a
, out
);
33 print_lv_ab(mrb_state
*mrb
, const mrb_irep
*irep
, uint16_t a
, uint16_t b
, FILE *out
)
35 if (!irep
->lv
|| (a
>= irep
->nlocals
&& b
>= irep
->nlocals
) || a
+b
== 0) {
40 if (a
> 0) print_r(mrb
, irep
, a
, out
);
41 if (b
> 0) print_r(mrb
, irep
, b
, out
);
46 print_header(mrb_state
*mrb
, const mrb_irep
*irep
, ptrdiff_t i
, FILE *out
)
50 mrb_assert(i
<= UINT32_MAX
);
51 line
= mrb_debug_get_line(mrb
, irep
, (uint32_t)i
);
56 fprintf(out
, "%5d ", line
);
59 fprintf(out
, "%03d ", (int)i
);
63 print_args(uint16_t i
, FILE *out
)
67 uint8_t nk
= (i
>>4)&0xf;
73 fprintf(out
, "n=%d", n
);
81 fprintf(out
, "nk=%d", nk
);
87 #define CASE(insn,ops) case insn: FETCH_ ## ops (); L_ ## insn
90 codedump(mrb_state
*mrb
, const mrb_irep
*irep
, FILE *out
)
92 const char *file
= NULL
;
95 fprintf(out
, "irep %p nregs=%d nlocals=%d pools=%d syms=%d reps=%d ilen=%d\n", (void*)irep
,
96 irep
->nregs
, irep
->nlocals
, (int)irep
->plen
, (int)irep
->slen
, (int)irep
->rlen
, (int)irep
->ilen
);
101 for (int i
= 1; i
< irep
->nlocals
; i
++) {
102 char const *s
= mrb_sym_dump(mrb
, irep
->lv
[i
- 1]);
106 fprintf(out
, "local variable names:\n");
108 fprintf(out
, " R%d:%s\n", i
, s
);
113 if (irep
->clen
> 0) {
114 const struct mrb_irep_catch_handler
*e
= mrb_irep_catch_handler_table(irep
);
116 for (int i
= irep
->clen
; i
> 0; i
--,e
++) {
117 uint32_t begin
= mrb_irep_catch_handler_unpack(e
->begin
);
118 uint32_t end
= mrb_irep_catch_handler_unpack(e
->end
);
119 uint32_t target
= mrb_irep_catch_handler_unpack(e
->target
);
124 case MRB_CATCH_RESCUE
:
127 case MRB_CATCH_ENSURE
:
132 snprintf(buf
, sizeof(buf
), "0x%02x <unknown>", (int)e
->type
);
136 fprintf(out
, "catch type: %-8s begin: %04" PRIu32
" end: %04" PRIu32
" target: %04" PRIu32
"\n", type
, begin
, end
, target
);
140 const mrb_code
*pc
= irep
->iseq
;
141 const mrb_code
*pcend
= pc
+ irep
->ilen
;
148 int ai
= mrb_gc_arena_save(mrb
);
149 ptrdiff_t i
= pc
- irep
->iseq
;
151 const char *next_file
= mrb_debug_get_filename(mrb
, irep
, (uint32_t)i
);
152 if (next_file
&& file
!= next_file
) {
153 fprintf(out
, "file: %s\n", next_file
);
156 print_header(mrb
, irep
, i
, out
);
160 fprintf(out
, "NOP\n");
163 fprintf(out
, "MOVE\t\tR%d\tR%d\t", a
, b
);
164 print_lv_ab(mrb
, irep
, a
, b
, out
);
168 switch (irep
->pool
[b
].tt
) {
171 fprintf(out
, "LOADL\t\tR%d\tL[%d]\t; %f", a
, b
, (double)irep
->pool
[b
].u
.f
);
175 fprintf(out
, "LOADL\t\tR%d\tL[%d]\t; %" PRId32
, a
, b
, irep
->pool
[b
].u
.i32
);
179 fprintf(out
, "LOADL\t\tR%d\tL[%d]\t; %" PRId64
, a
, b
, irep
->pool
[b
].u
.i64
);
183 fprintf(out
, "LOADL\t\tR%d\tL[%d]\t", a
, b
);
186 print_lv_a(mrb
, irep
, a
, out
);
189 fprintf(out
, "LOADI\t\tR%d\t%d\t", a
, b
);
190 print_lv_a(mrb
, irep
, a
, out
);
192 CASE(OP_LOADINEG
, BB
):
193 fprintf(out
, "LOADINEG\tR%d\t-%d\t", a
, b
);
194 print_lv_a(mrb
, irep
, a
, out
);
196 CASE(OP_LOADI16
, BS
):
197 fprintf(out
, "LOADI16\tR%d\t%d\t", a
, (int)(int16_t)b
);
198 print_lv_a(mrb
, irep
, a
, out
);
200 CASE(OP_LOADI32
, BSS
):
201 fprintf(out
, "LOADI32\tR%d\t%d\t", a
, (int32_t)(((uint32_t)b
<<16)+c
));
202 print_lv_a(mrb
, irep
, a
, out
);
204 CASE(OP_LOADI__1
, B
):
205 fprintf(out
, "LOADI__1\tR%d\t(-1)\t", a
);
206 print_lv_a(mrb
, irep
, a
, out
);
208 CASE(OP_LOADI_0
, B
): goto L_LOADI
;
209 CASE(OP_LOADI_1
, B
): goto L_LOADI
;
210 CASE(OP_LOADI_2
, B
): goto L_LOADI
;
211 CASE(OP_LOADI_3
, B
): goto L_LOADI
;
212 CASE(OP_LOADI_4
, B
): goto L_LOADI
;
213 CASE(OP_LOADI_5
, B
): goto L_LOADI
;
214 CASE(OP_LOADI_6
, B
): goto L_LOADI
;
217 b
= ins
-(int)OP_LOADI_0
;
218 fprintf(out
, "LOADI_%d\tR%d\t(%d)\t", b
, a
, b
);
219 print_lv_a(mrb
, irep
, a
, out
);
221 CASE(OP_LOADSYM
, BB
):
222 fprintf(out
, "LOADSYM\tR%d\t:%s\t", a
, mrb_sym_dump(mrb
, irep
->syms
[b
]));
223 print_lv_a(mrb
, irep
, a
, out
);
226 fprintf(out
, "LOADNIL\tR%d\t(nil)\t", a
);
227 print_lv_a(mrb
, irep
, a
, out
);
229 CASE(OP_LOADSELF
, B
):
230 fprintf(out
, "LOADSELF\tR%d\t(R0)\t", a
);
231 print_lv_a(mrb
, irep
, a
, out
);
234 fprintf(out
, "LOADT\t\tR%d\t(true)\t", a
);
235 print_lv_a(mrb
, irep
, a
, out
);
238 fprintf(out
, "LOADF\t\tR%d\t(false)\t", a
);
239 print_lv_a(mrb
, irep
, a
, out
);
242 fprintf(out
, "GETGV\t\tR%d\t%s\t", a
, mrb_sym_dump(mrb
, irep
->syms
[b
]));
243 print_lv_a(mrb
, irep
, a
, out
);
246 fprintf(out
, "SETGV\t\t%s\tR%d\t", mrb_sym_dump(mrb
, irep
->syms
[b
]), a
);
247 print_lv_a(mrb
, irep
, a
, out
);
250 fprintf(out
, "GETSV\t\tR%d\t%s\t", a
, mrb_sym_dump(mrb
, irep
->syms
[b
]));
251 print_lv_a(mrb
, irep
, a
, out
);
254 fprintf(out
, "SETSV\t\t%s\tR%d\t", mrb_sym_dump(mrb
, irep
->syms
[b
]), a
);
255 print_lv_a(mrb
, irep
, a
, out
);
257 CASE(OP_GETCONST
, BB
):
258 fprintf(out
, "GETCONST\tR%d\t%s\t", a
, mrb_sym_dump(mrb
, irep
->syms
[b
]));
259 print_lv_a(mrb
, irep
, a
, out
);
261 CASE(OP_SETCONST
, BB
):
262 fprintf(out
, "SETCONST\t%s\tR%d\t", mrb_sym_dump(mrb
, irep
->syms
[b
]), a
);
263 print_lv_a(mrb
, irep
, a
, out
);
265 CASE(OP_GETMCNST
, BB
):
266 fprintf(out
, "GETMCNST\tR%d\tR%d::%s\t", a
, a
, mrb_sym_dump(mrb
, irep
->syms
[b
]));
267 print_lv_a(mrb
, irep
, a
, out
);
269 CASE(OP_SETMCNST
, BB
):
270 fprintf(out
, "SETMCNST\tR%d::%s\tR%d\t", a
+1, mrb_sym_dump(mrb
, irep
->syms
[b
]), a
);
271 print_lv_a(mrb
, irep
, a
, out
);
274 fprintf(out
, "GETIV\t\tR%d\t%s\t", a
, mrb_sym_dump(mrb
, irep
->syms
[b
]));
275 print_lv_a(mrb
, irep
, a
, out
);
278 fprintf(out
, "SETIV\t\t%s\tR%d\t", mrb_sym_dump(mrb
, irep
->syms
[b
]), a
);
279 print_lv_a(mrb
, irep
, a
, out
);
281 CASE(OP_GETUPVAR
, BBB
):
282 fprintf(out
, "GETUPVAR\tR%d\t%d\t%d\t", a
, b
, c
);
283 print_lv_a(mrb
, irep
, a
, out
);
285 CASE(OP_SETUPVAR
, BBB
):
286 fprintf(out
, "SETUPVAR\tR%d\t%d\t%d\t", a
, b
, c
);
287 print_lv_a(mrb
, irep
, a
, out
);
290 fprintf(out
, "GETCV\t\tR%d\t%s\t", a
, mrb_sym_dump(mrb
, irep
->syms
[b
]));
291 print_lv_a(mrb
, irep
, a
, out
);
294 fprintf(out
, "SETCV\t\t%s\tR%d\t", mrb_sym_dump(mrb
, irep
->syms
[b
]), a
);
295 print_lv_a(mrb
, irep
, a
, out
);
298 fprintf(out
, "GETIDX\tR%d\tR%d\n", a
, a
+1);
301 fprintf(out
, "SETIDX\tR%d\tR%d\tR%d\n", a
, a
+1, a
+2);
305 fprintf(out
, "JMP\t\t%03d\n", (int)i
+(int16_t)a
);
309 fprintf(out
, "JMPUW\t\t%03d\n", (int)i
+(int16_t)a
);
313 fprintf(out
, "JMPIF\t\tR%d\t%03d\t", a
, (int)i
+(int16_t)b
);
314 print_lv_a(mrb
, irep
, a
, out
);
318 fprintf(out
, "JMPNOT\tR%d\t%03d\t", a
, (int)i
+(int16_t)b
);
319 print_lv_a(mrb
, irep
, a
, out
);
323 fprintf(out
, "JMPNIL\tR%d\t%03d\t", a
, (int)i
+(int16_t)b
);
324 print_lv_a(mrb
, irep
, a
, out
);
327 fprintf(out
, "SSEND\t\tR%d\t:%s\t", a
, mrb_sym_dump(mrb
, irep
->syms
[b
]));
330 CASE(OP_SSENDB
, BBB
):
331 fprintf(out
, "SSENDB\tR%d\t:%s\t", a
, mrb_sym_dump(mrb
, irep
->syms
[b
]));
335 fprintf(out
, "SEND\t\tR%d\t:%s\t", a
, mrb_sym_dump(mrb
, irep
->syms
[b
]));
339 fprintf(out
, "SENDB\t\tR%d\t:%s\t", a
, mrb_sym_dump(mrb
, irep
->syms
[b
]));
343 fprintf(out
, "CALL\n");
346 fprintf(out
, "SUPER\t\tR%d\t", a
);
350 fprintf(out
, "ARGARY\tR%d\t%d:%d:%d:%d (%d)\t", a
,
356 print_lv_a(mrb
, irep
, a
, out
);
359 fprintf(out
, "ENTER\t\t%d:%d:%d:%d:%d:%d:%d (0x%x)\n",
366 MRB_ASPEC_BLOCK(a
), a
);
369 fprintf(out
, "KEY_P\t\tR%d\t:%s\t", a
, mrb_sym_dump(mrb
, irep
->syms
[b
]));
370 print_lv_a(mrb
, irep
, a
, out
);
373 fprintf(out
, "KEYEND\n");
376 fprintf(out
, "KARG\t\tR%d\t:%s\t", a
, mrb_sym_dump(mrb
, irep
->syms
[b
]));
377 print_lv_a(mrb
, irep
, a
, out
);
380 fprintf(out
, "RETURN\tR%d\t\t", a
);
381 print_lv_a(mrb
, irep
, a
, out
);
383 CASE(OP_RETURN_BLK
, B
):
384 fprintf(out
, "RETURN_BLK\tR%d\t\t", a
);
385 print_lv_a(mrb
, irep
, a
, out
);
388 fprintf(out
, "BREAK\t\tR%d\t\t", a
);
389 print_lv_a(mrb
, irep
, a
, out
);
391 CASE(OP_BLKPUSH
, BS
):
392 fprintf(out
, "BLKPUSH\tR%d\t%d:%d:%d:%d (%d)\t", a
,
398 print_lv_a(mrb
, irep
, a
, out
);
401 fprintf(out
, "LAMBDA\tR%d\tI[%d]\n", a
, b
);
404 fprintf(out
, "BLOCK\t\tR%d\tI[%d]\n", a
, b
);
407 fprintf(out
, "METHOD\tR%d\tI[%d]\n", a
, b
);
409 CASE(OP_RANGE_INC
, B
):
410 fprintf(out
, "RANGE_INC\tR%d\n", a
);
412 CASE(OP_RANGE_EXC
, B
):
413 fprintf(out
, "RANGE_EXC\tR%d\n", a
);
416 fprintf(out
, "DEF\t\tR%d\t:%s\n", a
, mrb_sym_dump(mrb
, irep
->syms
[b
]));
419 fprintf(out
, "UNDEF\t\t:%s\n", mrb_sym_dump(mrb
, irep
->syms
[a
]));
422 fprintf(out
, "ALIAS\t\t:%s\t%s\n", mrb_sym_dump(mrb
, irep
->syms
[a
]), mrb_sym_dump(mrb
, irep
->syms
[b
]));
425 fprintf(out
, "ADD\t\tR%d\tR%d\n", a
, a
+1);
428 fprintf(out
, "ADDI\t\tR%d\t%d\t", a
, b
);
429 print_lv_a(mrb
, irep
, a
, out
);
432 fprintf(out
, "SUB\t\tR%d\tR%d\n", a
, a
+1);
435 fprintf(out
, "SUBI\t\tR%d\t%d\t", a
, b
);
436 print_lv_a(mrb
, irep
, a
, out
);
439 fprintf(out
, "MUL\t\tR%d\tR%d\n", a
, a
+1);
442 fprintf(out
, "DIV\t\tR%d\tR%d\n", a
, a
+1);
445 fprintf(out
, "LT\t\tR%d\tR%d\n", a
, a
+1);
448 fprintf(out
, "LE\t\tR%d\tR%d\n", a
, a
+1);
451 fprintf(out
, "GT\t\tR%d\tR%d\n", a
, a
+1);
454 fprintf(out
, "GE\t\tR%d\tR%d\n", a
, a
+1);
457 fprintf(out
, "EQ\t\tR%d\tR%d\n", a
, a
+1);
460 fprintf(out
, "ARRAY\t\tR%d\tR%d\t%d", a
, a
, b
);
461 print_lv_a(mrb
, irep
, a
, out
);
463 CASE(OP_ARRAY2
, BBB
):
464 fprintf(out
, "ARRAY\t\tR%d\tR%d\t%d", a
, b
, c
);
465 print_lv_ab(mrb
, irep
, a
, b
, out
);
468 fprintf(out
, "ARYCAT\tR%d\tR%d\t", a
, a
+1);
469 print_lv_a(mrb
, irep
, a
, out
);
471 CASE(OP_ARYPUSH
, BB
):
472 fprintf(out
, "ARYPUSH\tR%d\t%d\t", a
, b
);
473 print_lv_a(mrb
, irep
, a
, out
);
475 CASE(OP_ARYSPLAT
, B
):
476 fprintf(out
, "ARYSPLAT\tR%d\t", a
);
477 print_lv_a(mrb
, irep
, a
, out
);
480 fprintf(out
, "AREF\t\tR%d\tR%d\t%d", a
, b
, c
);
481 print_lv_ab(mrb
, irep
, a
, b
, out
);
484 fprintf(out
, "ASET\t\tR%d\tR%d\t%d", a
, b
, c
);
485 print_lv_ab(mrb
, irep
, a
, b
, out
);
488 fprintf(out
, "APOST\t\tR%d\t%d\t%d", a
, b
, c
);
489 print_lv_a(mrb
, irep
, a
, out
);
492 fprintf(out
, "INTERN\tR%d\t\t", a
);
493 print_lv_a(mrb
, irep
, a
, out
);
496 mrb_assert((irep
->pool
[b
].tt
&IREP_TT_NFLAG
)==0);
497 fprintf(out
, "SYMBOL\tR%d\tL[%d]\t; %s", a
, b
, irep
->pool
[b
].u
.str
);
498 print_lv_a(mrb
, irep
, a
, out
);
501 mrb_assert((irep
->pool
[b
].tt
&IREP_TT_NFLAG
)==0);
502 fprintf(out
, "STRING\tR%d\tL[%d]\t; %s", a
, b
, irep
->pool
[b
].u
.str
);
503 print_lv_a(mrb
, irep
, a
, out
);
506 fprintf(out
, "STRCAT\tR%d\tR%d\t", a
, a
+1);
507 print_lv_a(mrb
, irep
, a
, out
);
510 fprintf(out
, "HASH\t\tR%d\t%d\t", a
, b
);
511 print_lv_a(mrb
, irep
, a
, out
);
513 CASE(OP_HASHADD
, BB
):
514 fprintf(out
, "HASHADD\tR%d\t%d\t", a
, b
);
515 print_lv_a(mrb
, irep
, a
, out
);
518 fprintf(out
, "HASHCAT\tR%d\tR%d\t", a
, a
+1);
519 print_lv_a(mrb
, irep
, a
, out
);
523 fprintf(out
, "OCLASS\tR%d\t\t", a
);
524 print_lv_a(mrb
, irep
, a
, out
);
527 fprintf(out
, "CLASS\t\tR%d\t:%s", a
, mrb_sym_dump(mrb
, irep
->syms
[b
]));
528 print_lv_a(mrb
, irep
, a
, out
);
531 fprintf(out
, "MODULE\tR%d\t:%s", a
, mrb_sym_dump(mrb
, irep
->syms
[b
]));
532 print_lv_a(mrb
, irep
, a
, out
);
535 fprintf(out
, "EXEC\t\tR%d\tI[%d]", a
, b
);
536 print_lv_a(mrb
, irep
, a
, out
);
539 fprintf(out
, "SCLASS\tR%d\t", a
);
540 print_lv_a(mrb
, irep
, a
, out
);
543 fprintf(out
, "TCLASS\tR%d\t\t", a
);
544 print_lv_a(mrb
, irep
, a
, out
);
547 if ((irep
->pool
[a
].tt
& IREP_TT_NFLAG
) == 0) {
548 fprintf(out
, "ERR\t\t%s\n", irep
->pool
[a
].u
.str
);
551 fprintf(out
, "ERR\tL[%d]\n", a
);
555 fprintf(out
, "EXCEPT\tR%d\t\t", a
);
556 print_lv_a(mrb
, irep
, a
, out
);
559 fprintf(out
, "RESCUE\tR%d\tR%d", a
, b
);
560 print_lv_ab(mrb
, irep
, a
, b
, out
);
563 fprintf(out
, "RAISEIF\tR%d\t\t", a
);
564 print_lv_a(mrb
, irep
, a
, out
);
568 fprintf(out
, "DEBUG\t\t%d\t%d\t%d\n", a
, b
, c
);
572 fprintf(out
, "STOP\n");
576 fprintf(out
, "EXT1\n");
577 print_header(mrb
, irep
, pc
-irep
->iseq
, out
);
580 #define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _1 (); goto L_OP_ ## i;
581 #include <mruby/ops.h>
586 fprintf(out
, "EXT2\n");
587 print_header(mrb
, irep
, pc
-irep
->iseq
, out
);
590 #define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _2 (); goto L_OP_ ## i;
591 #include <mruby/ops.h>
596 fprintf(out
, "EXT3\n");
597 print_header(mrb
, irep
, pc
-irep
->iseq
, out
);
600 #define OPCODE(i,x) case OP_ ## i: FETCH_ ## x ## _3 (); goto L_OP_ ## i;
601 #include <mruby/ops.h>
607 fprintf(out
, "unknown_op (0x%x)\n", ins
);
610 mrb_gc_arena_restore(mrb
, ai
);
616 codedump_recur(mrb_state
*mrb
, const mrb_irep
*irep
, FILE *out
)
618 codedump(mrb
, irep
, out
);
620 for (int i
=0; i
<irep
->rlen
; i
++) {
621 codedump_recur(mrb
, irep
->reps
[i
], out
);
627 mrb_codedump_all_file(mrb_state
*mrb
, struct RProc
*proc
, FILE *out
)
629 codedump_recur(mrb
, proc
->body
.irep
, out
);
636 mrb_codedump_all(mrb_state
*mrb
, struct RProc
*proc
)
639 mrb_codedump_all_file(mrb
, proc
, stdout
);