read-rtl.c: split out read_rtx_operand from read_rtx_code

gcc/ChangeLog:
	* 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.

From-SVN: r240502
This commit is contained in:
David Malcolm 2016-09-26 16:39:15 +00:00 committed by David Malcolm
parent 2fd88f4ff2
commit f22735ae61
2 changed files with 218 additions and 193 deletions

View File

@ -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.

View File

@ -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