xref: /dflybsd-src/contrib/gcc-8.0/gcc/function-tests.c (revision 95059079af47f9a66a175f374f2da1a5020e3255)
138fd1498Szrj /* Unit tests for function-handling.
238fd1498Szrj    Copyright (C) 2015-2018 Free Software Foundation, Inc.
338fd1498Szrj 
438fd1498Szrj This file is part of GCC.
538fd1498Szrj 
638fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
738fd1498Szrj the terms of the GNU General Public License as published by the Free
838fd1498Szrj Software Foundation; either version 3, or (at your option) any later
938fd1498Szrj version.
1038fd1498Szrj 
1138fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1238fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
1338fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1438fd1498Szrj for more details.
1538fd1498Szrj 
1638fd1498Szrj You should have received a copy of the GNU General Public License
1738fd1498Szrj along with GCC; see the file COPYING3.  If not see
1838fd1498Szrj <http://www.gnu.org/licenses/>.  */
1938fd1498Szrj 
2038fd1498Szrj #include "config.h"
2138fd1498Szrj #include "system.h"
2238fd1498Szrj #include "coretypes.h"
2338fd1498Szrj #include "tm.h"
2438fd1498Szrj #include "opts.h"
2538fd1498Szrj #include "hash-set.h"
2638fd1498Szrj #include "fixed-value.h"
2738fd1498Szrj #include "alias.h"
2838fd1498Szrj #include "flags.h"
2938fd1498Szrj #include "symtab.h"
3038fd1498Szrj #include "tree-core.h"
3138fd1498Szrj #include "stor-layout.h"
3238fd1498Szrj #include "tree.h"
3338fd1498Szrj #include "stringpool.h"
3438fd1498Szrj #include "stor-layout.h"
3538fd1498Szrj #include "rtl.h"
3638fd1498Szrj #include "predict.h"
3738fd1498Szrj #include "vec.h"
3838fd1498Szrj #include "hashtab.h"
3938fd1498Szrj #include "hash-set.h"
4038fd1498Szrj #include "hard-reg-set.h"
4138fd1498Szrj #include "input.h"
4238fd1498Szrj #include "function.h"
4338fd1498Szrj #include "dominance.h"
4438fd1498Szrj #include "cfg.h"
4538fd1498Szrj #include "cfganal.h"
4638fd1498Szrj #include "basic-block.h"
4738fd1498Szrj #include "tree-ssa-alias.h"
4838fd1498Szrj #include "internal-fn.h"
4938fd1498Szrj #include "gimple-fold.h"
5038fd1498Szrj #include "gimple-expr.h"
5138fd1498Szrj #include "toplev.h"
5238fd1498Szrj #include "print-tree.h"
5338fd1498Szrj #include "tree-iterator.h"
5438fd1498Szrj #include "gimplify.h"
5538fd1498Szrj #include "tree-cfg.h"
5638fd1498Szrj #include "basic-block.h"
5738fd1498Szrj #include "alias.h"
5838fd1498Szrj #include "symtab.h"
5938fd1498Szrj #include "inchash.h"
6038fd1498Szrj #include "tree.h"
6138fd1498Szrj #include "fold-const.h"
6238fd1498Szrj #include "stor-layout.h"
6338fd1498Szrj #include "stmt.h"
6438fd1498Szrj #include "hash-table.h"
6538fd1498Szrj #include "tree-ssa-alias.h"
6638fd1498Szrj #include "internal-fn.h"
6738fd1498Szrj #include "gimple-expr.h"
6838fd1498Szrj #include "is-a.h"
6938fd1498Szrj #include "gimple.h"
7038fd1498Szrj #include "tree-pass.h"
7138fd1498Szrj #include "context.h"
7238fd1498Szrj #include "hash-map.h"
7338fd1498Szrj #include "plugin-api.h"
7438fd1498Szrj #include "ipa-ref.h"
7538fd1498Szrj #include "cgraph.h"
7638fd1498Szrj #include "selftest.h"
7738fd1498Szrj #include "print-rtl.h"
7838fd1498Szrj 
7938fd1498Szrj #if CHECKING_P
8038fd1498Szrj 
8138fd1498Szrj namespace selftest {
8238fd1498Szrj 
8338fd1498Szrj /* Helper function for selftests of function-creation.  */
8438fd1498Szrj 
8538fd1498Szrj static tree
8638fd1498Szrj make_fndecl (tree return_type,
8738fd1498Szrj 	     const char *name,
8838fd1498Szrj 	     vec <tree> &param_types,
8938fd1498Szrj 	     bool is_variadic = false)
9038fd1498Szrj {
9138fd1498Szrj   tree fn_type;
9238fd1498Szrj   if (is_variadic)
9338fd1498Szrj     fn_type = build_varargs_function_type_array (return_type,
9438fd1498Szrj 						 param_types.length (),
9538fd1498Szrj 						 param_types.address ());
9638fd1498Szrj   else
9738fd1498Szrj     fn_type = build_function_type_array (return_type,
9838fd1498Szrj 					 param_types.length (),
9938fd1498Szrj 					 param_types.address ());
10038fd1498Szrj   /* FIXME: this uses input_location: */
10138fd1498Szrj   tree fndecl = build_fn_decl (name, fn_type);
10238fd1498Szrj 
10338fd1498Szrj   return fndecl;
10438fd1498Szrj }
10538fd1498Szrj 
10638fd1498Szrj /* Verify creating a function declaration equivalent to the following
10738fd1498Szrj      int test_fndecl_int_void (void);
10838fd1498Szrj    C declaration.  */
10938fd1498Szrj 
11038fd1498Szrj static void
test_fndecl_int_void()11138fd1498Szrj test_fndecl_int_void ()
11238fd1498Szrj {
11338fd1498Szrj   auto_vec <tree> param_types;
11438fd1498Szrj   const char *name = "test_fndecl_int_void";
11538fd1498Szrj   tree fndecl = make_fndecl (integer_type_node,
11638fd1498Szrj 			     name,
11738fd1498Szrj 			     param_types);
11838fd1498Szrj   ASSERT_TRUE (fndecl != NULL);
11938fd1498Szrj 
12038fd1498Szrj   /* Verify name of decl.  */
12138fd1498Szrj   tree declname = DECL_NAME (fndecl);
12238fd1498Szrj   ASSERT_TRUE (declname != NULL);
12338fd1498Szrj   ASSERT_EQ (IDENTIFIER_NODE, TREE_CODE (declname));
12438fd1498Szrj   /* We expect it to use a *copy* of the string we passed in.  */
12538fd1498Szrj   const char *identifier_ptr = IDENTIFIER_POINTER (declname);
12638fd1498Szrj   ASSERT_NE (name, identifier_ptr);
12738fd1498Szrj   ASSERT_EQ (0, strcmp ("test_fndecl_int_void", identifier_ptr));
12838fd1498Szrj 
12938fd1498Szrj   /* Verify type of fndecl.  */
13038fd1498Szrj   ASSERT_EQ (FUNCTION_DECL, TREE_CODE (fndecl));
13138fd1498Szrj   tree fntype = TREE_TYPE (fndecl);
13238fd1498Szrj   ASSERT_EQ (FUNCTION_TYPE, TREE_CODE (fntype));
13338fd1498Szrj 
13438fd1498Szrj   /* Verify return type.  */
13538fd1498Szrj   ASSERT_EQ (integer_type_node, TREE_TYPE (fntype));
13638fd1498Szrj 
13738fd1498Szrj   /* Verify "void" args.  */
13838fd1498Szrj   tree argtypes = TYPE_ARG_TYPES (fntype);
13938fd1498Szrj   ASSERT_EQ (TREE_LIST, TREE_CODE (argtypes));
14038fd1498Szrj   ASSERT_EQ (void_type_node, TREE_VALUE (argtypes));
14138fd1498Szrj   ASSERT_EQ (NULL, TREE_CHAIN (argtypes));
14238fd1498Szrj }
14338fd1498Szrj 
14438fd1498Szrj /* Verify creating a function declaration equivalent to the following
14538fd1498Szrj      float test_fndecl_float_intchar (int, char);
14638fd1498Szrj    C declaration.  */
14738fd1498Szrj 
14838fd1498Szrj static void
test_fndecl_float_intchar()14938fd1498Szrj test_fndecl_float_intchar ()
15038fd1498Szrj {
15138fd1498Szrj   auto_vec <tree> param_types;
15238fd1498Szrj   param_types.safe_push (integer_type_node);
15338fd1498Szrj   param_types.safe_push (char_type_node);
15438fd1498Szrj   const char *name = "test_fndecl_float_intchar";
15538fd1498Szrj   tree fndecl = make_fndecl (float_type_node,
15638fd1498Szrj 			     name,
15738fd1498Szrj 			     param_types);
15838fd1498Szrj   ASSERT_TRUE (fndecl != NULL);
15938fd1498Szrj 
16038fd1498Szrj   /* Verify name of decl.  */
16138fd1498Szrj   tree declname = DECL_NAME (fndecl);
16238fd1498Szrj   ASSERT_TRUE (declname != NULL);
16338fd1498Szrj   ASSERT_EQ (IDENTIFIER_NODE, TREE_CODE (declname));
16438fd1498Szrj   /* We expect it to use a *copy* of the string we passed in.  */
16538fd1498Szrj   const char *identifier_ptr = IDENTIFIER_POINTER (declname);
16638fd1498Szrj   ASSERT_NE (name, identifier_ptr);
16738fd1498Szrj   ASSERT_EQ (0, strcmp (name, identifier_ptr));
16838fd1498Szrj 
16938fd1498Szrj   /* Verify type of fndecl.  */
17038fd1498Szrj   ASSERT_EQ (FUNCTION_DECL, TREE_CODE (fndecl));
17138fd1498Szrj   tree fntype = TREE_TYPE (fndecl);
17238fd1498Szrj   ASSERT_EQ (FUNCTION_TYPE, TREE_CODE (fntype));
17338fd1498Szrj 
17438fd1498Szrj   /* Verify return type.  */
17538fd1498Szrj   ASSERT_EQ (float_type_node, TREE_TYPE (fntype));
17638fd1498Szrj 
17738fd1498Szrj   /* Verify "(int, char)" args.  */
17838fd1498Szrj   tree arg0 = TYPE_ARG_TYPES (fntype);
17938fd1498Szrj   ASSERT_EQ (TREE_LIST, TREE_CODE (arg0));
18038fd1498Szrj   ASSERT_EQ (integer_type_node, TREE_VALUE (arg0));
18138fd1498Szrj   tree arg1 = TREE_CHAIN (arg0);
18238fd1498Szrj   ASSERT_TRUE (arg1 != NULL);
18338fd1498Szrj   ASSERT_EQ (TREE_LIST, TREE_CODE (arg1));
18438fd1498Szrj   ASSERT_EQ (char_type_node, TREE_VALUE (arg1));
18538fd1498Szrj   tree argterm = TREE_CHAIN (arg1);
18638fd1498Szrj   ASSERT_TRUE (argterm != NULL);
18738fd1498Szrj   ASSERT_EQ (TREE_LIST, TREE_CODE (argterm));
18838fd1498Szrj   ASSERT_EQ (void_type_node, TREE_VALUE (argterm));
18938fd1498Szrj   ASSERT_EQ (NULL, TREE_CHAIN (argterm));
19038fd1498Szrj }
19138fd1498Szrj 
19238fd1498Szrj /* The test cases using these helper functions take a trivial function:
19338fd1498Szrj 
19438fd1498Szrj      int test_fn (void) { return 42; }
19538fd1498Szrj 
19638fd1498Szrj    and test various conversions done to it:
19738fd1498Szrj 
19838fd1498Szrj    - gimplification
19938fd1498Szrj    - construction of the CFG
20038fd1498Szrj    - conversion to SSA form
20138fd1498Szrj    - expansion to RTL form
20238fd1498Szrj 
20338fd1498Szrj    In avoid having one overlong test case, this is broken
20438fd1498Szrj    up into separate test cases for each stage, with helper functions
20538fd1498Szrj    to minimize code duplication.
20638fd1498Szrj 
20738fd1498Szrj    Another approach would be to attempt to directly construct a function
20838fd1498Szrj    in the appropriate representation at each stage, though presumably
20938fd1498Szrj    that would exhibit different kinds of failure compared to this
21038fd1498Szrj    approach.  */
21138fd1498Szrj 
21238fd1498Szrj /* Construct this function:
21338fd1498Szrj    int test_fn (void) { return 42; }
21438fd1498Szrj    in generic tree form.  Return the fndecl.  */
21538fd1498Szrj 
21638fd1498Szrj static tree
build_trivial_generic_function()21738fd1498Szrj build_trivial_generic_function ()
21838fd1498Szrj {
21938fd1498Szrj   auto_vec <tree> param_types;
22038fd1498Szrj   tree fndecl = make_fndecl (integer_type_node,
22138fd1498Szrj 			     "test_fn",
22238fd1498Szrj 			     param_types);
22338fd1498Szrj   ASSERT_TRUE (fndecl != NULL);
22438fd1498Szrj 
22538fd1498Szrj   /* Populate the function.  */
22638fd1498Szrj   tree retval = build_decl (UNKNOWN_LOCATION, RESULT_DECL,
22738fd1498Szrj 			    NULL_TREE, integer_type_node);
22838fd1498Szrj   DECL_ARTIFICIAL (retval) = 1;
22938fd1498Szrj   DECL_IGNORED_P (retval) = 1;
23038fd1498Szrj   DECL_RESULT (fndecl) = retval;
23138fd1498Szrj 
23238fd1498Szrj   /* Create a BIND_EXPR, and within it, a statement list.  */
23338fd1498Szrj   tree stmt_list = alloc_stmt_list ();
23438fd1498Szrj   tree_stmt_iterator stmt_iter = tsi_start (stmt_list);
23538fd1498Szrj   tree block = make_node (BLOCK);
23638fd1498Szrj   tree bind_expr
23738fd1498Szrj     = build3 (BIND_EXPR, void_type_node, NULL, stmt_list, block);
23838fd1498Szrj 
23938fd1498Szrj   tree modify_retval = build2 (MODIFY_EXPR,
24038fd1498Szrj 			       integer_type_node,
24138fd1498Szrj 			       retval,
24238fd1498Szrj 			       build_int_cst (integer_type_node, 42));
24338fd1498Szrj   tree return_stmt = build1 (RETURN_EXPR,
24438fd1498Szrj 			     integer_type_node,
24538fd1498Szrj 			     modify_retval);
24638fd1498Szrj   tsi_link_after (&stmt_iter, return_stmt, TSI_CONTINUE_LINKING);
24738fd1498Szrj 
24838fd1498Szrj   DECL_INITIAL (fndecl) = block;
24938fd1498Szrj   BLOCK_SUPERCONTEXT (block) = fndecl;
25038fd1498Szrj 
25138fd1498Szrj   /* how to add to function? the following appears to be how to
25238fd1498Szrj      set the body of a fndecl: */
25338fd1498Szrj   DECL_SAVED_TREE(fndecl) = bind_expr;
25438fd1498Szrj 
25538fd1498Szrj   /* Ensure that locals appear in the debuginfo.  */
25638fd1498Szrj   BLOCK_VARS (block) = BIND_EXPR_VARS (bind_expr);
25738fd1498Szrj 
25838fd1498Szrj   return fndecl;
25938fd1498Szrj }
26038fd1498Szrj 
26138fd1498Szrj /* Construct this function:
26238fd1498Szrj      int test_fn (void) { return 42; }
26338fd1498Szrj    in "high gimple" form.  Return the fndecl.  */
26438fd1498Szrj 
26538fd1498Szrj static tree
build_trivial_high_gimple_function()26638fd1498Szrj build_trivial_high_gimple_function ()
26738fd1498Szrj {
26838fd1498Szrj   /* Construct a trivial function, and gimplify it: */
26938fd1498Szrj   tree fndecl = build_trivial_generic_function ();
27038fd1498Szrj   gimplify_function_tree (fndecl);
27138fd1498Szrj   return fndecl;
27238fd1498Szrj }
27338fd1498Szrj 
27438fd1498Szrj /* Build a CFG for a function in gimple form.  */
27538fd1498Szrj 
27638fd1498Szrj static void
build_cfg(tree fndecl)27738fd1498Szrj build_cfg (tree fndecl)
27838fd1498Szrj {
27938fd1498Szrj   function *fun = DECL_STRUCT_FUNCTION (fndecl);
28038fd1498Szrj   ASSERT_TRUE (fun != NULL);
28138fd1498Szrj   ASSERT_EQ (fndecl, fun->decl);
28238fd1498Szrj 
28338fd1498Szrj   /* We first have to lower control flow; for our trivial test function
28438fd1498Szrj      this gives us:
28538fd1498Szrj 	 test_fn ()
28638fd1498Szrj 	 {
28738fd1498Szrj 	   D.56 = 42;
28838fd1498Szrj 	   goto <D.57>;
28938fd1498Szrj 	   <D.57>:
29038fd1498Szrj 	   return D.56;
29138fd1498Szrj 	 }
29238fd1498Szrj   */
29338fd1498Szrj   gimple_opt_pass *lower_cf_pass = make_pass_lower_cf (g);
29438fd1498Szrj   push_cfun (fun);
29538fd1498Szrj   lower_cf_pass->execute (fun);
29638fd1498Szrj   pop_cfun ();
29738fd1498Szrj   delete lower_cf_pass;
29838fd1498Szrj 
29938fd1498Szrj   /* We can now convert to CFG form; for our trivial test function this
30038fd1498Szrj      gives us:
30138fd1498Szrj 	 test_fn ()
30238fd1498Szrj 	 {
30338fd1498Szrj 	   <bb 2>:
30438fd1498Szrj 	   D.56 = 42;
30538fd1498Szrj 	   return D.56;
30638fd1498Szrj 	 }
30738fd1498Szrj   */
30838fd1498Szrj   gimple_opt_pass *build_cfg_pass = make_pass_build_cfg (g);
30938fd1498Szrj   push_cfun (fun);
31038fd1498Szrj   build_cfg_pass->execute (fun);
31138fd1498Szrj   pop_cfun ();
31238fd1498Szrj   delete build_cfg_pass;
31338fd1498Szrj }
31438fd1498Szrj 
31538fd1498Szrj /* Convert a gimple+CFG function to SSA form.  */
31638fd1498Szrj 
31738fd1498Szrj static void
convert_to_ssa(tree fndecl)31838fd1498Szrj convert_to_ssa (tree fndecl)
31938fd1498Szrj {
32038fd1498Szrj   function *fun = DECL_STRUCT_FUNCTION (fndecl);
32138fd1498Szrj   ASSERT_TRUE (fun != NULL);
32238fd1498Szrj   ASSERT_EQ (fndecl, fun->decl);
32338fd1498Szrj 
32438fd1498Szrj   gimple_opt_pass *build_ssa_pass = make_pass_build_ssa (g);
32538fd1498Szrj   push_cfun (fun);
32638fd1498Szrj   build_ssa_pass->execute (fun);
32738fd1498Szrj   pop_cfun ();
32838fd1498Szrj   delete build_ssa_pass;
32938fd1498Szrj }
33038fd1498Szrj 
33138fd1498Szrj /* Assuming we have a simple 3-block CFG like this:
33238fd1498Szrj      [ENTRY] -> [block2] -> [EXIT]
33338fd1498Szrj    get the "real" basic block (block 2).  */
33438fd1498Szrj 
33538fd1498Szrj static basic_block
get_real_block(function * fun)33638fd1498Szrj get_real_block (function *fun)
33738fd1498Szrj {
33838fd1498Szrj   ASSERT_TRUE (fun->cfg != NULL);
33938fd1498Szrj   ASSERT_EQ (3, n_basic_blocks_for_fn (fun));
34038fd1498Szrj   basic_block bb2 = (*fun->cfg->x_basic_block_info)[2];
34138fd1498Szrj   ASSERT_TRUE (bb2 != NULL);
34238fd1498Szrj   return bb2;
34338fd1498Szrj }
34438fd1498Szrj 
34538fd1498Szrj /* Verify that we have a simple 3-block CFG: the two "fake" ones, and
34638fd1498Szrj    a "real" one:
34738fd1498Szrj      [ENTRY] -> [block2] -> [EXIT].  */
34838fd1498Szrj 
34938fd1498Szrj static void
verify_three_block_cfg(function * fun)35038fd1498Szrj verify_three_block_cfg (function *fun)
35138fd1498Szrj {
35238fd1498Szrj   ASSERT_TRUE (fun->cfg != NULL);
35338fd1498Szrj   ASSERT_EQ (3, n_basic_blocks_for_fn (fun));
35438fd1498Szrj   ASSERT_EQ (2, n_edges_for_fn (fun));
35538fd1498Szrj 
35638fd1498Szrj   /* The "fake" basic blocks.  */
35738fd1498Szrj   basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (fun);
35838fd1498Szrj   ASSERT_TRUE (entry != NULL);
35938fd1498Szrj   ASSERT_EQ (ENTRY_BLOCK, entry->index);
36038fd1498Szrj 
36138fd1498Szrj   basic_block exit = EXIT_BLOCK_PTR_FOR_FN (fun);
36238fd1498Szrj   ASSERT_TRUE (exit != NULL);
36338fd1498Szrj   ASSERT_EQ (EXIT_BLOCK, exit->index);
36438fd1498Szrj 
36538fd1498Szrj   /* The "real" basic block.  */
36638fd1498Szrj   basic_block bb2 = get_real_block (fun);
36738fd1498Szrj   ASSERT_TRUE (bb2 != NULL);
36838fd1498Szrj   ASSERT_EQ (2, bb2->index);
36938fd1498Szrj 
37038fd1498Szrj   /* Verify connectivity.  */
37138fd1498Szrj   ASSERT_EQ (NULL, entry->preds);
37238fd1498Szrj   ASSERT_EQ (1, entry->succs->length ());
37338fd1498Szrj 
37438fd1498Szrj   edge from_entry_to_bb2 = (*entry->succs)[0];
37538fd1498Szrj   ASSERT_EQ (entry, from_entry_to_bb2->src);
37638fd1498Szrj   ASSERT_EQ (bb2, from_entry_to_bb2->dest);
37738fd1498Szrj 
37838fd1498Szrj   ASSERT_EQ (1, bb2->preds->length ());
37938fd1498Szrj   ASSERT_EQ (from_entry_to_bb2, (*bb2->preds)[0]);
38038fd1498Szrj   ASSERT_EQ (1, bb2->succs->length ());
38138fd1498Szrj 
38238fd1498Szrj   edge from_bb2_to_exit = (*bb2->succs)[0];
38338fd1498Szrj   ASSERT_EQ (bb2, from_bb2_to_exit->src);
38438fd1498Szrj   ASSERT_EQ (exit, from_bb2_to_exit->dest);
38538fd1498Szrj 
38638fd1498Szrj   ASSERT_EQ (1, exit->preds->length ());
38738fd1498Szrj   ASSERT_EQ (from_bb2_to_exit, (*exit->preds)[0]);
38838fd1498Szrj   ASSERT_EQ (NULL, exit->succs);
38938fd1498Szrj }
39038fd1498Szrj 
39138fd1498Szrj /* As above, but additionally verify the gimple statements are sane.  */
39238fd1498Szrj 
39338fd1498Szrj static void
verify_three_block_gimple_cfg(function * fun)39438fd1498Szrj verify_three_block_gimple_cfg (function *fun)
39538fd1498Szrj {
39638fd1498Szrj   verify_three_block_cfg (fun);
39738fd1498Szrj 
39838fd1498Szrj   /* The "fake" basic blocks should be flagged as gimple, but with have no
39938fd1498Szrj      statements.  */
40038fd1498Szrj   basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (fun);
40138fd1498Szrj   ASSERT_TRUE (entry != NULL);
40238fd1498Szrj   ASSERT_EQ (0, entry->flags & BB_RTL);
40338fd1498Szrj   ASSERT_EQ (NULL, bb_seq (entry));
40438fd1498Szrj 
40538fd1498Szrj   basic_block exit = EXIT_BLOCK_PTR_FOR_FN (fun);
40638fd1498Szrj   ASSERT_TRUE (exit != NULL);
40738fd1498Szrj   ASSERT_EQ (0, entry->flags & BB_RTL);
40838fd1498Szrj   ASSERT_EQ (NULL, bb_seq (exit));
40938fd1498Szrj 
41038fd1498Szrj   /* The "real" basic block should be flagged as gimple, and have one
41138fd1498Szrj      or more statements.  */
41238fd1498Szrj   basic_block bb2 = get_real_block (fun);
41338fd1498Szrj   ASSERT_TRUE (bb2 != NULL);
41438fd1498Szrj   ASSERT_EQ (0, entry->flags & BB_RTL);
41538fd1498Szrj   ASSERT_TRUE (bb_seq (bb2) != NULL);
41638fd1498Szrj }
41738fd1498Szrj 
41838fd1498Szrj /* As above, but additionally verify the RTL insns are sane.  */
41938fd1498Szrj 
42038fd1498Szrj void
verify_three_block_rtl_cfg(function * fun)42138fd1498Szrj verify_three_block_rtl_cfg (function *fun)
42238fd1498Szrj {
42338fd1498Szrj   verify_three_block_cfg (fun);
42438fd1498Szrj 
42538fd1498Szrj   /* The "fake" basic blocks should be flagged as RTL, but with no
42638fd1498Szrj      insns.  */
42738fd1498Szrj   basic_block entry = ENTRY_BLOCK_PTR_FOR_FN (fun);
42838fd1498Szrj   ASSERT_TRUE (entry != NULL);
42938fd1498Szrj   ASSERT_EQ (BB_RTL, entry->flags & BB_RTL);
43038fd1498Szrj   ASSERT_EQ (NULL, BB_HEAD (entry));
43138fd1498Szrj 
43238fd1498Szrj   basic_block exit = EXIT_BLOCK_PTR_FOR_FN (fun);
43338fd1498Szrj   ASSERT_TRUE (exit != NULL);
43438fd1498Szrj   ASSERT_EQ (BB_RTL, exit->flags & BB_RTL);
43538fd1498Szrj   ASSERT_EQ (NULL, BB_HEAD (exit));
43638fd1498Szrj 
43738fd1498Szrj   /* The "real" basic block should be flagged as RTL, and have one
43838fd1498Szrj      or more insns.  */
43938fd1498Szrj   basic_block bb2 = get_real_block (fun);
44038fd1498Szrj   ASSERT_TRUE (bb2 != NULL);
44138fd1498Szrj   ASSERT_EQ (BB_RTL, bb2->flags & BB_RTL);
44238fd1498Szrj   ASSERT_TRUE (BB_HEAD (bb2) != NULL);
44338fd1498Szrj }
44438fd1498Szrj 
44538fd1498Szrj /* Test converting our trivial function:
44638fd1498Szrj      int test_fn (void) { return 42; }
44738fd1498Szrj    to gimple form.  */
44838fd1498Szrj 
44938fd1498Szrj static void
test_gimplification()45038fd1498Szrj test_gimplification ()
45138fd1498Szrj {
45238fd1498Szrj   tree fndecl = build_trivial_generic_function ();
45338fd1498Szrj 
45438fd1498Szrj   /* Convert to gimple: */
45538fd1498Szrj   gimplify_function_tree (fndecl);
45638fd1498Szrj 
45738fd1498Szrj   /* Verify that we got gimple out of it.  */
45838fd1498Szrj 
45938fd1498Szrj   /* The function is now in GIMPLE form but the CFG has not been
46038fd1498Szrj      built yet.  */
46138fd1498Szrj 
46238fd1498Szrj   /* We should have a struct function for the decl.  */
46338fd1498Szrj   function *fun = DECL_STRUCT_FUNCTION (fndecl);
46438fd1498Szrj   ASSERT_TRUE (fun != NULL);
46538fd1498Szrj   ASSERT_EQ (fndecl, fun->decl);
46638fd1498Szrj 
46738fd1498Szrj   /* We expect a GIMPLE_BIND, with two gimple statements within it:
46838fd1498Szrj        tmp = 42;
46938fd1498Szrj        return tmp;  */
47038fd1498Szrj 
47138fd1498Szrj   gimple_seq seq_fn_body = gimple_body (fndecl);
47238fd1498Szrj   ASSERT_TRUE (seq_fn_body != NULL);
47338fd1498Szrj   gimple *bind_stmt = gimple_seq_first_stmt (seq_fn_body);
47438fd1498Szrj   ASSERT_EQ (GIMPLE_BIND, gimple_code (bind_stmt));
47538fd1498Szrj   ASSERT_EQ (NULL, bind_stmt->next);
47638fd1498Szrj 
47738fd1498Szrj   gimple_seq seq_bind_body = gimple_bind_body (as_a <gbind *> (bind_stmt));
47838fd1498Szrj 
47938fd1498Szrj   /* Verify that we have the 2 statements we expect.  */
48038fd1498Szrj   ASSERT_TRUE (seq_bind_body != NULL);
48138fd1498Szrj   gimple *stmt1 = gimple_seq_first_stmt (seq_bind_body);
48238fd1498Szrj   ASSERT_TRUE (stmt1 != NULL);
48338fd1498Szrj   ASSERT_EQ (GIMPLE_ASSIGN, gimple_code (stmt1));
48438fd1498Szrj   gimple *stmt2 = stmt1->next;
48538fd1498Szrj   ASSERT_TRUE (stmt2 != NULL);
48638fd1498Szrj   ASSERT_EQ (stmt1, stmt2->prev);
48738fd1498Szrj   ASSERT_EQ (GIMPLE_RETURN, gimple_code (stmt2));
48838fd1498Szrj }
48938fd1498Szrj 
49038fd1498Szrj /* Test of building a CFG for a function in high gimple form.  */
49138fd1498Szrj 
49238fd1498Szrj static void
test_building_cfg()49338fd1498Szrj test_building_cfg ()
49438fd1498Szrj {
49538fd1498Szrj   /* Construct a trivial function, and gimplify it: */
49638fd1498Szrj   tree fndecl = build_trivial_high_gimple_function ();
49738fd1498Szrj   function *fun = DECL_STRUCT_FUNCTION (fndecl);
49838fd1498Szrj   ASSERT_TRUE (fun != NULL);
49938fd1498Szrj 
50038fd1498Szrj   /* Build a CFG.  */
50138fd1498Szrj   build_cfg (fndecl);
50238fd1498Szrj 
50338fd1498Szrj   /* The CFG-building code constructs a 4-block cfg (with
50438fd1498Szrj      ENTRY and EXIT):
50538fd1498Szrj        test_fn ()
50638fd1498Szrj        {
50738fd1498Szrj          <bb 2>:
50838fd1498Szrj 	 D.65 = 42;
50938fd1498Szrj 
51038fd1498Szrj 	 <bb 3>:
51138fd1498Szrj 	 return D.65;
51238fd1498Szrj        }
51338fd1498Szrj      and then ought to merge blocks 2 and 3 in cleanup_tree_cfg.
51438fd1498Szrj 
51538fd1498Szrj      Hence we should end up with a simple 3-block cfg, the two "fake" ones,
51638fd1498Szrj      and a "real" one:
51738fd1498Szrj        [ENTRY] -> [block2] -> [EXIT]
51838fd1498Szrj      with code like this:
51938fd1498Szrj 	 test_fn ()
52038fd1498Szrj 	 {
52138fd1498Szrj 	   <bb 2>:
52238fd1498Szrj 	   D.56 = 42;
52338fd1498Szrj 	   return D.56;
52438fd1498Szrj 	 }
52538fd1498Szrj   */
52638fd1498Szrj   verify_three_block_gimple_cfg (fun);
52738fd1498Szrj 
52838fd1498Szrj   /* Verify the statements within the "real" block.  */
52938fd1498Szrj   basic_block bb2 = get_real_block (fun);
53038fd1498Szrj   gimple *stmt_a = gimple_seq_first_stmt (bb_seq (bb2));
53138fd1498Szrj   ASSERT_EQ (GIMPLE_ASSIGN, gimple_code (stmt_a));
53238fd1498Szrj   gimple *stmt_b = stmt_a->next;
53338fd1498Szrj   ASSERT_EQ (GIMPLE_RETURN, gimple_code (stmt_b));
53438fd1498Szrj   ASSERT_EQ (NULL, stmt_b->next);
53538fd1498Szrj }
53638fd1498Szrj 
53738fd1498Szrj /* Test of conversion of gimple to SSA form.  */
53838fd1498Szrj 
53938fd1498Szrj static void
test_conversion_to_ssa()54038fd1498Szrj test_conversion_to_ssa ()
54138fd1498Szrj {
54238fd1498Szrj   /* As above, construct a trivial function, gimplify it, and build a CFG: */
54338fd1498Szrj   tree fndecl = build_trivial_high_gimple_function ();
54438fd1498Szrj   function *fun = DECL_STRUCT_FUNCTION (fndecl);
54538fd1498Szrj   ASSERT_TRUE (fun != NULL);
54638fd1498Szrj   build_cfg (fndecl);
54738fd1498Szrj 
54838fd1498Szrj   convert_to_ssa (fndecl);
54938fd1498Szrj 
55038fd1498Szrj   verify_three_block_gimple_cfg (fun);
55138fd1498Szrj 
55238fd1498Szrj   /* For out trivial test function we should now have something like
55338fd1498Szrj      this:
55438fd1498Szrj        test_fn ()
55538fd1498Szrj        {
55638fd1498Szrj 	 <bb 2>:
55738fd1498Szrj 	 _1 = 42;
55838fd1498Szrj 	 return _1;
55938fd1498Szrj        }
56038fd1498Szrj   */
56138fd1498Szrj   basic_block bb2 = get_real_block (fun);
56238fd1498Szrj   gimple *stmt_a = gimple_seq_first_stmt (bb_seq (bb2));
56338fd1498Szrj   ASSERT_EQ (GIMPLE_ASSIGN, gimple_code (stmt_a));
56438fd1498Szrj 
56538fd1498Szrj   gimple *stmt_b = stmt_a->next;
56638fd1498Szrj   ASSERT_EQ (GIMPLE_RETURN, gimple_code (stmt_b));
56738fd1498Szrj   ASSERT_EQ (NULL, stmt_b->next);
56838fd1498Szrj 
56938fd1498Szrj   greturn *return_stmt = as_a <greturn *> (stmt_b);
57038fd1498Szrj   ASSERT_EQ (SSA_NAME, TREE_CODE (gimple_return_retval (return_stmt)));
57138fd1498Szrj }
57238fd1498Szrj 
57338fd1498Szrj /* Test of expansion from gimple-ssa to RTL.  */
57438fd1498Szrj 
57538fd1498Szrj static void
test_expansion_to_rtl()57638fd1498Szrj test_expansion_to_rtl ()
57738fd1498Szrj {
57838fd1498Szrj   /* As above, construct a trivial function, gimplify it, build a CFG,
57938fd1498Szrj      and convert to SSA: */
58038fd1498Szrj   tree fndecl = build_trivial_high_gimple_function ();
58138fd1498Szrj   function *fun = DECL_STRUCT_FUNCTION (fndecl);
58238fd1498Szrj   ASSERT_TRUE (fun != NULL);
58338fd1498Szrj   build_cfg (fndecl);
58438fd1498Szrj   convert_to_ssa (fndecl);
58538fd1498Szrj 
58638fd1498Szrj   /* We need a cgraph_node for it.  */
58738fd1498Szrj   cgraph_node::get_create (fndecl);
58838fd1498Szrj   /* Normally, cgraph_node::expand () would call
58938fd1498Szrj      init_function_start (and a bunch of other stuff),
59038fd1498Szrj      and invoke the expand pass, but it also runs
59138fd1498Szrj      all of the other passes.  So just do the minimum
59238fd1498Szrj      needed to get from gimple-SSA to RTL.  */
59338fd1498Szrj   rtl_opt_pass *expand_pass = make_pass_expand (g);
59438fd1498Szrj   push_cfun (fun);
59538fd1498Szrj   init_function_start (fndecl);
59638fd1498Szrj   expand_pass->execute (fun);
59738fd1498Szrj   pop_cfun ();
59838fd1498Szrj   delete expand_pass;
59938fd1498Szrj 
60038fd1498Szrj   /* On x86_64, I get this:
60138fd1498Szrj        (note 3 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
60238fd1498Szrj        (note 2 3 5 2 NOTE_INSN_FUNCTION_BEG)
60338fd1498Szrj        (insn 5 2 6 2 (set (reg:SI 87 [ D.59 ])
60438fd1498Szrj 			  (const_int 42 [0x2a])) -1 (nil))
60538fd1498Szrj        (insn 6 5 10 2 (set (reg:SI 88 [ <retval> ])
60638fd1498Szrj 			   (reg:SI 87 [ D.59 ])) -1 (nil))
60738fd1498Szrj        (insn 10 6 11 2 (set (reg/i:SI 0 ax)
60838fd1498Szrj 			    (reg:SI 88 [ <retval> ])) -1 (nil))
60938fd1498Szrj        (insn 11 10 0 2 (use (reg/i:SI 0 ax)) -1 (nil))
61038fd1498Szrj 
61138fd1498Szrj      On cr16-elf I get this:
61238fd1498Szrj        (note 4 1 2 2 [bb 2] NOTE_INSN_BASIC_BLOCK)
61338fd1498Szrj        (insn 2 4 3 2 (set (reg:SI 24)
61438fd1498Szrj 	    (reg/f:SI 16 virtual-incoming-args)) -1
61538fd1498Szrj 	  (nil))
61638fd1498Szrj        (note 3 2 6 2 NOTE_INSN_FUNCTION_BEG)
61738fd1498Szrj        (insn 6 3 7 2 (set (reg:HI 22 [ _1 ])
61838fd1498Szrj 	    (const_int 42 [0x2a])) -1
61938fd1498Szrj 	 (nil))
62038fd1498Szrj        (insn 7 6 11 2 (set (reg:HI 23 [ <retval> ])
62138fd1498Szrj 	   (reg:HI 22 [ _1 ])) -1
62238fd1498Szrj 	 (nil))
62338fd1498Szrj        (insn 11 7 12 2 (set (reg/i:HI 0 r0)
62438fd1498Szrj 	   (reg:HI 23 [ <retval> ])) -1
62538fd1498Szrj 	 (nil))
62638fd1498Szrj        (insn 12 11 0 2 (use (reg/i:HI 0 r0)) -1
62738fd1498Szrj 	 (nil)).  */
62838fd1498Szrj   verify_three_block_rtl_cfg (fun);
62938fd1498Szrj 
63038fd1498Szrj   /* Verify as much of the RTL as we can whilst avoiding
63138fd1498Szrj      target-specific behavior.  */
63238fd1498Szrj   basic_block bb2 = get_real_block (fun);
63338fd1498Szrj 
63438fd1498Szrj   /* Expect a NOTE_INSN_BASIC_BLOCK... */
63538fd1498Szrj   rtx_insn *insn = BB_HEAD (bb2);
63638fd1498Szrj   ASSERT_TRUE (insn != NULL);
63738fd1498Szrj   ASSERT_EQ (NOTE, insn->code);
63838fd1498Szrj   ASSERT_EQ (NOTE_INSN_BASIC_BLOCK, NOTE_KIND (insn));
63938fd1498Szrj   ASSERT_EQ (bb2, NOTE_BASIC_BLOCK (insn));
64038fd1498Szrj 
64138fd1498Szrj   /* ...etc; any further checks are likely to over-specify things
64238fd1498Szrj      and run us into target dependencies.  */
64338fd1498Szrj 
64438fd1498Szrj   /* Verify that print_rtl_function is sane.  */
64538fd1498Szrj   named_temp_file tmp_out (".rtl");
64638fd1498Szrj   FILE *outfile = fopen (tmp_out.get_filename (), "w");
64738fd1498Szrj   print_rtx_function (outfile, fun, true);
64838fd1498Szrj   fclose (outfile);
64938fd1498Szrj 
65038fd1498Szrj   char *dump = read_file (SELFTEST_LOCATION, tmp_out.get_filename ());
65138fd1498Szrj   ASSERT_STR_CONTAINS (dump, "(function \"test_fn\"\n");
65238fd1498Szrj   ASSERT_STR_CONTAINS (dump, "  (insn-chain\n");
65338fd1498Szrj   ASSERT_STR_CONTAINS (dump, "    (block 2\n");
65438fd1498Szrj   ASSERT_STR_CONTAINS (dump, "      (edge-from entry (flags \"FALLTHRU\"))\n");
65538fd1498Szrj   ASSERT_STR_CONTAINS (dump, "      (cinsn "); /* ...etc.  */
65638fd1498Szrj   ASSERT_STR_CONTAINS (dump, "      (edge-to exit (flags \"FALLTHRU\"))\n");
65738fd1498Szrj   ASSERT_STR_CONTAINS (dump, "    ) ;; block 2\n");
65838fd1498Szrj   ASSERT_STR_CONTAINS (dump, "  ) ;; insn-chain\n");
65938fd1498Szrj   ASSERT_STR_CONTAINS (dump, "  (crtl\n");
66038fd1498Szrj   ASSERT_STR_CONTAINS (dump, "  ) ;; crtl\n");
66138fd1498Szrj   ASSERT_STR_CONTAINS (dump, ") ;; function \"test_fn\"\n");
66238fd1498Szrj 
66338fd1498Szrj   free (dump);
664*58e805e6Szrj   free_after_compilation (fun);
66538fd1498Szrj }
66638fd1498Szrj 
66738fd1498Szrj /* Run all of the selftests within this file.  */
66838fd1498Szrj 
66938fd1498Szrj void
function_tests_c_tests()67038fd1498Szrj function_tests_c_tests ()
67138fd1498Szrj {
67238fd1498Szrj   test_fndecl_int_void ();
67338fd1498Szrj   test_fndecl_float_intchar ();
67438fd1498Szrj   test_gimplification ();
67538fd1498Szrj   test_building_cfg ();
67638fd1498Szrj   test_conversion_to_ssa ();
67738fd1498Szrj   test_expansion_to_rtl ();
67838fd1498Szrj }
67938fd1498Szrj 
68038fd1498Szrj } // namespace selftest
68138fd1498Szrj 
68238fd1498Szrj #endif /* #if CHECKING_P */
683