From 22b75a53ae8d1d7a0df12977555b294915a30502 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Thu, 14 Apr 2016 15:39:12 -0400 Subject: [PATCH 91/91] FIXME: create edges in CFG --- gcc/rtl/rtl-frontend.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 121 insertions(+), 5 deletions(-) diff --git a/gcc/rtl/rtl-frontend.c b/gcc/rtl/rtl-frontend.c index d536319..0fb65c4 100644 --- a/gcc/rtl/rtl-frontend.c +++ b/gcc/rtl/rtl-frontend.c @@ -335,6 +335,7 @@ class function_reader : public rtx_reader void create_function (); void apply_fixups (); + void create_cfg_edges (); rtx_insn **get_insn_by_uid (int uid); @@ -343,7 +344,7 @@ class function_reader : public rtx_reader tree parse_mem_expr (const char *desc); private: - void create_cfg (); + void create_cfg_and_basic_blocks (); private: struct uid_hash : int_hash {}; @@ -610,7 +611,7 @@ function_reader::create_function () //struct function *fn = ; // DECL_STRUCT_FUNCTION (node->decl); //push_cfun (fn); - create_cfg (); + create_cfg_and_basic_blocks (); cfun->curr_properties = (PROP_cfg | PROP_rtl); //pop_cfun (); @@ -669,9 +670,11 @@ function_reader::get_insn_by_uid (int uid) return m_insns_by_uid.get (uid); } -/* Create cfun's CFG and populate with blocks (TODO: and edges), a helper +/* Create cfun's CFG and populate with blocks, a helper function for function_reader::create_function (). + The edges are created later on, after fixups are applied. + We can't call create_basic_block and use the regular RTL block-creation hooks, since this creates NOTE_INSN_BASIC_BLOCK instances. We don't want to do that; we want to use the notes we were provided with. @@ -690,7 +693,7 @@ function_reader::get_insn_by_uid (int uid) blocks (next_bb/prev_bb) skips over these "holes". */ void -function_reader::create_cfg () +function_reader::create_cfg_and_basic_blocks () { /* Create bare-bones cfg. This creates the entry and exit blocks. */ #if 1 @@ -733,9 +736,121 @@ function_reader::create_cfg () after = bb; } +} + +/* FIXME. */ + +static void +for_each_label_ref (rtx_jump_insn *jump_insn, + void (*cb) (rtx_jump_insn *jump_insn, + rtx label_ref, + void *user_data), + void *user_data) +{ + /* TODO: edges for jump. */ + /* FIXME: how to do this? there could be multiple labels + e.g. computed jump. */ + + if (any_condjump_p (jump_insn)) + { + rtx label_ref = condjump_label (jump_insn); + cb (jump_insn, label_ref, user_data); + return; + } + + if (simplejump_p (jump_insn)) + { + rtx label_ref = SET_SRC (PATTERN (jump_insn)); + cb (jump_insn, label_ref, user_data); + return; + } + + rtx_jump_table_data *tablep; + if (tablejump_p (jump_insn, NULL, &tablep)) + { + gcc_assert (tablep); + rtvec labels = tablep->get_labels (); + int i, veclen = GET_NUM_ELEM (labels); + for (i = 0; i < veclen; ++i) + { + rtx label_ref = RTVEC_ELT (labels, i); + cb (jump_insn, label_ref, user_data); + } + return; + } + + /* TODO: something else? */ + gcc_unreachable (); +} - /* TODO: create edges. */ +/* FIXME. */ +static void +add_edge (basic_block src, basic_block dst, int flags) +{ + if (0) + fprintf (stderr, "making edge %i->%i\n", + src->index, dst->index); + unchecked_make_edge (src, dst, flags); +} + +/* FIXME. */ + +static void +add_edge_cb (rtx_jump_insn *jump_insn, rtx label_ref, void *user_data) +{ + gcc_assert (jump_insn); + gcc_assert (label_ref); + rtx_insn *label_insn = as_a (LABEL_REF_LABEL (label_ref)); + add_edge (BLOCK_FOR_INSN (jump_insn), BLOCK_FOR_INSN (label_insn), 0); +} + +/* Create edges within cfun's CFG, by examining instructions in the + basic blocks and reconstructing the edges accordingly. + This is done after fixups are applied, since the latter is responsible + for setting up BB_HEAD and BB_END within each basic block. */ + +void +function_reader::create_cfg_edges () +{ + /* Create edge from ENTRY_BLOCK to block of first insn. */ + basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (cfun); + add_edge (entry, entry->next_bb, EDGE_FALLTHRU); + + /* Create other edges. + + The edge from the block of last insn to EXIT_BLOCK is created + below, by fall-through from the end of its block. */ + basic_block bb; + FOR_ALL_BB_FN (bb, cfun) + { + if (!BB_HEAD (bb)) + continue; + rtx_insn *end_insn = BB_END (bb); + if (rtx_jump_insn *jump_insn = dyn_cast (end_insn)) + { + if (0) + fprintf (stderr, "bb %i ends in jump\n", bb->index); + if (!any_uncondjump_p (end_insn)) + { + /* Add fallthrough edge first. */ + gcc_assert (bb->next_bb); + add_edge (bb, bb->next_bb, EDGE_FALLTHRU); + } + for_each_label_ref (jump_insn, add_edge_cb, NULL); + } + else + { + if (0) + fprintf (stderr, "bb %i ends in non-jump\n", bb->index); + if (bb->next_bb != NULL) + { + /* Add fallthrough edge. */ + gcc_assert (bb->next_bb); + add_edge (bb, bb->next_bb, EDGE_FALLTHRU); + } + } + } } /* Locate and run PASS_NAME on cfun. */ @@ -774,6 +889,7 @@ rtl_langhook_parse_file (void) reader.create_function (); reader.apply_fixups (); + reader.create_cfg_edges (); /* If -froundtrip=FILENAME was provided, immediately dump the result, so that the testsuite can compare it against the -- 1.8.5.3