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`)
parent 71eb4b2b
......@@ -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*);
......
......@@ -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);
}
......
......@@ -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 */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment