Skip to content

Commit bc9c47d

Browse files
committed
allow endian specification of mrb files by mrbc -e/-E
`mruby -b` now accepts both big/little endian mrb (compiled binary) files. `mrbc` generates mrb files in big endian for .mrb files and in native endian for C files (with -B option specified) by default. If you are cross compiling, you need to specify target endian by -e/-E options if it is different from host endian.
1 parent 089f1f6 commit bc9c47d

File tree

4 files changed

+180
-68
lines changed

4 files changed

+180
-68
lines changed

include/mruby/dump.h

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,16 @@ extern "C" {
1414
#include "mruby.h"
1515
#include "mruby/irep.h"
1616

17-
int mrb_dump_irep(mrb_state *mrb, mrb_irep *irep, int debug_info, uint8_t **bin, size_t *bin_size);
17+
#define DUMP_DEBUG_INFO 1
18+
#define DUMP_ENDIAN_BIG 2
19+
#define DUMP_ENDIAN_LIL 4
20+
#define DUMP_ENDIAN_NAT 6
21+
#define DUMP_ENDIAN_MASK 6
22+
23+
int mrb_dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size);
1824
#ifdef ENABLE_STDIO
19-
int mrb_dump_irep_binary(mrb_state*, mrb_irep*, int, FILE*);
20-
int mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep*, int, FILE *f, const char *initname);
25+
int mrb_dump_irep_binary(mrb_state*, mrb_irep*, uint8_t, FILE*);
26+
int mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep*, uint8_t flags, FILE *f, const char *initname);
2127
mrb_irep *mrb_read_irep_file(mrb_state*, FILE*);
2228
MRB_API mrb_value mrb_load_irep_file(mrb_state*,FILE*);
2329
MRB_API mrb_value mrb_load_irep_file_cxt(mrb_state*, FILE*, mrbc_context*);
@@ -42,25 +48,26 @@ MRB_API mrb_irep *mrb_read_irep(mrb_state*, const uint8_t*);
4248
#define MRB_DUMP_NULL_SYM_LEN 0xFFFF
4349

4450
/* Rite Binary File header */
45-
#define RITE_BINARY_IDENTIFIER "RITE"
51+
#define RITE_BINARY_IDENT "RITE"
52+
#define RITE_BINARY_IDENT_LIL "ETIR"
4653
#define RITE_BINARY_FORMAT_VER "0003"
4754
#define RITE_COMPILER_NAME "MATZ"
4855
#define RITE_COMPILER_VERSION "0000"
4956

5057
#define RITE_VM_VER "0000"
5158

5259
#define RITE_BINARY_EOF "END\0"
53-
#define RITE_SECTION_IREP_IDENTIFIER "IREP"
54-
#define RITE_SECTION_LINENO_IDENTIFIER "LINE"
55-
#define RITE_SECTION_DEBUG_IDENTIFIER "DBG\0"
56-
#define RITE_SECTION_LV_IDENTIFIER "LVAR"
60+
#define RITE_SECTION_IREP_IDENT "IREP"
61+
#define RITE_SECTION_LINENO_IDENT "LINE"
62+
#define RITE_SECTION_DEBUG_IDENT "DBG\0"
63+
#define RITE_SECTION_LV_IDENT "LVAR"
5764

5865
#define MRB_DUMP_DEFAULT_STR_LEN 128
5966
#define MRB_DUMP_ALIGNMENT sizeof(uint32_t)
6067

6168
/* binary header */
6269
struct rite_binary_header {
63-
uint8_t binary_identify[4]; /* Binary Identifier */
70+
uint8_t binary_ident[4]; /* Binary Identifier */
6471
uint8_t binary_version[4]; /* Binary Format Version */
6572
uint8_t binary_crc[2]; /* Binary CRC */
6673
uint8_t binary_size[4]; /* Binary Size */
@@ -70,7 +77,7 @@ struct rite_binary_header {
7077

7178
/* section header */
7279
#define RITE_SECTION_HEADER \
73-
uint8_t section_identify[4]; \
80+
uint8_t section_ident[4]; \
7481
uint8_t section_size[4]
7582

7683
struct rite_section_header {
@@ -101,6 +108,17 @@ struct rite_binary_footer {
101108
RITE_SECTION_HEADER;
102109
};
103110

111+
static inline int
112+
bigendian_p()
113+
{
114+
int i;
115+
char *p;
116+
117+
i = 1;
118+
p = (char*)&i;
119+
return p[0]?0:1;
120+
}
121+
104122
static inline size_t
105123
uint8_to_bin(uint8_t s, uint8_t *bin)
106124
{
@@ -126,6 +144,16 @@ uint32_to_bin(uint32_t l, uint8_t *bin)
126144
return sizeof(uint32_t);
127145
}
128146

147+
static inline size_t
148+
uint32l_to_bin(uint32_t l, uint8_t *bin)
149+
{
150+
bin[3] = (l >> 24) & 0xff;
151+
bin[2] = (l >> 16) & 0xff;
152+
bin[1] = (l >> 8) & 0xff;
153+
bin[0] = l & 0xff;
154+
return sizeof(uint32_t);
155+
}
156+
129157
static inline uint32_t
130158
bin_to_uint32(const uint8_t *bin)
131159
{
@@ -135,6 +163,15 @@ bin_to_uint32(const uint8_t *bin)
135163
(uint32_t)bin[3];
136164
}
137165

166+
static inline uint32_t
167+
bin_to_uint32l(const uint8_t *bin)
168+
{
169+
return (uint32_t)bin[3] << 24 |
170+
(uint32_t)bin[2] << 16 |
171+
(uint32_t)bin[1] << 8 |
172+
(uint32_t)bin[0];
173+
}
174+
138175
static inline uint16_t
139176
bin_to_uint16(const uint8_t *bin)
140177
{

src/dump.c

Lines changed: 90 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,25 @@ write_iseq_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf, uint8_t flags)
8080

8181
cur += uint32_to_bin(irep->ilen, cur); /* number of opcode */
8282
cur += write_padding(cur);
83-
if (flags & FLAG_BYTEORDER_NATIVE) {
84-
memcpy(cur, irep->iseq, irep->ilen * sizeof(mrb_code));
85-
cur += irep->ilen * sizeof(mrb_code);
86-
}
87-
else {
83+
switch (flags & DUMP_ENDIAN_NAT) {
84+
case DUMP_ENDIAN_BIG:
85+
if (bigendian_p()) goto native;
8886
for (iseq_no = 0; iseq_no < irep->ilen; iseq_no++) {
8987
cur += uint32_to_bin(irep->iseq[iseq_no], cur); /* opcode */
9088
}
89+
break;
90+
case DUMP_ENDIAN_LIL:
91+
if (!bigendian_p()) goto native;
92+
for (iseq_no = 0; iseq_no < irep->ilen; iseq_no++) {
93+
cur += uint32l_to_bin(irep->iseq[iseq_no], cur); /* opcode */
94+
}
95+
break;
96+
97+
native:
98+
case DUMP_ENDIAN_NAT:
99+
memcpy(cur, irep->iseq, irep->ilen * sizeof(mrb_code));
100+
cur += irep->ilen * sizeof(mrb_code);
101+
break;
91102
}
92103

93104
return cur - buf;
@@ -323,7 +334,7 @@ write_footer(mrb_state *mrb, uint8_t *bin)
323334
{
324335
struct rite_binary_footer footer;
325336

326-
memcpy(footer.section_identify, RITE_BINARY_EOF, sizeof(footer.section_identify));
337+
memcpy(footer.section_ident, RITE_BINARY_EOF, sizeof(footer.section_ident));
327338
uint32_to_bin(sizeof(struct rite_binary_footer), footer.section_size);
328339
memcpy(bin, &footer, sizeof(struct rite_binary_footer));
329340

@@ -336,7 +347,7 @@ write_section_irep_header(mrb_state *mrb, size_t section_size, uint8_t *bin)
336347
{
337348
struct rite_section_irep_header *header = (struct rite_section_irep_header*)bin;
338349

339-
memcpy(header->section_identify, RITE_SECTION_IREP_IDENTIFIER, sizeof(header->section_identify));
350+
memcpy(header->section_ident, RITE_SECTION_IREP_IDENT, sizeof(header->section_ident));
340351

341352
mrb_assert_int_fit(size_t, section_size, uint32_t, UINT32_MAX);
342353
uint32_to_bin((uint32_t)section_size, header->section_size);
@@ -373,7 +384,7 @@ write_section_lineno_header(mrb_state *mrb, size_t section_size, uint8_t *bin)
373384
{
374385
struct rite_section_lineno_header *header = (struct rite_section_lineno_header*)bin;
375386

376-
memcpy(header->section_identify, RITE_SECTION_LINENO_IDENTIFIER, sizeof(header->section_identify));
387+
memcpy(header->section_ident, RITE_SECTION_LINENO_IDENT, sizeof(header->section_ident));
377388
uint32_to_bin((uint32_t)section_size, header->section_size);
378389

379390
return MRB_DUMP_OK;
@@ -664,7 +675,7 @@ write_section_debug(mrb_state *mrb, mrb_irep *irep, uint8_t *cur, mrb_sym const
664675
dlen = write_debug_record(mrb, irep, cur, filenames, filenames_len);
665676
section_size += dlen;
666677

667-
memcpy(header->section_identify, RITE_SECTION_DEBUG_IDENTIFIER, sizeof(header->section_identify));
678+
memcpy(header->section_ident, RITE_SECTION_DEBUG_IDENT, sizeof(header->section_ident));
668679
mrb_assert(section_size <= INT32_MAX);
669680
uint32_to_bin(section_size, header->section_size);
670681

@@ -803,7 +814,7 @@ write_section_lv(mrb_state *mrb, mrb_irep *irep, uint8_t *start, mrb_sym const *
803814
goto lv_section_exit;
804815
}
805816

806-
memcpy(header->section_identify, RITE_SECTION_LV_IDENTIFIER, sizeof(header->section_identify));
817+
memcpy(header->section_ident, RITE_SECTION_LV_IDENT, sizeof(header->section_ident));
807818

808819
diff = cur - start;
809820
mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX);
@@ -820,19 +831,23 @@ write_rite_binary_header(mrb_state *mrb, size_t binary_size, uint8_t *bin, uint8
820831
uint16_t crc;
821832
uint32_t offset;
822833

823-
if (flags & FLAG_BYTEORDER_NATIVE) {
824-
uint32_t ident = 0;
825-
size_t i;
826-
827-
for(i=0; i<sizeof(ident); i++) {
828-
ident<<=8;
829-
ident|=RITE_BINARY_IDENTIFIER[i];
830-
}
831-
memcpy(header->binary_identify, (char*)&ident, sizeof(uint32_t));
832-
}
833-
else {
834-
memcpy(header->binary_identify, RITE_BINARY_IDENTIFIER, sizeof(header->binary_identify));
834+
switch (flags & DUMP_ENDIAN_NAT) {
835+
default:
836+
endian_big:
837+
case DUMP_ENDIAN_BIG:
838+
memcpy(header->binary_ident, RITE_BINARY_IDENT, sizeof(header->binary_ident));
839+
break;
840+
endian_little:
841+
case DUMP_ENDIAN_LIL:
842+
memcpy(header->binary_ident, RITE_BINARY_IDENT_LIL, sizeof(header->binary_ident));
843+
break;
844+
845+
case DUMP_ENDIAN_NAT:
846+
if (bigendian_p()) goto endian_big;
847+
goto endian_little;
848+
break;
835849
}
850+
836851
memcpy(header->binary_version, RITE_BINARY_FORMAT_VER, sizeof(header->binary_version));
837852
memcpy(header->compiler_name, RITE_COMPILER_NAME, sizeof(header->compiler_name));
838853
memcpy(header->compiler_version, RITE_COMPILER_VERSION, sizeof(header->compiler_version));
@@ -872,8 +887,23 @@ is_lv_defined(mrb_irep *irep)
872887
return FALSE;
873888
}
874889

890+
static uint8_t
891+
dump_flags(uint8_t flags, uint8_t native)
892+
{
893+
if (native == FLAG_BYTEORDER_NATIVE) {
894+
if ((flags & DUMP_ENDIAN_NAT) == 0) {
895+
return (flags & DUMP_DEBUG_INFO) | DUMP_ENDIAN_NAT;
896+
}
897+
return flags;
898+
}
899+
if ((flags & DUMP_ENDIAN_NAT) == 0) {
900+
return (flags & DUMP_DEBUG_INFO) | DUMP_ENDIAN_BIG;
901+
}
902+
return flags;
903+
}
904+
875905
static int
876-
dump_irep(mrb_state *mrb, mrb_irep *irep, int debug_info, uint8_t **bin, size_t *bin_size, uint8_t flags)
906+
dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size)
877907
{
878908
int result = MRB_DUMP_GENERAL_FAILURE;
879909
size_t malloc_size;
@@ -893,7 +923,7 @@ dump_irep(mrb_state *mrb, mrb_irep *irep, int debug_info, uint8_t **bin, size_t
893923
section_irep_size += get_irep_record_size(mrb, irep);
894924

895925
/* DEBUG section size */
896-
if (debug_info) {
926+
if (flags & DUMP_DEBUG_INFO) {
897927
if (debug_info_defined) {
898928
section_lineno_size += sizeof(struct rite_section_debug_header);
899929
/* filename table */
@@ -933,7 +963,7 @@ dump_irep(mrb_state *mrb, mrb_irep *irep, int debug_info, uint8_t **bin, size_t
933963
sizeof(struct rite_binary_footer);
934964

935965
/* write DEBUG section */
936-
if (debug_info) {
966+
if (flags & DUMP_DEBUG_INFO) {
937967
if (debug_info_defined) {
938968
result = write_section_debug(mrb, irep, cur, filenames, filenames_len);
939969
}
@@ -972,13 +1002,13 @@ dump_irep(mrb_state *mrb, mrb_irep *irep, int debug_info, uint8_t **bin, size_t
9721002
}
9731003

9741004
int
975-
mrb_dump_irep(mrb_state *mrb, mrb_irep *irep, int debug_info, uint8_t **bin, size_t *bin_size)
1005+
mrb_dump_irep(mrb_state *mrb, mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size)
9761006
{
977-
return dump_irep(mrb, irep, debug_info, bin, bin_size, FLAG_BYTEORDER_NONATIVE);
1007+
return dump_irep(mrb, irep, dump_flags(flags, FLAG_BYTEORDER_NONATIVE), bin, bin_size);
9781008
}
9791009

9801010
int
981-
mrb_dump_irep_binary(mrb_state *mrb, mrb_irep *irep, int debug_info, FILE* fp)
1011+
mrb_dump_irep_binary(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE* fp)
9821012
{
9831013
uint8_t *bin = NULL;
9841014
size_t bin_size = 0;
@@ -988,7 +1018,7 @@ mrb_dump_irep_binary(mrb_state *mrb, mrb_irep *irep, int debug_info, FILE* fp)
9881018
return MRB_DUMP_INVALID_ARGUMENT;
9891019
}
9901020

991-
result = dump_irep(mrb, irep, debug_info, &bin, &bin_size, FLAG_BYTEORDER_NONATIVE);
1021+
result = dump_irep(mrb, irep, dump_flags(flags, FLAG_BYTEORDER_NONATIVE), &bin, &bin_size);
9921022
if (result == MRB_DUMP_OK) {
9931023
if (fwrite(bin, sizeof(bin[0]), bin_size, fp) != bin_size) {
9941024
result = MRB_DUMP_WRITE_FAULT;
@@ -1015,8 +1045,22 @@ is_valid_c_symbol_name(const char *name)
10151045
return TRUE;
10161046
}
10171047

1048+
static int
1049+
dump_bigendian_p(uint8_t flags)
1050+
{
1051+
switch (flags & DUMP_ENDIAN_NAT) {
1052+
case DUMP_ENDIAN_BIG:
1053+
return TRUE;
1054+
case DUMP_ENDIAN_LIL:
1055+
return FALSE;
1056+
default:
1057+
case DUMP_ENDIAN_NAT:
1058+
return bigendian_p();
1059+
}
1060+
}
1061+
10181062
int
1019-
mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep *irep, int debug_info, FILE *fp, const char *initname)
1063+
mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep *irep, uint8_t flags, FILE *fp, const char *initname)
10201064
{
10211065
uint8_t *bin = NULL;
10221066
size_t bin_size = 0, bin_idx = 0;
@@ -1025,9 +1069,23 @@ mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep *irep, int debug_info, FILE *fp, co
10251069
if (fp == NULL || initname == NULL || !is_valid_c_symbol_name(initname)) {
10261070
return MRB_DUMP_INVALID_ARGUMENT;
10271071
}
1028-
1029-
result = dump_irep(mrb, irep, debug_info, &bin, &bin_size, FLAG_BYTEORDER_NATIVE);
1072+
flags = dump_flags(flags, FLAG_BYTEORDER_NATIVE);
1073+
result = dump_irep(mrb, irep, flags, &bin, &bin_size);
10301074
if (result == MRB_DUMP_OK) {
1075+
if (!dump_bigendian_p(flags)) {
1076+
if (fprintf(fp, "/* dumped in little endian order.\n"
1077+
" use `mrbc -E` option for big endian CPU. */\n") < 0) {
1078+
mrb_free(mrb, bin);
1079+
return MRB_DUMP_WRITE_FAULT;
1080+
}
1081+
}
1082+
else {
1083+
if (fprintf(fp, "/* dumped in big endian order.\n"
1084+
" use `mrbc -e` option for better performance on little endian CPU. */\n") < 0) {
1085+
mrb_free(mrb, bin);
1086+
return MRB_DUMP_WRITE_FAULT;
1087+
}
1088+
}
10311089
if (fprintf(fp, "#include <stdint.h>\n") < 0) { /* for uint8_t under at least Darwin */
10321090
mrb_free(mrb, bin);
10331091
return MRB_DUMP_WRITE_FAULT;

0 commit comments

Comments
 (0)