X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fgenmdesc.c;h=d00a24b54558c9f617a646f4b9768014bd53a6bd;hb=60979ce4a41d1be8f9d3d4d38162c0803207b4d5;hp=46af20a86ba76736f8396a8e9e1c62d0c58a4814;hpb=1c14f1ee6d701510c15499d71fc2b324151a8629;p=mono.git diff --git a/mono/mini/genmdesc.c b/mono/mini/genmdesc.c index 46af20a86ba..d00a24b5455 100644 --- a/mono/mini/genmdesc.c +++ b/mono/mini/genmdesc.c @@ -11,6 +11,35 @@ #include #include +#if defined(__native_client__) || defined(__native_client_codegen__) +volatile int __nacl_thread_suspension_needed = 0; +void __nacl_suspend_thread_if_needed() {} +#endif + +#define MINI_OP(a,b,dest,src1,src2) b, +#define MINI_OP3(a,b,dest,src1,src2,src3) b, +/* keep in sync with the enum in mini.h */ +static const char* const +opnames[] = { +#include "mini-ops.h" +}; +#undef MINI_OP +#undef MINI_OP3 + +/* + * Duplicate this from helpers.c, so the opcode name array can be omitted when + * DISABLE_JIT is set. + */ +static const char* +inst_name (int op) { + if (op >= OP_LOAD && op <= OP_LAST) + return opnames [op - OP_LOAD]; + if (op < OP_LOAD) + return mono_opcode_name (op); + g_error ("unknown opcode name for %d", op); + return NULL; +} + typedef struct { int num; const char *name; @@ -19,7 +48,9 @@ typedef struct { char spec [MONO_INST_MAX]; } OpDesc; +static int nacl = 0; static GHashTable *table; +static GHashTable *template_table; #define eat_whitespace(s) while (*(s) && isspace (*(s))) s++; @@ -40,7 +71,7 @@ load_file (const char *name) { * The format of the lines are: * # comment * opcode: [dest:format] [src1:format] [src2:format] [flags:format] [clob:format] - * [cost:num] [res:format] [delay:num] [len:num] + * [cost:num] [res:format] [delay:num] [len:num] [nacl:num] * format is a single letter that depends on the field * NOTE: no space between the field name and the ':' * @@ -48,6 +79,9 @@ load_file (const char *name) { */ line = 0; while ((str = fgets (buf, sizeof (buf), f))) { + gboolean is_template = FALSE; + gboolean nacl_length_set = FALSE; + ++line; eat_whitespace (str); if (!str [0]) @@ -61,11 +95,16 @@ load_file (const char *name) { g_error ("Invalid format at line %d in %s\n", line, name); *p++ = 0; eat_whitespace (p); - desc = g_hash_table_lookup (table, str); - if (!desc) - g_error ("Invalid opcode '%s' at line %d in %s\n", str, line, name); - if (desc->desc) - g_error ("Duplicated opcode '%s' at line %d in %s\n", str, line, name); + if (strcmp (str, "template") == 0) { + is_template = TRUE; + desc = g_new0 (OpDesc, 1); + } else { + desc = g_hash_table_lookup (table, str); + if (!desc) + g_error ("Invalid opcode '%s' at line %d in %s\n", str, line, name); + if (desc->desc) + g_error ("Duplicated opcode %s at line %d in %s\n", str, line, name); + } desc->desc = g_strdup (p); desc->comment = g_strdup (comment->str); g_string_truncate (comment, 0); @@ -79,12 +118,16 @@ load_file (const char *name) { } else if (strncmp (p, "src2:", 5) == 0) { desc->spec [MONO_INST_SRC2] = p [5]; p += 6; - } else if (strncmp (p, "cost:", 5) == 0) { - desc->spec [MONO_INST_COST] = p [5]; + } else if (strncmp (p, "src3:", 5) == 0) { + desc->spec [MONO_INST_SRC3] = p [5]; p += 6; } else if (strncmp (p, "clob:", 5) == 0) { desc->spec [MONO_INST_CLOB] = p [5]; p += 6; + /* Currently unused fields + } else if (strncmp (p, "cost:", 5) == 0) { + desc->spec [MONO_INST_COST] = p [5]; + p += 6; } else if (strncmp (p, "res:", 4) == 0) { desc->spec [MONO_INST_RES] = p [4]; p += 5; @@ -94,14 +137,59 @@ load_file (const char *name) { } else if (strncmp (p, "delay:", 6) == 0) { desc->spec [MONO_INST_DELAY] = p [6]; p += 7; + */ } else if (strncmp (p, "len:", 4) == 0) { + unsigned long size; p += 4; - desc->spec [MONO_INST_LEN] = strtoul (p, &p, 10); + size = strtoul (p, &p, 10); + if (!nacl_length_set) { + desc->spec [MONO_INST_LEN] = size; + } + } else if (strncmp (p, "nacl:", 5) == 0) { + unsigned long size; + p += 5; + size = strtoul (p, &p, 10); + if (nacl) { + desc->spec [MONO_INST_LEN] = size; + nacl_length_set = TRUE; + } + } else if (strncmp (p, "template:", 9) == 0) { + char *tname; + int i; + OpDesc *tdesc; + p += 9; + tname = p; + while (*p && isalnum (*p)) ++p; + *p++ = 0; + tdesc = g_hash_table_lookup (template_table, tname); + if (!tdesc) + g_error ("Invalid template name %s at '%s' at line %d in %s\n", tname, p, line, name); + for (i = 0; i < MONO_INST_MAX; ++i) { + if (desc->spec [i]) + g_error ("The template overrides any previous value set at line %d in %s\n", line, name); + } + memcpy (desc->spec, tdesc->spec, sizeof (desc->spec)); + } else if (strncmp (p, "name:", 5) == 0) { + char *tname; + if (!is_template) + g_error ("name tag only valid in templates at '%s' at line %d in %s\n", p, line, name); + if (desc->name) + g_error ("Duplicated name tag in template %s at '%s' at line %d in %s\n", desc->name, p, line, name); + p += 5; + tname = p; + while (*p && isalnum (*p)) ++p; + *p++ = 0; + if (g_hash_table_lookup (template_table, tname)) + g_error ("Duplicated template %s at line %d in %s\n", tname, line, name); + desc->name = g_strdup (tname); + g_hash_table_insert (template_table, (void*)desc->name, desc); } else { g_error ("Parse error at '%s' at line %d in %s\n", p, line, name); } eat_whitespace (p); } + if (is_template && !desc->name) + g_error ("Template without name at line %d in %s\n", line, name); } fclose (f); return 0; @@ -114,19 +202,14 @@ init_table (void) { int i; OpDesc *desc; + template_table = g_hash_table_new (g_str_hash, g_str_equal); table = g_hash_table_new (g_str_hash, g_str_equal); opcodes = g_new0 (OpDesc, OP_LAST); - for (i = 0; i < MONO_CEE_LAST; ++i) { - desc = opcodes + i; - desc->num = i; - desc->name = mono_inst_name (i); - g_hash_table_insert (table, (char *)desc->name, desc); - } for (i = OP_LOAD; i < OP_LAST; ++i) { desc = opcodes + i; desc->num = i; - desc->name = mono_inst_name (i); + desc->name = inst_name (i); g_hash_table_insert (table, (char *)desc->name, desc); } } @@ -142,38 +225,41 @@ output_char (FILE *f, char c) { static void build_table (const char *fname, const char *name) { FILE *f; - int i, j; + int i, j, idx; OpDesc *desc; + GString *idx_array = g_string_new (""); + /* use this to remove duplicates */ + GHashTable *desc_ht = g_hash_table_new (g_str_hash, g_str_equal); if (!(f = fopen (fname, "w"))) g_error ("Cannot open file '%s'", fname); fprintf (f, "/* File automatically generated by genmdesc, don't change */\n\n"); - fprintf (f, "const char * const %s [OP_LAST] = {\n", name); + fprintf (f, "const char %s [] = {\n", name); + fprintf (f, "\t\""); + for (j = 0; j < MONO_INST_MAX; ++j) + fprintf (f, "\\x0"); + fprintf (f, "\"\t/* null entry */\n"); + idx = 1; + g_string_append_printf (idx_array, "const guint16 %s_idx [] = {\n", name); - for (i = 0; i < MONO_CEE_LAST; ++i) { - desc = opcodes + i; - if (!desc->desc) - fprintf (f, "\tNULL,\t/* %s */\n", desc->name); - else { - fprintf (f, "\t\""); - for (j = 0; j < MONO_INST_MAX; ++j) - output_char (f, desc->spec [j]); - fprintf (f, "\",\t/* %s */\n", desc->name); - } - } for (i = OP_LOAD; i < OP_LAST; ++i) { desc = opcodes + i; if (!desc->desc) - fprintf (f, "\tNULL,\t/* %s */\n", desc->name); + g_string_append_printf (idx_array, "\t0,\t/* %s */\n", desc->name ? desc->name : ""); else { fprintf (f, "\t\""); for (j = 0; j < MONO_INST_MAX; ++j) output_char (f, desc->spec [j]); - fprintf (f, "\",\t/* %s */\n", desc->name); + fprintf (f, "\"\t/* %s */\n", desc->name); + g_string_append_printf (idx_array, "\t%d,\t/* %s */\n", idx * MONO_INST_MAX, desc->name); + ++idx; } } fprintf (f, "};\n\n"); + fprintf (f, "%s};\n\n", idx_array->str); fclose (f); + g_string_free (idx_array, TRUE); + g_hash_table_destroy (desc_ht); } static void @@ -212,21 +298,28 @@ int main (int argc, char* argv []) { init_table (); - switch (argc) { - case 2: + if (argc == 2) { /* useful to get a new file when some opcodes are added: looses the comments, though */ load_file (argv [1]); dump (); - break; - case 4: - load_file (argv [1]); - build_table (argv [2], argv [3]); - break; - default: + } else if (argc < 4) { g_print ("Usage: genmdesc arguments\n"); - g_print ("\tgenmdesc desc Output to stdout the description file.\n"); - g_print ("\tgenmdesc desc output name Write to output the description in a table named 'name'.\n"); + g_print ("\tgenmdesc desc Output to stdout the description file.\n"); + g_print ("\tgenmdesc [--nacl] output name desc [desc1...]\n" + " Write to output the description in a table named 'name',\n" + " use --nacl to generate Google NativeClient code\n"); return 1; + } else { + int i = 3; + if (strcmp (argv [1], "--nacl") == 0) { + nacl = 1; + i++; + } + + for (; i < argc; ++i) + load_file (argv [i]); + + build_table (argv [1 + nacl], argv [2 + nacl]); } return 0; }