#include "gimple.h"
#include "gimple-ssa.h"
#include "gimplify.h"
+#include "bbitmap.h"
struct target_rtl default_target_rtl;
#if SWITCHABLE_TARGET
return gen_int_mode (value, shift_mode);
}
+namespace {
+/* Helper class for expanding an rtx using the encoding generated by
+ genemit.cc. The code needs to be kept in sync with there. */
+
+class rtx_expander
+{
+public:
+ rtx_expander (const uint8_t *, rtx *);
+
+ rtx get_rtx ();
+ rtvec get_rtvec ();
+ void expand_seq ();
+
+protected:
+ uint64_t get_uint ();
+ machine_mode get_mode () { return machine_mode (get_uint ()); }
+ char *get_string ();
+ rtx get_shared_operand ();
+ rtx get_unshared_operand ();
+
+ rtx get_rtx (expand_opcode);
+ rtx get_rtx (rtx_code, machine_mode);
+
+ /* Points to the first unread byte. */
+ const uint8_t *m_seq;
+
+ /* The operands passed to the gen_* function. */
+ rtx *m_operands;
+
+ /* A bitmap of operands that have already been used to replace a
+ MATCH_OPERAND or MATCH_DUP. In order to ensure correct sharing,
+ further replacements need to use a copy of the operand, rather than
+ the original rtx. */
+ bbitmap<MAX_RECOG_OPERANDS> m_used;
+};
+}
+
+rtx_expander::rtx_expander (const uint8_t *seq, rtx *operands)
+ : m_seq (seq), m_operands (operands), m_used ()
+{}
+
+/* Read and return the next encoded "BEB128" integer. */
+
+inline uint64_t
+rtx_expander::get_uint ()
+{
+ const uint8_t *seq = m_seq;
+ uint64_t res = 0;
+ do
+ res = (res << 7) | (*seq & 127);
+ while (*seq++ >= 128);
+ m_seq = seq;
+ return res;
+}
+
+/* Read an operand number and return the associated operand rtx,
+ without copying it. */
+
+rtx
+rtx_expander::get_shared_operand ()
+{
+ return m_operands[get_uint ()];
+}
+
+/* Read an operand number and return a correctly-shared instance of
+ the associated operand rtx. This can be either the original rtx
+ or a copy. */
+
+rtx
+rtx_expander::get_unshared_operand ()
+{
+ auto opno = get_uint ();
+ auto mask = m_used.from_index (opno);
+ if (m_used & mask)
+ return copy_rtx (m_operands[opno]);
+
+ m_used |= mask;
+ return m_operands[opno];
+}
+
+/* Read an encoded rtx. */
+
+rtx
+rtx_expander::get_rtx ()
+{
+ auto FIRST_CODE = (unsigned) expand_opcode::FIRST_CODE;
+ auto opcode = get_uint ();
+ if (opcode < FIRST_CODE)
+ return get_rtx (expand_opcode (opcode));
+ return get_rtx (rtx_code (opcode - FIRST_CODE), NUM_MACHINE_MODES);
+}
+
+/* Read an encoded rtx that starts with the given opcode. */
+
+rtx
+rtx_expander::get_rtx (expand_opcode opcode)
+{
+ switch (opcode)
+ {
+ case expand_opcode::NO_RTX:
+ return NULL_RTX;
+
+ case expand_opcode::MATCH_OPERAND:
+ return get_unshared_operand ();
+
+ case expand_opcode::MATCH_OPERATOR_WITH_MODE:
+ {
+ auto mode = get_mode ();
+ auto op = get_shared_operand ();
+ return get_rtx (GET_CODE (op), mode);
+ }
+
+ case expand_opcode::MATCH_OPERATOR:
+ {
+ auto op = get_shared_operand ();
+ return get_rtx (GET_CODE (op), GET_MODE (op));
+ }
+
+ case expand_opcode::MATCH_PARALLEL:
+ return get_shared_operand ();
+
+ case expand_opcode::CLOBBER_REG:
+ {
+ auto mode = get_mode ();
+ auto regno = get_uint ();
+ return gen_hard_reg_clobber (mode, regno);
+ }
+
+ case expand_opcode::FIRST_CODE:
+ break;
+ }
+ gcc_unreachable ();
+}
+
+/* Read the rest of an rtx of code CODE. If such rtxes are not always
+ VOIDmode, MODE is the mode that the rtx should have, or NUM_MACHINE_MODES
+ if the mode is encoded at the current iterator position. */
+
+rtx
+rtx_expander::get_rtx (rtx_code code, machine_mode mode)
+{
+ switch (code)
+ {
+ /* Please keep the cases below in sync with gengenrtl.cc:special_rtx. */
+
+ case EXPR_LIST:
+ case INSN_LIST:
+ case INSN:
+ gcc_unreachable ();
+
+ case CONST_INT:
+ return GEN_INT (get_uint ());
+
+ case REG:
+ if (mode == NUM_MACHINE_MODES)
+ mode = get_mode ();
+ return gen_rtx_REG (mode, get_uint ());
+
+ case SUBREG:
+ {
+ if (mode == NUM_MACHINE_MODES)
+ mode = get_mode ();
+ auto reg = get_rtx ();
+ auto byte = get_uint ();
+ return gen_rtx_SUBREG (mode, reg, byte);
+ }
+
+ case MEM:
+ if (mode == NUM_MACHINE_MODES)
+ mode = get_mode ();
+ return gen_rtx_MEM (mode, get_rtx ());
+
+ case PC:
+ return pc_rtx;
+
+ case RETURN:
+ return ret_rtx;
+
+ case SIMPLE_RETURN:
+ return simple_return_rtx;
+
+ case CONST_VECTOR:
+ if (mode == NUM_MACHINE_MODES)
+ mode = get_mode ();
+ return gen_rtx_CONST_VECTOR (mode, get_rtvec ());
+
+ /* Please keep the cases below in sync with
+ gengenrtl.cc:excluded_rtx. */
+
+ case VAR_LOCATION:
+ gcc_unreachable ();
+
+ case CONST_DOUBLE:
+ /* genemit.cc only accepts zero const_doubles. */
+ if (mode == NUM_MACHINE_MODES)
+ mode = get_mode ();
+ return CONST0_RTX (mode);
+
+ case CONST_WIDE_INT:
+ case CONST_POLY_INT:
+ case CONST_FIXED:
+ gcc_unreachable ();
+
+ default:
+ break;
+ }
+
+ rtx x = rtx_alloc (code);
+ if (!always_void_p (code))
+ {
+ if (mode == NUM_MACHINE_MODES)
+ mode = get_mode ();
+ PUT_MODE_RAW (x, mode);
+ }
+
+ const char *fmt = GET_RTX_FORMAT (code);
+ for (unsigned int i = 0; fmt[i]; ++i)
+ switch (fmt[i])
+ {
+ /* Please keep these cases in sync with
+ gengenrtl.cc:type_from_format. */
+
+ case 'i':
+ XINT (x, i) = get_uint ();
+ break;
+
+ case 'L':
+ case 'w':
+ case 'p':
+ case 's':
+ gcc_unreachable ();
+
+ case 'e': case 'u':
+ XEXP (x, i) = get_rtx ();
+ break;
+
+ case 'E':
+ XVEC (x, i) = get_rtvec ();
+ break;
+
+ case 't':
+ case 'B':
+ default:
+ gcc_unreachable ();
+ }
+
+ return x;
+}
+
+/* Read an encoded rtvec. */
+
+rtvec
+rtx_expander::get_rtvec ()
+{
+ unsigned int len = get_uint ();
+ rtvec v = rtvec_alloc (len);
+ for (unsigned int i = 0; i < len; ++i)
+ RTVEC_ELT (v, i) = get_rtx ();
+ return v;
+}
+
+/* Read and emit an encoded sequence of instructions. */
+
+void
+rtx_expander::expand_seq ()
+{
+ unsigned int len = get_uint ();
+ for (unsigned int i = 0; i < len; ++i)
+ emit (get_rtx (), i < len - 1);
+}
+
+/* Read an rtx from the bytecode in SEQ, which was generated by genemit.cc.
+ Replace operand placeholders with the values given in OPERANDS. */
+
+rtx
+expand_rtx (const uint8_t *seq, rtx *operands)
+{
+ return rtx_expander (seq, operands).get_rtx ();
+}
+
+/* Read and emit a sequence of instructions from the bytecode in SEQ,
+ which was generated by genemit.cc. Replace operand placeholders with
+ the values given in OPERANDS. */
+
+rtx_insn *
+complete_seq (const uint8_t *seq, rtx *operands)
+{
+ rtx_expander (seq, operands).expand_seq ();
+ return end_sequence ();
+}
+
/* Initialize fields of rtl_data related to stack alignment. */
void
/* A list of the md constructs that need a gen_* function. */
static vec<md_rtx_info> queue;
-static void
-print_code (RTX_CODE code, FILE *file)
-{
- const char *p1;
- for (p1 = GET_RTX_NAME (code); *p1; p1++)
- fprintf (file, "%c", TOUPPER (*p1));
-}
+unsigned FIRST_CODE = (unsigned) expand_opcode::FIRST_CODE;
/* A structure used to generate code for a particular expansion. */
struct generator
{
- generator (rtx_code, char *, const md_rtx_info &, FILE *);
+ generator (const md_rtx_info &info) : info (info) {}
- void gen_rtx_scratch (rtx);
- void gen_exp (rtx);
- void gen_emit_seq (rtvec);
+ void add_uint (uint64_t);
+ void add_opcode (expand_opcode opcode) { add_uint ((unsigned) opcode); }
+ void add_code (rtx_code code) { add_uint (FIRST_CODE + (unsigned) code); }
+ void add_match_operator (machine_mode, int, rtvec);
+ void add_exp (rtx);
+ void add_vec (rtvec);
- /* The type of subroutine that we're expanding. */
- rtx_code subroutine_type;
-
- /* Index N indicates that the original operand N has already been used to
- replace a MATCH_OPERATOR or MATCH_DUP, and so any further replacements
- must make a copy. */
- char *used;
+ const char *gen_table (FILE *, const char *);
+ const char *gen_exp (FILE *, rtx);
+ const char *gen_emit_seq (FILE *, rtvec);
/* The construct that we're expanding. */
const md_rtx_info info;
- /* The output file. */
- FILE *file;
+ /* Used to build up the encoding of the expanded rtx sequence. */
+ auto_vec<uint8_t> bytes;
};
-generator::generator (rtx_code subroutine_type, char *used,
- const md_rtx_info &info, FILE *file)
- : subroutine_type (subroutine_type),
- used (used),
- info (info),
- file (file)
-{}
+/* Add VALUE to the encoding using "BEB128" (big-endian version of LEB128).
+ This is slightly easier for the consumer. */
void
-generator::gen_rtx_scratch (rtx x)
+generator::add_uint (uint64_t value)
{
- if (subroutine_type == DEFINE_PEEPHOLE2)
+ int shift = 0;
+ while ((value >> shift >> 7) > 0)
+ shift += 7;
+ do
{
- fprintf (file, "operands[%d]", XINT (x, 0));
+ bytes.safe_push (((value >> shift) & 127) | (shift > 0 ? 128 : 0));
+ shift -= 7;
}
- else
+ while (shift >= 0);
+}
+
+/* Add the rtx expansion of a MATCH_OPERATOR or MATCH_OP_DUP. OPNO is the
+ number of the matched operand. MODE is the mode that the rtx should have,
+ or NUM_MACHINE_MODES if the operand's original mode should be retained.
+ VEC is the vector of suboperands, which replace those of the original
+ operand. */
+
+void
+generator::add_match_operator (machine_mode mode, int opno, rtvec vec)
+{
+ if (mode != NUM_MACHINE_MODES)
{
- fprintf (file, "gen_rtx_SCRATCH (%smode)", GET_MODE_NAME (GET_MODE (x)));
+ add_opcode (expand_opcode::MATCH_OPERATOR_WITH_MODE);
+ add_uint (mode);
}
+ else
+ add_opcode (expand_opcode::MATCH_OPERATOR);
+ add_uint (opno);
+ for (int i = 0; i < GET_NUM_ELEM (vec); i++)
+ add_exp (RTVEC_ELT (vec, i));
}
-/* Print a C expression to construct an RTX just like X,
- substituting any operand references appearing within. */
+/* Add the expansion of X to the encoding. */
void
-generator::gen_exp (rtx x)
+generator::add_exp (rtx x)
{
- RTX_CODE code;
- int i;
- int len;
- const char *fmt;
- const char *sep = "";
-
if (x == 0)
{
- fprintf (file, "NULL_RTX");
+ add_opcode (expand_opcode::NO_RTX);
return;
}
- code = GET_CODE (x);
-
+ auto code = GET_CODE (x);
switch (code)
{
case MATCH_OPERAND:
case MATCH_DUP:
- if (used[XINT (x, 0)])
- {
- fprintf (file, "copy_rtx (operands[%d])", XINT (x, 0));
- return;
- }
- used[XINT (x, 0)] = 1;
- fprintf (file, "operands[%d]", XINT (x, 0));
+ add_opcode (expand_opcode::MATCH_OPERAND);
+ add_uint (XINT (x, 0));
return;
case MATCH_OP_DUP:
- fprintf (file, "gen_rtx_fmt_");
- for (i = 0; i < XVECLEN (x, 1); i++)
- fprintf (file, "e");
- fprintf (file, " (GET_CODE (operands[%d]), ", XINT (x, 0));
if (GET_MODE (x) == VOIDmode)
- fprintf (file, "GET_MODE (operands[%d])", XINT (x, 0));
+ add_match_operator (NUM_MACHINE_MODES, XINT (x, 0), XVEC (x, 1));
else
- fprintf (file, "%smode", GET_MODE_NAME (GET_MODE (x)));
- for (i = 0; i < XVECLEN (x, 1); i++)
- {
- fprintf (file, ",\n\t\t");
- gen_exp (XVECEXP (x, 1, i));
- }
- fprintf (file, ")");
+ add_match_operator (GET_MODE (x), XINT (x, 0), XVEC (x, 1));
return;
case MATCH_OPERATOR:
- fprintf (file, "gen_rtx_fmt_");
- for (i = 0; i < XVECLEN (x, 2); i++)
- fprintf (file, "e");
- fprintf (file, " (GET_CODE (operands[%d])", XINT (x, 0));
- fprintf (file, ", %smode", GET_MODE_NAME (GET_MODE (x)));
- for (i = 0; i < XVECLEN (x, 2); i++)
- {
- fprintf (file, ",\n\t\t");
- gen_exp (XVECEXP (x, 2, i));
- }
- fprintf (file, ")");
+ add_match_operator (GET_MODE (x), XINT (x, 0), XVEC (x, 2));
return;
case MATCH_PARALLEL:
case MATCH_PAR_DUP:
- fprintf (file, "operands[%d]", XINT (x, 0));
+ add_opcode (expand_opcode::MATCH_PARALLEL);
+ add_uint (XINT (x, 0));
return;
case MATCH_SCRATCH:
- gen_rtx_scratch (x);
+ add_code (SCRATCH);
+ add_uint (GET_MODE (x));
return;
- case PC:
- fprintf (file, "pc_rtx");
- return;
- case RETURN:
- fprintf (file, "ret_rtx");
- return;
- case SIMPLE_RETURN:
- fprintf (file, "simple_return_rtx");
- return;
case CLOBBER:
if (REG_P (XEXP (x, 0)))
{
- fprintf (file, "gen_hard_reg_clobber (%smode, %i)",
- GET_MODE_NAME (GET_MODE (XEXP (x, 0))),
- REGNO (XEXP (x, 0)));
+ add_opcode (expand_opcode::CLOBBER_REG);
+ add_uint (GET_MODE (XEXP (x, 0)));
+ add_uint (REGNO (XEXP (x, 0)));
return;
}
break;
case CONST_INT:
- if (INTVAL (x) == 0)
- fprintf (file, "const0_rtx");
- else if (INTVAL (x) == 1)
- fprintf (file, "const1_rtx");
- else if (INTVAL (x) == -1)
- fprintf (file, "constm1_rtx");
- else if (-MAX_SAVED_CONST_INT <= INTVAL (x)
- && INTVAL (x) <= MAX_SAVED_CONST_INT)
- fprintf (file, "const_int_rtx[MAX_SAVED_CONST_INT + (%d)]",
- (int) INTVAL (x));
- else if (INTVAL (x) == STORE_FLAG_VALUE)
- fprintf (file, "const_true_rtx");
- else
- {
- fprintf (file, "GEN_INT (");
- fprintf (file, HOST_WIDE_INT_PRINT_DEC_C, INTVAL (x));
- fprintf (file, ")");
- }
+ add_code (CONST_INT);
+ add_uint (UINTVAL (x));
return;
case CONST_DOUBLE:
/* Handle `const_double_zero' rtx. */
if (CONST_DOUBLE_REAL_VALUE (x)->cl == rvc_zero)
{
- fprintf (file, "CONST_DOUBLE_ATOF (\"0\", %smode)",
- GET_MODE_NAME (GET_MODE (x)));
+ add_code (CONST_DOUBLE);
+ add_uint (GET_MODE (x));
return;
}
/* Fall through. */
break;
}
- fprintf (file, "gen_rtx_");
- print_code (code, file);
- fprintf (file, " (");
+ add_code (code);
if (!always_void_p (code))
- {
- fprintf (file, "%smode", GET_MODE_NAME (GET_MODE (x)));
- sep = ",\n\t";
- }
+ add_uint (GET_MODE (x));
- fmt = GET_RTX_FORMAT (code);
- len = GET_RTX_LENGTH (code);
- for (i = 0; i < len; i++)
+ auto fmt = GET_RTX_FORMAT (code);
+ unsigned int len = GET_RTX_LENGTH (code);
+ for (unsigned int i = 0; i < len; i++)
{
if (fmt[i] == '0')
break;
- fputs (sep, file);
switch (fmt[i])
{
case 'e': case 'u':
- gen_exp (XEXP (x, i));
+ add_exp (XEXP (x, i));
break;
case 'i':
- fprintf (file, "%u", XINT (x, i));
+ add_uint (XUINT (x, i));
break;
case 'L':
break;
case 'r':
- fprintf (file, "%u", REGNO (x));
+ add_uint (REGNO (x));
break;
case 'p':
/* We don't have a way of parsing polynomial offsets yet,
and hopefully never will. */
- fprintf (file, "%d", SUBREG_BYTE (x).to_constant ());
+ add_uint (SUBREG_BYTE (x).to_constant ());
break;
case 'E':
- {
- int j;
- fprintf (file, "gen_rtvec (%d", XVECLEN (x, i));
- for (j = 0; j < XVECLEN (x, i); j++)
- {
- fprintf (file, ",\n\t\t");
- gen_exp (XVECEXP (x, i, j));
- }
- fprintf (file, ")");
- break;
- }
+ add_vec (XVEC (x, i));
+ break;
default:
gcc_unreachable ();
}
- sep = ",\n\t";
}
- fprintf (file, ")");
}
-/* Output code to emit the instruction patterns in VEC, with each element
- becoming a separate instruction. */
+/* Add the expansion of rtx vector VEC to the encoding. */
void
-generator::gen_emit_seq (rtvec vec)
+generator::add_vec (rtvec vec)
{
- for (int i = 0, len = GET_NUM_ELEM (vec); i < len; ++i)
- {
- bool last_p = (i == len - 1);
- rtx next = RTVEC_ELT (vec, i);
- if (const char *name = get_emit_function (next))
- {
- fprintf (file, " %s (", name);
- gen_exp (next);
- fprintf (file, ");\n");
- if (!last_p && needs_barrier_p (next))
- fprintf (file, " emit_barrier ();");
- }
- else
- {
- fprintf (file, " emit (");
- gen_exp (next);
- fprintf (file, ", %s);\n", last_p ? "false" : "true");
- }
- }
+ add_uint (GET_NUM_ELEM (vec));
+ for (int i = 0; i < GET_NUM_ELEM (vec); ++i)
+ add_exp (RTVEC_ELT (vec, i));
+}
+
+/* Emit the encoding as a static C++ array called NAME. Return NAME. */
+
+const char *
+generator::gen_table (FILE *file, const char *name)
+{
+ fprintf (file, " static const uint8_t %s[] = {", name);
+ for (size_t i = 0; i < bytes.length (); ++i)
+ fprintf (file, "%s%s 0x%02x",
+ i == 0 ? "" : ",",
+ i % 8 == 0 ? "\n " : "",
+ bytes[i]);
+ fprintf (file, "\n };\n");
+ return name;
+}
+
+/* Output the code necessary for generating rtx X and return the name
+ of the C++ array that contains the encoding. */
+
+const char *
+generator::gen_exp (FILE *file, rtx x)
+{
+ add_exp (x);
+ return gen_table (file, "expand_encoding");
+}
+
+/* Output the code necessary for emitting each element of VEC as a separate
+ instruction. Return the name of the C++ array that contains the
+ encoding. */
+
+const char *
+generator::gen_emit_seq (FILE *file, rtvec vec)
+{
+ add_vec (vec);
+ return gen_table (file, "expand_encoding");
}
\f
/* Emit the given C code to the output file. The code is allowed to
emit_c_code (const char *code, bool can_fail_p, const char *name, FILE *file)
{
if (can_fail_p)
- fprintf (file, "#define FAIL return (end_sequence (), _val)\n");
+ fprintf (file, "#define FAIL return (end_sequence (), nullptr)\n");
else
fprintf (file, "#define FAIL _Pragma (\"GCC error \\\"%s cannot FAIL\\\"\")"
" (void)0\n", name);
- fprintf (file, "#define DONE return (_val = get_insns (), "
- "end_sequence (), _val)\n");
+ fprintf (file, "#define DONE return end_sequence ()\n");
rtx_reader_ptr->print_md_ptr_loc (code, file);
fprintf (file, "%s\n", code);
/* Output the function name, argument declarations, and initial function
body for a pattern called NAME, given that it has the properties
- in STATS. */
+ in STATS. Return the C++ expression for the operands array. */
-static void
+static const char *
start_gen_insn (FILE *file, const char *name, const pattern_stats &stats)
{
fprintf (file, "rtx\ngen_%s (", name);
for (int i = 0; i < stats.num_generator_args; i++)
fprintf (file, "%s operand%d", i == 0 ? "" : ",", i);
fprintf (file, " };\n");
+ return "operands";
+ }
+
+ if (stats.num_operand_vars != 0)
+ {
+ fprintf (file, " rtx operands[%d] ATTRIBUTE_UNUSED;\n",
+ stats.num_operand_vars);
+ return "operands";
}
- else if (stats.num_operand_vars != 0)
- fprintf (file, " rtx operands[%d] ATTRIBUTE_UNUSED;\n",
- stats.num_operand_vars);
+
+ return "nullptr";
}
/* Generate the `gen_...' function for a DEFINE_INSN. */
fatal_at (info.loc, "match_dup operand number has no match_operand");
/* Output the function name and argument declarations. */
- start_gen_insn (file, XSTR (insn, 0), stats);
+ const char *operands = start_gen_insn (file, XSTR (insn, 0), stats);
/* Output code to construct and return the rtl for the instruction body. */
rtx pattern = add_implicit_parallel (XVEC (insn, 1));
- char *used = XCNEWVEC (char, stats.num_generator_args);
- fprintf (file, " return ");
- generator (DEFINE_INSN, used, info, file).gen_exp (pattern);
- fprintf (file, ";\n}\n\n");
- XDELETEVEC (used);
+ const char *table = generator (info).gen_exp (file, pattern);
+ fprintf (file, " return expand_rtx (%s, %s);\n}\n\n", table, operands);
}
\f
/* Process and queue the DEFINE_EXPAND in INFO. */
gen_expand (const md_rtx_info &info, FILE *file)
{
struct pattern_stats stats;
- char *used;
/* Find out how many operands this function has. */
rtx expand = info.def;
"numbers above all other operands", XSTR (expand, 0));
/* Output the function name and argument declarations. */
- start_gen_insn (file, XSTR (expand, 0), stats);
+ const char *operands = start_gen_insn (file, XSTR (expand, 0), stats);
/* If we don't have any C code to write, only one insn is being written,
and no MATCH_DUPs are present, we can just return the desired insn
&& stats.max_opno >= stats.max_dup_opno
&& XVECLEN (expand, 1) == 1)
{
- used = XCNEWVEC (char, stats.num_operand_vars);
- fprintf (file, " return ");
- generator (DEFINE_EXPAND, used, info, file)
- .gen_exp (XVECEXP (expand, 1, 0));
- fprintf (file, ";\n}\n\n");
- XDELETEVEC (used);
+ rtx pattern = XVECEXP (expand, 1, 0);
+ const char *table = generator (info).gen_exp (file, pattern);
+ fprintf (file, " return expand_rtx (%s, %s);\n}\n\n", table, operands);
return;
}
- fprintf (file, " rtx_insn *_val = 0;\n");
fprintf (file, " start_sequence ();\n");
/* The fourth operand of DEFINE_EXPAND is some code to be executed
fprintf (file, " }\n");
}
- used = XCNEWVEC (char, stats.num_operand_vars);
- generator (DEFINE_EXPAND, used, info, file).gen_emit_seq (XVEC (expand, 1));
- XDELETEVEC (used);
-
- /* Call `get_insns' to extract the list of all the
- insns emitted within this gen_... function. */
-
- fprintf (file, " _val = get_insns ();\n");
- fprintf (file, " end_sequence ();\n");
- fprintf (file, " return _val;\n}\n\n");
+ const char *table = generator (info).gen_emit_seq (file, XVEC (expand, 1));
+ fprintf (file, " return complete_seq (%s, %s);\n}\n\n", table, operands);
}
/* Process and queue the DEFINE_SPLIT or DEFINE_PEEPHOLE2 in INFO. */
const char *const name =
((GET_CODE (split) == DEFINE_PEEPHOLE2) ? "peephole2" : "split");
const char *unused;
- char *used;
/* Find out how many operands this function has. */
get_pattern_stats (&stats, XVEC (split, 2));
unused = (stats.num_operand_vars == 0 ? " ATTRIBUTE_UNUSED" : "");
- used = XCNEWVEC (char, stats.num_operand_vars);
/* Output the prototype, function name and argument declarations. */
if (GET_CODE (split) == DEFINE_PEEPHOLE2)
}
fprintf (file, "{\n");
- /* Declare all local variables. */
- fprintf (file, " rtx_insn *_val = NULL;\n");
-
if (GET_CODE (split) == DEFINE_PEEPHOLE2)
output_peephole2_scratches (split, file);
if (XSTR (split, 3))
emit_c_code (XSTR (split, 3), true, name, file);
- generator (GET_CODE (split), used, info, file)
- .gen_emit_seq (XVEC (split, 2));
-
- /* Call `get_insns' to make a list of all the
- insns emitted within this gen_... function. */
-
- fprintf (file, " _val = get_insns ();\n");
- fprintf (file, " end_sequence ();\n");
- fprintf (file, " return _val;\n}\n\n");
-
- free (used);
+ const char *table = generator (info).gen_emit_seq (file, XVEC (split, 2));
+ fprintf (file, " return complete_seq (%s, %s);\n}\n\n", table, "operands");
}
\f
/* Write a function, `add_clobbers', that is given a PARALLEL of sufficient