2 ** dump.c - mruby binary dumper (mrbc binary format)
4 ** See Copyright Notice in mruby.h
8 #include <mruby/dump.h>
9 #include <mruby/string.h>
10 #include <mruby/irep.h>
11 #include <mruby/debug.h>
15 #include <mruby/endian.h>
18 static size_t get_irep_record_size_1(mrb_state
*mrb
, const mrb_irep
*irep
);
20 #if UINT32_MAX > SIZE_MAX
21 # error This code cannot be built on your environment.
25 get_irep_header_size(mrb_state
*mrb
)
29 size
+= sizeof(uint32_t) * 1;
30 size
+= sizeof(uint16_t) * 3;
36 write_irep_header(mrb_state
*mrb
, const mrb_irep
*irep
, uint8_t *buf
)
40 cur
+= uint32_to_bin((uint32_t)get_irep_record_size_1(mrb
, irep
), cur
); /* record size */
41 cur
+= uint16_to_bin((uint16_t)irep
->nlocals
, cur
); /* number of local variable */
42 cur
+= uint16_to_bin((uint16_t)irep
->nregs
, cur
); /* number of register variable */
43 cur
+= uint16_to_bin((uint16_t)irep
->rlen
, cur
); /* number of child irep */
49 get_iseq_block_size(mrb_state
*mrb
, const mrb_irep
*irep
)
53 size
+= sizeof(uint16_t); /* clen */
54 size
+= sizeof(uint32_t); /* ilen */
55 size
+= irep
->ilen
* sizeof(mrb_code
); /* iseq(n) */
56 size
+= irep
->clen
* sizeof(struct mrb_irep_catch_handler
);
62 write_iseq_block(mrb_state
*mrb
, const mrb_irep
*irep
, uint8_t *buf
, uint8_t flags
)
65 size_t seqlen
= irep
->ilen
* sizeof(mrb_code
) +
66 irep
->clen
* sizeof(struct mrb_irep_catch_handler
);
68 cur
+= uint16_to_bin(irep
->clen
, cur
); /* number of catch handlers */
69 cur
+= uint32_to_bin(irep
->ilen
, cur
); /* number of opcode */
70 memcpy(cur
, irep
->iseq
, seqlen
);
78 dump_float(mrb_state
*mrb
, uint8_t *buf
, mrb_float f
)
80 /* dump IEEE754 binary in little endian */
83 char s
[sizeof(double)];
84 } u
= {.f
= (double)f
};
87 memcpy(buf
, u
.s
, sizeof(double));
90 for (size_t i
=0; i
<sizeof(double); i
++) {
91 buf
[i
] = u
.s
[sizeof(double)-i
-1];
98 get_pool_block_size(mrb_state
*mrb
, const mrb_irep
*irep
)
100 size_t size
= sizeof(uint16_t); /* plen */
101 size
+= irep
->plen
* sizeof(uint8_t); /* len(n) */
103 for (int pool_no
= 0; pool_no
< irep
->plen
; pool_no
++) {
104 int ai
= mrb_gc_arena_save(mrb
);
106 switch (irep
->pool
[pool_no
].tt
) {
108 #if defined(MRB_64BIT) || defined(MRB_INT64)
110 int64_t i
= irep
->pool
[pool_no
].u
.i64
;
112 if (i
< INT32_MIN
|| INT32_MAX
< i
)
122 size
+= 4; /* 32bits = 4bytes */
127 mrb_int len
= irep
->pool
[pool_no
].u
.str
[0];
128 mrb_assert_int_fit(mrb_int
, len
, size_t, SIZE_MAX
);
129 size
+= (size_t)len
+2;
136 size
+= sizeof(double);
141 default: /* packed IREP_TT_STRING */
143 mrb_int len
= irep
->pool
[pool_no
].tt
>> 2; /* unpack length */
144 mrb_assert_int_fit(mrb_int
, len
, size_t, SIZE_MAX
);
145 size
+= sizeof(uint16_t);
146 size
+= (size_t)len
+1;
150 mrb_gc_arena_restore(mrb
, ai
);
157 write_pool_block(mrb_state
*mrb
, const mrb_irep
*irep
, uint8_t *buf
)
163 cur
+= uint16_to_bin(irep
->plen
, cur
); /* number of pool */
165 for (int pool_no
= 0; pool_no
< irep
->plen
; pool_no
++) {
166 int ai
= mrb_gc_arena_save(mrb
);
168 switch (irep
->pool
[pool_no
].tt
) {
170 #if defined(MRB_64BIT) || defined(MRB_INT64)
172 int64_t i
= irep
->pool
[pool_no
].u
.i64
;
173 if (i
< INT32_MIN
|| INT32_MAX
< i
) {
174 cur
+= uint8_to_bin(IREP_TT_INT64
, cur
); /* data type */
175 cur
+= uint32_to_bin((uint32_t)((i
>>32) & 0xffffffff), cur
); /* i64 hi */
176 cur
+= uint32_to_bin((uint32_t)((i
) & 0xffffffff), cur
); /* i64 lo */
179 cur
+= uint8_to_bin(IREP_TT_INT32
, cur
); /* data type */
180 cur
+= uint32_to_bin(irep
->pool
[pool_no
].u
.i32
, cur
); /* i32 */
186 cur
+= uint8_to_bin(IREP_TT_INT32
, cur
); /* data type */
187 cur
+= uint32_to_bin(irep
->pool
[pool_no
].u
.i32
, cur
); /* i32 */
191 cur
+= uint8_to_bin(IREP_TT_BIGINT
, cur
); /* data type */
192 len
= irep
->pool
[pool_no
].u
.str
[0];
193 memcpy(cur
, irep
->pool
[pool_no
].u
.str
, (size_t)len
+2);
198 cur
+= uint8_to_bin(IREP_TT_FLOAT
, cur
); /* data type */
201 dump_float(mrb
, cur
,irep
->pool
[pool_no
].u
.f
);
202 cur
+= sizeof(double);
205 cur
+= uint16_to_bin(0, cur
); /* zero length */
209 default: /* string */
210 cur
+= uint8_to_bin(IREP_TT_STR
, cur
); /* data type */
211 ptr
= irep
->pool
[pool_no
].u
.str
;
212 len
= irep
->pool
[pool_no
].tt
>>2;
213 mrb_assert_int_fit(mrb_int
, len
, uint16_t, UINT16_MAX
);
214 cur
+= uint16_to_bin((uint16_t)len
, cur
); /* data length */
215 memcpy(cur
, ptr
, (size_t)len
);
220 mrb_gc_arena_restore(mrb
, ai
);
227 get_syms_block_size(mrb_state
*mrb
, const mrb_irep
*irep
)
233 size
+= sizeof(uint16_t); /* slen */
234 for (sym_no
= 0; sym_no
< irep
->slen
; sym_no
++) {
235 size
+= sizeof(uint16_t); /* snl(n) */
236 if (irep
->syms
[sym_no
] != 0) {
237 mrb_sym_name_len(mrb
, irep
->syms
[sym_no
], &len
);
238 size
+= len
+ 1; /* sn(n) + null char */
246 write_syms_block(mrb_state
*mrb
, const mrb_irep
*irep
, uint8_t *buf
)
250 cur
+= uint16_to_bin(irep
->slen
, cur
); /* number of symbol */
252 for (int sym_no
= 0; sym_no
< irep
->slen
; sym_no
++) {
253 if (irep
->syms
[sym_no
] != 0) {
255 const char *name
= mrb_sym_name_len(mrb
, irep
->syms
[sym_no
], &len
);
257 mrb_assert_int_fit(mrb_int
, len
, uint16_t, UINT16_MAX
);
258 cur
+= uint16_to_bin((uint16_t)len
, cur
); /* length of symbol name */
259 memcpy(cur
, name
, len
); /* symbol name */
260 cur
+= (uint16_t)len
;
264 cur
+= uint16_to_bin(MRB_DUMP_NULL_SYM_LEN
, cur
); /* length of symbol name */
272 get_irep_record_size_1(mrb_state
*mrb
, const mrb_irep
*irep
)
274 size_t size
= get_irep_header_size(mrb
);
275 size
+= get_iseq_block_size(mrb
, irep
);
276 size
+= get_pool_block_size(mrb
, irep
);
277 size
+= get_syms_block_size(mrb
, irep
);
282 get_irep_record_size(mrb_state
*mrb
, const mrb_irep
*irep
)
284 size_t size
= get_irep_record_size_1(mrb
, irep
);
286 for (int irep_no
= 0; irep_no
< irep
->rlen
; irep_no
++) {
287 size
+= get_irep_record_size(mrb
, irep
->reps
[irep_no
]);
293 write_irep_record(mrb_state
*mrb
, const mrb_irep
*irep
, uint8_t *bin
, size_t *irep_record_size
, uint8_t flags
)
298 return MRB_DUMP_INVALID_IREP
;
301 bin
+= write_irep_header(mrb
, irep
, bin
);
302 bin
+= write_iseq_block(mrb
, irep
, bin
, flags
);
303 bin
+= write_pool_block(mrb
, irep
, bin
);
304 bin
+= write_syms_block(mrb
, irep
, bin
);
306 for (int i
= 0; i
< irep
->rlen
; i
++) {
310 result
= write_irep_record(mrb
, irep
->reps
[i
], bin
, &rsize
, flags
);
311 if (result
!= MRB_DUMP_OK
) {
316 *irep_record_size
= bin
- src
;
321 write_footer(mrb_state
*mrb
, uint8_t *bin
)
323 struct rite_binary_footer footer
;
325 memcpy(footer
.section_ident
, RITE_BINARY_EOF
, sizeof(footer
.section_ident
));
326 uint32_to_bin(sizeof(struct rite_binary_footer
), footer
.section_size
);
327 memcpy(bin
, &footer
, sizeof(struct rite_binary_footer
));
329 return sizeof(struct rite_binary_footer
);
334 write_section_irep_header(mrb_state
*mrb
, size_t section_size
, uint8_t *bin
)
336 struct rite_section_irep_header
*header
= (struct rite_section_irep_header
*)bin
;
338 memcpy(header
->section_ident
, RITE_SECTION_IREP_IDENT
, sizeof(header
->section_ident
));
340 mrb_assert_int_fit(size_t, section_size
, uint32_t, UINT32_MAX
);
341 uint32_to_bin((uint32_t)section_size
, header
->section_size
);
342 memcpy(header
->rite_version
, RITE_VM_VER
, sizeof(header
->rite_version
));
348 write_section_irep(mrb_state
*mrb
, const mrb_irep
*irep
, uint8_t *bin
, size_t *len_p
, uint8_t flags
)
352 if (mrb
== NULL
|| bin
== NULL
) {
353 return MRB_DUMP_INVALID_ARGUMENT
;
356 cur
+= sizeof(struct rite_section_irep_header
);
359 int result
= write_irep_record(mrb
, irep
, cur
, &rsize
, flags
);
360 if (result
!= MRB_DUMP_OK
) {
363 mrb_assert(rsize
== get_irep_record_size(mrb
, irep
));
364 *len_p
= cur
- bin
+ rsize
;
365 write_section_irep_header(mrb
, *len_p
, bin
);
371 get_debug_record_size(mrb_state
*mrb
, const mrb_irep
*irep
)
373 size_t ret
= sizeof(uint32_t); /* record size */
374 ret
+= sizeof(uint16_t); /* file count */
376 for (uint16_t f_idx
= 0; f_idx
< irep
->debug_info
->flen
; ++f_idx
) {
377 mrb_irep_debug_info_file
const* file
= irep
->debug_info
->files
[f_idx
];
379 ret
+= sizeof(uint32_t); /* position */
380 ret
+= sizeof(uint16_t); /* filename index */
383 ret
+= sizeof(uint32_t); /* entry count */
384 ret
+= sizeof(uint8_t); /* line type */
385 switch (file
->line_type
) {
386 case mrb_debug_line_ary
:
387 ret
+= sizeof(uint16_t) * (size_t)(file
->line_entry_count
);
390 case mrb_debug_line_flat_map
:
391 ret
+= (sizeof(uint32_t) + sizeof(uint16_t)) * (size_t)(file
->line_entry_count
);
394 case mrb_debug_line_packed_map
:
395 ret
+= (size_t)(file
->line_entry_count
);
398 default: mrb_assert(0); break;
401 for (int i
=0; i
<irep
->rlen
; i
++) {
402 ret
+= get_debug_record_size(mrb
, irep
->reps
[i
]);
409 find_filename_index(const mrb_sym
*ary
, int ary_len
, mrb_sym s
)
411 for (int i
= 0; i
< ary_len
; i
++) {
412 if (ary
[i
] == s
) { return i
; }
418 get_filename_table_size(mrb_state
*mrb
, const mrb_irep
*irep
, mrb_sym
**fp
, uint16_t *lp
)
420 mrb_sym
*filenames
= *fp
;
422 const mrb_irep_debug_info
*di
= irep
->debug_info
;
425 for (int i
= 0; i
< di
->flen
; i
++) {
426 mrb_irep_debug_info_file
*file
;
427 mrb_int filename_len
;
430 if (find_filename_index(filenames
, *lp
, file
->filename_sym
) == -1) {
431 /* register filename */
433 *fp
= filenames
= (mrb_sym
*)mrb_realloc(mrb
, filenames
, sizeof(mrb_sym
) * (*lp
));
434 filenames
[*lp
- 1] = file
->filename_sym
;
437 mrb_sym_name_len(mrb
, file
->filename_sym
, &filename_len
);
438 size
+= sizeof(uint16_t) + (size_t)filename_len
;
441 for (int i
=0; i
<irep
->rlen
; i
++) {
442 size
+= get_filename_table_size(mrb
, irep
->reps
[i
], fp
, lp
);
448 write_debug_record_1(mrb_state
*mrb
, const mrb_irep
*irep
, uint8_t *bin
, mrb_sym
const* filenames
, uint16_t filenames_len
)
452 cur
= bin
+ sizeof(uint32_t); /* skip record size */
453 cur
+= uint16_to_bin(irep
->debug_info
->flen
, cur
); /* file count */
455 for (int f_idx
= 0; f_idx
< irep
->debug_info
->flen
; ++f_idx
) {
457 const mrb_irep_debug_info_file
*file
= irep
->debug_info
->files
[f_idx
];
460 cur
+= uint32_to_bin(file
->start_pos
, cur
);
463 filename_idx
= find_filename_index(filenames
, filenames_len
,
465 mrb_assert_int_fit(int, filename_idx
, uint16_t, UINT16_MAX
);
466 cur
+= uint16_to_bin((uint16_t)filename_idx
, cur
);
469 cur
+= uint32_to_bin(file
->line_entry_count
, cur
);
470 cur
+= uint8_to_bin(file
->line_type
, cur
);
471 switch (file
->line_type
) {
472 case mrb_debug_line_ary
: {
474 for (l
= 0; l
< file
->line_entry_count
; ++l
) {
475 cur
+= uint16_to_bin(file
->lines
.ary
[l
], cur
);
479 case mrb_debug_line_flat_map
: {
481 for (line
= 0; line
< file
->line_entry_count
; ++line
) {
482 cur
+= uint32_to_bin(file
->lines
.flat_map
[line
].start_pos
, cur
);
483 cur
+= uint16_to_bin(file
->lines
.flat_map
[line
].line
, cur
);
487 case mrb_debug_line_packed_map
: {
488 memcpy(cur
, file
->lines
.packed_map
, file
->line_entry_count
);
489 cur
+= file
->line_entry_count
;
492 default: mrb_assert(0); break;
496 ptrdiff_t ret
= cur
- bin
;
497 mrb_assert_int_fit(ptrdiff_t, ret
, uint32_t, UINT32_MAX
);
498 uint32_to_bin((uint32_t)ret
, bin
);
500 mrb_assert_int_fit(ptrdiff_t, ret
, size_t, SIZE_MAX
);
505 write_debug_record(mrb_state
*mrb
, const mrb_irep
*irep
, uint8_t *bin
, mrb_sym
const* filenames
, uint16_t filenames_len
)
507 size_t size
= write_debug_record_1(mrb
, irep
, bin
, filenames
, filenames_len
);
510 for (int irep_no
= 0; irep_no
< irep
->rlen
; irep_no
++) {
511 size_t len
= write_debug_record(mrb
, irep
->reps
[irep_no
], bin
, filenames
, filenames_len
);
516 mrb_assert(size
== get_debug_record_size(mrb
, irep
));
521 write_section_debug(mrb_state
*mrb
, const mrb_irep
*irep
, uint8_t *cur
, mrb_sym
const *filenames
, uint16_t filenames_len
)
523 const uint8_t *bin
= cur
;
525 if (mrb
== NULL
|| cur
== NULL
) {
526 return MRB_DUMP_INVALID_ARGUMENT
;
529 struct rite_section_debug_header
*header
= (struct rite_section_debug_header
*)bin
;
530 size_t section_size
= sizeof(struct rite_section_debug_header
);
534 cur
+= uint16_to_bin(filenames_len
, cur
);
535 section_size
+= sizeof(uint16_t);
536 for (int i
= 0; i
< filenames_len
; i
++) {
540 sym
= mrb_sym_name_len(mrb
, filenames
[i
], &sym_len
);
542 cur
+= uint16_to_bin((uint16_t)sym_len
, cur
);
543 memcpy(cur
, sym
, sym_len
);
545 section_size
+= sizeof(uint16_t) + sym_len
;
549 size_t dlen
= write_debug_record(mrb
, irep
, cur
, filenames
, filenames_len
);
550 section_size
+= dlen
;
552 memcpy(header
->section_ident
, RITE_SECTION_DEBUG_IDENT
, sizeof(header
->section_ident
));
553 mrb_assert(section_size
<= INT32_MAX
);
554 uint32_to_bin((uint32_t)section_size
, header
->section_size
);
560 create_lv_sym_table(mrb_state
*mrb
, const mrb_irep
*irep
, mrb_sym
**syms
, uint32_t *syms_len
)
563 *syms
= (mrb_sym
*)mrb_malloc(mrb
, sizeof(mrb_sym
) * 1);
566 for (int i
= 0; i
+ 1 < irep
->nlocals
; i
++) {
567 mrb_sym
const name
= irep
->lv
[i
];
568 if (name
== 0) continue;
569 if (find_filename_index(*syms
, *syms_len
, name
) != -1) continue;
572 *syms
= (mrb_sym
*)mrb_realloc(mrb
, *syms
, sizeof(mrb_sym
) * (*syms_len
));
573 (*syms
)[*syms_len
- 1] = name
;
576 for (int i
= 0; i
< irep
->rlen
; i
++) {
577 create_lv_sym_table(mrb
, irep
->reps
[i
], syms
, syms_len
);
582 write_lv_sym_table(mrb_state
*mrb
, uint8_t **start
, mrb_sym
const *syms
, uint32_t syms_len
)
584 uint8_t *cur
= *start
;
586 cur
+= uint32_to_bin(syms_len
, cur
);
588 for (uint32_t i
= 0; i
< syms_len
; i
++) {
590 const char *str
= mrb_sym_name_len(mrb
, syms
[i
], &str_len
);
591 cur
+= uint16_to_bin((uint16_t)str_len
, cur
);
592 memcpy(cur
, str
, str_len
);
602 write_lv_record(mrb_state
*mrb
, const mrb_irep
*irep
, uint8_t **start
, mrb_sym
const *syms
, uint32_t syms_len
)
604 uint8_t *cur
= *start
;
606 for (int i
= 0; i
+ 1 < irep
->nlocals
; i
++) {
607 if (irep
->lv
[i
] == 0) {
608 cur
+= uint16_to_bin(RITE_LV_NULL_MARK
, cur
);
611 int const sym_idx
= find_filename_index(syms
, syms_len
, irep
->lv
[i
]);
612 mrb_assert(sym_idx
!= -1); /* local variable name must be in syms */
614 cur
+= uint16_to_bin(sym_idx
, cur
);
618 for (int i
= 0; i
< irep
->rlen
; i
++) {
619 write_lv_record(mrb
, irep
->reps
[i
], &cur
, syms
, syms_len
);
628 get_lv_record_size(mrb_state
*mrb
, const mrb_irep
*irep
)
630 size_t ret
= sizeof(uint16_t) * (irep
->nlocals
- 1);
632 for (int i
= 0; i
< irep
->rlen
; i
++) {
633 ret
+= get_lv_record_size(mrb
, irep
->reps
[i
]);
640 get_lv_section_size(mrb_state
*mrb
, const mrb_irep
*irep
, mrb_sym
const *syms
, uint32_t syms_len
)
642 size_t ret
= sizeof(uint32_t); /* syms_len */
643 ret
+= sizeof(uint16_t) * syms_len
; /* symbol name lengths */
644 for (uint32_t i
= 0; i
< syms_len
; i
++) {
646 mrb_sym_name_len(mrb
, syms
[i
], &str_len
);
650 ret
+= get_lv_record_size(mrb
, irep
);
656 write_section_lv(mrb_state
*mrb
, const mrb_irep
*irep
, uint8_t *start
, mrb_sym
const *syms
, uint32_t const syms_len
)
658 uint8_t *cur
= start
;
660 if (mrb
== NULL
|| cur
== NULL
) {
661 return MRB_DUMP_INVALID_ARGUMENT
;
664 struct rite_section_lv_header
*header
= (struct rite_section_lv_header
*)cur
;
665 cur
+= sizeof(struct rite_section_lv_header
);
667 int result
= write_lv_sym_table(mrb
, &cur
, syms
, syms_len
);
668 if (result
!= MRB_DUMP_OK
) {
672 result
= write_lv_record(mrb
, irep
, &cur
, syms
, syms_len
);
673 if (result
!= MRB_DUMP_OK
) {
677 memcpy(header
->section_ident
, RITE_SECTION_LV_IDENT
, sizeof(header
->section_ident
));
679 ptrdiff_t diff
= cur
- start
;
680 mrb_assert_int_fit(ptrdiff_t, diff
, size_t, SIZE_MAX
);
681 uint32_to_bin((uint32_t)diff
, header
->section_size
);
687 write_rite_binary_header(mrb_state
*mrb
, size_t binary_size
, uint8_t *bin
, uint8_t flags
)
689 struct rite_binary_header
*header
= (struct rite_binary_header
*)bin
;
691 memcpy(header
->binary_ident
, RITE_BINARY_IDENT
, sizeof(header
->binary_ident
));
692 memcpy(header
->major_version
, RITE_BINARY_MAJOR_VER
, sizeof(header
->major_version
));
693 memcpy(header
->minor_version
, RITE_BINARY_MINOR_VER
, sizeof(header
->minor_version
));
694 memcpy(header
->compiler_name
, RITE_COMPILER_NAME
, sizeof(header
->compiler_name
));
695 memcpy(header
->compiler_version
, RITE_COMPILER_VERSION
, sizeof(header
->compiler_version
));
696 mrb_assert(binary_size
<= UINT32_MAX
);
697 uint32_to_bin((uint32_t)binary_size
, header
->binary_size
);
703 debug_info_defined_p(const mrb_irep
*irep
)
705 if (!irep
->debug_info
) return FALSE
;
706 for (int i
= 0; i
< irep
->rlen
; i
++) {
707 if (!debug_info_defined_p(irep
->reps
[i
])) return FALSE
;
713 lv_defined_p(const mrb_irep
*irep
)
715 if (irep
->lv
) { return TRUE
; }
717 for (int i
= 0; i
< irep
->rlen
; i
++) {
718 if (lv_defined_p(irep
->reps
[i
])) { return TRUE
; }
725 mrb_dump_irep(mrb_state
*mrb
, const mrb_irep
*irep
, uint8_t flags
, uint8_t **bin
, size_t *bin_size
)
727 size_t section_lineno_size
= 0, section_lv_size
= 0;
729 mrb_bool
const debug_info_defined
= debug_info_defined_p(irep
), lv_defined
= lv_defined_p(irep
);
730 mrb_sym
*lv_syms
= NULL
; uint32_t lv_syms_len
= 0;
731 mrb_sym
*filenames
= NULL
; uint16_t filenames_len
= 0;
735 return MRB_DUMP_GENERAL_FAILURE
;
738 size_t section_irep_size
= sizeof(struct rite_section_irep_header
);
739 section_irep_size
+= get_irep_record_size(mrb
, irep
);
741 /* DEBUG section size */
742 if (flags
& MRB_DUMP_DEBUG_INFO
) {
743 if (debug_info_defined
) {
744 section_lineno_size
+= sizeof(struct rite_section_debug_header
);
746 filenames
= (mrb_sym
*)mrb_malloc(mrb
, sizeof(mrb_sym
) + 1);
748 /* filename table size */
749 section_lineno_size
+= sizeof(uint16_t);
750 section_lineno_size
+= get_filename_table_size(mrb
, irep
, &filenames
, &filenames_len
);
752 section_lineno_size
+= get_debug_record_size(mrb
, irep
);
757 section_lv_size
+= sizeof(struct rite_section_lv_header
);
758 create_lv_sym_table(mrb
, irep
, &lv_syms
, &lv_syms_len
);
759 section_lv_size
+= get_lv_section_size(mrb
, irep
, lv_syms
, lv_syms_len
);
762 size_t malloc_size
= sizeof(struct rite_binary_header
) +
763 section_irep_size
+ section_lineno_size
+ section_lv_size
+
764 sizeof(struct rite_binary_footer
);
765 cur
= *bin
= (uint8_t*)mrb_malloc(mrb
, malloc_size
);
766 cur
+= sizeof(struct rite_binary_header
);
768 int result
= write_section_irep(mrb
, irep
, cur
, §ion_irep_size
, flags
);
769 if (result
!= MRB_DUMP_OK
) {
772 cur
+= section_irep_size
;
773 *bin_size
= sizeof(struct rite_binary_header
) +
774 section_irep_size
+ section_lineno_size
+ section_lv_size
+
775 sizeof(struct rite_binary_footer
);
777 /* write DEBUG section */
778 if (flags
& MRB_DUMP_DEBUG_INFO
) {
779 if (debug_info_defined
) {
780 result
= write_section_debug(mrb
, irep
, cur
, filenames
, filenames_len
);
781 if (result
!= MRB_DUMP_OK
) {
785 cur
+= section_lineno_size
;
789 result
= write_section_lv(mrb
, irep
, cur
, lv_syms
, lv_syms_len
);
790 if (result
!= MRB_DUMP_OK
) {
793 cur
+= section_lv_size
;
796 write_footer(mrb
, cur
);
797 write_rite_binary_header(mrb
, *bin_size
, *bin
, flags
);
800 if (result
!= MRB_DUMP_OK
) {
804 mrb_free(mrb
, lv_syms
);
805 mrb_free(mrb
, filenames
);
812 mrb_dump_irep_binary(mrb_state
*mrb
, const mrb_irep
*irep
, uint8_t flags
, FILE* fp
)
817 return MRB_DUMP_INVALID_ARGUMENT
;
821 int result
= mrb_dump_irep(mrb
, irep
, flags
, &bin
, &bin_size
);
822 if (result
== MRB_DUMP_OK
) {
823 if (fwrite(bin
, sizeof(bin
[0]), bin_size
, fp
) != bin_size
) {
824 result
= MRB_DUMP_WRITE_FAULT
;
833 mrb_dump_irep_cfunc(mrb_state
*mrb
, const mrb_irep
*irep
, uint8_t flags
, FILE *fp
, const char *initname
)
837 if (fp
== NULL
|| initname
== NULL
|| initname
[0] == '\0') {
838 return MRB_DUMP_INVALID_ARGUMENT
;
840 size_t bin_size
, bin_idx
= 0;
841 int result
= mrb_dump_irep(mrb
, irep
, flags
, &bin
, &bin_size
);
842 if (result
== MRB_DUMP_OK
) {
843 if (fprintf(fp
, "#include <stdint.h>\n") < 0) { /* for uint8_t under at least Darwin */
845 return MRB_DUMP_WRITE_FAULT
;
849 "const uint8_t %s[] = {",
850 (flags
& MRB_DUMP_STATIC
) ? "static"
851 : "#ifdef __cplusplus\n"
856 return MRB_DUMP_WRITE_FAULT
;
858 while (bin_idx
< bin_size
) {
859 if (bin_idx
% 16 == 0) {
860 if (fputs("\n", fp
) == EOF
) {
862 return MRB_DUMP_WRITE_FAULT
;
865 if (fprintf(fp
, "0x%02x,", bin
[bin_idx
++]) < 0) {
867 return MRB_DUMP_WRITE_FAULT
;
870 if (fputs("\n};\n", fp
) == EOF
) {
872 return MRB_DUMP_WRITE_FAULT
;
880 #endif /* MRB_NO_STDIO */