/* Generate code from machine description to extract operands from insn as rtl.
- Copyright (C) 1987-2015 Free Software Foundation, Inc.
+ Copyright (C) 1987-2020 Free Software Foundation, Inc.
This file is part of GCC.
#include "errors.h"
#include "read-md.h"
#include "gensupport.h"
-#include "vec.h"
/* This structure contains all the information needed to describe one
set of extractions methods. Each method may be used by more than
The string for each operand describes that path to the operand and
contains `0' through `9' when going into an expression and `a' through
- `z' when going into a vector. We assume here that only the first operand
- of an rtl expression is a vector. genrecog.c makes the same assumption
- (and uses the same representation) and it is currently true. */
+ `z' then 'A' through to 'Z' when going into a vector. We assume here that
+ only the first operand of an rtl expression is a vector. genrecog.c makes
+ the same assumption (and uses the same representation) and it is currently
+ true. */
typedef char *locstr;
data that will be used to produce an extractions structure. */
-struct accum_extract
+class accum_extract
{
- vec<locstr> oplocs;
- vec<locstr> duplocs;
- vec<int> dupnums;
- vec<char> pathstr;
-};
+public:
+ accum_extract () : oplocs (10), duplocs (10), dupnums (10), pathstr (20) {}
-int line_no;
+ auto_vec<locstr> oplocs;
+ auto_vec<locstr> duplocs;
+ auto_vec<int> dupnums;
+ auto_vec<char> pathstr;
+};
/* Forward declarations. */
-static void walk_rtx (rtx, struct accum_extract *);
+static void walk_rtx (md_rtx_info *, rtx, class accum_extract *);
+
+#define UPPER_OFFSET ('A' - ('z' - 'a' + 1))
+/* Convert integer OPERAND into a character - either into [a-zA-Z] for vector
+ operands or [0-9] for integer operands - and push onto the end of the path
+ in ACC. */
static void
-gen_insn (rtx insn, int insn_code_number)
+push_pathstr_operand (int operand, bool is_vector,
+ class accum_extract *acc)
+{
+ if (is_vector && 'a' + operand > 'z')
+ acc->pathstr.safe_push (operand + UPPER_OFFSET);
+ else if (is_vector)
+ acc->pathstr.safe_push (operand + 'a');
+ else
+ acc->pathstr.safe_push (operand + '0');
+}
+
+static void
+gen_insn (md_rtx_info *info)
{
int i;
unsigned int op_count, dup_count, j;
struct extraction *p;
struct code_ptr *link;
- struct accum_extract acc;
-
- acc.oplocs.create (10);
- acc.duplocs.create (10);
- acc.dupnums.create (10);
- acc.pathstr.create (20);
+ class accum_extract acc;
/* Walk the insn's pattern, remembering at all times the path
down to the walking point. */
+ rtx insn = info->def;
if (XVECLEN (insn, 1) == 1)
- walk_rtx (XVECEXP (insn, 1, 0), &acc);
+ walk_rtx (info, XVECEXP (insn, 1, 0), &acc);
else
for (i = XVECLEN (insn, 1) - 1; i >= 0; i--)
{
- acc.pathstr.safe_push ('a' + i);
- walk_rtx (XVECEXP (insn, 1, i), &acc);
+ push_pathstr_operand (i, true, &acc);
+ walk_rtx (info, XVECEXP (insn, 1, i), &acc);
acc.pathstr.pop ();
}
link = XNEW (struct code_ptr);
- link->insn_code = insn_code_number;
+ link->insn_code = info->index;
/* See if we find something that already had this extraction method. */
/* This extraction is the same as ours. Just link us in. */
link->next = p->insns;
p->insns = link;
- goto done;
+ return;
}
/* Otherwise, make a new extraction method. We stash the arrays
memcpy (p->oplocs, acc.oplocs.address (), op_count * sizeof (locstr));
memcpy (p->duplocs, acc.duplocs.address (), dup_count * sizeof (locstr));
memcpy (p->dupnums, acc.dupnums.address (), dup_count * sizeof (int));
-
- done:
- acc.oplocs.release ();
- acc.duplocs.release ();
- acc.dupnums.release ();
- acc.pathstr.release ();
}
\f
/* Helper subroutine of walk_rtx: given a vec<locstr>, an index, and a
string, insert the string at the index, which should either already
exist and be NULL, or not yet exist within the vector. In the latter
- case the vector is enlarged as appropriate. */
+ case the vector is enlarged as appropriate. INFO describes the
+ containing define_* expression. */
static void
-VEC_safe_set_locstr (vec<locstr> *vp, unsigned int ix, char *str)
+VEC_safe_set_locstr (md_rtx_info *info, vec<locstr> *vp,
+ unsigned int ix, char *str)
{
if (ix < (*vp).length ())
{
if ((*vp)[ix])
{
- message_with_line (line_no, "repeated operand number %d", ix);
+ message_at (info->loc, "repeated operand number %d", ix);
have_error = 1;
}
else
}
static void
-walk_rtx (rtx x, struct accum_extract *acc)
+walk_rtx (md_rtx_info *info, rtx x, class accum_extract *acc)
{
RTX_CODE code;
- int i, len, base;
+ int i, len;
const char *fmt;
if (x == 0)
case MATCH_OPERAND:
case MATCH_SCRATCH:
- VEC_safe_set_locstr (&acc->oplocs, XINT (x, 0),
+ VEC_safe_set_locstr (info, &acc->oplocs, XINT (x, 0),
VEC_char_to_string (acc->pathstr));
break;
case MATCH_OPERATOR:
case MATCH_PARALLEL:
- VEC_safe_set_locstr (&acc->oplocs, XINT (x, 0),
+ VEC_safe_set_locstr (info, &acc->oplocs, XINT (x, 0),
VEC_char_to_string (acc->pathstr));
- base = (code == MATCH_OPERATOR ? '0' : 'a');
for (i = XVECLEN (x, 2) - 1; i >= 0; i--)
{
- acc->pathstr.safe_push (base + i);
- walk_rtx (XVECEXP (x, 2, i), acc);
+ push_pathstr_operand (i, code != MATCH_OPERATOR, acc);
+ walk_rtx (info, XVECEXP (x, 2, i), acc);
acc->pathstr.pop ();
}
return;
if (code == MATCH_DUP)
break;
- base = (code == MATCH_OP_DUP ? '0' : 'a');
for (i = XVECLEN (x, 1) - 1; i >= 0; i--)
{
- acc->pathstr.safe_push (base + i);
- walk_rtx (XVECEXP (x, 1, i), acc);
+ push_pathstr_operand (i, code != MATCH_OP_DUP, acc);
+ walk_rtx (info, XVECEXP (x, 1, i), acc);
acc->pathstr.pop ();
}
return;
{
if (fmt[i] == 'e' || fmt[i] == 'u')
{
- acc->pathstr.safe_push ('0' + i);
- walk_rtx (XEXP (x, i), acc);
+ push_pathstr_operand (i, false, acc);
+ walk_rtx (info, XEXP (x, i), acc);
acc->pathstr.pop ();
}
else if (fmt[i] == 'E')
int j;
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
{
- acc->pathstr.safe_push ('a' + j);
- walk_rtx (XVECEXP (x, i, j), acc);
+ push_pathstr_operand (j, true, acc);
+ walk_rtx (info, XVECEXP (x, i, j), acc);
acc->pathstr.pop ();
}
}
for (i = len - 1; i >= 0 ; i--)
{
- if (ISLOWER (path[i]))
+ if (ISLOWER (path[i]) || ISUPPER (path[i]))
fputs ("XVECEXP (", stdout);
else if (ISDIGIT (path[i]))
fputs ("XEXP (", stdout);
for (i = 0; i < len; i++)
{
- if (ISLOWER (path[i]))
+ if (ISUPPER (path[i]))
+ printf (", 0, %d)", path[i] - UPPER_OFFSET);
+ else if (ISLOWER (path[i]))
printf (", 0, %d)", path[i] - 'a');
else if (ISDIGIT (path[i]))
printf (", %d)", path[i] - '0');
/* Generated automatically by the program `genextract'\n\
from the machine description file `md'. */\n\
\n\
+#define IN_TARGET_CODE 1\n\
#include \"config.h\"\n\
#include \"system.h\"\n\
#include \"coretypes.h\"\n\
rtx pat = PATTERN (insn);\n\
int i ATTRIBUTE_UNUSED; /* only for peepholes */\n\
\n\
-#ifdef ENABLE_CHECKING\n\
- memset (ro, 0xab, sizeof (*ro) * MAX_RECOG_OPERANDS);\n\
- memset (ro_loc, 0xab, sizeof (*ro_loc) * MAX_RECOG_OPERANDS);\n\
-#endif\n");
+ if (flag_checking)\n\
+ {\n\
+ memset (ro, 0xab, sizeof (*ro) * MAX_RECOG_OPERANDS);\n\
+ memset (ro_loc, 0xab, sizeof (*ro_loc) * MAX_RECOG_OPERANDS);\n\
+ }\n");
puts ("\
switch (INSN_CODE (insn))\n\
}
int
-main (int argc, char **argv)
+main (int argc, const char **argv)
{
- rtx desc;
unsigned int i;
struct extraction *p;
struct code_ptr *link;
const char *name;
- int insn_code_number;
progname = "genextract";
/* Read the machine description. */
- while ((desc = read_md_rtx (&line_no, &insn_code_number)) != NULL)
- {
- if (GET_CODE (desc) == DEFINE_INSN)
- gen_insn (desc, insn_code_number);
+ md_rtx_info info;
+ while (read_md_rtx (&info))
+ switch (GET_CODE (info.def))
+ {
+ case DEFINE_INSN:
+ gen_insn (&info);
+ break;
- else if (GET_CODE (desc) == DEFINE_PEEPHOLE)
+ case DEFINE_PEEPHOLE:
{
struct code_ptr *link = XNEW (struct code_ptr);
- link->insn_code = insn_code_number;
+ link->insn_code = info.index;
link->next = peepholes;
peepholes = link;
}
+ break;
+
+ default:
+ break;
}
if (have_error)