diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 289a9759a2a..e88c6641d55 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2016-09-26 David Malcolm <dmalcolm@redhat.com> + + * read-rtl.c (read_rtx_code): Rename local "i" to "idx", and use + "c" instead when parsing characters. Move operand parsing into... + (read_rtx_operand): ...this new function, renaming "i" to "idx", + and tightening the scope of various locals. + 2016-09-26 LH Mouse <lh_mouse@126.com> * config/i386/cygming.h (ASM_OUTPUT_DWARF_OFFSET): Fix typo. diff --git a/gcc/read-rtl.c b/gcc/read-rtl.c index eda938265c5..925ea451c9d 100644 --- a/gcc/read-rtl.c +++ b/gcc/read-rtl.c @@ -107,6 +107,7 @@ const char *current_iterator_name; static void validate_const_int (const char *); static rtx read_rtx_code (const char *); +static void read_rtx_operand (rtx, int); static rtx read_nested_rtx (void); static rtx read_rtx_variadic (rtx); @@ -1089,17 +1090,12 @@ read_rtx (const char *rtx_name, vec<rtx> *rtxen) static rtx read_rtx_code (const char *code_name) { - int i; RTX_CODE code; - struct mapping *iterator, *m; + struct mapping *iterator; const char *format_ptr; struct md_name name; rtx return_rtx; int c; - HOST_WIDE_INT tmp_wide; - char *str; - char *start, *end, *ptr; - char tmpstr[256]; /* Linked list structure for making RTXs: */ struct rtx_list @@ -1128,199 +1124,17 @@ read_rtx_code (const char *code_name) /* If what follows is `: mode ', read it and store the mode in the rtx. */ - i = read_skip_spaces (); - if (i == ':') + c = read_skip_spaces (); + if (c == ':') { read_name (&name); record_potential_iterator_use (&modes, return_rtx, name.string); } else - unread_char (i); + unread_char (c); - for (i = 0; format_ptr[i] != 0; i++) - switch (format_ptr[i]) - { - /* 0 means a field for internal use only. - Don't expect it to be present in the input. */ - case '0': - if (code == REG) - ORIGINAL_REGNO (return_rtx) = REGNO (return_rtx); - break; - - case 'e': - case 'u': - XEXP (return_rtx, i) = read_nested_rtx (); - break; - - case 'V': - /* 'V' is an optional vector: if a closeparen follows, - just store NULL for this element. */ - c = read_skip_spaces (); - unread_char (c); - if (c == ')') - { - XVEC (return_rtx, i) = 0; - break; - } - /* Now process the vector. */ - /* FALLTHRU */ - - case 'E': - { - /* Obstack to store scratch vector in. */ - struct obstack vector_stack; - int list_counter = 0; - rtvec return_vec = NULL_RTVEC; - - require_char_ws ('['); - - /* Add expressions to a list, while keeping a count. */ - obstack_init (&vector_stack); - while ((c = read_skip_spaces ()) && c != ']') - { - if (c == EOF) - fatal_expected_char (']', c); - unread_char (c); - list_counter++; - obstack_ptr_grow (&vector_stack, read_nested_rtx ()); - } - if (list_counter > 0) - { - return_vec = rtvec_alloc (list_counter); - memcpy (&return_vec->elem[0], obstack_finish (&vector_stack), - list_counter * sizeof (rtx)); - } - else if (format_ptr[i] == 'E') - fatal_with_file_and_line ("vector must have at least one element"); - XVEC (return_rtx, i) = return_vec; - obstack_free (&vector_stack, NULL); - /* close bracket gotten */ - } - break; - - case 'S': - case 'T': - case 's': - { - char *stringbuf; - int star_if_braced; - - c = read_skip_spaces (); - unread_char (c); - if (c == ')') - { - /* 'S' fields are optional and should be NULL if no string - was given. Also allow normal 's' and 'T' strings to be - omitted, treating them in the same way as empty strings. */ - XSTR (return_rtx, i) = (format_ptr[i] == 'S' ? NULL : ""); - break; - } - - /* The output template slot of a DEFINE_INSN, - DEFINE_INSN_AND_SPLIT, or DEFINE_PEEPHOLE automatically - gets a star inserted as its first character, if it is - written with a brace block instead of a string constant. */ - star_if_braced = (format_ptr[i] == 'T'); - - stringbuf = read_string (star_if_braced); - - /* For insn patterns, we want to provide a default name - based on the file and line, like "*foo.md:12", if the - given name is blank. These are only for define_insn and - define_insn_and_split, to aid debugging. */ - if (*stringbuf == '\0' - && i == 0 - && (GET_CODE (return_rtx) == DEFINE_INSN - || GET_CODE (return_rtx) == DEFINE_INSN_AND_SPLIT)) - { - char line_name[20]; - const char *read_md_filename = rtx_reader_ptr->get_filename (); - const char *fn = (read_md_filename ? read_md_filename : "rtx"); - const char *slash; - for (slash = fn; *slash; slash ++) - if (*slash == '/' || *slash == '\\' || *slash == ':') - fn = slash + 1; - obstack_1grow (&string_obstack, '*'); - obstack_grow (&string_obstack, fn, strlen (fn)); - sprintf (line_name, ":%d", rtx_reader_ptr->get_lineno ()); - obstack_grow (&string_obstack, line_name, strlen (line_name)+1); - stringbuf = XOBFINISH (&string_obstack, char *); - } - - /* Find attr-names in the string. */ - ptr = &tmpstr[0]; - end = stringbuf; - while ((start = strchr (end, '<')) && (end = strchr (start, '>'))) - { - if ((end - start - 1 > 0) - && (end - start - 1 < (int)sizeof (tmpstr))) - { - strncpy (tmpstr, start+1, end-start-1); - tmpstr[end-start-1] = 0; - end++; - } - else - break; - m = (struct mapping *) htab_find (substs.attrs, &ptr); - if (m != 0) - { - /* Here we should find linked subst-iter. */ - str = find_subst_iter_by_attr (ptr); - if (str) - m = (struct mapping *) htab_find (substs.iterators, &str); - else - m = 0; - } - if (m != 0) - record_iterator_use (m, return_rtx); - } - - if (star_if_braced) - XTMPL (return_rtx, i) = stringbuf; - else - XSTR (return_rtx, i) = stringbuf; - } - break; - - case 'w': - read_name (&name); - validate_const_int (name.string); -#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT - tmp_wide = atoi (name.string); -#else -#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG - tmp_wide = atol (name.string); -#else - /* Prefer atoll over atoq, since the former is in the ISO C99 standard. - But prefer not to use our hand-rolled function above either. */ -#if HAVE_DECL_ATOLL || !defined(HAVE_ATOQ) - tmp_wide = atoll (name.string); -#else - tmp_wide = atoq (name.string); -#endif -#endif -#endif - XWINT (return_rtx, i) = tmp_wide; - break; - - case 'i': - case 'n': - /* Can be an iterator or an integer constant. */ - read_name (&name); - record_potential_iterator_use (&ints, &XINT (return_rtx, i), - name.string); - break; - - case 'r': - read_name (&name); - validate_const_int (name.string); - set_regno_raw (return_rtx, atoi (name.string), 1); - REG_ATTRS (return_rtx) = NULL; - break; - - default: - gcc_unreachable (); - } + for (int idx = 0; format_ptr[idx] != 0; idx++) + read_rtx_operand (return_rtx, idx); if (CONST_WIDE_INT_P (return_rtx)) { @@ -1382,6 +1196,210 @@ read_rtx_code (const char *code_name) return return_rtx; } +/* Subroutine of read_rtx_code. Parse operand IDX within RETURN_RTX, + based on the corresponding format character within GET_RTX_FORMAT + for the GET_CODE (RETURN_RTX). */ + +static void +read_rtx_operand (rtx return_rtx, int idx) +{ + RTX_CODE code = GET_CODE (return_rtx); + const char *format_ptr = GET_RTX_FORMAT (code); + int c; + struct md_name name; + + switch (format_ptr[idx]) + { + /* 0 means a field for internal use only. + Don't expect it to be present in the input. */ + case '0': + if (code == REG) + ORIGINAL_REGNO (return_rtx) = REGNO (return_rtx); + break; + + case 'e': + case 'u': + XEXP (return_rtx, idx) = read_nested_rtx (); + break; + + case 'V': + /* 'V' is an optional vector: if a closeparen follows, + just store NULL for this element. */ + c = read_skip_spaces (); + unread_char (c); + if (c == ')') + { + XVEC (return_rtx, idx) = 0; + break; + } + /* Now process the vector. */ + /* FALLTHRU */ + + case 'E': + { + /* Obstack to store scratch vector in. */ + struct obstack vector_stack; + int list_counter = 0; + rtvec return_vec = NULL_RTVEC; + + require_char_ws ('['); + + /* Add expressions to a list, while keeping a count. */ + obstack_init (&vector_stack); + while ((c = read_skip_spaces ()) && c != ']') + { + if (c == EOF) + fatal_expected_char (']', c); + unread_char (c); + list_counter++; + obstack_ptr_grow (&vector_stack, read_nested_rtx ()); + } + if (list_counter > 0) + { + return_vec = rtvec_alloc (list_counter); + memcpy (&return_vec->elem[0], obstack_finish (&vector_stack), + list_counter * sizeof (rtx)); + } + else if (format_ptr[idx] == 'E') + fatal_with_file_and_line ("vector must have at least one element"); + XVEC (return_rtx, idx) = return_vec; + obstack_free (&vector_stack, NULL); + /* close bracket gotten */ + } + break; + + case 'S': + case 'T': + case 's': + { + char *stringbuf; + int star_if_braced; + + c = read_skip_spaces (); + unread_char (c); + if (c == ')') + { + /* 'S' fields are optional and should be NULL if no string + was given. Also allow normal 's' and 'T' strings to be + omitted, treating them in the same way as empty strings. */ + XSTR (return_rtx, idx) = (format_ptr[idx] == 'S' ? NULL : ""); + break; + } + + /* The output template slot of a DEFINE_INSN, + DEFINE_INSN_AND_SPLIT, or DEFINE_PEEPHOLE automatically + gets a star inserted as its first character, if it is + written with a brace block instead of a string constant. */ + star_if_braced = (format_ptr[idx] == 'T'); + + stringbuf = read_string (star_if_braced); + + /* For insn patterns, we want to provide a default name + based on the file and line, like "*foo.md:12", if the + given name is blank. These are only for define_insn and + define_insn_and_split, to aid debugging. */ + if (*stringbuf == '\0' + && idx == 0 + && (GET_CODE (return_rtx) == DEFINE_INSN + || GET_CODE (return_rtx) == DEFINE_INSN_AND_SPLIT)) + { + char line_name[20]; + const char *read_md_filename = rtx_reader_ptr->get_filename (); + const char *fn = (read_md_filename ? read_md_filename : "rtx"); + const char *slash; + for (slash = fn; *slash; slash ++) + if (*slash == '/' || *slash == '\\' || *slash == ':') + fn = slash + 1; + obstack_1grow (&string_obstack, '*'); + obstack_grow (&string_obstack, fn, strlen (fn)); + sprintf (line_name, ":%d", rtx_reader_ptr->get_lineno ()); + obstack_grow (&string_obstack, line_name, strlen (line_name)+1); + stringbuf = XOBFINISH (&string_obstack, char *); + } + + /* Find attr-names in the string. */ + char *str; + char *start, *end, *ptr; + char tmpstr[256]; + ptr = &tmpstr[0]; + end = stringbuf; + while ((start = strchr (end, '<')) && (end = strchr (start, '>'))) + { + if ((end - start - 1 > 0) + && (end - start - 1 < (int)sizeof (tmpstr))) + { + strncpy (tmpstr, start+1, end-start-1); + tmpstr[end-start-1] = 0; + end++; + } + else + break; + struct mapping *m + = (struct mapping *) htab_find (substs.attrs, &ptr); + if (m != 0) + { + /* Here we should find linked subst-iter. */ + str = find_subst_iter_by_attr (ptr); + if (str) + m = (struct mapping *) htab_find (substs.iterators, &str); + else + m = 0; + } + if (m != 0) + record_iterator_use (m, return_rtx); + } + + if (star_if_braced) + XTMPL (return_rtx, idx) = stringbuf; + else + XSTR (return_rtx, idx) = stringbuf; + } + break; + + case 'w': + { + HOST_WIDE_INT tmp_wide; + read_name (&name); + validate_const_int (name.string); +#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT + tmp_wide = atoi (name.string); +#else +#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG + tmp_wide = atol (name.string); +#else + /* Prefer atoll over atoq, since the former is in the ISO C99 standard. + But prefer not to use our hand-rolled function above either. */ +#if HAVE_DECL_ATOLL || !defined(HAVE_ATOQ) + tmp_wide = atoll (name.string); +#else + tmp_wide = atoq (name.string); +#endif +#endif +#endif + XWINT (return_rtx, idx) = tmp_wide; + } + break; + + case 'i': + case 'n': + /* Can be an iterator or an integer constant. */ + read_name (&name); + record_potential_iterator_use (&ints, &XINT (return_rtx, idx), + name.string); + break; + + case 'r': + read_name (&name); + validate_const_int (name.string); + set_regno_raw (return_rtx, atoi (name.string), 1); + REG_ATTRS (return_rtx) = NULL; + break; + + default: + gcc_unreachable (); + } +} + /* Read a nested rtx construct from the MD file and return it. */ static rtx