13ad841b2Smrg /* read-rtl-function.c - Reader for RTL function dumps
2*4c3eb207Smrg Copyright (C) 2016-2020 Free Software Foundation, Inc.
33ad841b2Smrg
43ad841b2Smrg This file is part of GCC.
53ad841b2Smrg
63ad841b2Smrg GCC is free software; you can redistribute it and/or modify it under
73ad841b2Smrg the terms of the GNU General Public License as published by the Free
83ad841b2Smrg Software Foundation; either version 3, or (at your option) any later
93ad841b2Smrg version.
103ad841b2Smrg
113ad841b2Smrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
123ad841b2Smrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
133ad841b2Smrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
143ad841b2Smrg for more details.
153ad841b2Smrg
163ad841b2Smrg You should have received a copy of the GNU General Public License
173ad841b2Smrg along with GCC; see the file COPYING3. If not see
183ad841b2Smrg <http://www.gnu.org/licenses/>. */
193ad841b2Smrg
203ad841b2Smrg #include "config.h"
213ad841b2Smrg #include "system.h"
223ad841b2Smrg #include "coretypes.h"
233ad841b2Smrg #include "target.h"
243ad841b2Smrg #include "tree.h"
253ad841b2Smrg #include "diagnostic.h"
263ad841b2Smrg #include "read-md.h"
273ad841b2Smrg #include "rtl.h"
283ad841b2Smrg #include "cfghooks.h"
293ad841b2Smrg #include "stringpool.h"
303ad841b2Smrg #include "function.h"
313ad841b2Smrg #include "tree-cfg.h"
323ad841b2Smrg #include "cfg.h"
333ad841b2Smrg #include "basic-block.h"
343ad841b2Smrg #include "cfgrtl.h"
353ad841b2Smrg #include "memmodel.h"
363ad841b2Smrg #include "emit-rtl.h"
373ad841b2Smrg #include "cgraph.h"
383ad841b2Smrg #include "tree-pass.h"
393ad841b2Smrg #include "toplev.h"
403ad841b2Smrg #include "varasm.h"
413ad841b2Smrg #include "read-rtl-function.h"
423ad841b2Smrg #include "selftest.h"
433ad841b2Smrg #include "selftest-rtl.h"
44*4c3eb207Smrg #include "regs.h"
45*4c3eb207Smrg #include "function-abi.h"
463ad841b2Smrg
473ad841b2Smrg /* Forward decls. */
483ad841b2Smrg class function_reader;
493ad841b2Smrg class fixup;
503ad841b2Smrg
513ad841b2Smrg /* Edges are recorded when parsing the "insn-chain" directive,
523ad841b2Smrg and created at the end when all the blocks ought to exist.
533ad841b2Smrg This struct records an "edge-from" or "edge-to" directive seen
543ad841b2Smrg at LOC, which will be turned into an actual CFG edge once
553ad841b2Smrg the "insn-chain" is fully parsed. */
563ad841b2Smrg
57*4c3eb207Smrg class deferred_edge
583ad841b2Smrg {
59*4c3eb207Smrg public:
deferred_edge(file_location loc,int src_bb_idx,int dest_bb_idx,int flags)603ad841b2Smrg deferred_edge (file_location loc, int src_bb_idx, int dest_bb_idx, int flags)
613ad841b2Smrg : m_loc (loc), m_src_bb_idx (src_bb_idx), m_dest_bb_idx (dest_bb_idx),
623ad841b2Smrg m_flags (flags)
633ad841b2Smrg {}
643ad841b2Smrg
653ad841b2Smrg file_location m_loc;
663ad841b2Smrg int m_src_bb_idx;
673ad841b2Smrg int m_dest_bb_idx;
683ad841b2Smrg int m_flags;
693ad841b2Smrg };
703ad841b2Smrg
713ad841b2Smrg /* Subclass of rtx_reader for reading function dumps. */
723ad841b2Smrg
733ad841b2Smrg class function_reader : public rtx_reader
743ad841b2Smrg {
753ad841b2Smrg public:
763ad841b2Smrg function_reader ();
773ad841b2Smrg ~function_reader ();
783ad841b2Smrg
793ad841b2Smrg /* Overridden vfuncs of class md_reader. */
803ad841b2Smrg void handle_unknown_directive (file_location, const char *) FINAL OVERRIDE;
813ad841b2Smrg
823ad841b2Smrg /* Overridden vfuncs of class rtx_reader. */
833ad841b2Smrg rtx read_rtx_operand (rtx x, int idx) FINAL OVERRIDE;
843ad841b2Smrg void handle_any_trailing_information (rtx x) FINAL OVERRIDE;
853ad841b2Smrg rtx postprocess (rtx) FINAL OVERRIDE;
863ad841b2Smrg const char *finalize_string (char *stringbuf) FINAL OVERRIDE;
873ad841b2Smrg
883ad841b2Smrg rtx_insn **get_insn_by_uid (int uid);
893ad841b2Smrg tree parse_mem_expr (const char *desc);
903ad841b2Smrg
913ad841b2Smrg private:
923ad841b2Smrg void parse_function ();
933ad841b2Smrg void create_function ();
943ad841b2Smrg void parse_param ();
953ad841b2Smrg void parse_insn_chain ();
963ad841b2Smrg void parse_block ();
973ad841b2Smrg int parse_bb_idx ();
983ad841b2Smrg void parse_edge (basic_block block, bool from);
993ad841b2Smrg rtx_insn *parse_insn (file_location loc, const char *name);
1003ad841b2Smrg void parse_cfg (file_location loc);
1013ad841b2Smrg void parse_crtl (file_location loc);
1023ad841b2Smrg void create_edges ();
1033ad841b2Smrg
1043ad841b2Smrg int parse_enum_value (int num_values, const char *const *strings);
1053ad841b2Smrg
1063ad841b2Smrg void read_rtx_operand_u (rtx x, int idx);
1073ad841b2Smrg void read_rtx_operand_i_or_n (rtx x, int idx, char format_char);
1083ad841b2Smrg rtx read_rtx_operand_r (rtx x);
1093ad841b2Smrg rtx extra_parsing_for_operand_code_0 (rtx x, int idx);
1103ad841b2Smrg
1113ad841b2Smrg void add_fixup_insn_uid (file_location loc, rtx insn, int operand_idx,
1123ad841b2Smrg int insn_uid);
1133ad841b2Smrg
1143ad841b2Smrg void add_fixup_note_insn_basic_block (file_location loc, rtx insn,
1153ad841b2Smrg int operand_idx, int bb_idx);
1163ad841b2Smrg
1173ad841b2Smrg void add_fixup_source_location (file_location loc, rtx_insn *insn,
118*4c3eb207Smrg const char *filename, int lineno, int colno);
1193ad841b2Smrg
1203ad841b2Smrg void add_fixup_expr (file_location loc, rtx x,
1213ad841b2Smrg const char *desc);
1223ad841b2Smrg
1233ad841b2Smrg rtx consolidate_singletons (rtx x);
1243ad841b2Smrg rtx parse_rtx ();
1253ad841b2Smrg void maybe_read_location (rtx_insn *insn);
1263ad841b2Smrg
1273ad841b2Smrg void handle_insn_uids ();
1283ad841b2Smrg void apply_fixups ();
1293ad841b2Smrg
1303ad841b2Smrg private:
1313ad841b2Smrg struct uid_hash : int_hash <int, -1, -2> {};
1323ad841b2Smrg hash_map<uid_hash, rtx_insn *> m_insns_by_uid;
1333ad841b2Smrg auto_vec<fixup *> m_fixups;
1343ad841b2Smrg rtx_insn *m_first_insn;
1353ad841b2Smrg auto_vec<tree> m_fake_scope;
1363ad841b2Smrg char *m_name;
1373ad841b2Smrg bool m_have_crtl_directive;
1383ad841b2Smrg basic_block m_bb_to_insert_after;
1393ad841b2Smrg auto_vec <deferred_edge> m_deferred_edges;
1403ad841b2Smrg int m_highest_bb_idx;
1413ad841b2Smrg };
1423ad841b2Smrg
1433ad841b2Smrg /* Abstract base class for recording post-processing steps that must be
1443ad841b2Smrg done after reading a .rtl file. */
1453ad841b2Smrg
1463ad841b2Smrg class fixup
1473ad841b2Smrg {
1483ad841b2Smrg public:
1493ad841b2Smrg /* Constructor for a fixup at LOC affecting X. */
fixup(file_location loc,rtx x)1503ad841b2Smrg fixup (file_location loc, rtx x)
1513ad841b2Smrg : m_loc (loc), m_rtx (x)
1523ad841b2Smrg {}
~fixup()1533ad841b2Smrg virtual ~fixup () {}
1543ad841b2Smrg
1553ad841b2Smrg virtual void apply (function_reader *reader) const = 0;
1563ad841b2Smrg
1573ad841b2Smrg protected:
1583ad841b2Smrg file_location m_loc;
1593ad841b2Smrg rtx m_rtx;
1603ad841b2Smrg };
1613ad841b2Smrg
1623ad841b2Smrg /* An abstract subclass of fixup for post-processing steps that
1633ad841b2Smrg act on a specific operand of a specific instruction. */
1643ad841b2Smrg
1653ad841b2Smrg class operand_fixup : public fixup
1663ad841b2Smrg {
1673ad841b2Smrg public:
1683ad841b2Smrg /* Constructor for a fixup at LOC affecting INSN's operand
1693ad841b2Smrg with index OPERAND_IDX. */
operand_fixup(file_location loc,rtx insn,int operand_idx)1703ad841b2Smrg operand_fixup (file_location loc, rtx insn, int operand_idx)
1713ad841b2Smrg : fixup (loc, insn), m_operand_idx (operand_idx)
1723ad841b2Smrg {}
1733ad841b2Smrg
1743ad841b2Smrg protected:
1753ad841b2Smrg int m_operand_idx;
1763ad841b2Smrg };
1773ad841b2Smrg
1783ad841b2Smrg /* A concrete subclass of operand_fixup: fixup an rtx_insn *
1793ad841b2Smrg field based on an integer UID. */
1803ad841b2Smrg
1813ad841b2Smrg class fixup_insn_uid : public operand_fixup
1823ad841b2Smrg {
1833ad841b2Smrg public:
1843ad841b2Smrg /* Constructor for a fixup at LOC affecting INSN's operand
1853ad841b2Smrg with index OPERAND_IDX. Record INSN_UID as the uid. */
fixup_insn_uid(file_location loc,rtx insn,int operand_idx,int insn_uid)1863ad841b2Smrg fixup_insn_uid (file_location loc, rtx insn, int operand_idx, int insn_uid)
1873ad841b2Smrg : operand_fixup (loc, insn, operand_idx),
1883ad841b2Smrg m_insn_uid (insn_uid)
1893ad841b2Smrg {}
1903ad841b2Smrg
1913ad841b2Smrg void apply (function_reader *reader) const;
1923ad841b2Smrg
1933ad841b2Smrg private:
1943ad841b2Smrg int m_insn_uid;
1953ad841b2Smrg };
1963ad841b2Smrg
1973ad841b2Smrg /* A concrete subclass of operand_fixup: fix up a
1983ad841b2Smrg NOTE_INSN_BASIC_BLOCK based on an integer block ID. */
1993ad841b2Smrg
2003ad841b2Smrg class fixup_note_insn_basic_block : public operand_fixup
2013ad841b2Smrg {
2023ad841b2Smrg public:
fixup_note_insn_basic_block(file_location loc,rtx insn,int operand_idx,int bb_idx)2033ad841b2Smrg fixup_note_insn_basic_block (file_location loc, rtx insn, int operand_idx,
2043ad841b2Smrg int bb_idx)
2053ad841b2Smrg : operand_fixup (loc, insn, operand_idx),
2063ad841b2Smrg m_bb_idx (bb_idx)
2073ad841b2Smrg {}
2083ad841b2Smrg
2093ad841b2Smrg void apply (function_reader *reader) const;
2103ad841b2Smrg
2113ad841b2Smrg private:
2123ad841b2Smrg int m_bb_idx;
2133ad841b2Smrg };
2143ad841b2Smrg
2153ad841b2Smrg /* A concrete subclass of fixup (not operand_fixup): fix up
2163ad841b2Smrg the expr of an rtx (REG or MEM) based on a textual dump. */
2173ad841b2Smrg
2183ad841b2Smrg class fixup_expr : public fixup
2193ad841b2Smrg {
2203ad841b2Smrg public:
fixup_expr(file_location loc,rtx x,const char * desc)2213ad841b2Smrg fixup_expr (file_location loc, rtx x, const char *desc)
2223ad841b2Smrg : fixup (loc, x),
2233ad841b2Smrg m_desc (xstrdup (desc))
2243ad841b2Smrg {}
2253ad841b2Smrg
~fixup_expr()2263ad841b2Smrg ~fixup_expr () { free (m_desc); }
2273ad841b2Smrg
2283ad841b2Smrg void apply (function_reader *reader) const;
2293ad841b2Smrg
2303ad841b2Smrg private:
2313ad841b2Smrg char *m_desc;
2323ad841b2Smrg };
2333ad841b2Smrg
2343ad841b2Smrg /* Return a textual description of the operand of INSN with
2353ad841b2Smrg index OPERAND_IDX. */
2363ad841b2Smrg
2373ad841b2Smrg static const char *
get_operand_name(rtx insn,int operand_idx)2383ad841b2Smrg get_operand_name (rtx insn, int operand_idx)
2393ad841b2Smrg {
2403ad841b2Smrg gcc_assert (is_a <rtx_insn *> (insn));
2413ad841b2Smrg switch (operand_idx)
2423ad841b2Smrg {
2433ad841b2Smrg case 0:
2443ad841b2Smrg return "PREV_INSN";
2453ad841b2Smrg case 1:
2463ad841b2Smrg return "NEXT_INSN";
2473ad841b2Smrg default:
2483ad841b2Smrg return NULL;
2493ad841b2Smrg }
2503ad841b2Smrg }
2513ad841b2Smrg
2523ad841b2Smrg /* Fixup an rtx_insn * field based on an integer UID, as read by READER. */
2533ad841b2Smrg
2543ad841b2Smrg void
apply(function_reader * reader)2553ad841b2Smrg fixup_insn_uid::apply (function_reader *reader) const
2563ad841b2Smrg {
2573ad841b2Smrg rtx_insn **insn_from_uid = reader->get_insn_by_uid (m_insn_uid);
2583ad841b2Smrg if (insn_from_uid)
2593ad841b2Smrg XEXP (m_rtx, m_operand_idx) = *insn_from_uid;
2603ad841b2Smrg else
2613ad841b2Smrg {
2623ad841b2Smrg const char *op_name = get_operand_name (m_rtx, m_operand_idx);
2633ad841b2Smrg if (op_name)
2643ad841b2Smrg error_at (m_loc,
2653ad841b2Smrg "insn with UID %i not found for operand %i (`%s') of insn %i",
2663ad841b2Smrg m_insn_uid, m_operand_idx, op_name, INSN_UID (m_rtx));
2673ad841b2Smrg else
2683ad841b2Smrg error_at (m_loc,
2693ad841b2Smrg "insn with UID %i not found for operand %i of insn %i",
2703ad841b2Smrg m_insn_uid, m_operand_idx, INSN_UID (m_rtx));
2713ad841b2Smrg }
2723ad841b2Smrg }
2733ad841b2Smrg
2743ad841b2Smrg /* Fix up a NOTE_INSN_BASIC_BLOCK based on an integer block ID. */
2753ad841b2Smrg
2763ad841b2Smrg void
apply(function_reader *)2773ad841b2Smrg fixup_note_insn_basic_block::apply (function_reader *) const
2783ad841b2Smrg {
2793ad841b2Smrg basic_block bb = BASIC_BLOCK_FOR_FN (cfun, m_bb_idx);
2803ad841b2Smrg gcc_assert (bb);
2813ad841b2Smrg NOTE_BASIC_BLOCK (m_rtx) = bb;
2823ad841b2Smrg }
2833ad841b2Smrg
2843ad841b2Smrg /* Fix up the expr of an rtx (REG or MEM) based on a textual dump
2853ad841b2Smrg read by READER. */
2863ad841b2Smrg
2873ad841b2Smrg void
apply(function_reader * reader)2883ad841b2Smrg fixup_expr::apply (function_reader *reader) const
2893ad841b2Smrg {
2903ad841b2Smrg tree expr = reader->parse_mem_expr (m_desc);
2913ad841b2Smrg switch (GET_CODE (m_rtx))
2923ad841b2Smrg {
2933ad841b2Smrg case REG:
2943ad841b2Smrg set_reg_attrs_for_decl_rtl (expr, m_rtx);
2953ad841b2Smrg break;
2963ad841b2Smrg case MEM:
2973ad841b2Smrg set_mem_expr (m_rtx, expr);
2983ad841b2Smrg break;
2993ad841b2Smrg default:
3003ad841b2Smrg gcc_unreachable ();
3013ad841b2Smrg }
3023ad841b2Smrg }
3033ad841b2Smrg
3043ad841b2Smrg /* Strip trailing whitespace from DESC. */
3053ad841b2Smrg
3063ad841b2Smrg static void
strip_trailing_whitespace(char * desc)3073ad841b2Smrg strip_trailing_whitespace (char *desc)
3083ad841b2Smrg {
3093ad841b2Smrg char *terminator = desc + strlen (desc);
3103ad841b2Smrg while (desc < terminator)
3113ad841b2Smrg {
3123ad841b2Smrg terminator--;
3133ad841b2Smrg if (ISSPACE (*terminator))
3143ad841b2Smrg *terminator = '\0';
3153ad841b2Smrg else
3163ad841b2Smrg break;
3173ad841b2Smrg }
3183ad841b2Smrg }
3193ad841b2Smrg
3203ad841b2Smrg /* Return the numeric value n for GET_NOTE_INSN_NAME (n) for STRING,
3213ad841b2Smrg or fail if STRING isn't recognized. */
3223ad841b2Smrg
3233ad841b2Smrg static int
parse_note_insn_name(const char * string)3243ad841b2Smrg parse_note_insn_name (const char *string)
3253ad841b2Smrg {
3263ad841b2Smrg for (int i = 0; i < NOTE_INSN_MAX; i++)
327cef8759bSmrg if (strcmp (string, GET_NOTE_INSN_NAME (i)) == 0)
3283ad841b2Smrg return i;
3293ad841b2Smrg fatal_with_file_and_line ("unrecognized NOTE_INSN name: `%s'", string);
3303ad841b2Smrg }
3313ad841b2Smrg
3323ad841b2Smrg /* Return the register number for NAME, or return -1 if it isn't
3333ad841b2Smrg recognized. */
3343ad841b2Smrg
3353ad841b2Smrg static int
lookup_reg_by_dump_name(const char * name)3363ad841b2Smrg lookup_reg_by_dump_name (const char *name)
3373ad841b2Smrg {
3383ad841b2Smrg for (int i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3393ad841b2Smrg if (reg_names[i][0]
3403ad841b2Smrg && ! strcmp (name, reg_names[i]))
3413ad841b2Smrg return i;
3423ad841b2Smrg
3433ad841b2Smrg /* Also lookup virtuals. */
3443ad841b2Smrg if (!strcmp (name, "virtual-incoming-args"))
3453ad841b2Smrg return VIRTUAL_INCOMING_ARGS_REGNUM;
3463ad841b2Smrg if (!strcmp (name, "virtual-stack-vars"))
3473ad841b2Smrg return VIRTUAL_STACK_VARS_REGNUM;
3483ad841b2Smrg if (!strcmp (name, "virtual-stack-dynamic"))
3493ad841b2Smrg return VIRTUAL_STACK_DYNAMIC_REGNUM;
3503ad841b2Smrg if (!strcmp (name, "virtual-outgoing-args"))
3513ad841b2Smrg return VIRTUAL_OUTGOING_ARGS_REGNUM;
3523ad841b2Smrg if (!strcmp (name, "virtual-cfa"))
3533ad841b2Smrg return VIRTUAL_CFA_REGNUM;
3543ad841b2Smrg if (!strcmp (name, "virtual-preferred-stack-boundary"))
3553ad841b2Smrg return VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM;
3563ad841b2Smrg /* TODO: handle "virtual-reg-%d". */
3573ad841b2Smrg
3583ad841b2Smrg /* In compact mode, pseudos are printed with '< and '>' wrapping the regno,
3593ad841b2Smrg offseting it by (LAST_VIRTUAL_REGISTER + 1), so that the
3603ad841b2Smrg first non-virtual pseudo is dumped as "<0>". */
3613ad841b2Smrg if (name[0] == '<' && name[strlen (name) - 1] == '>')
3623ad841b2Smrg {
3633ad841b2Smrg int dump_num = atoi (name + 1);
3643ad841b2Smrg return dump_num + LAST_VIRTUAL_REGISTER + 1;
3653ad841b2Smrg }
3663ad841b2Smrg
3673ad841b2Smrg /* Not found. */
3683ad841b2Smrg return -1;
3693ad841b2Smrg }
3703ad841b2Smrg
3713ad841b2Smrg /* class function_reader : public rtx_reader */
3723ad841b2Smrg
3733ad841b2Smrg /* function_reader's constructor. */
3743ad841b2Smrg
function_reader()3753ad841b2Smrg function_reader::function_reader ()
3763ad841b2Smrg : rtx_reader (true),
3773ad841b2Smrg m_first_insn (NULL),
3783ad841b2Smrg m_name (NULL),
3793ad841b2Smrg m_have_crtl_directive (false),
3803ad841b2Smrg m_bb_to_insert_after (NULL),
3813ad841b2Smrg m_highest_bb_idx (EXIT_BLOCK)
3823ad841b2Smrg {
3833ad841b2Smrg }
3843ad841b2Smrg
3853ad841b2Smrg /* function_reader's destructor. */
3863ad841b2Smrg
~function_reader()3873ad841b2Smrg function_reader::~function_reader ()
3883ad841b2Smrg {
3893ad841b2Smrg int i;
3903ad841b2Smrg fixup *f;
3913ad841b2Smrg FOR_EACH_VEC_ELT (m_fixups, i, f)
3923ad841b2Smrg delete f;
3933ad841b2Smrg
3943ad841b2Smrg free (m_name);
3953ad841b2Smrg }
3963ad841b2Smrg
3973ad841b2Smrg /* Implementation of rtx_reader::handle_unknown_directive,
3983ad841b2Smrg for parsing the remainder of a directive with name NAME
3993ad841b2Smrg seen at START_LOC.
4003ad841b2Smrg
4013ad841b2Smrg Require a top-level "function" directive, as emitted by
4023ad841b2Smrg print_rtx_function, and parse it. */
4033ad841b2Smrg
4043ad841b2Smrg void
handle_unknown_directive(file_location start_loc,const char * name)4053ad841b2Smrg function_reader::handle_unknown_directive (file_location start_loc,
4063ad841b2Smrg const char *name)
4073ad841b2Smrg {
4083ad841b2Smrg if (strcmp (name, "function"))
4093ad841b2Smrg fatal_at (start_loc, "expected 'function'");
4103ad841b2Smrg
4113ad841b2Smrg if (flag_lto)
4123ad841b2Smrg error ("%<__RTL%> function cannot be compiled with %<-flto%>");
4133ad841b2Smrg
4143ad841b2Smrg parse_function ();
4153ad841b2Smrg }
4163ad841b2Smrg
4173ad841b2Smrg /* Parse the output of print_rtx_function (or hand-written data in the
4183ad841b2Smrg same format), having already parsed the "(function" heading, and
4193ad841b2Smrg finishing immediately before the final ")".
4203ad841b2Smrg
4213ad841b2Smrg The "param" and "crtl" clauses are optional. */
4223ad841b2Smrg
4233ad841b2Smrg void
parse_function()4243ad841b2Smrg function_reader::parse_function ()
4253ad841b2Smrg {
4263ad841b2Smrg m_name = xstrdup (read_string (0));
4273ad841b2Smrg
4283ad841b2Smrg create_function ();
4293ad841b2Smrg
4303ad841b2Smrg while (1)
4313ad841b2Smrg {
4323ad841b2Smrg int c = read_skip_spaces ();
4333ad841b2Smrg if (c == ')')
4343ad841b2Smrg {
4353ad841b2Smrg unread_char (c);
4363ad841b2Smrg break;
4373ad841b2Smrg }
4383ad841b2Smrg unread_char (c);
4393ad841b2Smrg require_char ('(');
4403ad841b2Smrg file_location loc = get_current_location ();
4413ad841b2Smrg struct md_name directive;
4423ad841b2Smrg read_name (&directive);
4433ad841b2Smrg if (strcmp (directive.string, "param") == 0)
4443ad841b2Smrg parse_param ();
4453ad841b2Smrg else if (strcmp (directive.string, "insn-chain") == 0)
4463ad841b2Smrg parse_insn_chain ();
4473ad841b2Smrg else if (strcmp (directive.string, "crtl") == 0)
4483ad841b2Smrg parse_crtl (loc);
4493ad841b2Smrg else
4503ad841b2Smrg fatal_with_file_and_line ("unrecognized directive: %s",
4513ad841b2Smrg directive.string);
4523ad841b2Smrg }
4533ad841b2Smrg
4543ad841b2Smrg handle_insn_uids ();
4553ad841b2Smrg
4563ad841b2Smrg apply_fixups ();
4573ad841b2Smrg
4583ad841b2Smrg /* Rebuild the JUMP_LABEL field of any JUMP_INSNs in the chain, and the
4593ad841b2Smrg LABEL_NUSES of any CODE_LABELs.
4603ad841b2Smrg
4613ad841b2Smrg This has to happen after apply_fixups, since only after then do
4623ad841b2Smrg LABEL_REFs have their label_ref_label set up. */
4633ad841b2Smrg rebuild_jump_labels (get_insns ());
4643ad841b2Smrg
4653ad841b2Smrg crtl->init_stack_alignment ();
4663ad841b2Smrg }
4673ad841b2Smrg
4683ad841b2Smrg /* Set up state for the function *before* fixups are applied.
4693ad841b2Smrg
4703ad841b2Smrg Create "cfun" and a decl for the function.
4713ad841b2Smrg By default, every function decl is hardcoded as
4723ad841b2Smrg int test_1 (int i, int j, int k);
4733ad841b2Smrg Set up various other state:
4743ad841b2Smrg - the cfg and basic blocks (edges are created later, *after* fixups
4753ad841b2Smrg are applied).
4763ad841b2Smrg - add the function to the callgraph. */
4773ad841b2Smrg
4783ad841b2Smrg void
create_function()4793ad841b2Smrg function_reader::create_function ()
4803ad841b2Smrg {
4813ad841b2Smrg /* We start in cfgrtl mode, rather than cfglayout mode. */
4823ad841b2Smrg rtl_register_cfg_hooks ();
4833ad841b2Smrg
4843ad841b2Smrg /* When run from selftests or "rtl1", cfun is NULL.
4853ad841b2Smrg When run from "cc1" for a C function tagged with __RTL, cfun is the
4863ad841b2Smrg tagged function. */
4873ad841b2Smrg if (!cfun)
4883ad841b2Smrg {
4893ad841b2Smrg tree fn_name = get_identifier (m_name ? m_name : "test_1");
4903ad841b2Smrg tree int_type = integer_type_node;
4913ad841b2Smrg tree return_type = int_type;
4923ad841b2Smrg tree arg_types[3] = {int_type, int_type, int_type};
4933ad841b2Smrg tree fn_type = build_function_type_array (return_type, 3, arg_types);
4943ad841b2Smrg tree fndecl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL, fn_name, fn_type);
4953ad841b2Smrg tree resdecl = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE,
4963ad841b2Smrg return_type);
4973ad841b2Smrg DECL_ARTIFICIAL (resdecl) = 1;
4983ad841b2Smrg DECL_IGNORED_P (resdecl) = 1;
4993ad841b2Smrg DECL_RESULT (fndecl) = resdecl;
5003ad841b2Smrg allocate_struct_function (fndecl, false);
5013ad841b2Smrg /* This sets cfun. */
5023ad841b2Smrg current_function_decl = fndecl;
5033ad841b2Smrg }
5043ad841b2Smrg
5053ad841b2Smrg gcc_assert (cfun);
5063ad841b2Smrg gcc_assert (current_function_decl);
5073ad841b2Smrg tree fndecl = current_function_decl;
5083ad841b2Smrg
5093ad841b2Smrg /* Mark this function as being specified as __RTL. */
5103ad841b2Smrg cfun->curr_properties |= PROP_rtl;
5113ad841b2Smrg
5123ad841b2Smrg /* cc1 normally inits DECL_INITIAL (fndecl) to be error_mark_node.
5133ad841b2Smrg Create a dummy block for it. */
5143ad841b2Smrg DECL_INITIAL (fndecl) = make_node (BLOCK);
5153ad841b2Smrg
5163ad841b2Smrg cfun->curr_properties = (PROP_cfg | PROP_rtl);
5173ad841b2Smrg
5183ad841b2Smrg /* Do we need this to force cgraphunit.c to output the function? */
5193ad841b2Smrg DECL_EXTERNAL (fndecl) = 0;
5203ad841b2Smrg DECL_PRESERVE_P (fndecl) = 1;
5213ad841b2Smrg
5223ad841b2Smrg /* Add to cgraph. */
5233ad841b2Smrg cgraph_node::finalize_function (fndecl, false);
5243ad841b2Smrg
5253ad841b2Smrg /* Create bare-bones cfg. This creates the entry and exit blocks. */
5263ad841b2Smrg init_empty_tree_cfg_for_function (cfun);
5273ad841b2Smrg ENTRY_BLOCK_PTR_FOR_FN (cfun)->flags |= BB_RTL;
5283ad841b2Smrg EXIT_BLOCK_PTR_FOR_FN (cfun)->flags |= BB_RTL;
5293ad841b2Smrg init_rtl_bb_info (ENTRY_BLOCK_PTR_FOR_FN (cfun));
5303ad841b2Smrg init_rtl_bb_info (EXIT_BLOCK_PTR_FOR_FN (cfun));
5313ad841b2Smrg m_bb_to_insert_after = ENTRY_BLOCK_PTR_FOR_FN (cfun);
5323ad841b2Smrg
5333ad841b2Smrg }
5343ad841b2Smrg
535*4c3eb207Smrg /* Look within the params of FNDECL for a param named NAME.
5363ad841b2Smrg Return NULL_TREE if one isn't found. */
5373ad841b2Smrg
5383ad841b2Smrg static tree
find_param_by_name(tree fndecl,const char * name)5393ad841b2Smrg find_param_by_name (tree fndecl, const char *name)
5403ad841b2Smrg {
5413ad841b2Smrg for (tree arg = DECL_ARGUMENTS (fndecl); arg; arg = TREE_CHAIN (arg))
542cef8759bSmrg if (id_equal (DECL_NAME (arg), name))
5433ad841b2Smrg return arg;
5443ad841b2Smrg return NULL_TREE;
5453ad841b2Smrg }
5463ad841b2Smrg
5473ad841b2Smrg /* Parse the content of a "param" directive, having already parsed the
5483ad841b2Smrg "(param". Consume the trailing ')'. */
5493ad841b2Smrg
5503ad841b2Smrg void
parse_param()5513ad841b2Smrg function_reader::parse_param ()
5523ad841b2Smrg {
5533ad841b2Smrg require_char_ws ('"');
5543ad841b2Smrg file_location loc = get_current_location ();
5553ad841b2Smrg char *name = read_quoted_string ();
5563ad841b2Smrg
5573ad841b2Smrg /* Lookup param by name. */
5583ad841b2Smrg tree t_param = find_param_by_name (cfun->decl, name);
5593ad841b2Smrg if (!t_param)
5603ad841b2Smrg fatal_at (loc, "param not found: %s", name);
5613ad841b2Smrg
5623ad841b2Smrg /* Parse DECL_RTL. */
5633ad841b2Smrg require_char_ws ('(');
5643ad841b2Smrg require_word_ws ("DECL_RTL");
5653ad841b2Smrg DECL_WRTL_CHECK (t_param)->decl_with_rtl.rtl = parse_rtx ();
5663ad841b2Smrg require_char_ws (')');
5673ad841b2Smrg
5683ad841b2Smrg /* Parse DECL_RTL_INCOMING. */
5693ad841b2Smrg require_char_ws ('(');
5703ad841b2Smrg require_word_ws ("DECL_RTL_INCOMING");
5713ad841b2Smrg DECL_INCOMING_RTL (t_param) = parse_rtx ();
5723ad841b2Smrg require_char_ws (')');
5733ad841b2Smrg
5743ad841b2Smrg require_char_ws (')');
5753ad841b2Smrg }
5763ad841b2Smrg
5773ad841b2Smrg /* Parse zero or more child insn elements within an
5783ad841b2Smrg "insn-chain" element. Consume the trailing ')'. */
5793ad841b2Smrg
5803ad841b2Smrg void
parse_insn_chain()5813ad841b2Smrg function_reader::parse_insn_chain ()
5823ad841b2Smrg {
5833ad841b2Smrg while (1)
5843ad841b2Smrg {
5853ad841b2Smrg int c = read_skip_spaces ();
5863ad841b2Smrg file_location loc = get_current_location ();
5873ad841b2Smrg if (c == ')')
5883ad841b2Smrg break;
5893ad841b2Smrg else if (c == '(')
5903ad841b2Smrg {
5913ad841b2Smrg struct md_name directive;
5923ad841b2Smrg read_name (&directive);
5933ad841b2Smrg if (strcmp (directive.string, "block") == 0)
5943ad841b2Smrg parse_block ();
5953ad841b2Smrg else
5963ad841b2Smrg parse_insn (loc, directive.string);
5973ad841b2Smrg }
5983ad841b2Smrg else
5993ad841b2Smrg fatal_at (loc, "expected '(' or ')'");
6003ad841b2Smrg }
6013ad841b2Smrg
6023ad841b2Smrg create_edges ();
6033ad841b2Smrg }
6043ad841b2Smrg
6053ad841b2Smrg /* Parse zero or more child directives (edges and insns) within a
6063ad841b2Smrg "block" directive, having already parsed the "(block " heading.
6073ad841b2Smrg Consume the trailing ')'. */
6083ad841b2Smrg
6093ad841b2Smrg void
parse_block()6103ad841b2Smrg function_reader::parse_block ()
6113ad841b2Smrg {
6123ad841b2Smrg /* Parse the index value from the dump. This will be an integer;
6133ad841b2Smrg we don't support "entry" or "exit" here (unlike for edges). */
6143ad841b2Smrg struct md_name name;
6153ad841b2Smrg read_name (&name);
6163ad841b2Smrg int bb_idx = atoi (name.string);
6173ad841b2Smrg
6183ad841b2Smrg /* The term "index" has two meanings for basic blocks in a CFG:
6193ad841b2Smrg (a) the "index" field within struct basic_block_def.
6203ad841b2Smrg (b) the index of a basic_block within the cfg's x_basic_block_info
6213ad841b2Smrg vector, as accessed via BASIC_BLOCK_FOR_FN.
6223ad841b2Smrg
6233ad841b2Smrg These can get out-of-sync when basic blocks are optimized away.
6243ad841b2Smrg They get back in sync by "compact_blocks".
6253ad841b2Smrg We reconstruct cfun->cfg->x_basic_block_info->m_vecdata with NULL
6263ad841b2Smrg values in it for any missing basic blocks, so that (a) == (b) for
6273ad841b2Smrg all of the blocks we create. The doubly-linked list of basic
6283ad841b2Smrg blocks (next_bb/prev_bb) skips over these "holes". */
6293ad841b2Smrg
6303ad841b2Smrg if (m_highest_bb_idx < bb_idx)
6313ad841b2Smrg m_highest_bb_idx = bb_idx;
6323ad841b2Smrg
6333ad841b2Smrg size_t new_size = m_highest_bb_idx + 1;
6343ad841b2Smrg if (basic_block_info_for_fn (cfun)->length () < new_size)
6353ad841b2Smrg vec_safe_grow_cleared (basic_block_info_for_fn (cfun), new_size);
6363ad841b2Smrg
6373ad841b2Smrg last_basic_block_for_fn (cfun) = new_size;
6383ad841b2Smrg
6393ad841b2Smrg /* Create the basic block.
6403ad841b2Smrg
6413ad841b2Smrg We can't call create_basic_block and use the regular RTL block-creation
6423ad841b2Smrg hooks, since this creates NOTE_INSN_BASIC_BLOCK instances. We don't
6433ad841b2Smrg want to do that; we want to use the notes we were provided with. */
6443ad841b2Smrg basic_block bb = alloc_block ();
6453ad841b2Smrg init_rtl_bb_info (bb);
6463ad841b2Smrg bb->index = bb_idx;
6473ad841b2Smrg bb->flags = BB_NEW | BB_RTL;
6483ad841b2Smrg link_block (bb, m_bb_to_insert_after);
6493ad841b2Smrg m_bb_to_insert_after = bb;
6503ad841b2Smrg
6513ad841b2Smrg n_basic_blocks_for_fn (cfun)++;
6523ad841b2Smrg SET_BASIC_BLOCK_FOR_FN (cfun, bb_idx, bb);
6533ad841b2Smrg BB_SET_PARTITION (bb, BB_UNPARTITIONED);
6543ad841b2Smrg
6553ad841b2Smrg /* Handle insns, edge-from and edge-to directives. */
6563ad841b2Smrg while (1)
6573ad841b2Smrg {
6583ad841b2Smrg int c = read_skip_spaces ();
6593ad841b2Smrg file_location loc = get_current_location ();
6603ad841b2Smrg if (c == ')')
6613ad841b2Smrg break;
6623ad841b2Smrg else if (c == '(')
6633ad841b2Smrg {
6643ad841b2Smrg struct md_name directive;
6653ad841b2Smrg read_name (&directive);
6663ad841b2Smrg if (strcmp (directive.string, "edge-from") == 0)
6673ad841b2Smrg parse_edge (bb, true);
6683ad841b2Smrg else if (strcmp (directive.string, "edge-to") == 0)
6693ad841b2Smrg parse_edge (bb, false);
6703ad841b2Smrg else
6713ad841b2Smrg {
6723ad841b2Smrg rtx_insn *insn = parse_insn (loc, directive.string);
6733ad841b2Smrg set_block_for_insn (insn, bb);
6743ad841b2Smrg if (!BB_HEAD (bb))
6753ad841b2Smrg BB_HEAD (bb) = insn;
6763ad841b2Smrg BB_END (bb) = insn;
6773ad841b2Smrg }
6783ad841b2Smrg }
6793ad841b2Smrg else
6803ad841b2Smrg fatal_at (loc, "expected '(' or ')'");
6813ad841b2Smrg }
6823ad841b2Smrg }
6833ad841b2Smrg
6843ad841b2Smrg /* Subroutine of function_reader::parse_edge.
6853ad841b2Smrg Parse a basic block index, handling "entry" and "exit". */
6863ad841b2Smrg
6873ad841b2Smrg int
parse_bb_idx()6883ad841b2Smrg function_reader::parse_bb_idx ()
6893ad841b2Smrg {
6903ad841b2Smrg struct md_name name;
6913ad841b2Smrg read_name (&name);
6923ad841b2Smrg if (strcmp (name.string, "entry") == 0)
6933ad841b2Smrg return ENTRY_BLOCK;
6943ad841b2Smrg if (strcmp (name.string, "exit") == 0)
6953ad841b2Smrg return EXIT_BLOCK;
6963ad841b2Smrg return atoi (name.string);
6973ad841b2Smrg }
6983ad841b2Smrg
6993ad841b2Smrg /* Subroutine of parse_edge_flags.
7003ad841b2Smrg Parse TOK, a token such as "FALLTHRU", converting to the flag value.
7013ad841b2Smrg Issue an error if the token is unrecognized. */
7023ad841b2Smrg
7033ad841b2Smrg static int
parse_edge_flag_token(const char * tok)7043ad841b2Smrg parse_edge_flag_token (const char *tok)
7053ad841b2Smrg {
7063ad841b2Smrg #define DEF_EDGE_FLAG(NAME,IDX) \
7073ad841b2Smrg do { \
7083ad841b2Smrg if (strcmp (tok, #NAME) == 0) \
7093ad841b2Smrg return EDGE_##NAME; \
7103ad841b2Smrg } while (0);
7113ad841b2Smrg #include "cfg-flags.def"
7123ad841b2Smrg #undef DEF_EDGE_FLAG
713*4c3eb207Smrg error ("unrecognized edge flag: %qs", tok);
7143ad841b2Smrg return 0;
7153ad841b2Smrg }
7163ad841b2Smrg
7173ad841b2Smrg /* Subroutine of function_reader::parse_edge.
7183ad841b2Smrg Parse STR and convert to a flag value (or issue an error).
7193ad841b2Smrg The parser uses strtok and hence modifiers STR in-place. */
7203ad841b2Smrg
7213ad841b2Smrg static int
parse_edge_flags(char * str)7223ad841b2Smrg parse_edge_flags (char *str)
7233ad841b2Smrg {
7243ad841b2Smrg int result = 0;
7253ad841b2Smrg
7263ad841b2Smrg char *tok = strtok (str, "| ");
7273ad841b2Smrg while (tok)
7283ad841b2Smrg {
7293ad841b2Smrg result |= parse_edge_flag_token (tok);
7303ad841b2Smrg tok = strtok (NULL, "| ");
7313ad841b2Smrg }
7323ad841b2Smrg
7333ad841b2Smrg return result;
7343ad841b2Smrg }
7353ad841b2Smrg
7363ad841b2Smrg /* Parse an "edge-from" or "edge-to" directive within the "block"
7373ad841b2Smrg directive for BLOCK, having already parsed the "(edge" heading.
7383ad841b2Smrg Consume the final ")". Record the edge within m_deferred_edges.
7393ad841b2Smrg FROM is true for an "edge-from" directive, false for an "edge-to"
7403ad841b2Smrg directive. */
7413ad841b2Smrg
7423ad841b2Smrg void
parse_edge(basic_block block,bool from)7433ad841b2Smrg function_reader::parse_edge (basic_block block, bool from)
7443ad841b2Smrg {
7453ad841b2Smrg gcc_assert (block);
7463ad841b2Smrg int this_bb_idx = block->index;
7473ad841b2Smrg file_location loc = get_current_location ();
7483ad841b2Smrg int other_bb_idx = parse_bb_idx ();
7493ad841b2Smrg
7503ad841b2Smrg /* "(edge-from 2)" means src = 2, dest = this_bb_idx, whereas
7513ad841b2Smrg "(edge-to 3)" means src = this_bb_idx, dest = 3. */
7523ad841b2Smrg int src_idx = from ? other_bb_idx : this_bb_idx;
7533ad841b2Smrg int dest_idx = from ? this_bb_idx : other_bb_idx;
7543ad841b2Smrg
7553ad841b2Smrg /* Optional "(flags)". */
7563ad841b2Smrg int flags = 0;
7573ad841b2Smrg int c = read_skip_spaces ();
7583ad841b2Smrg if (c == '(')
7593ad841b2Smrg {
7603ad841b2Smrg require_word_ws ("flags");
7613ad841b2Smrg require_char_ws ('"');
7623ad841b2Smrg char *str = read_quoted_string ();
7633ad841b2Smrg flags = parse_edge_flags (str);
7643ad841b2Smrg require_char_ws (')');
7653ad841b2Smrg }
7663ad841b2Smrg else
7673ad841b2Smrg unread_char (c);
7683ad841b2Smrg
7693ad841b2Smrg require_char_ws (')');
7703ad841b2Smrg
7713ad841b2Smrg /* This BB already exists, but the other BB might not yet.
7723ad841b2Smrg For now, save the edges, and create them at the end of insn-chain
7733ad841b2Smrg processing. */
7743ad841b2Smrg /* For now, only process the (edge-from) to this BB, and (edge-to)
7753ad841b2Smrg that go to the exit block.
7763ad841b2Smrg FIXME: we don't yet verify that the edge-from and edge-to directives
7773ad841b2Smrg are consistent. */
7783ad841b2Smrg if (from || dest_idx == EXIT_BLOCK)
7793ad841b2Smrg m_deferred_edges.safe_push (deferred_edge (loc, src_idx, dest_idx, flags));
7803ad841b2Smrg }
7813ad841b2Smrg
7823ad841b2Smrg /* Parse an rtx instruction, having parsed the opening and parenthesis, and
7833ad841b2Smrg name NAME, seen at START_LOC, by calling read_rtx_code, calling
7843ad841b2Smrg set_first_insn and set_last_insn as appropriate, and
7853ad841b2Smrg adding the insn to the insn chain.
7863ad841b2Smrg Consume the trailing ')'. */
7873ad841b2Smrg
7883ad841b2Smrg rtx_insn *
parse_insn(file_location start_loc,const char * name)7893ad841b2Smrg function_reader::parse_insn (file_location start_loc, const char *name)
7903ad841b2Smrg {
7913ad841b2Smrg rtx x = read_rtx_code (name);
7923ad841b2Smrg if (!x)
7933ad841b2Smrg fatal_at (start_loc, "expected insn type; got '%s'", name);
7943ad841b2Smrg rtx_insn *insn = dyn_cast <rtx_insn *> (x);
7953ad841b2Smrg if (!insn)
7963ad841b2Smrg fatal_at (start_loc, "expected insn type; got '%s'", name);
7973ad841b2Smrg
7983ad841b2Smrg /* Consume the trailing ')'. */
7993ad841b2Smrg require_char_ws (')');
8003ad841b2Smrg
8013ad841b2Smrg rtx_insn *last_insn = get_last_insn ();
8023ad841b2Smrg
8033ad841b2Smrg /* Add "insn" to the insn chain. */
8043ad841b2Smrg if (last_insn)
8053ad841b2Smrg {
8063ad841b2Smrg gcc_assert (NEXT_INSN (last_insn) == NULL);
8073ad841b2Smrg SET_NEXT_INSN (last_insn) = insn;
8083ad841b2Smrg }
8093ad841b2Smrg SET_PREV_INSN (insn) = last_insn;
8103ad841b2Smrg
8113ad841b2Smrg /* Add it to the sequence. */
8123ad841b2Smrg set_last_insn (insn);
8133ad841b2Smrg if (!m_first_insn)
8143ad841b2Smrg {
8153ad841b2Smrg m_first_insn = insn;
8163ad841b2Smrg set_first_insn (insn);
8173ad841b2Smrg }
8183ad841b2Smrg
8193ad841b2Smrg if (rtx_code_label *label = dyn_cast <rtx_code_label *> (insn))
8203ad841b2Smrg maybe_set_max_label_num (label);
8213ad841b2Smrg
8223ad841b2Smrg return insn;
8233ad841b2Smrg }
8243ad841b2Smrg
8253ad841b2Smrg /* Postprocessing subroutine for parse_insn_chain: all the basic blocks
8263ad841b2Smrg should have been created by now; create the edges that were seen. */
8273ad841b2Smrg
8283ad841b2Smrg void
create_edges()8293ad841b2Smrg function_reader::create_edges ()
8303ad841b2Smrg {
8313ad841b2Smrg int i;
8323ad841b2Smrg deferred_edge *de;
8333ad841b2Smrg FOR_EACH_VEC_ELT (m_deferred_edges, i, de)
8343ad841b2Smrg {
8353ad841b2Smrg /* The BBs should already have been created by parse_block. */
8363ad841b2Smrg basic_block src = BASIC_BLOCK_FOR_FN (cfun, de->m_src_bb_idx);
8373ad841b2Smrg if (!src)
8383ad841b2Smrg fatal_at (de->m_loc, "error: block index %i not found",
8393ad841b2Smrg de->m_src_bb_idx);
8403ad841b2Smrg basic_block dst = BASIC_BLOCK_FOR_FN (cfun, de->m_dest_bb_idx);
8413ad841b2Smrg if (!dst)
8423ad841b2Smrg fatal_at (de->m_loc, "error: block with index %i not found",
8433ad841b2Smrg de->m_dest_bb_idx);
8443ad841b2Smrg unchecked_make_edge (src, dst, de->m_flags);
8453ad841b2Smrg }
8463ad841b2Smrg }
8473ad841b2Smrg
8483ad841b2Smrg /* Parse a "crtl" directive, having already parsed the "(crtl" heading
8493ad841b2Smrg at location LOC.
8503ad841b2Smrg Consume the final ")". */
8513ad841b2Smrg
8523ad841b2Smrg void
parse_crtl(file_location loc)8533ad841b2Smrg function_reader::parse_crtl (file_location loc)
8543ad841b2Smrg {
8553ad841b2Smrg if (m_have_crtl_directive)
8563ad841b2Smrg error_at (loc, "more than one 'crtl' directive");
8573ad841b2Smrg m_have_crtl_directive = true;
8583ad841b2Smrg
8593ad841b2Smrg /* return_rtx. */
8603ad841b2Smrg require_char_ws ('(');
8613ad841b2Smrg require_word_ws ("return_rtx");
8623ad841b2Smrg crtl->return_rtx = parse_rtx ();
8633ad841b2Smrg require_char_ws (')');
8643ad841b2Smrg
8653ad841b2Smrg require_char_ws (')');
8663ad841b2Smrg }
8673ad841b2Smrg
8683ad841b2Smrg /* Parse operand IDX of X, returning X, or an equivalent rtx
8693ad841b2Smrg expression (for consolidating singletons).
8703ad841b2Smrg This is an overridden implementation of rtx_reader::read_rtx_operand for
8713ad841b2Smrg function_reader, handling various extra data printed by print_rtx,
8723ad841b2Smrg and sometimes calling the base class implementation. */
8733ad841b2Smrg
8743ad841b2Smrg rtx
read_rtx_operand(rtx x,int idx)8753ad841b2Smrg function_reader::read_rtx_operand (rtx x, int idx)
8763ad841b2Smrg {
8773ad841b2Smrg RTX_CODE code = GET_CODE (x);
8783ad841b2Smrg const char *format_ptr = GET_RTX_FORMAT (code);
8793ad841b2Smrg const char format_char = format_ptr[idx];
8803ad841b2Smrg struct md_name name;
8813ad841b2Smrg
8823ad841b2Smrg /* Override the regular parser for some format codes. */
8833ad841b2Smrg switch (format_char)
8843ad841b2Smrg {
8853ad841b2Smrg case 'e':
8863ad841b2Smrg if (idx == 7 && CALL_P (x))
8873ad841b2Smrg {
8883ad841b2Smrg m_in_call_function_usage = true;
8893ad841b2Smrg return rtx_reader::read_rtx_operand (x, idx);
8903ad841b2Smrg m_in_call_function_usage = false;
8913ad841b2Smrg }
8923ad841b2Smrg else
8933ad841b2Smrg return rtx_reader::read_rtx_operand (x, idx);
8943ad841b2Smrg break;
8953ad841b2Smrg
8963ad841b2Smrg case 'u':
8973ad841b2Smrg read_rtx_operand_u (x, idx);
8983ad841b2Smrg /* Don't run regular parser for 'u'. */
8993ad841b2Smrg return x;
9003ad841b2Smrg
9013ad841b2Smrg case 'i':
9023ad841b2Smrg case 'n':
9033ad841b2Smrg read_rtx_operand_i_or_n (x, idx, format_char);
9043ad841b2Smrg /* Don't run regular parser for these codes. */
9053ad841b2Smrg return x;
9063ad841b2Smrg
9073ad841b2Smrg case 'B':
9083ad841b2Smrg gcc_assert (is_compact ());
9093ad841b2Smrg /* Compact mode doesn't store BBs. */
9103ad841b2Smrg /* Don't run regular parser. */
9113ad841b2Smrg return x;
9123ad841b2Smrg
9133ad841b2Smrg case 'r':
9143ad841b2Smrg /* Don't run regular parser for 'r'. */
9153ad841b2Smrg return read_rtx_operand_r (x);
9163ad841b2Smrg
9173ad841b2Smrg default:
9183ad841b2Smrg break;
9193ad841b2Smrg }
9203ad841b2Smrg
9213ad841b2Smrg /* Call base class implementation. */
9223ad841b2Smrg x = rtx_reader::read_rtx_operand (x, idx);
9233ad841b2Smrg
9243ad841b2Smrg /* Handle any additional parsing needed to handle what the dump
9253ad841b2Smrg could contain. */
9263ad841b2Smrg switch (format_char)
9273ad841b2Smrg {
9283ad841b2Smrg case '0':
9293ad841b2Smrg x = extra_parsing_for_operand_code_0 (x, idx);
9303ad841b2Smrg break;
9313ad841b2Smrg
9323ad841b2Smrg case 'w':
9333ad841b2Smrg if (!is_compact ())
9343ad841b2Smrg {
9353ad841b2Smrg /* Strip away the redundant hex dump of the value. */
9363ad841b2Smrg require_char_ws ('[');
9373ad841b2Smrg read_name (&name);
9383ad841b2Smrg require_char_ws (']');
9393ad841b2Smrg }
9403ad841b2Smrg break;
9413ad841b2Smrg
9423ad841b2Smrg default:
9433ad841b2Smrg break;
9443ad841b2Smrg }
9453ad841b2Smrg
9463ad841b2Smrg return x;
9473ad841b2Smrg }
9483ad841b2Smrg
9493ad841b2Smrg /* Parse operand IDX of X, of code 'u', when reading function dumps.
9503ad841b2Smrg
9513ad841b2Smrg The RTL file recorded the ID of an insn (or 0 for NULL); we
9523ad841b2Smrg must store this as a pointer, but the insn might not have
9533ad841b2Smrg been loaded yet. Store the ID away for now, via a fixup. */
9543ad841b2Smrg
9553ad841b2Smrg void
read_rtx_operand_u(rtx x,int idx)9563ad841b2Smrg function_reader::read_rtx_operand_u (rtx x, int idx)
9573ad841b2Smrg {
9583ad841b2Smrg /* In compact mode, the PREV/NEXT insn uids are not dumped, so skip
9593ad841b2Smrg the "uu" when reading. */
9603ad841b2Smrg if (is_compact () && GET_CODE (x) != LABEL_REF)
9613ad841b2Smrg return;
9623ad841b2Smrg
9633ad841b2Smrg struct md_name name;
9643ad841b2Smrg file_location loc = read_name (&name);
9653ad841b2Smrg int insn_id = atoi (name.string);
9663ad841b2Smrg if (insn_id)
9673ad841b2Smrg add_fixup_insn_uid (loc, x, idx, insn_id);
9683ad841b2Smrg }
9693ad841b2Smrg
9703ad841b2Smrg /* Read a name, looking for a match against a string found in array
9713ad841b2Smrg STRINGS of size NUM_VALUES.
972*4c3eb207Smrg Return the index of the matched string, or emit an error. */
9733ad841b2Smrg
9743ad841b2Smrg int
parse_enum_value(int num_values,const char * const * strings)9753ad841b2Smrg function_reader::parse_enum_value (int num_values, const char *const *strings)
9763ad841b2Smrg {
9773ad841b2Smrg struct md_name name;
9783ad841b2Smrg read_name (&name);
9793ad841b2Smrg for (int i = 0; i < num_values; i++)
9803ad841b2Smrg {
9813ad841b2Smrg if (strcmp (name.string, strings[i]) == 0)
9823ad841b2Smrg return i;
9833ad841b2Smrg }
984*4c3eb207Smrg error ("unrecognized enum value: %qs", name.string);
9853ad841b2Smrg return 0;
9863ad841b2Smrg }
9873ad841b2Smrg
9883ad841b2Smrg /* Parse operand IDX of X, of code 'i' or 'n' (as specified by FORMAT_CHAR).
9893ad841b2Smrg Special-cased handling of these, for reading function dumps. */
9903ad841b2Smrg
9913ad841b2Smrg void
read_rtx_operand_i_or_n(rtx x,int idx,char format_char)9923ad841b2Smrg function_reader::read_rtx_operand_i_or_n (rtx x, int idx,
9933ad841b2Smrg char format_char)
9943ad841b2Smrg {
9953ad841b2Smrg /* Handle some of the extra information that print_rtx
9963ad841b2Smrg can write out for these cases. */
9973ad841b2Smrg /* print_rtx only writes out operand 5 for notes
9983ad841b2Smrg for NOTE_KIND values NOTE_INSN_DELETED_LABEL
9993ad841b2Smrg and NOTE_INSN_DELETED_DEBUG_LABEL. */
10003ad841b2Smrg if (idx == 5 && NOTE_P (x))
10013ad841b2Smrg return;
10023ad841b2Smrg
10033ad841b2Smrg if (idx == 4 && INSN_P (x))
10043ad841b2Smrg {
10053ad841b2Smrg maybe_read_location (as_a <rtx_insn *> (x));
10063ad841b2Smrg return;
10073ad841b2Smrg }
10083ad841b2Smrg
10093ad841b2Smrg /* INSN_CODEs aren't printed in compact mode, so don't attempt to
10103ad841b2Smrg parse them. */
10113ad841b2Smrg if (is_compact ()
10123ad841b2Smrg && INSN_P (x)
10133ad841b2Smrg && &INSN_CODE (x) == &XINT (x, idx))
10143ad841b2Smrg {
10153ad841b2Smrg INSN_CODE (x) = -1;
10163ad841b2Smrg return;
10173ad841b2Smrg }
10183ad841b2Smrg
10193ad841b2Smrg /* Handle UNSPEC and UNSPEC_VOLATILE's operand 1. */
10203ad841b2Smrg #if !defined(GENERATOR_FILE) && NUM_UNSPECV_VALUES > 0
10213ad841b2Smrg if (idx == 1
10223ad841b2Smrg && GET_CODE (x) == UNSPEC_VOLATILE)
10233ad841b2Smrg {
10243ad841b2Smrg XINT (x, 1)
10253ad841b2Smrg = parse_enum_value (NUM_UNSPECV_VALUES, unspecv_strings);
10263ad841b2Smrg return;
10273ad841b2Smrg }
10283ad841b2Smrg #endif
10293ad841b2Smrg #if !defined(GENERATOR_FILE) && NUM_UNSPEC_VALUES > 0
10303ad841b2Smrg if (idx == 1
10313ad841b2Smrg && (GET_CODE (x) == UNSPEC
10323ad841b2Smrg || GET_CODE (x) == UNSPEC_VOLATILE))
10333ad841b2Smrg {
10343ad841b2Smrg XINT (x, 1)
10353ad841b2Smrg = parse_enum_value (NUM_UNSPEC_VALUES, unspec_strings);
10363ad841b2Smrg return;
10373ad841b2Smrg }
10383ad841b2Smrg #endif
10393ad841b2Smrg
10403ad841b2Smrg struct md_name name;
10413ad841b2Smrg read_name (&name);
10423ad841b2Smrg int value;
10433ad841b2Smrg if (format_char == 'n')
10443ad841b2Smrg value = parse_note_insn_name (name.string);
10453ad841b2Smrg else
10463ad841b2Smrg value = atoi (name.string);
10473ad841b2Smrg XINT (x, idx) = value;
10483ad841b2Smrg }
10493ad841b2Smrg
10503ad841b2Smrg /* Parse the 'r' operand of X, returning X, or an equivalent rtx
10513ad841b2Smrg expression (for consolidating singletons).
10523ad841b2Smrg Special-cased handling of code 'r' for reading function dumps. */
10533ad841b2Smrg
10543ad841b2Smrg rtx
read_rtx_operand_r(rtx x)10553ad841b2Smrg function_reader::read_rtx_operand_r (rtx x)
10563ad841b2Smrg {
10573ad841b2Smrg struct md_name name;
10583ad841b2Smrg file_location loc = read_name (&name);
10593ad841b2Smrg int regno = lookup_reg_by_dump_name (name.string);
10603ad841b2Smrg if (regno == -1)
10613ad841b2Smrg fatal_at (loc, "unrecognized register: '%s'", name.string);
10623ad841b2Smrg
10633ad841b2Smrg set_regno_raw (x, regno, 1);
10643ad841b2Smrg
10653ad841b2Smrg /* Consolidate singletons. */
10663ad841b2Smrg x = consolidate_singletons (x);
10673ad841b2Smrg
10683ad841b2Smrg ORIGINAL_REGNO (x) = regno;
10693ad841b2Smrg
10703ad841b2Smrg /* Parse extra stuff at end of 'r'.
10713ad841b2Smrg We may have zero, one, or two sections marked by square
10723ad841b2Smrg brackets. */
10733ad841b2Smrg int ch = read_skip_spaces ();
10743ad841b2Smrg bool expect_original_regno = false;
10753ad841b2Smrg if (ch == '[')
10763ad841b2Smrg {
10773ad841b2Smrg file_location loc = get_current_location ();
10783ad841b2Smrg char *desc = read_until ("]", true);
10793ad841b2Smrg strip_trailing_whitespace (desc);
10803ad841b2Smrg const char *desc_start = desc;
10813ad841b2Smrg /* If ORIGINAL_REGNO (rtx) != regno, we will have:
10823ad841b2Smrg "orig:%i", ORIGINAL_REGNO (rtx).
10833ad841b2Smrg Consume it, we don't set ORIGINAL_REGNO, since we can
10843ad841b2Smrg get that from the 2nd copy later. */
1085cef8759bSmrg if (strncmp (desc, "orig:", 5) == 0)
10863ad841b2Smrg {
10873ad841b2Smrg expect_original_regno = true;
10883ad841b2Smrg desc_start += 5;
10893ad841b2Smrg /* Skip to any whitespace following the integer. */
10903ad841b2Smrg const char *space = strchr (desc_start, ' ');
10913ad841b2Smrg if (space)
10923ad841b2Smrg desc_start = space + 1;
10933ad841b2Smrg }
10943ad841b2Smrg /* Any remaining text may be the REG_EXPR. Alternatively we have
10953ad841b2Smrg no REG_ATTRS, and instead we have ORIGINAL_REGNO. */
10963ad841b2Smrg if (ISDIGIT (*desc_start))
10973ad841b2Smrg {
10983ad841b2Smrg /* Assume we have ORIGINAL_REGNO. */
10993ad841b2Smrg ORIGINAL_REGNO (x) = atoi (desc_start);
11003ad841b2Smrg }
11013ad841b2Smrg else
11023ad841b2Smrg {
11033ad841b2Smrg /* Assume we have REG_EXPR. */
11043ad841b2Smrg add_fixup_expr (loc, x, desc_start);
11053ad841b2Smrg }
11063ad841b2Smrg free (desc);
11073ad841b2Smrg }
11083ad841b2Smrg else
11093ad841b2Smrg unread_char (ch);
11103ad841b2Smrg if (expect_original_regno)
11113ad841b2Smrg {
11123ad841b2Smrg require_char_ws ('[');
11133ad841b2Smrg char *desc = read_until ("]", true);
11143ad841b2Smrg ORIGINAL_REGNO (x) = atoi (desc);
11153ad841b2Smrg free (desc);
11163ad841b2Smrg }
11173ad841b2Smrg
11183ad841b2Smrg return x;
11193ad841b2Smrg }
11203ad841b2Smrg
11213ad841b2Smrg /* Additional parsing for format code '0' in dumps, handling a variety
11223ad841b2Smrg of special-cases in print_rtx, when parsing operand IDX of X.
11233ad841b2Smrg Return X, or possibly a reallocated copy of X. */
11243ad841b2Smrg
11253ad841b2Smrg rtx
extra_parsing_for_operand_code_0(rtx x,int idx)11263ad841b2Smrg function_reader::extra_parsing_for_operand_code_0 (rtx x, int idx)
11273ad841b2Smrg {
11283ad841b2Smrg RTX_CODE code = GET_CODE (x);
11293ad841b2Smrg int c;
11303ad841b2Smrg struct md_name name;
11313ad841b2Smrg
11323ad841b2Smrg if (idx == 1 && code == SYMBOL_REF)
11333ad841b2Smrg {
11343ad841b2Smrg /* Possibly wrote " [flags %#x]", SYMBOL_REF_FLAGS (in_rtx). */
11353ad841b2Smrg c = read_skip_spaces ();
11363ad841b2Smrg if (c == '[')
11373ad841b2Smrg {
11383ad841b2Smrg file_location loc = read_name (&name);
11393ad841b2Smrg if (strcmp (name.string, "flags"))
11403ad841b2Smrg error_at (loc, "was expecting `%s'", "flags");
11413ad841b2Smrg read_name (&name);
11423ad841b2Smrg SYMBOL_REF_FLAGS (x) = strtol (name.string, NULL, 16);
11433ad841b2Smrg
11443ad841b2Smrg /* The standard RTX_CODE_SIZE (SYMBOL_REF) used when allocating
11453ad841b2Smrg x doesn't have space for the block_symbol information, so
11463ad841b2Smrg we must reallocate it if this flag is set. */
11473ad841b2Smrg if (SYMBOL_REF_HAS_BLOCK_INFO_P (x))
11483ad841b2Smrg {
11493ad841b2Smrg /* Emulate the allocation normally done by
11503ad841b2Smrg varasm.c:create_block_symbol. */
11513ad841b2Smrg unsigned int size = RTX_HDR_SIZE + sizeof (struct block_symbol);
11523ad841b2Smrg rtx new_x = (rtx) ggc_internal_alloc (size);
11533ad841b2Smrg
11543ad841b2Smrg /* Copy data over from the smaller SYMBOL_REF. */
11553ad841b2Smrg memcpy (new_x, x, RTX_CODE_SIZE (SYMBOL_REF));
11563ad841b2Smrg x = new_x;
11573ad841b2Smrg
11583ad841b2Smrg /* We can't reconstruct SYMBOL_REF_BLOCK; set it to NULL. */
11593ad841b2Smrg SYMBOL_REF_BLOCK (x) = NULL;
11603ad841b2Smrg
11613ad841b2Smrg /* Zero the offset. */
11623ad841b2Smrg SYMBOL_REF_BLOCK_OFFSET (x) = 0;
11633ad841b2Smrg }
11643ad841b2Smrg
11653ad841b2Smrg require_char (']');
11663ad841b2Smrg }
11673ad841b2Smrg else
11683ad841b2Smrg unread_char (c);
11693ad841b2Smrg
11703ad841b2Smrg /* If X had a non-NULL SYMBOL_REF_DECL,
11713ad841b2Smrg rtx_writer::print_rtx_operand_code_0 would have dumped it
11723ad841b2Smrg using print_node_brief.
11733ad841b2Smrg Skip the content for now. */
11743ad841b2Smrg c = read_skip_spaces ();
11753ad841b2Smrg if (c == '<')
11763ad841b2Smrg {
11773ad841b2Smrg while (1)
11783ad841b2Smrg {
11793ad841b2Smrg char ch = read_char ();
11803ad841b2Smrg if (ch == '>')
11813ad841b2Smrg break;
11823ad841b2Smrg }
11833ad841b2Smrg }
11843ad841b2Smrg else
11853ad841b2Smrg unread_char (c);
11863ad841b2Smrg }
11873ad841b2Smrg else if (idx == 3 && code == NOTE)
11883ad841b2Smrg {
11893ad841b2Smrg /* Note-specific data appears for operand 3, which annoyingly
11903ad841b2Smrg is before the enum specifying which kind of note we have
11913ad841b2Smrg (operand 4). */
11923ad841b2Smrg c = read_skip_spaces ();
11933ad841b2Smrg if (c == '[')
11943ad841b2Smrg {
11953ad841b2Smrg /* Possibly data for a NOTE_INSN_BASIC_BLOCK, of the form:
11963ad841b2Smrg [bb %d]. */
11973ad841b2Smrg file_location bb_loc = read_name (&name);
11983ad841b2Smrg if (strcmp (name.string, "bb"))
11993ad841b2Smrg error_at (bb_loc, "was expecting `%s'", "bb");
12003ad841b2Smrg read_name (&name);
12013ad841b2Smrg int bb_idx = atoi (name.string);
12023ad841b2Smrg add_fixup_note_insn_basic_block (bb_loc, x, idx,
12033ad841b2Smrg bb_idx);
12043ad841b2Smrg require_char_ws (']');
12053ad841b2Smrg }
12063ad841b2Smrg else
12073ad841b2Smrg unread_char (c);
12083ad841b2Smrg }
12093ad841b2Smrg
12103ad841b2Smrg return x;
12113ad841b2Smrg }
12123ad841b2Smrg
12133ad841b2Smrg /* Implementation of rtx_reader::handle_any_trailing_information.
12143ad841b2Smrg Handle the various additional information that print-rtl.c can
12153ad841b2Smrg write after the regular fields, when parsing X. */
12163ad841b2Smrg
12173ad841b2Smrg void
handle_any_trailing_information(rtx x)12183ad841b2Smrg function_reader::handle_any_trailing_information (rtx x)
12193ad841b2Smrg {
12203ad841b2Smrg struct md_name name;
12213ad841b2Smrg
12223ad841b2Smrg switch (GET_CODE (x))
12233ad841b2Smrg {
12243ad841b2Smrg case MEM:
12253ad841b2Smrg {
12263ad841b2Smrg int ch;
12273ad841b2Smrg require_char_ws ('[');
12283ad841b2Smrg read_name (&name);
12293ad841b2Smrg set_mem_alias_set (x, atoi (name.string));
12303ad841b2Smrg /* We have either a MEM_EXPR, or a space. */
12313ad841b2Smrg if (peek_char () != ' ')
12323ad841b2Smrg {
12333ad841b2Smrg file_location loc = get_current_location ();
12343ad841b2Smrg char *desc = read_until (" +", false);
12353ad841b2Smrg add_fixup_expr (loc, consolidate_singletons (x), desc);
12363ad841b2Smrg free (desc);
12373ad841b2Smrg }
12383ad841b2Smrg else
12393ad841b2Smrg read_char ();
12403ad841b2Smrg
12413ad841b2Smrg /* We may optionally have '+' for MEM_OFFSET_KNOWN_P. */
12423ad841b2Smrg ch = read_skip_spaces ();
12433ad841b2Smrg if (ch == '+')
12443ad841b2Smrg {
12453ad841b2Smrg read_name (&name);
12463ad841b2Smrg set_mem_offset (x, atoi (name.string));
12473ad841b2Smrg }
12483ad841b2Smrg else
12493ad841b2Smrg unread_char (ch);
12503ad841b2Smrg
12513ad841b2Smrg /* Handle optional " S" for MEM_SIZE. */
12523ad841b2Smrg ch = read_skip_spaces ();
12533ad841b2Smrg if (ch == 'S')
12543ad841b2Smrg {
12553ad841b2Smrg read_name (&name);
12563ad841b2Smrg set_mem_size (x, atoi (name.string));
12573ad841b2Smrg }
12583ad841b2Smrg else
12593ad841b2Smrg unread_char (ch);
12603ad841b2Smrg
12613ad841b2Smrg /* Handle optional " A" for MEM_ALIGN. */
12623ad841b2Smrg ch = read_skip_spaces ();
12633ad841b2Smrg if (ch == 'A' && peek_char () != 'S')
12643ad841b2Smrg {
12653ad841b2Smrg read_name (&name);
12663ad841b2Smrg set_mem_align (x, atoi (name.string));
12673ad841b2Smrg }
12683ad841b2Smrg else
12693ad841b2Smrg unread_char (ch);
12703ad841b2Smrg
12713ad841b2Smrg /* Handle optional " AS" for MEM_ADDR_SPACE. */
12723ad841b2Smrg ch = read_skip_spaces ();
12733ad841b2Smrg if (ch == 'A' && peek_char () == 'S')
12743ad841b2Smrg {
12753ad841b2Smrg read_char ();
12763ad841b2Smrg read_name (&name);
12773ad841b2Smrg set_mem_addr_space (x, atoi (name.string));
12783ad841b2Smrg }
12793ad841b2Smrg else
12803ad841b2Smrg unread_char (ch);
12813ad841b2Smrg
12823ad841b2Smrg require_char (']');
12833ad841b2Smrg }
12843ad841b2Smrg break;
12853ad841b2Smrg
12863ad841b2Smrg case CODE_LABEL:
12873ad841b2Smrg /* Assume that LABEL_NUSES was not dumped. */
12883ad841b2Smrg /* TODO: parse LABEL_KIND. */
12893ad841b2Smrg /* For now, skip until closing ')'. */
12903ad841b2Smrg do
12913ad841b2Smrg {
12923ad841b2Smrg char ch = read_char ();
12933ad841b2Smrg if (ch == ')')
12943ad841b2Smrg {
12953ad841b2Smrg unread_char (ch);
12963ad841b2Smrg break;
12973ad841b2Smrg }
12983ad841b2Smrg }
12993ad841b2Smrg while (1);
13003ad841b2Smrg break;
13013ad841b2Smrg
13023ad841b2Smrg default:
13033ad841b2Smrg break;
13043ad841b2Smrg }
13053ad841b2Smrg }
13063ad841b2Smrg
13073ad841b2Smrg /* Parse a tree dump for a MEM_EXPR in DESC and turn it back into a tree.
13083ad841b2Smrg We handle "<retval>" and param names within cfun, but for anything else
13093ad841b2Smrg we "cheat" by building a global VAR_DECL of type "int" with that name
13103ad841b2Smrg (returning the same global for a name if we see the same name more
13113ad841b2Smrg than once). */
13123ad841b2Smrg
13133ad841b2Smrg tree
parse_mem_expr(const char * desc)13143ad841b2Smrg function_reader::parse_mem_expr (const char *desc)
13153ad841b2Smrg {
13163ad841b2Smrg tree fndecl = cfun->decl;
13173ad841b2Smrg
1318cef8759bSmrg if (strcmp (desc, "<retval>") == 0)
13193ad841b2Smrg return DECL_RESULT (fndecl);
13203ad841b2Smrg
13213ad841b2Smrg tree param = find_param_by_name (fndecl, desc);
13223ad841b2Smrg if (param)
13233ad841b2Smrg return param;
13243ad841b2Smrg
13253ad841b2Smrg /* Search within decls we already created.
13263ad841b2Smrg FIXME: use a hash rather than linear search. */
13273ad841b2Smrg int i;
13283ad841b2Smrg tree t;
13293ad841b2Smrg FOR_EACH_VEC_ELT (m_fake_scope, i, t)
1330cef8759bSmrg if (id_equal (DECL_NAME (t), desc))
13313ad841b2Smrg return t;
13323ad841b2Smrg
13333ad841b2Smrg /* Not found? Create it.
13343ad841b2Smrg This allows mimicking of real data but avoids having to specify
13353ad841b2Smrg e.g. names of locals, params etc.
13363ad841b2Smrg Though this way we don't know if we have a PARM_DECL vs a VAR_DECL,
13373ad841b2Smrg and we don't know the types. Fake it by making everything be
13383ad841b2Smrg a VAR_DECL of "int" type. */
13393ad841b2Smrg t = build_decl (UNKNOWN_LOCATION, VAR_DECL,
13403ad841b2Smrg get_identifier (desc),
13413ad841b2Smrg integer_type_node);
13423ad841b2Smrg m_fake_scope.safe_push (t);
13433ad841b2Smrg return t;
13443ad841b2Smrg }
13453ad841b2Smrg
13463ad841b2Smrg /* Record that at LOC we saw an insn uid INSN_UID for the operand with index
13473ad841b2Smrg OPERAND_IDX within INSN, so that the pointer value can be fixed up in
13483ad841b2Smrg later post-processing. */
13493ad841b2Smrg
13503ad841b2Smrg void
add_fixup_insn_uid(file_location loc,rtx insn,int operand_idx,int insn_uid)13513ad841b2Smrg function_reader::add_fixup_insn_uid (file_location loc, rtx insn, int operand_idx,
13523ad841b2Smrg int insn_uid)
13533ad841b2Smrg {
13543ad841b2Smrg m_fixups.safe_push (new fixup_insn_uid (loc, insn, operand_idx, insn_uid));
13553ad841b2Smrg }
13563ad841b2Smrg
13573ad841b2Smrg /* Record that at LOC we saw an basic block index BB_IDX for the operand with index
13583ad841b2Smrg OPERAND_IDX within INSN, so that the pointer value can be fixed up in
13593ad841b2Smrg later post-processing. */
13603ad841b2Smrg
13613ad841b2Smrg void
add_fixup_note_insn_basic_block(file_location loc,rtx insn,int operand_idx,int bb_idx)13623ad841b2Smrg function_reader::add_fixup_note_insn_basic_block (file_location loc, rtx insn,
13633ad841b2Smrg int operand_idx, int bb_idx)
13643ad841b2Smrg {
13653ad841b2Smrg m_fixups.safe_push (new fixup_note_insn_basic_block (loc, insn, operand_idx,
13663ad841b2Smrg bb_idx));
13673ad841b2Smrg }
13683ad841b2Smrg
13693ad841b2Smrg /* Placeholder hook for recording source location information seen in a dump.
13703ad841b2Smrg This is empty for now. */
13713ad841b2Smrg
13723ad841b2Smrg void
add_fixup_source_location(file_location,rtx_insn *,const char *,int,int)13733ad841b2Smrg function_reader::add_fixup_source_location (file_location, rtx_insn *,
1374*4c3eb207Smrg const char *, int, int)
13753ad841b2Smrg {
13763ad841b2Smrg }
13773ad841b2Smrg
13783ad841b2Smrg /* Record that at LOC we saw textual description DESC of the MEM_EXPR or REG_EXPR
13793ad841b2Smrg of INSN, so that the fields can be fixed up in later post-processing. */
13803ad841b2Smrg
13813ad841b2Smrg void
add_fixup_expr(file_location loc,rtx insn,const char * desc)13823ad841b2Smrg function_reader::add_fixup_expr (file_location loc, rtx insn,
13833ad841b2Smrg const char *desc)
13843ad841b2Smrg {
13853ad841b2Smrg gcc_assert (desc);
13863ad841b2Smrg /* Fail early if the RTL reader erroneously hands us an int. */
13873ad841b2Smrg gcc_assert (!ISDIGIT (desc[0]));
13883ad841b2Smrg
13893ad841b2Smrg m_fixups.safe_push (new fixup_expr (loc, insn, desc));
13903ad841b2Smrg }
13913ad841b2Smrg
13923ad841b2Smrg /* Helper function for consolidate_reg. Return the global rtx for
13933ad841b2Smrg the register with regno REGNO. */
13943ad841b2Smrg
13953ad841b2Smrg static rtx
lookup_global_register(int regno)13963ad841b2Smrg lookup_global_register (int regno)
13973ad841b2Smrg {
13983ad841b2Smrg /* We can't use a switch here, as some of the REGNUMs might not be constants
13993ad841b2Smrg for some targets. */
14003ad841b2Smrg if (regno == STACK_POINTER_REGNUM)
14013ad841b2Smrg return stack_pointer_rtx;
14023ad841b2Smrg else if (regno == FRAME_POINTER_REGNUM)
14033ad841b2Smrg return frame_pointer_rtx;
14043ad841b2Smrg else if (regno == HARD_FRAME_POINTER_REGNUM)
14053ad841b2Smrg return hard_frame_pointer_rtx;
14063ad841b2Smrg else if (regno == ARG_POINTER_REGNUM)
14073ad841b2Smrg return arg_pointer_rtx;
14083ad841b2Smrg else if (regno == VIRTUAL_INCOMING_ARGS_REGNUM)
14093ad841b2Smrg return virtual_incoming_args_rtx;
14103ad841b2Smrg else if (regno == VIRTUAL_STACK_VARS_REGNUM)
14113ad841b2Smrg return virtual_stack_vars_rtx;
14123ad841b2Smrg else if (regno == VIRTUAL_STACK_DYNAMIC_REGNUM)
14133ad841b2Smrg return virtual_stack_dynamic_rtx;
14143ad841b2Smrg else if (regno == VIRTUAL_OUTGOING_ARGS_REGNUM)
14153ad841b2Smrg return virtual_outgoing_args_rtx;
14163ad841b2Smrg else if (regno == VIRTUAL_CFA_REGNUM)
14173ad841b2Smrg return virtual_cfa_rtx;
14183ad841b2Smrg else if (regno == VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM)
14193ad841b2Smrg return virtual_preferred_stack_boundary_rtx;
14203ad841b2Smrg #ifdef return_ADDRESS_POINTER_REGNUM
14213ad841b2Smrg else if (regno == RETURN_ADDRESS_POINTER_REGNUM)
14223ad841b2Smrg return return_address_pointer_rtx;
14233ad841b2Smrg #endif
14243ad841b2Smrg
14253ad841b2Smrg return NULL;
14263ad841b2Smrg }
14273ad841b2Smrg
14283ad841b2Smrg /* Ensure that the backend can cope with a REG with regno REGNO.
14293ad841b2Smrg Normally REG instances are created by gen_reg_rtx which updates
14303ad841b2Smrg regno_reg_rtx, growing it as necessary.
14313ad841b2Smrg The REG instances created from the dumpfile weren't created this
14323ad841b2Smrg way, so we need to manually update regno_reg_rtx. */
14333ad841b2Smrg
14343ad841b2Smrg static void
ensure_regno(int regno)14353ad841b2Smrg ensure_regno (int regno)
14363ad841b2Smrg {
14373ad841b2Smrg if (reg_rtx_no < regno + 1)
14383ad841b2Smrg reg_rtx_no = regno + 1;
14393ad841b2Smrg
14403ad841b2Smrg crtl->emit.ensure_regno_capacity ();
14413ad841b2Smrg gcc_assert (regno < crtl->emit.regno_pointer_align_length);
14423ad841b2Smrg }
14433ad841b2Smrg
14443ad841b2Smrg /* Helper function for consolidate_singletons, for handling REG instances.
14453ad841b2Smrg Given REG instance X of some regno, return the singleton rtx for that
14463ad841b2Smrg regno, if it exists, or X. */
14473ad841b2Smrg
14483ad841b2Smrg static rtx
consolidate_reg(rtx x)14493ad841b2Smrg consolidate_reg (rtx x)
14503ad841b2Smrg {
14513ad841b2Smrg gcc_assert (GET_CODE (x) == REG);
14523ad841b2Smrg
14533ad841b2Smrg unsigned int regno = REGNO (x);
14543ad841b2Smrg
14553ad841b2Smrg ensure_regno (regno);
14563ad841b2Smrg
14573ad841b2Smrg /* Some register numbers have their rtx created in init_emit_regs
14583ad841b2Smrg e.g. stack_pointer_rtx for STACK_POINTER_REGNUM.
14593ad841b2Smrg Consolidate on this. */
14603ad841b2Smrg rtx global_reg = lookup_global_register (regno);
14613ad841b2Smrg if (global_reg)
14623ad841b2Smrg return global_reg;
14633ad841b2Smrg
14643ad841b2Smrg /* Populate regno_reg_rtx if necessary. */
14653ad841b2Smrg if (regno_reg_rtx[regno] == NULL)
14663ad841b2Smrg regno_reg_rtx[regno] = x;
14673ad841b2Smrg /* Use it. */
14683ad841b2Smrg gcc_assert (GET_CODE (regno_reg_rtx[regno]) == REG);
14693ad841b2Smrg gcc_assert (REGNO (regno_reg_rtx[regno]) == regno);
14703ad841b2Smrg if (GET_MODE (x) == GET_MODE (regno_reg_rtx[regno]))
14713ad841b2Smrg return regno_reg_rtx[regno];
14723ad841b2Smrg
14733ad841b2Smrg return x;
14743ad841b2Smrg }
14753ad841b2Smrg
14763ad841b2Smrg /* When reading RTL function dumps, we must consolidate some
14773ad841b2Smrg rtx so that we use singletons where singletons are expected
14783ad841b2Smrg (e.g. we don't want multiple "(const_int 0 [0])" rtx, since
14793ad841b2Smrg these are tested via pointer equality against const0_rtx.
14803ad841b2Smrg
14813ad841b2Smrg Return the equivalent singleton rtx for X, if any, otherwise X. */
14823ad841b2Smrg
14833ad841b2Smrg rtx
consolidate_singletons(rtx x)14843ad841b2Smrg function_reader::consolidate_singletons (rtx x)
14853ad841b2Smrg {
14863ad841b2Smrg if (!x)
14873ad841b2Smrg return x;
14883ad841b2Smrg
14893ad841b2Smrg switch (GET_CODE (x))
14903ad841b2Smrg {
14913ad841b2Smrg case PC: return pc_rtx;
14923ad841b2Smrg case RETURN: return ret_rtx;
14933ad841b2Smrg case SIMPLE_RETURN: return simple_return_rtx;
14943ad841b2Smrg case CC0: return cc0_rtx;
14953ad841b2Smrg
14963ad841b2Smrg case REG:
14973ad841b2Smrg return consolidate_reg (x);
14983ad841b2Smrg
14993ad841b2Smrg case CONST_INT:
15003ad841b2Smrg return gen_rtx_CONST_INT (GET_MODE (x), INTVAL (x));
15013ad841b2Smrg
15023ad841b2Smrg default:
15033ad841b2Smrg break;
15043ad841b2Smrg }
15053ad841b2Smrg
15063ad841b2Smrg return x;
15073ad841b2Smrg }
15083ad841b2Smrg
15093ad841b2Smrg /* Parse an rtx directive, including both the opening/closing parentheses,
15103ad841b2Smrg and the name. */
15113ad841b2Smrg
15123ad841b2Smrg rtx
parse_rtx()15133ad841b2Smrg function_reader::parse_rtx ()
15143ad841b2Smrg {
15153ad841b2Smrg require_char_ws ('(');
15163ad841b2Smrg struct md_name directive;
15173ad841b2Smrg read_name (&directive);
15183ad841b2Smrg rtx result
15193ad841b2Smrg = consolidate_singletons (read_rtx_code (directive.string));
15203ad841b2Smrg require_char_ws (')');
15213ad841b2Smrg
15223ad841b2Smrg return result;
15233ad841b2Smrg }
15243ad841b2Smrg
15253ad841b2Smrg /* Implementation of rtx_reader::postprocess for reading function dumps.
15263ad841b2Smrg Return the equivalent singleton rtx for X, if any, otherwise X. */
15273ad841b2Smrg
15283ad841b2Smrg rtx
postprocess(rtx x)15293ad841b2Smrg function_reader::postprocess (rtx x)
15303ad841b2Smrg {
15313ad841b2Smrg return consolidate_singletons (x);
15323ad841b2Smrg }
15333ad841b2Smrg
15343ad841b2Smrg /* Implementation of rtx_reader::finalize_string for reading function dumps.
15353ad841b2Smrg Make a GC-managed copy of STRINGBUF. */
15363ad841b2Smrg
15373ad841b2Smrg const char *
finalize_string(char * stringbuf)15383ad841b2Smrg function_reader::finalize_string (char *stringbuf)
15393ad841b2Smrg {
15403ad841b2Smrg return ggc_strdup (stringbuf);
15413ad841b2Smrg }
15423ad841b2Smrg
15433ad841b2Smrg /* Attempt to parse optional location information for insn INSN, as
15443ad841b2Smrg potentially written out by rtx_writer::print_rtx_operand_code_i.
15453ad841b2Smrg We look for a quoted string followed by a colon. */
15463ad841b2Smrg
15473ad841b2Smrg void
maybe_read_location(rtx_insn * insn)15483ad841b2Smrg function_reader::maybe_read_location (rtx_insn *insn)
15493ad841b2Smrg {
15503ad841b2Smrg file_location loc = get_current_location ();
15513ad841b2Smrg
15523ad841b2Smrg /* Attempt to parse a quoted string. */
15533ad841b2Smrg int ch = read_skip_spaces ();
15543ad841b2Smrg if (ch == '"')
15553ad841b2Smrg {
15563ad841b2Smrg char *filename = read_quoted_string ();
15573ad841b2Smrg require_char (':');
15583ad841b2Smrg struct md_name line_num;
15593ad841b2Smrg read_name (&line_num);
1560*4c3eb207Smrg
1561*4c3eb207Smrg int column = 0;
1562*4c3eb207Smrg int ch = read_char ();
1563*4c3eb207Smrg if (ch == ':')
1564*4c3eb207Smrg {
1565*4c3eb207Smrg struct md_name column_num;
1566*4c3eb207Smrg read_name (&column_num);
1567*4c3eb207Smrg column = atoi (column_num.string);
1568*4c3eb207Smrg }
1569*4c3eb207Smrg else
1570*4c3eb207Smrg unread_char (ch);
1571*4c3eb207Smrg add_fixup_source_location (loc, insn, filename,
1572*4c3eb207Smrg atoi (line_num.string),
1573*4c3eb207Smrg column);
15743ad841b2Smrg }
15753ad841b2Smrg else
15763ad841b2Smrg unread_char (ch);
15773ad841b2Smrg }
15783ad841b2Smrg
15793ad841b2Smrg /* Postprocessing subroutine of function_reader::parse_function.
15803ad841b2Smrg Populate m_insns_by_uid. */
15813ad841b2Smrg
15823ad841b2Smrg void
handle_insn_uids()15833ad841b2Smrg function_reader::handle_insn_uids ()
15843ad841b2Smrg {
15853ad841b2Smrg /* Locate the currently assigned INSN_UID values, storing
15863ad841b2Smrg them in m_insns_by_uid. */
15873ad841b2Smrg int max_uid = 0;
15883ad841b2Smrg for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
15893ad841b2Smrg {
15903ad841b2Smrg if (m_insns_by_uid.get (INSN_UID (insn)))
15913ad841b2Smrg error ("duplicate insn UID: %i", INSN_UID (insn));
15923ad841b2Smrg m_insns_by_uid.put (INSN_UID (insn), insn);
15933ad841b2Smrg if (INSN_UID (insn) > max_uid)
15943ad841b2Smrg max_uid = INSN_UID (insn);
15953ad841b2Smrg }
15963ad841b2Smrg
15973ad841b2Smrg /* Ensure x_cur_insn_uid is 1 more than the biggest insn UID seen.
15983ad841b2Smrg This is normally updated by the various make_*insn_raw functions. */
15993ad841b2Smrg crtl->emit.x_cur_insn_uid = max_uid + 1;
16003ad841b2Smrg }
16013ad841b2Smrg
16023ad841b2Smrg /* Apply all of the recorded fixups. */
16033ad841b2Smrg
16043ad841b2Smrg void
apply_fixups()16053ad841b2Smrg function_reader::apply_fixups ()
16063ad841b2Smrg {
16073ad841b2Smrg int i;
16083ad841b2Smrg fixup *f;
16093ad841b2Smrg FOR_EACH_VEC_ELT (m_fixups, i, f)
16103ad841b2Smrg f->apply (this);
16113ad841b2Smrg }
16123ad841b2Smrg
16133ad841b2Smrg /* Given a UID value, try to locate a pointer to the corresponding
1614*4c3eb207Smrg rtx_insn *, or NULL if it can't be found. */
16153ad841b2Smrg
16163ad841b2Smrg rtx_insn **
get_insn_by_uid(int uid)16173ad841b2Smrg function_reader::get_insn_by_uid (int uid)
16183ad841b2Smrg {
16193ad841b2Smrg return m_insns_by_uid.get (uid);
16203ad841b2Smrg }
16213ad841b2Smrg
16223ad841b2Smrg /* Run the RTL dump parser, parsing a dump located at PATH.
16233ad841b2Smrg Return true iff the file was successfully parsed. */
16243ad841b2Smrg
16253ad841b2Smrg bool
read_rtl_function_body(const char * path)16263ad841b2Smrg read_rtl_function_body (const char *path)
16273ad841b2Smrg {
16283ad841b2Smrg initialize_rtl ();
1629*4c3eb207Smrg crtl->abi = &default_function_abi;
16303ad841b2Smrg init_emit ();
16313ad841b2Smrg init_varasm_status ();
16323ad841b2Smrg
16333ad841b2Smrg function_reader reader;
16343ad841b2Smrg if (!reader.read_file (path))
16353ad841b2Smrg return false;
16363ad841b2Smrg
16373ad841b2Smrg return true;
16383ad841b2Smrg }
16393ad841b2Smrg
16403ad841b2Smrg /* Run the RTL dump parser on the range of lines between START_LOC and
16413ad841b2Smrg END_LOC (including those lines). */
16423ad841b2Smrg
16433ad841b2Smrg bool
read_rtl_function_body_from_file_range(location_t start_loc,location_t end_loc)16443ad841b2Smrg read_rtl_function_body_from_file_range (location_t start_loc,
16453ad841b2Smrg location_t end_loc)
16463ad841b2Smrg {
16473ad841b2Smrg expanded_location exploc_start = expand_location (start_loc);
16483ad841b2Smrg expanded_location exploc_end = expand_location (end_loc);
16493ad841b2Smrg
16503ad841b2Smrg if (exploc_start.file != exploc_end.file)
16513ad841b2Smrg {
16523ad841b2Smrg error_at (end_loc, "start/end of RTL fragment are in different files");
16533ad841b2Smrg return false;
16543ad841b2Smrg }
16553ad841b2Smrg if (exploc_start.line >= exploc_end.line)
16563ad841b2Smrg {
16573ad841b2Smrg error_at (end_loc,
16583ad841b2Smrg "start of RTL fragment must be on an earlier line than end");
16593ad841b2Smrg return false;
16603ad841b2Smrg }
16613ad841b2Smrg
16623ad841b2Smrg initialize_rtl ();
1663*4c3eb207Smrg crtl->abi = &fndecl_abi (cfun->decl).base_abi ();
16643ad841b2Smrg init_emit ();
16653ad841b2Smrg init_varasm_status ();
16663ad841b2Smrg
16673ad841b2Smrg function_reader reader;
16683ad841b2Smrg if (!reader.read_file_fragment (exploc_start.file, exploc_start.line,
16693ad841b2Smrg exploc_end.line - 1))
16703ad841b2Smrg return false;
16713ad841b2Smrg
16723ad841b2Smrg return true;
16733ad841b2Smrg }
16743ad841b2Smrg
16753ad841b2Smrg #if CHECKING_P
16763ad841b2Smrg
16773ad841b2Smrg namespace selftest {
16783ad841b2Smrg
16793ad841b2Smrg /* Verify that parse_edge_flags works. */
16803ad841b2Smrg
16813ad841b2Smrg static void
test_edge_flags()16823ad841b2Smrg test_edge_flags ()
16833ad841b2Smrg {
16843ad841b2Smrg /* parse_edge_flags modifies its input (due to strtok), so we must make
16853ad841b2Smrg a copy of the literals. */
16863ad841b2Smrg #define ASSERT_PARSE_EDGE_FLAGS(EXPECTED, STR) \
16873ad841b2Smrg do { \
16883ad841b2Smrg char *str = xstrdup (STR); \
16893ad841b2Smrg ASSERT_EQ (EXPECTED, parse_edge_flags (str)); \
16903ad841b2Smrg free (str); \
16913ad841b2Smrg } while (0)
16923ad841b2Smrg
16933ad841b2Smrg ASSERT_PARSE_EDGE_FLAGS (0, "");
16943ad841b2Smrg ASSERT_PARSE_EDGE_FLAGS (EDGE_FALLTHRU, "FALLTHRU");
16953ad841b2Smrg ASSERT_PARSE_EDGE_FLAGS (EDGE_ABNORMAL_CALL, "ABNORMAL_CALL");
16963ad841b2Smrg ASSERT_PARSE_EDGE_FLAGS (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL,
16973ad841b2Smrg "ABNORMAL | ABNORMAL_CALL");
16983ad841b2Smrg
16993ad841b2Smrg #undef ASSERT_PARSE_EDGE_FLAGS
17003ad841b2Smrg }
17013ad841b2Smrg
17023ad841b2Smrg /* Verify that lookup_reg_by_dump_name works. */
17033ad841b2Smrg
17043ad841b2Smrg static void
test_parsing_regnos()17053ad841b2Smrg test_parsing_regnos ()
17063ad841b2Smrg {
17073ad841b2Smrg ASSERT_EQ (-1, lookup_reg_by_dump_name ("this is not a register"));
17083ad841b2Smrg
17093ad841b2Smrg /* Verify lookup of virtual registers. */
17103ad841b2Smrg ASSERT_EQ (VIRTUAL_INCOMING_ARGS_REGNUM,
17113ad841b2Smrg lookup_reg_by_dump_name ("virtual-incoming-args"));
17123ad841b2Smrg ASSERT_EQ (VIRTUAL_STACK_VARS_REGNUM,
17133ad841b2Smrg lookup_reg_by_dump_name ("virtual-stack-vars"));
17143ad841b2Smrg ASSERT_EQ (VIRTUAL_STACK_DYNAMIC_REGNUM,
17153ad841b2Smrg lookup_reg_by_dump_name ("virtual-stack-dynamic"));
17163ad841b2Smrg ASSERT_EQ (VIRTUAL_OUTGOING_ARGS_REGNUM,
17173ad841b2Smrg lookup_reg_by_dump_name ("virtual-outgoing-args"));
17183ad841b2Smrg ASSERT_EQ (VIRTUAL_CFA_REGNUM,
17193ad841b2Smrg lookup_reg_by_dump_name ("virtual-cfa"));
17203ad841b2Smrg ASSERT_EQ (VIRTUAL_PREFERRED_STACK_BOUNDARY_REGNUM,
17213ad841b2Smrg lookup_reg_by_dump_name ("virtual-preferred-stack-boundary"));
17223ad841b2Smrg
17233ad841b2Smrg /* Verify lookup of non-virtual pseudos. */
17243ad841b2Smrg ASSERT_EQ (LAST_VIRTUAL_REGISTER + 1, lookup_reg_by_dump_name ("<0>"));
17253ad841b2Smrg ASSERT_EQ (LAST_VIRTUAL_REGISTER + 2, lookup_reg_by_dump_name ("<1>"));
17263ad841b2Smrg }
17273ad841b2Smrg
17283ad841b2Smrg /* Verify that edge E is as expected, with the src and dest basic blocks
17293ad841b2Smrg having indices EXPECTED_SRC_IDX and EXPECTED_DEST_IDX respectively, and
17303ad841b2Smrg the edge having flags equal to EXPECTED_FLAGS.
17313ad841b2Smrg Use LOC as the effective location when reporting failures. */
17323ad841b2Smrg
17333ad841b2Smrg static void
assert_edge_at(const location & loc,edge e,int expected_src_idx,int expected_dest_idx,int expected_flags)17343ad841b2Smrg assert_edge_at (const location &loc, edge e, int expected_src_idx,
17353ad841b2Smrg int expected_dest_idx, int expected_flags)
17363ad841b2Smrg {
17373ad841b2Smrg ASSERT_EQ_AT (loc, expected_src_idx, e->src->index);
17383ad841b2Smrg ASSERT_EQ_AT (loc, expected_dest_idx, e->dest->index);
17393ad841b2Smrg ASSERT_EQ_AT (loc, expected_flags, e->flags);
17403ad841b2Smrg }
17413ad841b2Smrg
17423ad841b2Smrg /* Verify that edge EDGE is as expected, with the src and dest basic blocks
17433ad841b2Smrg having indices EXPECTED_SRC_IDX and EXPECTED_DEST_IDX respectively, and
17443ad841b2Smrg the edge having flags equal to EXPECTED_FLAGS. */
17453ad841b2Smrg
17463ad841b2Smrg #define ASSERT_EDGE(EDGE, EXPECTED_SRC_IDX, EXPECTED_DEST_IDX, \
17473ad841b2Smrg EXPECTED_FLAGS) \
17483ad841b2Smrg assert_edge_at (SELFTEST_LOCATION, EDGE, EXPECTED_SRC_IDX, \
17493ad841b2Smrg EXPECTED_DEST_IDX, EXPECTED_FLAGS)
17503ad841b2Smrg
17513ad841b2Smrg /* Verify that we can load RTL dumps. */
17523ad841b2Smrg
17533ad841b2Smrg static void
test_loading_dump_fragment_1()17543ad841b2Smrg test_loading_dump_fragment_1 ()
17553ad841b2Smrg {
17563ad841b2Smrg // TODO: filter on target?
17573ad841b2Smrg rtl_dump_test t (SELFTEST_LOCATION, locate_file ("asr_div1.rtl"));
17583ad841b2Smrg
17593ad841b2Smrg /* Verify that the insns were loaded correctly. */
17603ad841b2Smrg rtx_insn *insn_1 = get_insns ();
17613ad841b2Smrg ASSERT_TRUE (insn_1);
17623ad841b2Smrg ASSERT_EQ (1, INSN_UID (insn_1));
17633ad841b2Smrg ASSERT_EQ (INSN, GET_CODE (insn_1));
17643ad841b2Smrg ASSERT_EQ (SET, GET_CODE (PATTERN (insn_1)));
17653ad841b2Smrg ASSERT_EQ (NULL, PREV_INSN (insn_1));
17663ad841b2Smrg
17673ad841b2Smrg rtx_insn *insn_2 = NEXT_INSN (insn_1);
17683ad841b2Smrg ASSERT_TRUE (insn_2);
17693ad841b2Smrg ASSERT_EQ (2, INSN_UID (insn_2));
17703ad841b2Smrg ASSERT_EQ (INSN, GET_CODE (insn_2));
17713ad841b2Smrg ASSERT_EQ (insn_1, PREV_INSN (insn_2));
17723ad841b2Smrg ASSERT_EQ (NULL, NEXT_INSN (insn_2));
17733ad841b2Smrg
17743ad841b2Smrg /* Verify that registers were loaded correctly. */
17753ad841b2Smrg rtx insn_1_dest = SET_DEST (PATTERN (insn_1));
17763ad841b2Smrg ASSERT_EQ (REG, GET_CODE (insn_1_dest));
17773ad841b2Smrg ASSERT_EQ ((LAST_VIRTUAL_REGISTER + 1) + 2, REGNO (insn_1_dest));
17783ad841b2Smrg rtx insn_1_src = SET_SRC (PATTERN (insn_1));
17793ad841b2Smrg ASSERT_EQ (LSHIFTRT, GET_CODE (insn_1_src));
17803ad841b2Smrg rtx reg = XEXP (insn_1_src, 0);
17813ad841b2Smrg ASSERT_EQ (REG, GET_CODE (reg));
17823ad841b2Smrg ASSERT_EQ (LAST_VIRTUAL_REGISTER + 1, REGNO (reg));
17833ad841b2Smrg
17843ad841b2Smrg /* Verify that get_insn_by_uid works. */
17853ad841b2Smrg ASSERT_EQ (insn_1, get_insn_by_uid (1));
17863ad841b2Smrg ASSERT_EQ (insn_2, get_insn_by_uid (2));
17873ad841b2Smrg
17883ad841b2Smrg /* Verify that basic blocks were created. */
17893ad841b2Smrg ASSERT_EQ (2, BLOCK_FOR_INSN (insn_1)->index);
17903ad841b2Smrg ASSERT_EQ (2, BLOCK_FOR_INSN (insn_2)->index);
17913ad841b2Smrg
17923ad841b2Smrg /* Verify that the CFG was recreated. */
17933ad841b2Smrg ASSERT_TRUE (cfun);
17943ad841b2Smrg verify_three_block_rtl_cfg (cfun);
17953ad841b2Smrg basic_block bb2 = BASIC_BLOCK_FOR_FN (cfun, 2);
17963ad841b2Smrg ASSERT_TRUE (bb2 != NULL);
17973ad841b2Smrg ASSERT_EQ (BB_RTL, bb2->flags & BB_RTL);
17983ad841b2Smrg ASSERT_EQ (2, bb2->index);
17993ad841b2Smrg ASSERT_EQ (insn_1, BB_HEAD (bb2));
18003ad841b2Smrg ASSERT_EQ (insn_2, BB_END (bb2));
18013ad841b2Smrg }
18023ad841b2Smrg
18033ad841b2Smrg /* Verify loading another RTL dump. */
18043ad841b2Smrg
18053ad841b2Smrg static void
test_loading_dump_fragment_2()18063ad841b2Smrg test_loading_dump_fragment_2 ()
18073ad841b2Smrg {
18083ad841b2Smrg rtl_dump_test t (SELFTEST_LOCATION, locate_file ("simple-cse.rtl"));
18093ad841b2Smrg
18103ad841b2Smrg rtx_insn *insn_1 = get_insn_by_uid (1);
18113ad841b2Smrg rtx_insn *insn_2 = get_insn_by_uid (2);
18123ad841b2Smrg rtx_insn *insn_3 = get_insn_by_uid (3);
18133ad841b2Smrg
18143ad841b2Smrg rtx set1 = single_set (insn_1);
18153ad841b2Smrg ASSERT_NE (NULL, set1);
18163ad841b2Smrg rtx set2 = single_set (insn_2);
18173ad841b2Smrg ASSERT_NE (NULL, set2);
18183ad841b2Smrg rtx set3 = single_set (insn_3);
18193ad841b2Smrg ASSERT_NE (NULL, set3);
18203ad841b2Smrg
18213ad841b2Smrg rtx src1 = SET_SRC (set1);
18223ad841b2Smrg ASSERT_EQ (PLUS, GET_CODE (src1));
18233ad841b2Smrg
18243ad841b2Smrg rtx src2 = SET_SRC (set2);
18253ad841b2Smrg ASSERT_EQ (PLUS, GET_CODE (src2));
18263ad841b2Smrg
18273ad841b2Smrg /* Both src1 and src2 refer to "(reg:SI %0)".
18283ad841b2Smrg Verify that we have pointer equality. */
18293ad841b2Smrg rtx lhs1 = XEXP (src1, 0);
18303ad841b2Smrg rtx lhs2 = XEXP (src2, 0);
18313ad841b2Smrg ASSERT_EQ (lhs1, lhs2);
18323ad841b2Smrg
18333ad841b2Smrg /* Verify that the CFG was recreated. */
18343ad841b2Smrg ASSERT_TRUE (cfun);
18353ad841b2Smrg verify_three_block_rtl_cfg (cfun);
18363ad841b2Smrg }
18373ad841b2Smrg
18383ad841b2Smrg /* Verify that CODE_LABEL insns are loaded correctly. */
18393ad841b2Smrg
18403ad841b2Smrg static void
test_loading_labels()18413ad841b2Smrg test_loading_labels ()
18423ad841b2Smrg {
18433ad841b2Smrg rtl_dump_test t (SELFTEST_LOCATION, locate_file ("example-labels.rtl"));
18443ad841b2Smrg
18453ad841b2Smrg rtx_insn *insn_100 = get_insn_by_uid (100);
18463ad841b2Smrg ASSERT_EQ (CODE_LABEL, GET_CODE (insn_100));
18473ad841b2Smrg ASSERT_EQ (100, INSN_UID (insn_100));
18483ad841b2Smrg ASSERT_EQ (NULL, LABEL_NAME (insn_100));
18493ad841b2Smrg ASSERT_EQ (0, LABEL_NUSES (insn_100));
18503ad841b2Smrg ASSERT_EQ (30, CODE_LABEL_NUMBER (insn_100));
18513ad841b2Smrg
18523ad841b2Smrg rtx_insn *insn_200 = get_insn_by_uid (200);
18533ad841b2Smrg ASSERT_EQ (CODE_LABEL, GET_CODE (insn_200));
18543ad841b2Smrg ASSERT_EQ (200, INSN_UID (insn_200));
18553ad841b2Smrg ASSERT_STREQ ("some_label_name", LABEL_NAME (insn_200));
18563ad841b2Smrg ASSERT_EQ (0, LABEL_NUSES (insn_200));
18573ad841b2Smrg ASSERT_EQ (40, CODE_LABEL_NUMBER (insn_200));
18583ad841b2Smrg
18593ad841b2Smrg /* Ensure that the presence of CODE_LABEL_NUMBER == 40
18603ad841b2Smrg means that the next label num to be handed out will be 41. */
18613ad841b2Smrg ASSERT_EQ (41, max_label_num ());
18623ad841b2Smrg
18633ad841b2Smrg /* Ensure that label names read from a dump are GC-managed
18643ad841b2Smrg and are found through the insn. */
18653ad841b2Smrg forcibly_ggc_collect ();
18663ad841b2Smrg ASSERT_TRUE (ggc_marked_p (insn_200));
18673ad841b2Smrg ASSERT_TRUE (ggc_marked_p (LABEL_NAME (insn_200)));
18683ad841b2Smrg }
18693ad841b2Smrg
18703ad841b2Smrg /* Verify that the loader copes with an insn with a mode. */
18713ad841b2Smrg
18723ad841b2Smrg static void
test_loading_insn_with_mode()18733ad841b2Smrg test_loading_insn_with_mode ()
18743ad841b2Smrg {
18753ad841b2Smrg rtl_dump_test t (SELFTEST_LOCATION, locate_file ("insn-with-mode.rtl"));
18763ad841b2Smrg rtx_insn *insn = get_insns ();
18773ad841b2Smrg ASSERT_EQ (INSN, GET_CODE (insn));
18783ad841b2Smrg
18793ad841b2Smrg /* Verify that the "TI" mode was set from "insn:TI". */
18803ad841b2Smrg ASSERT_EQ (TImode, GET_MODE (insn));
18813ad841b2Smrg }
18823ad841b2Smrg
18833ad841b2Smrg /* Verify that the loader copes with a jump_insn to a label_ref. */
18843ad841b2Smrg
18853ad841b2Smrg static void
test_loading_jump_to_label_ref()18863ad841b2Smrg test_loading_jump_to_label_ref ()
18873ad841b2Smrg {
18883ad841b2Smrg rtl_dump_test t (SELFTEST_LOCATION, locate_file ("jump-to-label-ref.rtl"));
18893ad841b2Smrg
18903ad841b2Smrg rtx_insn *jump_insn = get_insn_by_uid (1);
18913ad841b2Smrg ASSERT_EQ (JUMP_INSN, GET_CODE (jump_insn));
18923ad841b2Smrg
18933ad841b2Smrg rtx_insn *barrier = get_insn_by_uid (2);
18943ad841b2Smrg ASSERT_EQ (BARRIER, GET_CODE (barrier));
18953ad841b2Smrg
18963ad841b2Smrg rtx_insn *code_label = get_insn_by_uid (100);
18973ad841b2Smrg ASSERT_EQ (CODE_LABEL, GET_CODE (code_label));
18983ad841b2Smrg
18993ad841b2Smrg /* Verify the jump_insn. */
19003ad841b2Smrg ASSERT_EQ (4, BLOCK_FOR_INSN (jump_insn)->index);
19013ad841b2Smrg ASSERT_EQ (SET, GET_CODE (PATTERN (jump_insn)));
19023ad841b2Smrg /* Ensure that the "(pc)" is using the global singleton. */
19033ad841b2Smrg ASSERT_RTX_PTR_EQ (pc_rtx, SET_DEST (PATTERN (jump_insn)));
19043ad841b2Smrg rtx label_ref = SET_SRC (PATTERN (jump_insn));
19053ad841b2Smrg ASSERT_EQ (LABEL_REF, GET_CODE (label_ref));
19063ad841b2Smrg ASSERT_EQ (code_label, label_ref_label (label_ref));
19073ad841b2Smrg ASSERT_EQ (code_label, JUMP_LABEL (jump_insn));
19083ad841b2Smrg
19093ad841b2Smrg /* Verify the code_label. */
19103ad841b2Smrg ASSERT_EQ (5, BLOCK_FOR_INSN (code_label)->index);
19113ad841b2Smrg ASSERT_EQ (NULL, LABEL_NAME (code_label));
19123ad841b2Smrg ASSERT_EQ (1, LABEL_NUSES (code_label));
19133ad841b2Smrg
19143ad841b2Smrg /* Verify the generated CFG. */
19153ad841b2Smrg
19163ad841b2Smrg /* Locate blocks. */
19173ad841b2Smrg basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun);
19183ad841b2Smrg ASSERT_TRUE (entry != NULL);
19193ad841b2Smrg ASSERT_EQ (ENTRY_BLOCK, entry->index);
19203ad841b2Smrg
19213ad841b2Smrg basic_block exit = EXIT_BLOCK_PTR_FOR_FN (cfun);
19223ad841b2Smrg ASSERT_TRUE (exit != NULL);
19233ad841b2Smrg ASSERT_EQ (EXIT_BLOCK, exit->index);
19243ad841b2Smrg
19253ad841b2Smrg basic_block bb4 = (*cfun->cfg->x_basic_block_info)[4];
19263ad841b2Smrg basic_block bb5 = (*cfun->cfg->x_basic_block_info)[5];
19273ad841b2Smrg ASSERT_EQ (4, bb4->index);
19283ad841b2Smrg ASSERT_EQ (5, bb5->index);
19293ad841b2Smrg
19303ad841b2Smrg /* Entry block. */
19313ad841b2Smrg ASSERT_EQ (NULL, entry->preds);
19323ad841b2Smrg ASSERT_EQ (1, entry->succs->length ());
19333ad841b2Smrg ASSERT_EDGE ((*entry->succs)[0], 0, 4, EDGE_FALLTHRU);
19343ad841b2Smrg
19353ad841b2Smrg /* bb4. */
19363ad841b2Smrg ASSERT_EQ (1, bb4->preds->length ());
19373ad841b2Smrg ASSERT_EDGE ((*bb4->preds)[0], 0, 4, EDGE_FALLTHRU);
19383ad841b2Smrg ASSERT_EQ (1, bb4->succs->length ());
19393ad841b2Smrg ASSERT_EDGE ((*bb4->succs)[0], 4, 5, 0x0);
19403ad841b2Smrg
19413ad841b2Smrg /* bb5. */
19423ad841b2Smrg ASSERT_EQ (1, bb5->preds->length ());
19433ad841b2Smrg ASSERT_EDGE ((*bb5->preds)[0], 4, 5, 0x0);
19443ad841b2Smrg ASSERT_EQ (1, bb5->succs->length ());
19453ad841b2Smrg ASSERT_EDGE ((*bb5->succs)[0], 5, 1, EDGE_FALLTHRU);
19463ad841b2Smrg
19473ad841b2Smrg /* Exit block. */
19483ad841b2Smrg ASSERT_EQ (1, exit->preds->length ());
19493ad841b2Smrg ASSERT_EDGE ((*exit->preds)[0], 5, 1, EDGE_FALLTHRU);
19503ad841b2Smrg ASSERT_EQ (NULL, exit->succs);
19513ad841b2Smrg }
19523ad841b2Smrg
19533ad841b2Smrg /* Verify that the loader copes with a jump_insn to a label_ref
19543ad841b2Smrg marked "return". */
19553ad841b2Smrg
19563ad841b2Smrg static void
test_loading_jump_to_return()19573ad841b2Smrg test_loading_jump_to_return ()
19583ad841b2Smrg {
19593ad841b2Smrg rtl_dump_test t (SELFTEST_LOCATION, locate_file ("jump-to-return.rtl"));
19603ad841b2Smrg
19613ad841b2Smrg rtx_insn *jump_insn = get_insn_by_uid (1);
19623ad841b2Smrg ASSERT_EQ (JUMP_INSN, GET_CODE (jump_insn));
19633ad841b2Smrg ASSERT_RTX_PTR_EQ (ret_rtx, JUMP_LABEL (jump_insn));
19643ad841b2Smrg }
19653ad841b2Smrg
19663ad841b2Smrg /* Verify that the loader copes with a jump_insn to a label_ref
19673ad841b2Smrg marked "simple_return". */
19683ad841b2Smrg
19693ad841b2Smrg static void
test_loading_jump_to_simple_return()19703ad841b2Smrg test_loading_jump_to_simple_return ()
19713ad841b2Smrg {
19723ad841b2Smrg rtl_dump_test t (SELFTEST_LOCATION,
19733ad841b2Smrg locate_file ("jump-to-simple-return.rtl"));
19743ad841b2Smrg
19753ad841b2Smrg rtx_insn *jump_insn = get_insn_by_uid (1);
19763ad841b2Smrg ASSERT_EQ (JUMP_INSN, GET_CODE (jump_insn));
19773ad841b2Smrg ASSERT_RTX_PTR_EQ (simple_return_rtx, JUMP_LABEL (jump_insn));
19783ad841b2Smrg }
19793ad841b2Smrg
19803ad841b2Smrg /* Verify that the loader copes with a NOTE_INSN_BASIC_BLOCK. */
19813ad841b2Smrg
19823ad841b2Smrg static void
test_loading_note_insn_basic_block()19833ad841b2Smrg test_loading_note_insn_basic_block ()
19843ad841b2Smrg {
19853ad841b2Smrg rtl_dump_test t (SELFTEST_LOCATION,
19863ad841b2Smrg locate_file ("note_insn_basic_block.rtl"));
19873ad841b2Smrg
19883ad841b2Smrg rtx_insn *note = get_insn_by_uid (1);
19893ad841b2Smrg ASSERT_EQ (NOTE, GET_CODE (note));
19903ad841b2Smrg ASSERT_EQ (2, BLOCK_FOR_INSN (note)->index);
19913ad841b2Smrg
19923ad841b2Smrg ASSERT_EQ (NOTE_INSN_BASIC_BLOCK, NOTE_KIND (note));
19933ad841b2Smrg ASSERT_EQ (2, NOTE_BASIC_BLOCK (note)->index);
19943ad841b2Smrg ASSERT_EQ (BASIC_BLOCK_FOR_FN (cfun, 2), NOTE_BASIC_BLOCK (note));
19953ad841b2Smrg }
19963ad841b2Smrg
19973ad841b2Smrg /* Verify that the loader copes with a NOTE_INSN_DELETED. */
19983ad841b2Smrg
19993ad841b2Smrg static void
test_loading_note_insn_deleted()20003ad841b2Smrg test_loading_note_insn_deleted ()
20013ad841b2Smrg {
20023ad841b2Smrg rtl_dump_test t (SELFTEST_LOCATION, locate_file ("note-insn-deleted.rtl"));
20033ad841b2Smrg
20043ad841b2Smrg rtx_insn *note = get_insn_by_uid (1);
20053ad841b2Smrg ASSERT_EQ (NOTE, GET_CODE (note));
20063ad841b2Smrg ASSERT_EQ (NOTE_INSN_DELETED, NOTE_KIND (note));
20073ad841b2Smrg }
20083ad841b2Smrg
20093ad841b2Smrg /* Verify that the const_int values are consolidated, since
20103ad841b2Smrg pointer equality corresponds to value equality.
20113ad841b2Smrg TODO: do this for all in CASE_CONST_UNIQUE. */
20123ad841b2Smrg
20133ad841b2Smrg static void
test_loading_const_int()20143ad841b2Smrg test_loading_const_int ()
20153ad841b2Smrg {
20163ad841b2Smrg rtl_dump_test t (SELFTEST_LOCATION, locate_file ("const-int.rtl"));
20173ad841b2Smrg
20183ad841b2Smrg /* Verify that const_int values below MAX_SAVED_CONST_INT use
20193ad841b2Smrg the global values. */
20203ad841b2Smrg ASSERT_EQ (const0_rtx, SET_SRC (PATTERN (get_insn_by_uid (1))));
20213ad841b2Smrg ASSERT_EQ (const1_rtx, SET_SRC (PATTERN (get_insn_by_uid (2))));
20223ad841b2Smrg ASSERT_EQ (constm1_rtx, SET_SRC (PATTERN (get_insn_by_uid (3))));
20233ad841b2Smrg
20243ad841b2Smrg /* Verify that other const_int values are consolidated. */
20253ad841b2Smrg rtx int256 = gen_rtx_CONST_INT (SImode, 256);
20263ad841b2Smrg ASSERT_EQ (int256, SET_SRC (PATTERN (get_insn_by_uid (4))));
20273ad841b2Smrg }
20283ad841b2Smrg
20293ad841b2Smrg /* Verify that the loader copes with a SYMBOL_REF. */
20303ad841b2Smrg
20313ad841b2Smrg static void
test_loading_symbol_ref()20323ad841b2Smrg test_loading_symbol_ref ()
20333ad841b2Smrg {
20343ad841b2Smrg rtl_dump_test t (SELFTEST_LOCATION, locate_file ("symbol-ref.rtl"));
20353ad841b2Smrg
20363ad841b2Smrg rtx_insn *insn = get_insns ();
20373ad841b2Smrg
20383ad841b2Smrg rtx high = SET_SRC (PATTERN (insn));
20393ad841b2Smrg ASSERT_EQ (HIGH, GET_CODE (high));
20403ad841b2Smrg
20413ad841b2Smrg rtx symbol_ref = XEXP (high, 0);
20423ad841b2Smrg ASSERT_EQ (SYMBOL_REF, GET_CODE (symbol_ref));
20433ad841b2Smrg
20443ad841b2Smrg /* Verify that "[flags 0xc0]" was parsed. */
20453ad841b2Smrg ASSERT_EQ (0xc0, SYMBOL_REF_FLAGS (symbol_ref));
20463ad841b2Smrg /* TODO: we don't yet load SYMBOL_REF_DECL. */
20473ad841b2Smrg }
20483ad841b2Smrg
20493ad841b2Smrg /* Verify that the loader can rebuild a CFG. */
20503ad841b2Smrg
20513ad841b2Smrg static void
test_loading_cfg()20523ad841b2Smrg test_loading_cfg ()
20533ad841b2Smrg {
20543ad841b2Smrg rtl_dump_test t (SELFTEST_LOCATION, locate_file ("cfg-test.rtl"));
20553ad841b2Smrg
20563ad841b2Smrg ASSERT_STREQ ("cfg_test", IDENTIFIER_POINTER (DECL_NAME (cfun->decl)));
20573ad841b2Smrg
20583ad841b2Smrg ASSERT_TRUE (cfun);
20593ad841b2Smrg
20603ad841b2Smrg ASSERT_TRUE (cfun->cfg != NULL);
20613ad841b2Smrg ASSERT_EQ (6, n_basic_blocks_for_fn (cfun));
20623ad841b2Smrg ASSERT_EQ (6, n_edges_for_fn (cfun));
20633ad841b2Smrg
20643ad841b2Smrg /* The "fake" basic blocks. */
20653ad841b2Smrg basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun);
20663ad841b2Smrg ASSERT_TRUE (entry != NULL);
20673ad841b2Smrg ASSERT_EQ (ENTRY_BLOCK, entry->index);
20683ad841b2Smrg
20693ad841b2Smrg basic_block exit = EXIT_BLOCK_PTR_FOR_FN (cfun);
20703ad841b2Smrg ASSERT_TRUE (exit != NULL);
20713ad841b2Smrg ASSERT_EQ (EXIT_BLOCK, exit->index);
20723ad841b2Smrg
20733ad841b2Smrg /* The "real" basic blocks. */
20743ad841b2Smrg basic_block bb2 = (*cfun->cfg->x_basic_block_info)[2];
20753ad841b2Smrg basic_block bb3 = (*cfun->cfg->x_basic_block_info)[3];
20763ad841b2Smrg basic_block bb4 = (*cfun->cfg->x_basic_block_info)[4];
20773ad841b2Smrg basic_block bb5 = (*cfun->cfg->x_basic_block_info)[5];
20783ad841b2Smrg
20793ad841b2Smrg ASSERT_EQ (2, bb2->index);
20803ad841b2Smrg ASSERT_EQ (3, bb3->index);
20813ad841b2Smrg ASSERT_EQ (4, bb4->index);
20823ad841b2Smrg ASSERT_EQ (5, bb5->index);
20833ad841b2Smrg
20843ad841b2Smrg /* Verify connectivity. */
20853ad841b2Smrg
20863ad841b2Smrg /* Entry block. */
20873ad841b2Smrg ASSERT_EQ (NULL, entry->preds);
20883ad841b2Smrg ASSERT_EQ (1, entry->succs->length ());
20893ad841b2Smrg ASSERT_EDGE ((*entry->succs)[0], 0, 2, EDGE_FALLTHRU);
20903ad841b2Smrg
20913ad841b2Smrg /* bb2. */
20923ad841b2Smrg ASSERT_EQ (1, bb2->preds->length ());
20933ad841b2Smrg ASSERT_EDGE ((*bb2->preds)[0], 0, 2, EDGE_FALLTHRU);
20943ad841b2Smrg ASSERT_EQ (2, bb2->succs->length ());
20953ad841b2Smrg ASSERT_EDGE ((*bb2->succs)[0], 2, 3, EDGE_TRUE_VALUE);
20963ad841b2Smrg ASSERT_EDGE ((*bb2->succs)[1], 2, 4, EDGE_FALSE_VALUE);
20973ad841b2Smrg
20983ad841b2Smrg /* bb3. */
20993ad841b2Smrg ASSERT_EQ (1, bb3->preds->length ());
21003ad841b2Smrg ASSERT_EDGE ((*bb3->preds)[0], 2, 3, EDGE_TRUE_VALUE);
21013ad841b2Smrg ASSERT_EQ (1, bb3->succs->length ());
21023ad841b2Smrg ASSERT_EDGE ((*bb3->succs)[0], 3, 5, EDGE_FALLTHRU);
21033ad841b2Smrg
21043ad841b2Smrg /* bb4. */
21053ad841b2Smrg ASSERT_EQ (1, bb4->preds->length ());
21063ad841b2Smrg ASSERT_EDGE ((*bb4->preds)[0], 2, 4, EDGE_FALSE_VALUE);
21073ad841b2Smrg ASSERT_EQ (1, bb4->succs->length ());
21083ad841b2Smrg ASSERT_EDGE ((*bb4->succs)[0], 4, 5, EDGE_FALLTHRU);
21093ad841b2Smrg
21103ad841b2Smrg /* bb5. */
21113ad841b2Smrg ASSERT_EQ (2, bb5->preds->length ());
21123ad841b2Smrg ASSERT_EDGE ((*bb5->preds)[0], 3, 5, EDGE_FALLTHRU);
21133ad841b2Smrg ASSERT_EDGE ((*bb5->preds)[1], 4, 5, EDGE_FALLTHRU);
21143ad841b2Smrg ASSERT_EQ (1, bb5->succs->length ());
21153ad841b2Smrg ASSERT_EDGE ((*bb5->succs)[0], 5, 1, EDGE_FALLTHRU);
21163ad841b2Smrg
21173ad841b2Smrg /* Exit block. */
21183ad841b2Smrg ASSERT_EQ (1, exit->preds->length ());
21193ad841b2Smrg ASSERT_EDGE ((*exit->preds)[0], 5, 1, EDGE_FALLTHRU);
21203ad841b2Smrg ASSERT_EQ (NULL, exit->succs);
21213ad841b2Smrg }
21223ad841b2Smrg
21233ad841b2Smrg /* Verify that the loader copes with sparse block indices.
21243ad841b2Smrg This testcase loads a file with a "(block 42)". */
21253ad841b2Smrg
21263ad841b2Smrg static void
test_loading_bb_index()21273ad841b2Smrg test_loading_bb_index ()
21283ad841b2Smrg {
21293ad841b2Smrg rtl_dump_test t (SELFTEST_LOCATION, locate_file ("bb-index.rtl"));
21303ad841b2Smrg
21313ad841b2Smrg ASSERT_STREQ ("test_bb_index", IDENTIFIER_POINTER (DECL_NAME (cfun->decl)));
21323ad841b2Smrg
21333ad841b2Smrg ASSERT_TRUE (cfun);
21343ad841b2Smrg
21353ad841b2Smrg ASSERT_TRUE (cfun->cfg != NULL);
21363ad841b2Smrg ASSERT_EQ (3, n_basic_blocks_for_fn (cfun));
21373ad841b2Smrg ASSERT_EQ (43, basic_block_info_for_fn (cfun)->length ());
21383ad841b2Smrg ASSERT_EQ (2, n_edges_for_fn (cfun));
21393ad841b2Smrg
21403ad841b2Smrg ASSERT_EQ (NULL, (*cfun->cfg->x_basic_block_info)[41]);
21413ad841b2Smrg basic_block bb42 = (*cfun->cfg->x_basic_block_info)[42];
21423ad841b2Smrg ASSERT_NE (NULL, bb42);
21433ad841b2Smrg ASSERT_EQ (42, bb42->index);
21443ad841b2Smrg }
21453ad841b2Smrg
21463ad841b2Smrg /* Verify that function_reader::handle_any_trailing_information correctly
21473ad841b2Smrg parses all the possible items emitted for a MEM. */
21483ad841b2Smrg
21493ad841b2Smrg static void
test_loading_mem()21503ad841b2Smrg test_loading_mem ()
21513ad841b2Smrg {
21523ad841b2Smrg rtl_dump_test t (SELFTEST_LOCATION, locate_file ("mem.rtl"));
21533ad841b2Smrg
21543ad841b2Smrg ASSERT_STREQ ("test_mem", IDENTIFIER_POINTER (DECL_NAME (cfun->decl)));
21553ad841b2Smrg ASSERT_TRUE (cfun);
21563ad841b2Smrg
21573ad841b2Smrg /* Verify parsing of "[42 i+17 S8 A128 AS5]". */
21583ad841b2Smrg rtx_insn *insn_1 = get_insn_by_uid (1);
21593ad841b2Smrg rtx set1 = single_set (insn_1);
21603ad841b2Smrg rtx mem1 = SET_DEST (set1);
21613ad841b2Smrg ASSERT_EQ (42, MEM_ALIAS_SET (mem1));
21623ad841b2Smrg /* "+17". */
21633ad841b2Smrg ASSERT_TRUE (MEM_OFFSET_KNOWN_P (mem1));
2164cef8759bSmrg ASSERT_KNOWN_EQ (17, MEM_OFFSET (mem1));
21653ad841b2Smrg /* "S8". */
2166cef8759bSmrg ASSERT_KNOWN_EQ (8, MEM_SIZE (mem1));
21673ad841b2Smrg /* "A128. */
21683ad841b2Smrg ASSERT_EQ (128, MEM_ALIGN (mem1));
21693ad841b2Smrg /* "AS5. */
21703ad841b2Smrg ASSERT_EQ (5, MEM_ADDR_SPACE (mem1));
21713ad841b2Smrg
21723ad841b2Smrg /* Verify parsing of "43 i+18 S9 AS6"
21733ad841b2Smrg (an address space without an alignment). */
21743ad841b2Smrg rtx_insn *insn_2 = get_insn_by_uid (2);
21753ad841b2Smrg rtx set2 = single_set (insn_2);
21763ad841b2Smrg rtx mem2 = SET_DEST (set2);
21773ad841b2Smrg ASSERT_EQ (43, MEM_ALIAS_SET (mem2));
21783ad841b2Smrg /* "+18". */
21793ad841b2Smrg ASSERT_TRUE (MEM_OFFSET_KNOWN_P (mem2));
2180cef8759bSmrg ASSERT_KNOWN_EQ (18, MEM_OFFSET (mem2));
21813ad841b2Smrg /* "S9". */
2182cef8759bSmrg ASSERT_KNOWN_EQ (9, MEM_SIZE (mem2));
21833ad841b2Smrg /* "AS6. */
21843ad841b2Smrg ASSERT_EQ (6, MEM_ADDR_SPACE (mem2));
21853ad841b2Smrg }
21863ad841b2Smrg
2187627f7eb2Smrg /* Verify that "repeated xN" is read correctly. */
2188627f7eb2Smrg
2189627f7eb2Smrg static void
test_loading_repeat()2190627f7eb2Smrg test_loading_repeat ()
2191627f7eb2Smrg {
2192627f7eb2Smrg rtl_dump_test t (SELFTEST_LOCATION, locate_file ("repeat.rtl"));
2193627f7eb2Smrg
2194627f7eb2Smrg rtx_insn *insn_1 = get_insn_by_uid (1);
2195627f7eb2Smrg ASSERT_EQ (PARALLEL, GET_CODE (PATTERN (insn_1)));
2196627f7eb2Smrg ASSERT_EQ (64, XVECLEN (PATTERN (insn_1), 0));
2197627f7eb2Smrg for (int i = 0; i < 64; i++)
2198627f7eb2Smrg ASSERT_EQ (const0_rtx, XVECEXP (PATTERN (insn_1), 0, i));
2199627f7eb2Smrg }
2200627f7eb2Smrg
22013ad841b2Smrg /* Run all of the selftests within this file. */
22023ad841b2Smrg
22033ad841b2Smrg void
read_rtl_function_c_tests()22043ad841b2Smrg read_rtl_function_c_tests ()
22053ad841b2Smrg {
22063ad841b2Smrg test_edge_flags ();
22073ad841b2Smrg test_parsing_regnos ();
22083ad841b2Smrg test_loading_dump_fragment_1 ();
22093ad841b2Smrg test_loading_dump_fragment_2 ();
22103ad841b2Smrg test_loading_labels ();
22113ad841b2Smrg test_loading_insn_with_mode ();
22123ad841b2Smrg test_loading_jump_to_label_ref ();
22133ad841b2Smrg test_loading_jump_to_return ();
22143ad841b2Smrg test_loading_jump_to_simple_return ();
22153ad841b2Smrg test_loading_note_insn_basic_block ();
22163ad841b2Smrg test_loading_note_insn_deleted ();
22173ad841b2Smrg test_loading_const_int ();
22183ad841b2Smrg test_loading_symbol_ref ();
22193ad841b2Smrg test_loading_cfg ();
22203ad841b2Smrg test_loading_bb_index ();
22213ad841b2Smrg test_loading_mem ();
2222627f7eb2Smrg test_loading_repeat ();
22233ad841b2Smrg }
22243ad841b2Smrg
22253ad841b2Smrg } // namespace selftest
22263ad841b2Smrg
22273ad841b2Smrg #endif /* #if CHECKING_P */
2228