diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2020-06-08 18:52:34 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2020-10-12 16:21:07 +0900 |
| commit | ad15e59cd942486d87e2fb38d30993f15dc29433 (patch) | |
| tree | 504c26ae1d06d52c2d6d62335940a4613c16c7e5 | |
| parent | 71eb4b2b227c083f187c634212f5fc557f392fb9 (diff) | |
| download | mruby-ad15e59cd942486d87e2fb38d30993f15dc29433.tar.gz mruby-ad15e59cd942486d87e2fb38d30993f15dc29433.zip | |
Add `irep` C struct dump from `mrbc` with `-S` option.
But we need more work:
- recursive `irep` dump (`irep->reps`)
- pool values dump (`irep->pool`)
| -rw-r--r-- | include/mruby/dump.h | 1 | ||||
| -rw-r--r-- | mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c | 12 | ||||
| -rw-r--r-- | src/dump.c | 148 |
3 files changed, 160 insertions, 1 deletions
diff --git a/include/mruby/dump.h b/include/mruby/dump.h index 2fa5e4d3c..384521c45 100644 --- a/include/mruby/dump.h +++ b/include/mruby/dump.h @@ -22,6 +22,7 @@ int mrb_dump_irep(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, uint8_t * #ifndef MRB_DISABLE_STDIO int mrb_dump_irep_binary(mrb_state*, const mrb_irep*, uint8_t, FILE*); int mrb_dump_irep_cfunc(mrb_state *mrb, const mrb_irep*, uint8_t flags, FILE *f, const char *initname); +int mrb_dump_irep_cstruct(mrb_state *mrb, const mrb_irep*, uint8_t flags, FILE *f, const char *initname); mrb_irep *mrb_read_irep_file(mrb_state*, FILE*); MRB_API mrb_value mrb_load_irep_file(mrb_state*,FILE*); MRB_API mrb_value mrb_load_irep_file_cxt(mrb_state*, FILE*, mrbc_context*); diff --git a/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c b/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c index 5cd9a27fc..3be40df76 100644 --- a/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c +++ b/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c @@ -20,6 +20,7 @@ struct mrbc_args { const char *prog; const char *outfile; const char *initname; + mrb_bool dump_struct : 1; mrb_bool check_syntax : 1; mrb_bool verbose : 1; mrb_bool remove_lv : 1; @@ -36,6 +37,7 @@ usage(const char *name) "-v print version number, then turn on verbose mode", "-g produce debugging information", "-B<symbol> binary <symbol> output in C language format", + "-S dump C struct (requires -B)", "--remove-lv remove local variables", "--verbose run at verbose mode", "--version print the version", @@ -105,6 +107,9 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct mrbc_args *args) args->outfile = get_outfilename(mrb, argv[i] + 2, ""); } break; + case 'S': + args->dump_struct = TRUE; + break; case 'B': if (argv[i][2] == '\0' && argv[i+1]) { i++; @@ -244,7 +249,12 @@ dump_file(mrb_state *mrb, FILE *wfp, const char *outfile, struct RProc *proc, st mrb_irep_remove_lv(mrb, (mrb_irep*)irep); } if (args->initname) { - n = mrb_dump_irep_cfunc(mrb, irep, args->flags, wfp, args->initname); + if (args->dump_struct) { + n = mrb_dump_irep_cstruct(mrb, irep, args->flags, wfp, args->initname); + } + else { + n = mrb_dump_irep_cfunc(mrb, irep, args->flags, wfp, args->initname); + } if (n == MRB_DUMP_INVALID_ARGUMENT) { fprintf(stderr, "%s: invalid C language symbol name\n", args->initname); } diff --git a/src/dump.c b/src/dump.c index 770c133fb..093e4c256 100644 --- a/src/dump.c +++ b/src/dump.c @@ -918,4 +918,152 @@ mrb_dump_irep_cfunc(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, FILE *f return result; } +static struct { + const char *op; + const char *name; +} op_table[] = { + {"!", "not"}, + {"!=", "neq"}, + {"!~", "nmatch"}, + {"%", "mod"}, + {"&", "and"}, + {"&&", "andand"}, + {"*", "mul"}, + {"**", "pow"}, + {"+", "add"}, + {"+@", "plus"}, + {"-", "sub"}, + {"-@", "minus"}, + {"/", "div"}, + {"<", "lt"}, + {"<=", "le"}, + {"<<", "lshift"}, + {"<=>", "cmp"}, + {"==", "eq"}, + {"===", "eqq"}, + {"=~", "match"}, + {">", "gt"}, + {">=", "ge"}, + {">>", "rshift"}, + {"[]", "aref"}, + {"[]=", "aset"}, + {"^", "xor"}, + {"`", "tick"}, + {"|", "or"}, + {"||", "oror"}, + {"~", "neg"}, + {0}, +}; + +static int +dump_sym(mrb_state *mrb, mrb_sym sym, FILE *fp) +{ + mrb_int len; + const char *name = mrb_sym_name_len(mrb, sym, &len); + int i; + + if (len == 0 || len != strlen(name)) + return MRB_DUMP_INVALID_ARGUMENT; + for (i=0; op_table[i].op; i++) { + if (strcmp(name, op_table[i].op) == 0) { + fprintf(fp, "MRB_QSYM(%s),", op_table[i].name); + return MRB_DUMP_OK; + } + } + if (name[0] == '@') { + fprintf(fp, "MRB_QSYM(a_%s),", name+1); + } + else if (name[0] == '$') { + fprintf(fp, "MRB_QSYM(d_%s),", name+1); + } + else if (name[len-1] == '!') { + fprintf(fp, "MRB_QSYM(%.*s_b),", (int)len-1, name); + } + else if (name[len-1] == '?') { + fprintf(fp, "MRB_QSYM(%.*s_p),", (int)len-1, name); + } + else { + fprintf(fp, "MRB_SYM(%s),", name); + } + return MRB_DUMP_OK; +} + +static int +dump_irep_struct(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, FILE *fp, const char *name, int *np) +{ + int n = *np; /* this level */ + int i, len; + + /* dump reps */ + /* dump pool */ + /* dump syms */ + if (irep->syms) { + fprintf(fp, "static const mrb_sym %s_syms_%d = {", name, n); + for (i=0,len=irep->slen; i<len; i++) { + if (dump_sym(mrb, irep->syms[i], fp) != MRB_DUMP_OK) + return MRB_DUMP_INVALID_ARGUMENT; + } + fputs("};\n", fp); + } + /* dump iseq */ + fprintf(fp, "static const mrb_code %s_iseq_%d[] = {", name, n); + for (i=0,len=irep->ilen; i<len; i++) { + if (i%8 == 0) fputs("\n", fp); + fprintf(fp, "0x%02x,", irep->iseq[i]); + } + fputs("};\n", fp); + /* dump irep */ + if (n == 0) { /* topleve irep */ + fprintf(fp, "static const mrb_irep %s = {\n", name); + } + else { + fprintf(fp, "static const mrb_irep %s_%d = {\n", name, n); + } + fprintf(fp, " %d,\t\t\t\t\t/* nlocals */\n", irep->nlocals); + fprintf(fp, " %d,\t\t\t\t\t/* nregs */\n", irep->nregs); + fputs( " MRB_ISEQ_NO_FREE|MRB_IREP_NO_FREE,\t/* flags */\n", fp); + fprintf(fp, " %s_iseq_%d,\t\t\t/* iseq */\n", name, n); + if (irep->pool) { + fprintf(fp, " %s_pool_%d,\t\t/* pool */\n", name, n); + } + else { + fputs( " NULL,\t\t\t\t\t/* pool */\n", fp); + } + if (irep->syms) { + fprintf(fp, " %s_syms_%d,\t\t\t/* syms */\n", name, n); + } + else { + fputs( " NULL,\t\t\t\t\t/* syms */\n", fp); + } + if (irep->reps) { + fprintf(fp, " %s_reps_%d,\t\t\t/* reps */\n", name, n); + } + else { + fputs( " NULL,\t\t\t\t\t/* reps */\n", fp); + } + fputs( " NULL,\t\t\t\t\t/* lv */\n", fp); + fputs( " NULL,\t\t\t\t\t/* debug_info */\n", fp); + fprintf(fp, " %d,\t\t\t\t\t/* ilen */\n", irep->ilen); + fprintf(fp, " %d,\t\t\t\t\t/* plen */\n", irep->plen); + fprintf(fp, " %d,\t\t\t\t\t/* slen */\n", irep->slen); + fprintf(fp, " %d,\t\t\t\t\t/* rlen */\n", irep->rlen); + fputs( " 0,\t\t\t\t\t/* refcnt */\n};\n", fp); + + return MRB_DUMP_OK; +} + +int +mrb_dump_irep_cstruct(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, FILE *fp, const char *initname) +{ + int n = 0; + + if (fp == NULL || initname == NULL || initname[0] == '\0') { + return MRB_DUMP_INVALID_ARGUMENT; + } + if (fprintf(fp, "#include <mruby.h>\n" "#include <mruby/irep.h>\n\n") < 0) { + return MRB_DUMP_WRITE_FAULT; + } + return dump_irep_struct(mrb, irep, flags, fp, initname, &n); +} + #endif /* MRB_DISABLE_STDIO */ |
