Mercurial > hg > CbC > CbC_gcc
diff gcc/read-rtl.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
line wrap: on
line diff
--- a/gcc/read-rtl.c Fri Oct 27 22:46:09 2017 +0900 +++ b/gcc/read-rtl.c Thu Oct 25 07:37:49 2018 +0900 @@ -1,5 +1,5 @@ /* RTL reader for GCC. - Copyright (C) 1987-2017 Free Software Foundation, Inc. + Copyright (C) 1987-2018 Free Software Foundation, Inc. This file is part of GCC. @@ -72,6 +72,9 @@ iterators. */ htab_t attrs, iterators; + /* The C++ type of the iterator, such as "machine_mode" for modes. */ + const char *type; + /* Treat the given string as the name of a standard mode, etc., and return its integer value. */ int (*find_builtin) (const char *); @@ -80,6 +83,9 @@ If the iterator applies to operands, the second argument gives the operand index, otherwise it is ignored. */ void (*apply_iterator) (rtx, unsigned int, int); + + /* Return the C token for the given standard mode, code, etc. */ + const char *(*get_c_token) (int); }; /* Records one use of an iterator. */ @@ -163,6 +169,12 @@ PUT_MODE (x, (machine_mode) mode); } +static const char * +get_mode_token (int mode) +{ + return concat ("E_", GET_MODE_NAME (mode), "mode", NULL); +} + /* In compact dumps, the code of insns is prefixed with "c", giving "cinsn", "cnote" etc, and CODE_LABEL is special-cased as "clabel". */ @@ -206,6 +218,15 @@ PUT_CODE (x, (enum rtx_code) code); } +static const char * +get_code_token (int code) +{ + char *name = xstrdup (GET_RTX_NAME (code)); + for (int i = 0; name[i]; ++i) + name[i] = TOUPPER (name[i]); + return name; +} + /* Implementations of the iterator_group callbacks for ints. */ /* Since GCC does not construct a table of valid constants, @@ -222,7 +243,18 @@ static void apply_int_iterator (rtx x, unsigned int index, int value) { - XINT (x, index) = value; + if (GET_CODE (x) == SUBREG) + SUBREG_BYTE (x) = value; + else + XINT (x, index) = value; +} + +static const char * +get_int_token (int value) +{ + char buffer[HOST_BITS_PER_INT + 1]; + sprintf (buffer, "%d", value); + return xstrdup (buffer); } #ifdef GENERATOR_FILE @@ -314,10 +346,11 @@ } /* Map attribute string P to its current value. Return null if the attribute - isn't known. */ + isn't known. If ITERATOR_OUT is nonnull, store the associated iterator + there. */ static struct map_value * -map_attr_string (const char *p) +map_attr_string (const char *p, mapping **iterator_out = 0) { const char *attr; struct mapping *iterator; @@ -366,7 +399,11 @@ iterator value. */ for (v = m->values; v; v = v->next) if (v->number == iterator->current_value->number) - return v; + { + if (iterator_out) + *iterator_out = iterator; + return v; + } } } return NULL; @@ -542,6 +579,178 @@ return 1; } +/* Return a hash value for overloaded_name UNCAST_ONAME. There shouldn't + be many instances of two overloaded_names having the same name but + different arguments, so hashing on the name should be good enough in + practice. */ + +static hashval_t +overloaded_name_hash (const void *uncast_oname) +{ + const overloaded_name *oname = (const overloaded_name *) uncast_oname; + return htab_hash_string (oname->name); +} + +/* Return true if two overloaded_names are similar enough to share + the same generated functions. */ + +static int +overloaded_name_eq_p (const void *uncast_oname1, const void *uncast_oname2) +{ + const overloaded_name *oname1 = (const overloaded_name *) uncast_oname1; + const overloaded_name *oname2 = (const overloaded_name *) uncast_oname2; + if (strcmp (oname1->name, oname2->name) != 0 + || oname1->arg_types.length () != oname2->arg_types.length ()) + return 0; + + for (unsigned int i = 0; i < oname1->arg_types.length (); ++i) + if (strcmp (oname1->arg_types[i], oname2->arg_types[i]) != 0) + return 0; + + return 1; +} + +/* Return true if X has an instruction name in XSTR (X, 0). */ + +static bool +named_rtx_p (rtx x) +{ + switch (GET_CODE (x)) + { + case DEFINE_EXPAND: + case DEFINE_INSN: + case DEFINE_INSN_AND_SPLIT: + return true; + + default: + return false; + } +} + +/* Check whether ORIGINAL is a named pattern whose name starts with '@'. + If so, return the associated overloaded_name and add the iterator for + each argument to ITERATORS. Return null otherwise. */ + +overloaded_name * +md_reader::handle_overloaded_name (rtx original, vec<mapping *> *iterators) +{ + /* Check for the leading '@'. */ + if (!named_rtx_p (original) || XSTR (original, 0)[0] != '@') + return NULL; + + /* Remove the '@', so that no other code needs to worry about it. */ + const char *name = XSTR (original, 0); + copy_md_ptr_loc (name + 1, name); + name += 1; + XSTR (original, 0) = name; + + /* Build a copy of the name without the '<...>' attribute strings. + Add the iterator associated with each such attribute string to ITERATORS + and add an associated argument to TMP_ONAME. */ + char *copy = ASTRDUP (name); + char *base = copy, *start, *end; + overloaded_name tmp_oname; + tmp_oname.arg_types.create (current_iterators.length ()); + bool pending_underscore_p = false; + while ((start = strchr (base, '<')) && (end = strchr (start, '>'))) + { + *end = 0; + mapping *iterator; + if (!map_attr_string (start + 1, &iterator)) + fatal_with_file_and_line ("unknown iterator `%s'", start + 1); + *end = '>'; + + /* Remove a trailing underscore, so that we don't end a name + with "_" or turn "_<...>_" into "__". */ + if (start != base && start[-1] == '_') + { + start -= 1; + pending_underscore_p = true; + } + + /* Add the text between either the last '>' or the start of + the string and this '<'. */ + obstack_grow (&m_string_obstack, base, start - base); + base = end + 1; + + /* If there's a character we need to keep after the '>', check + whether we should prefix it with a previously-dropped '_'. */ + if (base[0] != 0 && base[0] != '<') + { + if (pending_underscore_p && base[0] != '_') + obstack_1grow (&m_string_obstack, '_'); + pending_underscore_p = false; + } + + /* Record an argument for ITERATOR. */ + iterators->safe_push (iterator); + tmp_oname.arg_types.safe_push (iterator->group->type); + } + if (base == copy) + fatal_with_file_and_line ("no iterator attributes in name `%s'", name); + + size_t length = obstack_object_size (&m_string_obstack); + if (length == 0) + fatal_with_file_and_line ("`%s' only contains iterator attributes", name); + + /* Get the completed name. */ + obstack_grow (&m_string_obstack, base, strlen (base) + 1); + char *new_name = XOBFINISH (&m_string_obstack, char *); + tmp_oname.name = new_name; + + if (!m_overloads_htab) + m_overloads_htab = htab_create (31, overloaded_name_hash, + overloaded_name_eq_p, NULL); + + /* See whether another pattern had the same overload name and list + of argument types. Create a new permanent one if not. */ + void **slot = htab_find_slot (m_overloads_htab, &tmp_oname, INSERT); + overloaded_name *oname = (overloaded_name *) *slot; + if (!oname) + { + *slot = oname = new overloaded_name; + oname->name = tmp_oname.name; + oname->arg_types = tmp_oname.arg_types; + oname->next = NULL; + oname->first_instance = NULL; + oname->next_instance_ptr = &oname->first_instance; + + *m_next_overload_ptr = oname; + m_next_overload_ptr = &oname->next; + } + else + { + obstack_free (&m_string_obstack, new_name); + tmp_oname.arg_types.release (); + } + + return oname; +} + +/* Add an instance of ONAME for instruction pattern X. ITERATORS[I] + gives the iterator associated with argument I of ONAME. */ + +static void +add_overload_instance (overloaded_name *oname, vec<mapping *> iterators, rtx x) +{ + /* Create the instance. */ + overloaded_instance *instance = new overloaded_instance; + instance->next = NULL; + instance->arg_values.create (oname->arg_types.length ()); + for (unsigned int i = 0; i < iterators.length (); ++i) + { + int value = iterators[i]->current_value->number; + const char *name = iterators[i]->group->get_c_token (value); + instance->arg_values.quick_push (name); + } + instance->name = XSTR (x, 0); + instance->insn = x; + + /* Chain it onto the end of ONAME's list. */ + *oname->next_instance_ptr = instance; + oname->next_instance_ptr = &instance->next; +} + /* Expand all iterators in the current rtx, which is given as ORIGINAL. Build a list of expanded rtxes in the EXPR_LIST pointed to by QUEUE. */ @@ -559,6 +768,10 @@ { /* Raise an error if any attributes were used. */ apply_attribute_uses (); + + if (named_rtx_p (original) && XSTR (original, 0)[0] == '@') + fatal_with_file_and_line ("'@' used without iterators"); + queue->safe_push (original); return; } @@ -580,6 +793,11 @@ htab_traverse (substs.iterators, add_current_iterators, NULL); gcc_assert (!current_iterators.is_empty ()); + /* Check whether this is a '@' overloaded pattern. */ + auto_vec<mapping *, 16> iterators; + overloaded_name *oname + = rtx_reader_ptr->handle_overloaded_name (original, &iterators); + for (;;) { /* Apply the current iterator values. Accumulate a condition to @@ -613,6 +831,10 @@ v->number); } } + + if (oname) + add_overload_instance (oname, iterators, x); + /* Add the new rtx to the end of the queue. */ queue->safe_push (x); @@ -689,28 +911,36 @@ modes.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0); modes.iterators = htab_create (13, leading_string_hash, leading_string_eq_p, 0); + modes.type = "machine_mode"; modes.find_builtin = find_mode; modes.apply_iterator = apply_mode_iterator; + modes.get_c_token = get_mode_token; codes.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0); codes.iterators = htab_create (13, leading_string_hash, leading_string_eq_p, 0); + codes.type = "rtx_code"; codes.find_builtin = find_code; codes.apply_iterator = apply_code_iterator; + codes.get_c_token = get_code_token; ints.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0); ints.iterators = htab_create (13, leading_string_hash, leading_string_eq_p, 0); + ints.type = "int"; ints.find_builtin = find_int; ints.apply_iterator = apply_int_iterator; + ints.get_c_token = get_int_token; substs.attrs = htab_create (13, leading_string_hash, leading_string_eq_p, 0); substs.iterators = htab_create (13, leading_string_hash, leading_string_eq_p, 0); + substs.type = "int"; substs.find_builtin = find_int; /* We don't use it, anyway. */ #ifdef GENERATOR_FILE substs.apply_iterator = apply_subst_iterator; #endif + substs.get_c_token = get_int_token; lower = add_mapping (&modes, modes.attrs, "mode"); upper = add_mapping (&modes, modes.attrs, "MODE"); @@ -1229,7 +1459,7 @@ parse_reg_note_name (const char *string) { for (int i = 0; i < REG_NOTE_MAX; i++) - if (0 == strcmp (string, GET_REG_NOTE_NAME (i))) + if (strcmp (string, GET_REG_NOTE_NAME (i)) == 0) return i; fatal_with_file_and_line ("unrecognized REG_NOTE name: `%s'", string); } @@ -1460,6 +1690,7 @@ struct obstack vector_stack; int list_counter = 0; rtvec return_vec = NULL_RTVEC; + rtx saved_rtx = NULL_RTX; require_char_ws ('['); @@ -1470,8 +1701,34 @@ if (c == EOF) fatal_expected_char (']', c); unread_char (c); - list_counter++; - obstack_ptr_grow (&vector_stack, read_nested_rtx ()); + + rtx value; + int repeat_count = 1; + if (c == 'r') + { + /* Process "repeated xN" directive. */ + read_name (&name); + if (strcmp (name.string, "repeated")) + fatal_with_file_and_line ("invalid directive \"%s\"\n", + name.string); + read_name (&name); + if (!sscanf (name.string, "x%d", &repeat_count)) + fatal_with_file_and_line ("invalid repeat count \"%s\"\n", + name.string); + + /* We already saw one of the instances. */ + repeat_count--; + value = saved_rtx; + } + else + value = read_nested_rtx (); + + for (; repeat_count > 0; repeat_count--) + { + list_counter++; + obstack_ptr_grow (&vector_stack, value); + } + saved_rtx = value; } if (list_counter > 0) { @@ -1608,6 +1865,7 @@ case 'i': case 'n': + case 'p': /* Can be an iterator or an integer constant. */ read_name (&name); record_potential_iterator_use (&ints, return_rtx, idx, name.string);