summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2020-06-08 18:52:34 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2020-10-12 16:21:07 +0900
commitad15e59cd942486d87e2fb38d30993f15dc29433 (patch)
tree504c26ae1d06d52c2d6d62335940a4613c16c7e5
parent71eb4b2b227c083f187c634212f5fc557f392fb9 (diff)
downloadmruby-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.h1
-rw-r--r--mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c12
-rw-r--r--src/dump.c148
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 */