2020-02-03 Bill Schmidt <wschm...@linux.ibm.com> * config/rs6000/rs6000-genbif.c (typemap): New struct. (TYPE_MAP_SIZE): New defined constant. (type_map): New filescope variable. (write_fntype): New callback function. (map_token_to_type_node): New function. (write_type_node): New function. (write_fntype_init): New function. (write_init_bif_table): New function. (write_init_ovld_table): New function. (write_init_file): Implement. --- gcc/config/rs6000/rs6000-genbif.c | 367 ++++++++++++++++++++++++++++++ 1 file changed, 367 insertions(+)
diff --git a/gcc/config/rs6000/rs6000-genbif.c b/gcc/config/rs6000/rs6000-genbif.c index c84df1aa30f..ac640e14def 100644 --- a/gcc/config/rs6000/rs6000-genbif.c +++ b/gcc/config/rs6000/rs6000-genbif.c @@ -311,6 +311,52 @@ static rbt_strings bif_rbt; static rbt_strings ovld_rbt; static rbt_strings fntype_rbt; +/* Mapping from type tokens to type node names. */ +struct typemap +{ + const char *key; + const char *value; +}; + +/* This table must be kept in alphabetical order, as we use binary + search for table lookups in map_token_to_type_node. */ +#define TYPE_MAP_SIZE 32 +static typemap type_map[TYPE_MAP_SIZE] = + { + { "df", "double" }, + { "di", "intDI" }, + { "hi", "intHI" }, + { "pv", "ptr" }, + { "qi", "intQI" }, + { "sf", "float" }, + { "si", "intSI" }, + { "tf", "long_double" }, + { "ti", "intTI" }, + { "udi", "unsigned_intDI" }, + { "uhi", "unsigned_intHI" }, + { "uqi", "unsigned_intQI" }, + { "usi", "unsigned_intSI" }, + { "uti", "unsigned_intTI" }, + { "uv16qi", "unsigned_V16QI" }, + { "uv1ti", "unsigned_V1TI" }, + { "uv2di", "unsigned_V2DI" }, + { "uv4si", "unsigned_V4SI" }, + { "uv8hi", "unsigned_V8HI" }, + { "v", "void" }, + { "v16qi", "V16QI" }, + { "v1ti", "V1TI" }, + { "v2df", "V2DF" }, + { "v2di", "V2DI" }, + { "v4sf", "V4SF" }, + { "v4si", "V4SI" }, + { "v8hi", "V8HI" }, + { "vb16qi", "bool_V16QI" }, + { "vb2di", "bool_V2DI" }, + { "vb4si", "bool_V4SI" }, + { "vb8hi", "bool_V8HI" }, + { "vp8hi", "pixel_V8HI" }, + }; + /* Pointer to a diagnostic function. */ void (*diag) (const char *, ...) __attribute__ ((format (printf, 1, 2))) = NULL; @@ -1761,6 +1807,80 @@ write_extern_fntype (char *str) fprintf (header_file, "extern tree %s;\n", str); } +void +write_fntype (char *str) +{ + fprintf (init_file, "tree %s;\n", str); +} + +/* Look up TOK in the type map and return the corresponding string used + to build the type node. */ +static const char * +map_token_to_type_node (char *tok) +{ + int low = 0; + int high = TYPE_MAP_SIZE - 1; + int mid = (low + high) >> 1; + int cmp; + + while ((cmp = strcmp (type_map[mid].key, tok)) && low < high) + { + if (cmp < 0) + low = (low == mid ? mid + 1 : mid); + else + high = (high == mid ? mid - 1: mid); + mid = (low + high) >> 1; + } + + if (low > high) + { + (*diag) ("token '%s' doesn't appear in the type map!\n", tok); + exit (EC_INTERR); + } + + return type_map[mid].value; +} + +/* Write the type node corresponding to TOK. */ +static void +write_type_node (char *tok) +{ + const char *str = map_token_to_type_node (tok); + fprintf (init_file, "%s_type_node", str); +} + +/* Write an initializer for a function type identified by STR. */ +void +write_fntype_init (char *str) +{ + char *tok; + + /* Avoid side effects of strtok on the original string by using a copy. */ + char *buf = (char *) malloc (strlen (str) + 1); + strcpy (buf, str); + + fprintf (init_file, " %s\n = build_function_type_list (", buf); + tok = strtok (buf, "_"); + write_type_node (tok); + tok = strtok (0, "_"); + assert (tok); + assert (!strcmp (tok, "ftype")); + + tok = strtok (0, "_"); + if (tok) + fprintf (init_file, ",\n\t\t\t\t"); + + /* Note: A function with no arguments ends with '_ftype_v'. */ + while (tok && strcmp (tok, "v")) + { + write_type_node (tok); + tok = strtok (0, "_"); + fprintf (init_file, ",\n\t\t\t\t"); + } + fprintf (init_file, "NULL_TREE);\n"); + free (buf); +} + /* Write everything to the header file (rs6000-bif.h). */ static int write_header_file () @@ -1784,10 +1904,257 @@ write_header_file () return 1; } +/* Write code to initialize the built-in function table. */ +static void +write_init_bif_table () +{ + int last_stanza = -1; + + for (int i = 0; i <= curr_bif; i++) + { + if (last_stanza != bifs[i].stanza) + { + if (last_stanza != -1) + fprintf (init_file, " }\n"); + fprintf (init_file, " if (%s)\n {\n", + bif_stanzas[bifs[i].stanza]); + last_stanza = bifs[i].stanza; + } + fprintf (init_file, + " rs6000_builtin_info_x[RS6000_BIF_%s].bifname" + "\n = \"%s\";\n", + bifs[i].idname, bifs[i].proto.bifname); + fprintf (init_file, + " rs6000_builtin_info_x[RS6000_BIF_%s].fntype" + "\n = %s;\n", + bifs[i].idname, bifs[i].fndecl); + fprintf (init_file, + " rs6000_builtin_info_x[RS6000_BIF_%s].icode" + "\n = CODE_FOR_%s;\n", + bifs[i].idname, bifs[i].patname); + fprintf (init_file, + " rs6000_builtin_info_x[RS6000_BIF_%s].bifattrs" + "\n = 0", + bifs[i].idname); + if (bifs[i].kind == FNK_CONST) + fprintf (init_file, " | bif_const_bit"); + else if (bifs[i].kind == FNK_PURE) + fprintf (init_file, " | bif_pure_bit"); + else if (bifs[i].kind == FNK_MATH) + fprintf (init_file, " | bif_round_bit"); + if (bifs[i].attrs.isinit) + fprintf (init_file, " | bif_init_bit"); + if (bifs[i].attrs.isset) + fprintf (init_file, " | bif_set_bit"); + if (bifs[i].attrs.isext) + fprintf (init_file, " | bif_ext_bit"); + if (bifs[i].attrs.isnosoft) + fprintf (init_file, " | bif_nosoft_bit"); + if (bifs[i].attrs.isldv) + fprintf (init_file, " | bif_ldv_bit"); + if (bifs[i].attrs.isstv) + fprintf (init_file, " | bif_stv_bit"); + if (bifs[i].attrs.isreve) + fprintf (init_file, " | bif_reve_bit"); + if (bifs[i].attrs.isabs) + fprintf (init_file, " | bif_abs_bit"); + if (bifs[i].attrs.ispred) + fprintf (init_file, " | bif_pred_bit"); + if (bifs[i].attrs.ishtm) + fprintf (init_file, " | bif_htm_bit"); + fprintf (init_file, ";\n"); + fprintf (init_file, + " rs6000_builtin_info_x[RS6000_BIF_%s].restr_opnd" + "\n = %d;\n", + bifs[i].idname, bifs[i].proto.restr_opnd); + if (bifs[i].proto.restr_opnd) + { + const char *res + = (bifs[i].proto.restr == RES_BITS ? "RES_BITS" + : (bifs[i].proto.restr == RES_RANGE ? "RES_RANGE" + : (bifs[i].proto.restr == RES_VALUES ? "RES_VALUES" + : "ERROR"))); + fprintf (init_file, + " rs6000_builtin_info_x[RS6000_BIF_%s].restr" + "\n = %s;\n", + bifs[i].idname, res); + fprintf (init_file, + " rs6000_builtin_info_x[RS6000_BIF_%s].restr_val1" + "\n = %d;\n", + bifs[i].idname, bifs[i].proto.restr_val1); + fprintf (init_file, + " rs6000_builtin_info_x[RS6000_BIF_%s].restr_val2" + "\n = %d;\n", + bifs[i].idname, bifs[i].proto.restr_val2); + } + fprintf (init_file, "\n"); + + fprintf (init_file, + " bifaddr = &rs6000_builtin_info_x[RS6000_BIF_%s];\n", + bifs[i].idname); + fprintf (init_file, + " hash = rs6000_bif_hasher::hash (bifaddr);\n"); + fprintf (init_file, + " slot = bif_hash.find_slot_with_hash (\n"); + fprintf (init_file, + " \"%s\", hash, INSERT\n", + bifs[i].proto.bifname); + fprintf (init_file, + " );\n"); + fprintf (init_file, + " *slot = bifaddr;\n\n"); + + fprintf (init_file, + "#ifdef NEW_BUILTINS_ARE_LIVE\n"); + fprintf (init_file, + " rs6000_builtin_decls[(int)RS6000_BIF_%s]\n", + bifs[i].idname); + fprintf (init_file, + " = add_builtin_function (\"%s\",\n", + bifs[i].proto.bifname); + fprintf (init_file, + " %s,\n", + bifs[i].fndecl); + fprintf (init_file, + " (int)RS6000_BIF_%s, NULL," + " NULL_TREE);\n", + bifs[i].idname); + fprintf (init_file, + "#endif\n"); + + if (i < curr_bif) + fprintf (init_file, "\n"); + } + fprintf (init_file, " }\n\n"); +} + +/* Write code to initialize the overload table. */ +static void +write_init_ovld_table () +{ + fprintf (init_file, " int base = RS6000_BIF_MAX;\n\n"); + + for (int i = 0; i <= curr_ovld; i++) + { + fprintf (init_file, + " rs6000_overload_info[RS6000_OVLD_%s - base].bifname" + "\n = \"%s\";\n", + ovlds[i].idname, ovlds[i].proto.bifname); + fprintf (init_file, + " rs6000_overload_info[RS6000_OVLD_%s - base].bifid" + "\n = RS6000_BIF_%s;\n", + ovlds[i].idname, ovlds[i].idname); + fprintf (init_file, + " rs6000_overload_info[RS6000_OVLD_%s - base].fntype" + "\n = %s;\n", + ovlds[i].idname, ovlds[i].fndecl); + fprintf (init_file, + " rs6000_overload_info[RS6000_OVLD_%s - base].next" + "\n = ", ovlds[i].idname); + if (i < curr_ovld + && !strcmp (ovlds[i+1].proto.bifname, ovlds[i].proto.bifname)) + fprintf (init_file, + "&rs6000_overload_info[RS6000_OVLD_%s - base];\n", + ovlds[i+1].idname); + else + fprintf (init_file, "NULL;\n"); + + if (i == 0 || ovlds[i].stanza != ovlds[i-1].stanza) + { + fprintf (init_file, "\n"); + + fprintf (init_file, + " ovldaddr = &rs6000_overload_info" + "[RS6000_OVLD_%s - base];\n", + ovlds[i].idname); + fprintf (init_file, + " hash = rs6000_ovld_hasher::hash (ovldaddr);\n"); + fprintf (init_file, + " oslot = ovld_hash.find_slot_with_hash (\n"); + fprintf (init_file, + " \"%s\", hash, INSERT\n", + ovlds[i].proto.bifname); + fprintf (init_file, + " );\n"); + fprintf (init_file, + " *oslot = ovldaddr;\n"); + } + + if (i < curr_ovld) + fprintf (init_file, "\n"); + } +} + /* Write everything to the initialization file (rs6000-bif.c). */ static int write_init_file () { + write_autogenerated_header (init_file); + + fprintf (init_file, "#include \"config.h\"\n"); + fprintf (init_file, "#include \"system.h\"\n"); + fprintf (init_file, "#include \"coretypes.h\"\n"); + fprintf (init_file, "#include \"backend.h\"\n"); + fprintf (init_file, "#include \"rtl.h\"\n"); + fprintf (init_file, "#include \"tree.h\"\n"); + fprintf (init_file, "#include \"insn-codes.h\"\n"); + fprintf (init_file, "#include \"rs6000-bif.h\"\n"); + fprintf (init_file, "\n"); + + fprintf (init_file, + "bifdata rs6000_builtin_info_x[RS6000_BIF_MAX];\n\n"); + fprintf (init_file, + "ovlddata rs6000_overload_info[RS6000_OVLD_MAX" + " - RS6000_BIF_MAX];\n\n"); + + rbt_inorder_callback (&fntype_rbt, fntype_rbt.rbt_root, write_fntype); + fprintf (init_file, "\n"); + + fprintf (init_file, "hashval_t\n"); + fprintf (init_file, "rs6000_bif_hasher::hash (bifdata *bd)\n"); + fprintf (init_file, "{\n"); + fprintf (init_file, " return htab_hash_string (bd->bifname);\n"); + fprintf (init_file, "}\n\n"); + + fprintf (init_file, "bool\n"); + fprintf (init_file, + "rs6000_bif_hasher::equal (bifdata *bd, const char *name)\n"); + fprintf (init_file, "{\n"); + fprintf (init_file, " return bd && name && !strcmp (bd->bifname, name);\n"); + fprintf (init_file, "}\n\n"); + + fprintf (init_file, "hash_table<rs6000_bif_hasher> bif_hash (1024);\n\n"); + + fprintf (init_file, "hashval_t\n"); + fprintf (init_file, "rs6000_ovld_hasher::hash (ovlddata *od)\n"); + fprintf (init_file, "{\n"); + fprintf (init_file, " return htab_hash_string (od->bifname);\n"); + fprintf (init_file, "}\n\n"); + + fprintf (init_file, "bool\n"); + fprintf (init_file, + "rs6000_ovld_hasher::equal (ovlddata *od, const char *name)\n"); + fprintf (init_file, "{\n"); + fprintf (init_file, " return od && name && !strcmp (od->bifname, name);\n"); + fprintf (init_file, "}\n\n"); + + fprintf (init_file, "hash_table<rs6000_ovld_hasher> ovld_hash (512);\n\n"); + + fprintf (init_file, "void\n"); + fprintf (init_file, "rs6000_autoinit_builtins ()\n"); + fprintf (init_file, "{\n"); + fprintf (init_file, " bifdata **slot;\n"); + fprintf (init_file, " bifdata *bifaddr;\n"); + fprintf (init_file, " hashval_t hash;\n"); + fprintf (init_file, " ovlddata **oslot;\n"); + fprintf (init_file, " ovlddata *ovldaddr;\n\n"); + rbt_inorder_callback (&fntype_rbt, fntype_rbt.rbt_root, write_fntype_init); + fprintf (init_file, "\n"); + + write_init_bif_table (); + write_init_ovld_table (); + + fprintf (init_file, "}\n"); return 1; } -- 2.17.1